aboutsummaryrefslogtreecommitdiff
path: root/flx/flx.c
diff options
context:
space:
mode:
Diffstat (limited to 'flx/flx.c')
-rw-r--r--flx/flx.c115
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);
+}
+