#include #include "utils.h" #include "flx.h" #include "output.h" #include "source_type.h" #include "flx_fcntl.h" int Sorted = (INPUT_SORTED|OUTPUT_SORTED); /* input/output sorted status */ t_file_desc *free_file_desc(t_file_desc *desc) { if (!desc) return (NULL); if (desc->md5) FREE(desc->md5); if (desc->link) FREE(desc->link); FREE(desc); return (NULL); } t_file_desc *fct_free_file_desc(void *data, t_file_desc *desc) { return (free_file_desc(desc)); } /* this function free file tree and return 1 if the free is completed * it doesn't free the element (base) */ int ft_free(t_ft *tree, void *(*fct_free)(void *data, void *desc), void *data) { t_ft *next; /* nothing have change, do not free */ if (IS(Sorted, OUTPUT_SORTED) && !IS(Sorted, INPUT_SORTED)) return (0); /* remove description */ if (IS(tree->status, FILLED)) { if (tree->desc && fct_free) tree->desc = fct_free(data, tree->desc); UNSET(tree->status, FILLED); } /* check for recursion */ if (!IS(tree->status, CHANGED) || IS(tree->status, SORTING) || !tree->subtree) { UNSET(tree->status, CHANGED); return (1); } /* look for first soon */ tree = tree->subtree->next; while (!IS(tree->status, BASE)) { /* pass unchanged elements */ if (!IS(tree->status, CHANGED)) { tree = tree->next; continue ; } /* unset filled and remove data */ if (IS(tree->status, FILLED)) { if (tree->desc && fct_free) tree->desc = fct_free(data, tree->desc); UNSET(tree->status, FILLED); } /* stop if necessary */ if (IS(Sorted, OUTPUT_SORTED) && IS(tree->status, SORTING)) return (0); /* check if having to look at subtree */ if (tree->subtree && !IS_PDOTF(tree)) { if (ft_free(tree, fct_free, data)) { if (tree->subtree == tree->subtree->next) POOL_FREE(t_file_tree, tree->subtree); } else return (0); } /* free filename memory */ if (tree->filename) FREE(tree->filename); /* unchain and go to the next */ next = tree->next; UNSET(tree->status, CHANGED); if (fct_free) { LIST_UNCHAIN(tree); POOL_FREE(t_file_tree, tree); } tree = next; } return (1); } int output_write(t_db_output *out, void *data, int number) { t_device *dst; void *current; int valid = 1; for (current = out->outputs; current ; current = SIMPLE_LIST_NEXT(current)) { dst = SIMPLE_LIST_PTR(current); if (dst->opened->write) valid = dst->opened->write(dst->env, data, number) && valid; } return (valid); } int output_add(t_db_output *out, char *desc, t_source_type *sourcestype) { char tmp[BUFFER_LENGTH], *ptmp, *otmp = NULL; int i; t_device *new; strcpy(tmp, desc); if ((ptmp = backslashed_strchr(tmp, ':'))) { *ptmp++ = 0; /* look for options */ if ((otmp = strchr(tmp, '+'))) *otmp++ = 0; /* find corresponding source */ for (i = 0; sourcestype[i].name; i++) if (!strcmp(tmp, sourcestype[i].name)) break; if (!sourcestype[i].name) { /* not found, error */ error("can't find source type %s (%s:%s)", tmp, tmp, ptmp); return (0); } } else { error("no source type specified"); return (0); } /* allocate memory for new device */ new = MALLOC(sizeof(*new)); new->opened = &sourcestype[i]; if (new->opened->open) { if (!(new->env = new->opened->open(ptmp, otmp))) { error("can't open '%s'", desc); FREE(new); return (0); } if (new->opened->fcntl) Sorted |= (new->opened->fcntl(new->env, IS_SORTED) ? OUTPUT_SORTED : 0); } else new->env = NULL; SIMPLE_LIST_PUSH(out->outputs, new); return (1); } t_db_output *output_alloc() { t_db_output *out; out = MALLOC(sizeof(*out)); bzero(out, sizeof(*out)); return (out); } t_db_output *output_free(t_db_output *old) { t_device *dst; while (old->outputs) { dst = SIMPLE_LIST_POP(old->outputs); if (dst->opened->close) dst->opened->close(dst->env); FREE(dst); } FREE(old); return (NULL); }