From 8d7b4a74c710909f6b5d3ffefba6edb5db1d76a8 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 30 Sep 2010 23:04:11 +0200 Subject: [PATCH] notify/fscrawl: fixed up src/notify/tree, ADT, new API, new name. --- Makefile | 2 +- src/notify/fscrawl.c | 184 +++++++++++++++++++++++++++++++++++++++++ src/notify/fscrawl.h | 30 +++++++ src/notify/tree.c | 193 ------------------------------------------- src/notify/tree.h | 42 ---------- test/Makefile | 10 +-- test/t_fscrawl.c | 40 +++++++++ test/t_tree.c | 36 -------- 8 files changed, 260 insertions(+), 277 deletions(-) create mode 100644 src/notify/fscrawl.c create mode 100644 src/notify/fscrawl.h delete mode 100644 src/notify/tree.c delete mode 100644 src/notify/tree.h create mode 100644 test/t_fscrawl.c delete mode 100644 test/t_tree.c diff --git a/Makefile b/Makefile index 681989c..3e95fd4 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ obj += src/output/$(output).o obj += src/notify/inotify.o obj += src/notify/event.o -obj += src/notify/tree.o +obj += src/notify/fscrawl.o obj += src/notify/queue.o obj += src/arch.o diff --git a/src/notify/fscrawl.c b/src/notify/fscrawl.c new file mode 100644 index 0000000..f19e912 --- /dev/null +++ b/src/notify/fscrawl.c @@ -0,0 +1,184 @@ +/* notify/fscrawl.c - Filesystem traversal + * + * (C) Copyright 2010 Henrik Hautakoski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include + +#include "../common/strbuf.h" +#include "../common/path.h" +#include "../common/debug.h" +#include "fscrawl.h" + +#define MAX_DEPTH 0x20 + +#define isrefdir(x) (!strcmp((x)->d_name, ".") || !strcmp((x)->d_name, "..")) + +struct __fscrawl { + strbuf_t path; + DIR *dirs[MAX_DEPTH]; + unsigned char depth; + fs_entry ent; +}; + +static int mvup(struct __fscrawl *f) { + + if (closedir(f->dirs[f->depth]) == -1) { + perror("TREE"); + return -1; + } + + if (f->depth == 0) + return 0; + + dprint("tree_next_ent: tree depth is: %i \n", f->depth); + + f->depth--; + + if (f->path.buf[f->path.len-1] == '/') + strbuf_reduce(&f->path, 1); + strbuf_rchop(&f->path, '/'); + strbuf_term(&f->path, '/'); + + return 1; +} + +static int mvdown(struct __fscrawl *f, const char *dir) { + + DIR *ds = NULL; + + if (f->depth >= MAX_DEPTH-1) + return 0; + + strbuf_term(&f->path, '/'); + strbuf_append_str(&f->path, dir); + strbuf_term(&f->path, '/'); + + ds = opendir(f->path.buf); + + if (!ds) { + if (errno != EACCES) + perror("opendir"); + errno = 0; + + strbuf_reduce(&f->path, 1); + strbuf_rchop(&f->path, '/'); + strbuf_term(&f->path, '/'); + return 0; + } + + f->dirs[++f->depth] = ds; + + return 1; +} + +fscrawl_t fsc_open(const char *path) { + + int i; + struct __fscrawl *f = malloc(sizeof(struct __fscrawl)); + + if (f == NULL) + return NULL; + + strbuf_init(&f->path); + + + char *npath = path_normalize(path, NULL, 1); + + if (!npath) + return NULL; + + /* set the normalized path as the string buffer */ + strbuf_attach(&f->path, npath, strlen(npath), strlen(npath)); + + f->depth = 0; + + f->dirs[f->depth] = opendir(f->path.buf); + + if (!f->dirs[f->depth]) { + + perror("fsc_open"); + errno = 0; + + strbuf_free(&f->path); + free(f); + return NULL; + } + + f->ent.name = NULL; + f->ent.base = NULL; + f->ent.dir = 0; + + return f; +} + +void fsc_close(fscrawl_t f) { + + int i; + + for(i=0; i < f->depth; i++) + closedir(f->dirs[i]); + + strbuf_free(&f->path); + free(f); +} + +fs_entry* fsc_cpy(fs_entry *ent) { + + void *ptr = malloc(sizeof(fs_entry)); + + if (ptr == NULL) + return NULL; + + memcpy(ptr, ent, sizeof(fs_entry)); + + return ptr; +} + +fs_entry* fsc_read(fscrawl_t f) { + + struct dirent *ent = NULL; + + if (!f) + return NULL; + + if (f->ent.dir) + mvdown(f, f->ent.name); + + for(;;) { + + ent = readdir(f->dirs[f->depth]); + + if (ent) { + if (isrefdir(ent)) + continue; + break; + } + + if (errno) { + perror("fsc_read"); + errno = 0; + continue; + } + + if (mvup(f)) + continue; + + fsc_close(f); + return NULL; + } + + f->ent.base = f->path.buf; + f->ent.name = &ent->d_name[0]; + f->ent.dir = ent->d_type == 4; + + return &f->ent; +} diff --git a/src/notify/fscrawl.h b/src/notify/fscrawl.h new file mode 100644 index 0000000..820ae35 --- /dev/null +++ b/src/notify/fscrawl.h @@ -0,0 +1,30 @@ +/* notify/fscrawl.h - Filesystem traversal + * + * (C) Copyright 2010 Henrik Hautakoski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + */ + +#ifndef __NOTIFY_FSCRAWL_H +#define __NOTIFY_FSCRAWL_H + +typedef struct { + char *name; + char *base; + unsigned char dir; +} fs_entry; + +typedef struct __fscrawl *fscrawl_t; + +fscrawl_t fsc_open(const char *path); + +void fsc_close(fscrawl_t f); + +fs_entry* fsc_cpy(fs_entry *ent); + +fs_entry* fsc_read(fscrawl_t f); + +#endif /* __NOTIFY_FSCRAWL_H */ diff --git a/src/notify/tree.c b/src/notify/tree.c deleted file mode 100644 index 62012c4..0000000 --- a/src/notify/tree.c +++ /dev/null @@ -1,193 +0,0 @@ -/* notify/tree.c - Filesystem traversal - * - * (C) Copyright 2010 Henrik Hautakoski - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - */ -#include -#include -#include -#include -#include -#include - -#include "../common/path.h" -#include "tree.h" - -#if 0 - #define pdebug(...) fprintf(stderr, __VA_ARGS__) -#else - #define pdebug(...) 0 -#endif - -#define isrefdir(x) (!strcmp(x->d_name, ".") || !strcmp(x->d_name, "..")) - -/* REF:1 */ -static int have_perm(const char *base, const char *name) { - - char buf[1024]; - - sprintf(buf, "%s%s", base, name); - - return access(buf, R_OK | X_OK) == 0; -} - -struct tree* tree_new(const char *path) { - - int i; - struct tree *t = malloc(sizeof(struct tree)); - - if (t == NULL) - return NULL; - - t->path = path_normalize(path, NULL, 0); - - if (t->path == NULL) { - free(t); - return NULL; - } - - t->depth = 0; - - t->dirs[0] = opendir(t->path); - - if (!t->dirs[0]) { - free(t->path); - free(t); - return NULL; - } - - t->ent.name = NULL; - t->ent.base = NULL; - t->ent.dir = 0; - - return t; -} - -void tree_del(struct tree *tree) { - - int i; - - for(i=0; i < tree->depth; i++) - closedir(tree->dirs[i]); - - if (tree->path != NULL) - free(tree->path); - - free(tree); -} - -/* REF:1 */ -int tree_mvup(struct tree *tree) { - - char *slash; - - if (closedir(tree->dirs[tree->depth]) == -1) { - perror("TREE"); - return -1; - } - - if (tree->depth == 0) - return 0; -#if __DEBUG__ - printf("tree_next_ent: tree depth is: %i \n", tree->depth); -#endif - tree->depth--; - - slash = tree->path + strlen(tree->path)-1; - if (*slash == '/') - *slash = 0; - - slash = strrchr(tree->path, '/'); - *(slash+1) = 0; - - tree->path = realloc(tree->path, sizeof(char) * (strlen(tree->path)+1)); - - return 1; -} - -/* REF:1 */ -int tree_mvdown(struct tree *tree, const char *dir) { - - char buf[PATH_MAX]; - DIR *ds; - - if (tree->depth >= MAX_DEPTH-1) - return 0; - - sprintf(buf, "%s%s/\0", tree->path, dir); - - if ((ds = opendir(buf)) == NULL) { - if (errno != EACCES) - perror("DIROPEN"); - return 0; - } - - tree->path = realloc(tree->path, sizeof(char) * (strlen(buf)+1)); - memcpy(tree->path, buf, strlen(buf)+1); - - tree->dirs[++tree->depth] = ds; - - return 1; -} - -struct entry* tree_cpy_ent(struct entry *ent) { - - struct entry *ptr = malloc(sizeof(struct entry)); - - if (ptr == NULL) - return NULL; - - memcpy(ptr, ent, sizeof(struct entry)); - - return ptr; -} - -/* - * NOTE: only read from the struct returned and DO NOT free it. - * use tree_cpy_ent() if you need to store it. - */ -struct entry* tree_next_ent(struct tree *tree) { - - struct dirent *ent = NULL; - - if (tree == NULL) - return NULL; - - if (tree->ent.dir) - tree_mvdown(tree, tree->ent.name); - - for(;;) { - - ent = readdir(tree->dirs[tree->depth]); - - if (ent == NULL) { - - if (tree_mvup(tree)) - continue; - - tree_del(tree); - return NULL; - } else if (isrefdir(ent)) { - continue; - - } else if (ent->d_type == 4) { - - if (have_perm(tree->path, ent->d_name)) - break; - - } else { - break; - } - - } - - tree->ent.dir = ent->d_type == 4; - tree->ent.base = tree->path; - tree->ent.name = &ent->d_name[0]; - - return &tree->ent; -} diff --git a/src/notify/tree.h b/src/notify/tree.h deleted file mode 100644 index 8d87fa0..0000000 --- a/src/notify/tree.h +++ /dev/null @@ -1,42 +0,0 @@ -/* notify/tree.h - Filesystem traversal - * - * (C) Copyright 2010 Henrik Hautakoski - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - */ - -#ifndef __NOTIFY_TREE_H -#define __NOTIFY_TREE_H - -#define MAX_DEPTH 0x20 - -#include - -struct tree { - char *path; - DIR *dirs[MAX_DEPTH]; - unsigned char depth; - /* REF:2 */ - struct entry { - char *name; - char *base; - unsigned char dir; - } ent; -}; - -struct tree* tree_new(const char *path); - -void tree_del(struct tree *tree); - -int tree_mvup(struct tree *tree); - -int tree_mvdown(struct tree *tree, const char *dir); - -struct entry* tree_cpy_ent(struct entry *ent); - -struct entry* tree_next_ent(struct tree *tree); - -#endif /* __NOTIFY_TREE_H */ diff --git a/test/Makefile b/test/Makefile index b008e46..6d3eb84 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,7 +3,7 @@ CC=gcc CFLAGS=-g -D__DEBUG__ LDFLAGS=-L/usr/lib64/mysql -lmysqlclient -all : raw_inotify strbuf path rbtree inotify tree mysql stdout queue +all : raw_inotify strbuf path rbtree inotify fscrawl mysql stdout queue raw_inotify : $(CC) -linotifytools t_raw_inotify.c -o test_raw_inotify @@ -39,19 +39,19 @@ inotify : ../src/common/strbuf.c \ ../src/common/path.c \ ../src/notify/event.c \ - ../src/notify/tree.c \ + ../src/notify/fscrawl.c \ ../src/notify/queue.c \ ../src/notify/inotify.c \ t_inotify.c -o test_inotify -tree : +fscrawl : $(CC) $(CFLAGS) \ ../src/common/path.c \ - ../src/notify/tree.c \ + ../src/notify/fscrawl.c \ ../src/common/xalloc.c \ ../src/common/die.c \ ../src/common/strbuf.c \ - t_tree.c -o test_tree + t_fscrawl.c -o test_fscrawl mysql : $(CC) -D DB_DEBUG $(CFLAGS) $(LDFLAGS) \ diff --git a/test/t_fscrawl.c b/test/t_fscrawl.c new file mode 100644 index 0000000..ae35ca0 --- /dev/null +++ b/test/t_fscrawl.c @@ -0,0 +1,40 @@ + +#include +#include "../src/notify/fscrawl.h" + +int main(int argc, char *argv[]) { + + fscrawl_t crawl; + unsigned int c_ent = 0; + + if (argc < 2) + return 1; + + crawl = fsc_open(argv[1]); + + if (crawl == NULL) { + printf("Invalid path\n"); + return 1; + } + + for(;;) { + + fs_entry *ent = fsc_read(crawl); + + if (!ent) + break; + + printf("%s%s", ent->base, ent->name); + + if (ent->dir) + printf("/\n"); + else + printf("\n"); + + c_ent++; + } + + printf("%i Entries\n", c_ent); + + return 0; +} diff --git a/test/t_tree.c b/test/t_tree.c deleted file mode 100644 index 6bc6b5e..0000000 --- a/test/t_tree.c +++ /dev/null @@ -1,36 +0,0 @@ - -#include -#include "../src/notify/tree.h" - -int main(int argc, char *argv[]) { - - struct entry *ent; - struct tree *tree; - unsigned int c_ent = 0; - - if (argc < 2) - return 1; - - tree = tree_new(argv[1]); - - if (tree == NULL) { - printf("error\n"); - return 1; - } - - for(;;) { - - ent = tree_next_ent(tree); - - if (ent == NULL) - break; - - printf("%s%s\n", ent->base, ent->name); - - c_ent++; - } - - printf("%i Entries\n", c_ent); - - return 0; -}