//list.h
#ifndef _LIST_H
#define _LIST_H
#include
#include
#include
typedef struct
{
time_t mtime;
char name[256];
}File;
typedef struct _ListNode
{
File data;
struct _ListNode *next;
}ListNode;
typedef struct
{
ListNode *head;
ListNode *tail;
}List;
List* InitList();
int ListDestroy(List *lp);
int ListInsertHead(List *lp, File *data);
int ListDelete(List *lp, int n);
int ListEmpty(List *lp);
ListNode* NewNode(File *data);
#endif
//list.c
#include "list.h"
File g_data;
List *InitList()
{
List *p = NULL;
ListNode *pdata = NULL;
p = (List *)malloc(sizeof(List));
if (!p)
return p;
pdata = NewNode(&g_data);
p->head = pdata;
return p;
}
int ListDestroy(List *lp)
{
if (!lp)
{
return 0;
}
while (ListDelete(lp, 1));
free(lp);
return 1;
}
int ListInsertHead(List *lp, File *data)
{
ListNode *p = NULL;
p = NewNode(data);
if (!p)
{
return 0;
}
p->next = lp->head->next;
lp->head->next = p;
return 1;
}
int ListDelete(List *lp, int n)
{
int i = 0;
if (n < 0)
return 0;
ListNode *p = lp->head;
ListNode *p1 = NULL;
for (;i < n-1 && p; p = p->next, ++i);
p1 = p->next;
p->next = p1->next;
free(p1);
return 1;
}
ListNode* NewNode(File *data)
{
ListNode *p = NULL;
p = (ListNode *)malloc(sizeof(ListNode));
if (!p)
{
return p;
}
memcpy(&p->data, data, sizeof(File));
p->next = NULL;
return p;
}
//monitorfile.h
#ifndef _MONITORFILE_H
#define _MONITORFILE_h
void sys_err(char *str);
void demon();
void dirwalk(List *lp, char *path, void (*fun)(List *lp, char *name));
void fize(List *lp, char *name);
void monitorfile();
#endif
//monitorfile.c
#include "list.h"
#include "monitorfile.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_PATH 1024
int g_first = 0;
void sys_err(char *str)
{
write(1, str, strlen(str));
exit(1);
}
//创建守护进程
void demon()
{
pid_t pid;
if ((pid = fork()) < 0)
{
sys_err("fork");
}
else if (pid > 0)
{
exit(0);
}
setsid();
if (chdir("/tmp/") < 0)
{
sys_err("chdir");
}
umask(0);
close(0);
close(1);
close(2);
open("filechangedlog", O_RDWR | O_CREAT, 0666);
open("errorlog", O_RDWR | O_CREAT, 0666);
}
ListNode* Find(List *lp, char *name)
{
ListNode *p = lp->head;
for (; p;p = p->next)
{
if (strcmp(name, p->data.name) == 0)
{
return p;
}
}
return NULL;
}
void dirwalk(List *lp, char *path, void (*fun)(List *lp, char *name))
{
char name[MAX_PATH];
struct dirent *dir;
DIR *pdir;
if ( (pdir = opendir(path)) == NULL)
{
sys_err("opendir");
}
while ( (dir = readdir(pdir)) != NULL )
{
//将某些目录和文件剔除
if (strncmp(dir->d_name, ".", 1) == 0 || strcmp(dir->d_name, "..") == 0)
{
continue;
}
if (strlen(path) + strlen(dir->d_name) + 2 > sizeof(name))
{
sprintf(name, "%s %s too long", path, dir->d_name);
sys_err(name);
}
else
{
sprintf(name, "%s/%s", path, dir->d_name);
(*fun)(lp, name);
}
}
closedir(pdir);
}
void fize(List *lp, char *name)
{
struct stat buf;
File data;
if (stat(name, &buf) < 0)
{
sys_err("stat");
}
if ((buf.st_mode & S_IFMT) == S_IFDIR)
{
dirwalk(lp, name, fize);
}
else
{
data.mtime = buf.st_mtime;
strcpy(data.name, name);
//第一次 直接将节点插入
if (g_first == 0)
{
ListInsertHead(lp, &data);
}
else
{
ListNode *p = Find(lp, data.name);
char buffer[1024];
//返回NULL 不存在 直接插入
if (p == NULL)
{
sprintf(buffer, "%s crate %s\n", data.name, ctime(&data.mtime));
write(0, buffer, strlen(buffer));
ListInsertHead(lp, &data);
}
else
{
//时间被改变
if (data.mtime != p->data.mtime)
{
sprintf(buffer, "%s changed %s\n", data.name, ctime(&data.mtime));
write(0, buffer, strlen(buffer));
}
}
}
}
}
//检测文件是否存在
void CheckFile(List *lp)
{
ListNode *p = NULL;
struct stat buf;
char buffer[1024];
time_t t;
int i = 1;
for (p = lp->head->next; p; p = p->next, ++i)
{
if (stat(p->data.name, &buf) < 0)
{
//如果不存在 直接删除节点
if (errno == ENOENT)
{
t = time(NULL);
sprintf(buffer, "%s delete %s\n", p->data.name, ctime(&t));
write(0, buffer, strlen(buffer));
ListDelete(lp, i);
}
}
}
}
void monitorfile()
{
ListNode *p = NULL;
List *lp = InitList();
demon();
fize(lp, "/home/stucky/");
g_first = 1;
while (1)
{
sleep(3);
fize(lp, "/home/stucky/");
CheckFile(lp);
}
ListDestroy(lp);
}
//main.c
#include "list.h"
#include "monitorfile.h"
int main(void)
{
monitorfile();
return 0;
}
利用单链表、守护进程、目录遍历来实现监控某个目录下的文件更改、删除、创建。