/* parses compile options of a port through scan for all .if defined or .if !defined in port's Makefile */ List * parse_options(char *mkfile) { FILE *fd; char line[MAX_TOKEN]; char option[MAX_PATH]; char *start; char *end; List *l; TNode *t = NULL; extern void *exists; int i; if ((fd = fopen(mkfile, "r")) == NULL) return NULL; /* error */ /* init */ l = (List *)malloc(sizeof(List)); l->head = NULL; l->tail = NULL; l->num_of_items = 0; while (fgets(line, MAX_TOKEN, fd) != NULL) { if ((strstr(line, ".if") != NULL) && (strstr(line, "defined") != NULL)) { Option *opt = (Option *)malloc(sizeof(Option)); opt->type = OPTION; opt->state = STATE_NOT_SELECTED; i = 0; start = strpbrk(line, "({"); start++; end = strpbrk(line, ")}"); while (start != end) option[i++] = *start++; option[i] = '\0'; sprintf(line, "%-.50s (port specific compile option)", option); opt->name = strdup(line); sprintf(line, "%s=yes", option); opt->arg = strdup(line); exists = NULL; t = add_tree_item(t, opt, cmp_name); if (exists != NULL) { /* option does exist */ /* clean up */ free(opt->name); free(opt->arg); free(opt); } } } fclose(fd); create_inorder_list(l, t); return l; }
static void update_node(tree** t, tree* p, int (*compare_keys)(const void* key1, const void* key2)) { /*overwrite existing node item with new node item */ add_tree_item(*t, p->item, p->item_sz); /*copy node key then delete old key*/ void* key = malloc(p->key_sz); int key_sz = p->key_sz; memcpy(key, p->key, p->key_sz); delete_tree(t, p->key, compare_keys); /*delete before re-assignment of key*/ free((*t)->key); (*t)->key = key; (*t)->key_sz = key_sz; }
/* adds a category in sorted order if it does not already exist, returns pointer of the new or existing category with name "name" */ Category * add_category(char *name, List *lpdir) { extern TNode *tcat; extern void *exists; Category *newcat = NULL; newcat = (Category *)malloc(sizeof(Category)); newcat->type = CATEGORY; newcat->name = strdup(name); exists = NULL; tcat = add_tree_item(tcat, newcat, cmp_name); if (exists != NULL) { /* category does exist */ /* clean up */ free(newcat->name); free(newcat); /* use existing pointer for return */ newcat = (Category *)((TNode *)exists)->item; } else { /* category does not exist yet */ /* check, if this category is a meta category or not */ Iter itr = lpdir->head; while (itr != NULL) { if (strcmp((char *)itr->item, name) == 0) /* physically existing */ break; itr = itr->next; } newcat->meta = (itr == NULL) ? TRUE : FALSE; newcat->num_of_ports = 0; newcat->num_of_inst_ports = 0; newcat->num_of_marked_ports = 0; newcat->num_of_inst_ports = 0; newcat->num_of_deinst_ports = 0; newcat->lprts = (List *)malloc(sizeof(List)); newcat->lprts->num_of_items = 0; newcat->lprts->head = NULL; newcat->lprts->tail = NULL; } return newcat; }
/* creates linear list of dir names, returns list of directories */ TNode * parse_dir(char *path) { struct dirent *dp; DIR *dfd; TNode *t = NULL; /* if the directory doesn't exist or there is another reason, it returns NULL */ if ((dfd = opendir(path)) == NULL) return NULL; /* generates entries */ while ((dp = readdir(dfd)) != NULL) { /* exlude hidden files or "." and ".." */ if ((dp->d_name)[0] != '.') { t = add_tree_item(t, strdup(dp->d_name), cmp_str); } } closedir(dfd); /* finished */ /* number of entries */ return t; }
/* parses the FreeBSD ports INDEX file and creates a list of categories with dedicated ports, it also creates a meta-category "all", all lists and categories are sorted ascending. */ int parse_index() { FILE *fd; int c, i, readyToken; int pipes = 0; char tok[MAX_TOKEN]; extern Config config; extern List *lprts; extern List *lcats; extern void *exists; extern TNode *tcat; TNode *tdirs; TNode *tprt = NULL; List *lpdir = (List *)malloc(sizeof(List)); Port *p, *dprt; int num_of_inst_ports = 0; /* init */ p = NULL; tcat = NULL; lpdir->num_of_items = 0; lpdir->head = NULL; lpdir->tail = NULL; if ((fd = fopen(config.index_file, "r")) == NULL) return ERROR_OPEN_INDEX; /* error */ /* parse installed pkgs */ tdirs = parse_dir(config.inst_pkg_dir); /* parse ports dir and create list */ create_inorder_list(lpdir, parse_dir(config.ports_dir)); i = 0; readyToken = 0; /* token not ready */ while (feof(fd) == 0) { c = fgetc(fd); /* get next char */ switch (c) { case '|': /* next token */ readyToken = 1; /* ready token */ break; case '\n': /* end of port */ #if defined(__FreeBSD__) if (pipes != PORT_URL) /* seems to be some strange INDEX */ return ERROR_CORRUPT_INDEX; #endif readyToken = 1; /* tail token of port ready */ break; default: if ((pipes != PORT_CATEGORY) && (pipes != PORT_BUILD_DEPENDENCY) && (pipes != PORT_RUN_DEPENDENCY)) /* default, no port category, build dep or run dep modus */ tok[i++] = (char)c; break; } /* to speed up the parsing, we also parse categories here, I guessed if it'll be senseful to also parse BDEP and RDEP, but this makes no sense until there aren't all entries scanned */ if (pipes == PORT_CATEGORY) { /* port category mode */ if ((c == ' ') || (c == '|')) { if (i > 0) { /* maybe there're ports without a category */ tok[i] = '\0'; /* terminate current cat token */ add_list_item(p->lcats, add_category(tok, lpdir)); i = 0; /* reset i */ } } else { /* inside a token */ tok[i++] = (char)c; } } else if ((pipes == PORT_BUILD_DEPENDENCY) || (pipes == PORT_RUN_DEPENDENCY)) { /* port build/run dep mode */ if ((c == ' ') || (c == '|')) { if (i > 0) { /* maybe there're ports without a build dep */ tok[i] = '\0'; dprt = create_port(tok, tdirs); exists = NULL; tprt = add_tree_item(tprt, dprt, cmp_name); if (exists != NULL) { free_port(dprt); dprt = (Port *)((TNode *)exists)->item; } else { if (dprt->state >= STATE_INSTALLED) num_of_inst_ports++; } if (pipes == PORT_BUILD_DEPENDENCY) { add_list_item(p->lbdep, dprt); } else if (pipes == PORT_RUN_DEPENDENCY) { add_list_item(p->lrdep, dprt); } /* add also p to dprt->ldep, so that dprt knows the port for which dprt is a dependency, this helps seeking for unused ports */ add_list_item(dprt->ldep, p); i = 0; /* reset i */ } } else { /* inside a token */ tok[i++] = (char)c; } } if (readyToken == 1) { /* a new token is ready */ tok[i] = '\0'; /* terminate current token */ switch (pipes) { case PORT_NAME_VERSION: p = create_port(tok, tdirs); /* add the port */ exists = NULL; tprt = add_tree_item(tprt, p, cmp_name); if (exists != NULL) { free_port(p); p = (Port *)((TNode *)exists)->item; } else { if (p->state >= STATE_INSTALLED) num_of_inst_ports++; } break; case PORT_PATH: p->path = strdup(tok); break; #if defined(__FreeBSD__) case PORT_INSTALL_PREFIX: p->instpfx = strdup(tok); break; #endif case PORT_DESCR: p->descr = strdup(tok); break; case PORT_PKGDESCR: p->pathpkgdesc = strdup(tok); break; case PORT_MAINTAINER: p->maintainer = strdup(tok); break; #if defined(__FreeBSD__) case PORT_URL: p->url = strdup(tok); pipes = -1; break; #endif } readyToken = i = 0; /* token processed, not ready token anymore */ pipes++; } } fclose(fd); /* close INDEX file */ create_inorder_list(lcats, tcat); create_inorder_list(lprts, tprt); create_categories(num_of_inst_ports); free_tree(tdirs); /* finished */ return (0); }