#include #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); }