diff options
Diffstat (limited to 'flx/flx.c')
-rw-r--r-- | flx/flx.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/flx/flx.c b/flx/flx.c new file mode 100644 index 0000000..8aed3ab --- /dev/null +++ b/flx/flx.c @@ -0,0 +1,115 @@ +#include <string.h> +#include "utils.h" +#include "flx.h" + + +/* cette fonction ajoute et place un chainon dans la chaine t_file_tree (brother) + * le pointeur pfilename est le pointeur à utiliser pour le nom, attention + * aux allocations (il n'est pas logique qu'il contienne un '/' + * elle retourne un pointeur sur le nouveau chainon + */ +t_ft *ft_add(t_ft *base, char *pfilename, void *(*fct_init_desc)(), void *data) { + t_ft *new; + int ret = 1; + + /* base initialisation */ + if (!pfilename || !base) { + new = POOL_ALLOC(t_file_tree); + new->prev = new->next = new; + /* be the root dir */ + new->parent = (!base) ? new : base; + new->filename = NULL; + new->desc = fct_init_desc ? fct_init_desc(data) : NULL; + new->subtree = NULL; + new->status = BASE; + return (new); + } + /* possibly pass first element */ + if (!base->filename) base = base->next; + /* find best place */ + while (base->filename && (ret = strcmp(pfilename, base->filename)) > 0) + base = base->next; + /* already exist */ + if (ret == 0) return (base); + + /* create new element and fill it */ + new = POOL_ALLOC(t_file_tree); + /* data */ + new->status = 0; + new->desc = NULL; + new->filename = pfilename; + + /* description pointer initialization */ + new->desc = fct_init_desc ? fct_init_desc(data) : NULL; + + /* parent is the same for each soon, or be root dir */ + new->parent = (!base->parent) ? new : base->parent; + + /* special traitment for '.' and '..' */ + new->subtree = NULL; + if (base && base->parent && IS_DOT(pfilename)) + new->subtree = base->parent->subtree; + if (base && base->parent && base->parent->parent && IS_DOTDOT(pfilename)) + new->subtree = base->parent->parent->subtree; + + /* place at the before current base */ + LIST_CHAIN(base->prev, new, base); + return (new); +} + +/* cette fonction supprime un chainon dans une chaine t_file_tree + * elle retourne le pointeur sur le chainon précédent + */ +t_ft *ft_del(t_ft *old, void (*fct_free_desc)(void *data, void *desc), void *data) { + t_ft *prev; + + prev = LIST_UNCHAIN(old); + if (old->filename) FREE(old->filename); + if (old->desc) { + if (fct_free_desc) fct_free_desc(data, old->desc); + // else warning("Possibly unfree memory"); + } + if (old->subtree && !IS_PDOTF(old)) { + t_ft *c; + for (c = old->subtree->next; c != old->subtree; c = c->next) + c = ft_del(c, fct_free_desc, data); + POOL_FREE(t_file_tree, old->subtree); + } + POOL_FREE(t_file_tree, old); + return (prev); +} + +/* return (and build) tree structure for matching path */ +/* path : directory to search (and create) + * tree : current directories structure + * (return) : pointer to a new base tree + */ +t_ft *ft_get(t_ft *tree, char *path) { + char tfilename[BUFFER_LENGTH]; + char *beginpath; + int len; + + /* no more subtree, break to current */ + while (path && *path) { + /* the first level path filename */ + beginpath = path; + if ((path = strchr(beginpath, '/'))) path++; + len = (path ? (path - beginpath - 1) : strlen(beginpath)); + + /* put filename in buffer */ + strncpy(tfilename, beginpath, len); tfilename[len] = 0; + + /* want subdir but don't exist, should create */ + if (!tree->subtree) tree->subtree = NEWDIR(tree); + + /* get it in current directory */ + tree = ft_add(tree->subtree, tfilename, NULL, NULL); + + /* new entry, allocate memory for filename */ + if (tree->filename == tfilename) + tree->filename = strdup(tree->filename); + + } + return (tree); +} + |