static void expand_class_path(char *cp, struct strlist *dst) { struct strlist wildcards; size_t i; strlist_init(&wildcards, 16); split(cp, ':', &wildcards); for (i = 0; i < wildcards.size; i++) { expand_jars(wildcards.items[i], dst); } strlist_destroy(&wildcards); }
int archwriter_init(carchwriter *ai) { assert(ai); memset(ai, 0, sizeof(struct s_archwriter)); strlist_init(&ai->vollist); ai->newarch=false; ai->archfd=-1; ai->archid=0; ai->curvol=0; return 0; }
static char* create_class_path_option(char *cp) { struct strlist parts; char *result; strlist_init(&parts, 128); strlist_add(&parts, "-Djava.class.path="); expand_class_path(cp, &parts); if (parts.size > 1) { strlist_remove_last(&parts); /* last entry is a ':' */ } result = strlist_concat(&parts); strlist_destroy(&parts); return result; }
retvalue exportmode_init(/*@out@*/struct exportmode *mode, bool uncompressed, /*@null@*/const char *release, const char *indexfile) { strlist_init(&mode->hooks); mode->compressions = IC_FLAG(ic_gzip) | (uncompressed ? IC_FLAG(ic_uncompressed) : 0); mode->filename = strdup(indexfile); if (FAILEDTOALLOC(mode->filename)) return RET_ERROR_OOM; if (release == NULL) mode->release = NULL; else { mode->release = strdup(release); if (FAILEDTOALLOC(mode->release)) return RET_ERROR_OOM; } return RET_OK; }
static retvalue parse_stringpart(/*@out@*/struct strlist *strings, const char **pp, const struct filebeingparsed *fbp, int column) { const char *p = *pp; retvalue r; strlist_init(strings); do { const char *startp, *endp; char *n; while (*p != '\0' && xisspace(*p)) p++; if (*p != '\'') { errorcol(fbp, column + (int)(p - *pp), "starting \"'\" expected!"); return RET_ERROR; } p++; startp = p; while (*p != '\0' && *p != '\'') p++; if (*p == '\0') { errorcol(fbp, column + (int)(p - *pp), "closing \"'\" expected!"); return RET_ERROR; } assert (*p == '\''); endp = p; p++; n = strndup(startp, endp - startp); if (FAILEDTOALLOC(n)) return RET_ERROR_OOM; r = strlist_adduniq(strings, n); if (RET_WAS_ERROR(r)) return r; while (*p != '\0' && xisspace(*p)) p++; column += (p - *pp); *pp = p; if (**pp == '|') { p++; } } while (**pp == '|'); *pp = p; return RET_OK; }
retvalue chunk_getextralinelist(const char *chunk, const char *name, struct strlist *strlist) { retvalue r; const char *f, *b, *e; char *v; f = chunk_getfield(name, chunk); if (f == NULL) return RET_NOTHING; strlist_init(strlist); /* walk over the first line */ while (*f != '\0' && *f != '\n') f++; /* nothing there is an empty list */ if (*f == '\0') return RET_OK; f++; /* while lines begin with ' ' or '\t', add them */ while (*f == ' ' || *f == '\t') { while (*f != '\0' && xisblank(*f)) f++; b = f; while (*f != '\0' && *f != '\n') f++; e = f; while (e > b && *e != '\0' && xisspace(*e)) e--; if (!xisspace(*e)) v = strndup(b, e - b + 1); else v = strdup(""); if (FAILEDTOALLOC(v)) { strlist_done(strlist); return RET_ERROR_OOM; } r = strlist_add(strlist, v); if (!RET_IS_OK(r)) { strlist_done(strlist); return r; } if (*f == '\0') return RET_OK; f++; } return RET_OK; }
static inline retvalue trackedpackage_removeall(trackingdb tracks, struct trackedpackage *pkg) { retvalue result = RET_OK, r; char *id; // printf("[trackedpackage_removeall %s %s %s]\n", tracks->codename, pkg->sourcename, pkg->sourceversion); id = calc_trackreferee(tracks->codename, pkg->sourcename, pkg->sourceversion); if (FAILEDTOALLOC(id)) return RET_ERROR_OOM; pkg->flags.deleted = true; r = references_delete(id, &pkg->filekeys, NULL); RET_UPDATE(result, r); free(id); strlist_done(&pkg->filekeys); strlist_init(&pkg->filekeys); free(pkg->refcounts); pkg->refcounts = NULL; return result; }
retvalue chunk_getuniqwordlist(const char *chunk, const char *name, struct strlist *strlist) { retvalue r; const char *f, *b; char *v; f = chunk_getfield(name, chunk); if (f == NULL) return RET_NOTHING; strlist_init(strlist); while (*f != '\0') { /* walk over spaces */ while (*f != '\0' && xisspace(*f)) { if (*f == '\n') { f++; if (*f != ' ' && *f != '\t') return RET_OK; } else f++; } if (*f == '\0') return RET_OK; b = f; /* search for end of word */ while (*f != '\0' && !xisspace(*f)) f++; v = strndup(b, f - b); if (FAILEDTOALLOC(v)) { strlist_done(strlist); return RET_ERROR_OOM; } r = strlist_adduniq(strlist, v); if (!RET_IS_OK(r)) { strlist_done(strlist); return r; } } return RET_OK; }
static int fit_config_get_hash_list(void *fit, int conf_noffset, int sig_offset, struct strlist *node_inc) { int allow_missing; const char *prop, *iname, *end; const char *conf_name, *sig_name; char name[200], path[200]; int image_count; int ret, len; conf_name = fit_get_name(fit, conf_noffset, NULL); sig_name = fit_get_name(fit, sig_offset, NULL); /* * Build a list of nodes we need to hash. We always need the root * node and the configuration. */ strlist_init(node_inc); snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name); if (strlist_add(node_inc, "/") || strlist_add(node_inc, name)) goto err_mem; /* Get a list of images that we intend to sign */ prop = fit_config_get_image_list(fit, sig_offset, &len, &allow_missing); if (!prop) return 0; /* Locate the images */ end = prop + len; image_count = 0; for (iname = prop; iname < end; iname += strlen(iname) + 1) { int noffset; int image_noffset; int hash_count; image_noffset = fit_conf_get_prop_node(fit, conf_noffset, iname); if (image_noffset < 0) { printf("Failed to find image '%s' in configuration '%s/%s'\n", iname, conf_name, sig_name); if (allow_missing) continue; return -ENOENT; } ret = fdt_get_path(fit, image_noffset, path, sizeof(path)); if (ret < 0) goto err_path; if (strlist_add(node_inc, path)) goto err_mem; snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name); /* Add all this image's hashes */ hash_count = 0; for (noffset = fdt_first_subnode(fit, image_noffset); noffset >= 0; noffset = fdt_next_subnode(fit, noffset)) { const char *name = fit_get_name(fit, noffset, NULL); if (strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) continue; ret = fdt_get_path(fit, noffset, path, sizeof(path)); if (ret < 0) goto err_path; if (strlist_add(node_inc, path)) goto err_mem; hash_count++; } if (!hash_count) { printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n", conf_name, sig_name, iname); return -ENOMSG; } image_count++; } if (!image_count) { printf("Failed to find any images for configuration '%s/%s'\n", conf_name, sig_name); return -ENOMSG; } return 0; err_mem: printf("Out of memory processing configuration '%s/%s'\n", conf_name, sig_name); return -ENOMEM; err_path: printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n", iname, conf_name, sig_name, fdt_strerror(ret)); return -ENOENT; }
static retvalue parse_condition(const struct filebeingparsed *fbp, int column, const char **pp, /*@out@*/struct upload_condition *condition) { const char *p = *pp; struct upload_condition *fallback, *last, *or_scope; setzero(struct upload_condition, condition); /* allocate a new fallback-node: * (this one is used to make it easier to concatenate those decision * trees, especially it keeps open the possibility to have deny * decisions) */ fallback = zNEW(struct upload_condition); if (FAILEDTOALLOC(fallback)) return RET_ERROR_OOM; fallback->type = uc_ALWAYS; assert(!fallback->accept_if_true); /* the queue with next has all nodes, so they can be freed * (or otherwise modified) */ condition->next = fallback; last = condition; or_scope = condition; while (true) { if (strncmp(p, "not", 3) == 0 && xisspace(p[3])) { p += 3; while (*p != '\0' && xisspace(*p)) p++; /* negate means false is good and true * is bad: */ last->accept_if_false = true; last->accept_if_true = false; last->next_if_false = NULL; last->next_if_true = fallback; } else { last->accept_if_false = false; last->accept_if_true = true; last->next_if_false = fallback; last->next_if_true = NULL; } if (p[0] == '*' && xisspace(p[1])) { last->type = uc_ALWAYS; p++; } else if (strncmp(p, "architectures", 13) == 0 && strchr(" \t'", p[13]) != NULL) { retvalue r; last->type = uc_ARCHITECTURES; last->needs = needs_all; p += 13; while (*p != '\0' && xisspace(*p)) p++; if (strncmp(p, "contain", 7) == 0 && strchr(" \t'", p[7]) != NULL) { last->needs = needs_any; p += 7; } r = parse_architectures(&last->atoms, &p, fbp, column + (p-*pp)); if (RET_WAS_ERROR(r)) { uploadpermission_release(condition); return r; } } else if (strncmp(p, "binaries", 8) == 0 && strchr(" \t'", p[8]) != NULL) { retvalue r; last->type = uc_BINARIES; last->needs = needs_all; p += 8; while (*p != '\0' && xisspace(*p)) p++; if (strncmp(p, "contain", 7) == 0 && strchr(" \t'", p[7]) != NULL) { last->needs = needs_any; p += 7; } r = parse_stringpart(&last->strings, &p, fbp, column + (p-*pp)); if (RET_WAS_ERROR(r)) { uploadpermission_release(condition); return r; } } else if (strncmp(p, "byhand", 6) == 0 && strchr(" \t'", p[6]) != NULL) { retvalue r; last->type = uc_BYHAND; last->needs = needs_existsall; p += 8; while (*p != '\0' && xisspace(*p)) p++; if (*p != '\'') { strlist_init(&last->strings); r = RET_OK; } else r = parse_stringpart(&last->strings, &p, fbp, column + (p-*pp)); if (RET_WAS_ERROR(r)) { uploadpermission_release(condition); return r; } } else if (strncmp(p, "sections", 8) == 0 && strchr(" \t'", p[8]) != NULL) { retvalue r; last->type = uc_SECTIONS; last->needs = needs_all; p += 8; while (*p != '\0' && xisspace(*p)) p++; if (strncmp(p, "contain", 7) == 0 && strchr(" \t'", p[7]) != NULL) { last->needs = needs_any; p += 7; } r = parse_stringpart(&last->strings, &p, fbp, column + (p-*pp)); if (RET_WAS_ERROR(r)) { uploadpermission_release(condition); return r; } } else if (strncmp(p, "source", 6) == 0 && strchr(" \t'", p[6]) != NULL) { retvalue r; last->type = uc_SOURCENAME; p += 6; r = parse_stringpart(&last->strings, &p, fbp, column + (p-*pp)); if (RET_WAS_ERROR(r)) { uploadpermission_release(condition); return r; } } else if (strncmp(p, "distribution", 12) == 0 && strchr(" \t'", p[12]) != NULL) { retvalue r; last->type = uc_CODENAME; p += 12; r = parse_stringpart(&last->strings, &p, fbp, column + (p-*pp)); if (RET_WAS_ERROR(r)) { uploadpermission_release(condition); return r; } } else { errorcol(fbp, column + (int)(p - *pp), "condition expected after 'allow' keyword!"); uploadpermission_release(condition); return RET_ERROR; } while (*p != '\0' && xisspace(*p)) p++; if (strncmp(p, "and", 3) == 0 && xisspace(p[3])) { struct upload_condition *n, *c; p += 3; n = zNEW(struct upload_condition); if (FAILEDTOALLOC(n)) { uploadpermission_release(condition); return RET_ERROR_OOM; } /* everything that yet made it succeed makes it need * to check this condition: */ for (c = condition ; c != NULL ; c = c->next) { if (c->accept_if_true) { c->next_if_true = n; c->accept_if_true = false; } if (c->accept_if_false) { c->next_if_false = n; c->accept_if_false = false; } } /* or will only bind to this one */ or_scope = n; /* add it to queue: */ assert (last->next == fallback); n->next = fallback; last->next = n; last = n; } else if (strncmp(p, "or", 2) == 0 && xisspace(p[2])) { struct upload_condition *n, *c; p += 2; n = zNEW(struct upload_condition); if (FAILEDTOALLOC(n)) { uploadpermission_release(condition); return RET_ERROR_OOM; } /* everything in current scope that made it fail * now makes it check this: (currently that will * only be true at most for c == last, but with * parentheses this all will be needed) */ for (c = or_scope ; c != NULL ; c = c->next) { if (c->next_if_true == fallback) c->next_if_true = n; if (c->next_if_false == fallback) c->next_if_false = n; } /* add it to queue: */ assert (last->next == fallback); n->next = fallback; last->next = n; last = n; } else if (strncmp(p, "by", 2) == 0 && xisspace(p[2])) {
int extfs_mkfs(cdico *d, char *partition, int extfstype, char *fsoptions) { cstrlist strfeatures; u64 features_tab[3]; u64 fsextrevision; int origextfstype; char buffer[2048]; char command[2048]; char options[2048]; char temp[1024]; char progname[64]; u64 e2fstoolsver; int compat_type; u64 temp64; int exitst; int ret=0; int res; int i; // init memset(options, 0, sizeof(options)); snprintf(progname, sizeof(progname), "mke2fs"); strlist_init(&strfeatures); // ---- check that mkfs is installed and get its version if (exec_command(command, sizeof(command), NULL, NULL, 0, NULL, 0, "%s -V", progname)!=0) { errprintf("%s not found. please install a recent e2fsprogs on your system or check the PATH.\n", progname); ret=-1; goto extfs_mkfs_cleanup; } e2fstoolsver=check_prog_version(progname); // ---- filesystem revision (good-old-rev or dynamic) if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTREVISION, &fsextrevision)!=0) fsextrevision=EXT2_DYNAMIC_REV; // don't fail (case of fs conversion to extfs) // "mke2fs -q" prevents problems in exec_command when too many output details printed strlcatf(options, sizeof(options), " -q "); // filesystem revision: good-old-rev or dynamic strlcatf(options, sizeof(options), " -r %d ", (int)fsextrevision); strlcatf(options, sizeof(options), " %s ", fsoptions); // ---- set the advanced filesystem settings from the dico if (dico_get_string(d, 0, FSYSHEADKEY_FSLABEL, buffer, sizeof(buffer))==0 && strlen(buffer)>0) strlcatf(options, sizeof(options), " -L '%.16s' ", buffer); if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTBLOCKSIZE, &temp64)==0) strlcatf(options, sizeof(options), " -b %ld ", (long)temp64); if (dico_get_u64(d, 0, FSYSHEADKEY_FSINODESIZE, &temp64)==0) strlcatf(options, sizeof(options), " -I %ld ", (long)temp64); // ---- get original filesystem features (if the original filesystem was an ext{2,3,4}) if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFEATURECOMPAT, &features_tab[E2P_FEATURE_COMPAT])!=0 || dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFEATUREINCOMPAT, &features_tab[E2P_FEATURE_INCOMPAT])!=0 || dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFEATUREROCOMPAT, &features_tab[E2P_FEATURE_RO_INCOMPAT])!=0) { // dont fail the original filesystem may not be ext{2,3,4}. in that case set defaults features features_tab[E2P_FEATURE_COMPAT]=EXT2_FEATURE_COMPAT_RESIZE_INODE|EXT2_FEATURE_COMPAT_DIR_INDEX; features_tab[E2P_FEATURE_INCOMPAT]=EXT2_FEATURE_INCOMPAT_FILETYPE; features_tab[E2P_FEATURE_RO_INCOMPAT]=EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; } // ---- check that fsarchiver is aware of all the filesystem features used on that filesystem if (extfs_check_compatibility(features_tab[E2P_FEATURE_COMPAT], features_tab[E2P_FEATURE_INCOMPAT], features_tab[E2P_FEATURE_RO_INCOMPAT])!=0) { errprintf("this filesystem has ext{2,3,4} features which are not supported by this fsarchiver version.\n"); return -1; } // ---- get original filesystem type origextfstype=extfs_get_fstype_from_compat_flags(features_tab[E2P_FEATURE_COMPAT], features_tab[E2P_FEATURE_INCOMPAT], features_tab[E2P_FEATURE_RO_INCOMPAT]); msgprintf(MSG_VERB2, "the filesystem type determined by the original filesystem features is [%s]\n", format_fstype(origextfstype)); // remove all the features not supported by the filesystem to create (conversion = downgrade fs) for (i=0; mkfeatures[i].name; i++) { compat_type=mkfeatures[i].compat; if (mkfeatures[i].firstfs > extfstype) features_tab[compat_type] &= ~mkfeatures[i].mask; } // add new features if the filesystem to create is newer than the filesystem type that was backed up // eg: user did a "savefs" of an ext3 and does a "restfs mkfs=ext4" --> add features to force ext4 // it's a bit more difficult because we only want to add such a feature if no feature of the new // filesystem is currently enabled. msgprintf(MSG_VERB2, "the filesystem type to create considering the command options is [%s]\n", format_fstype(extfstype)); if (origextfstype==EXTFSTYPE_EXT2 && extfstype>EXTFSTYPE_EXT2) // upgrade ext2 to ext{3,4} { fsextrevision=EXT2_DYNAMIC_REV; features_tab[E2P_FEATURE_COMPAT]|=EXT3_FEATURE_COMPAT_HAS_JOURNAL; } if (origextfstype<EXTFSTYPE_EXT4 && extfstype>=EXTFSTYPE_EXT4) // upgrade ext{2,3} to ext4 { fsextrevision=EXT2_DYNAMIC_REV; features_tab[E2P_FEATURE_INCOMPAT]|=EXT3_FEATURE_INCOMPAT_EXTENTS; } // convert int features to string to be passed to mkfs for (i=0; mkfeatures[i].name; i++) { if (mkfeatures[i].firste2p<=e2fstoolsver) // don't pass an option to a program that does not support it { compat_type=mkfeatures[i].compat; if (features_tab[compat_type] & mkfeatures[i].mask) { msgprintf(MSG_VERB2, "--> feature [%s]=YES\n", mkfeatures[i].name); strlist_add(&strfeatures, mkfeatures[i].name); } else { msgprintf(MSG_VERB2, "--> feature [%s]=NO\n", mkfeatures[i].name); snprintf(temp, sizeof(temp), "^%s", mkfeatures[i].name); // exclude feature strlist_add(&strfeatures, temp); } } } // if extfs revision is dynamic and there are features in the list if (fsextrevision!=EXT2_GOOD_OLD_REV && strlist_count(&strfeatures)>0) { strlist_merge(&strfeatures, temp, sizeof(temp), ','); strlcatf(options, sizeof(options), " -O %s ", temp); msgprintf(MSG_VERB2, "features: mkfs_options+=[-O %s]\n", temp); } // ---- check mke2fs version requirement msgprintf(MSG_VERB2, "mke2fs version detected: %s\n", format_prog_version(e2fstoolsver, temp, sizeof(temp))); msgprintf(MSG_VERB2, "mke2fs version required: %s\n", format_prog_version(e2fsprogs_minver[extfstype], temp, sizeof(temp))); if (e2fstoolsver < e2fsprogs_minver[extfstype]) { errprintf("mke2fs was found but is too old, please upgrade to a version %s or more recent.\n", format_prog_version(e2fsprogs_minver[extfstype], temp, sizeof(temp))); ret=-1; goto extfs_mkfs_cleanup; } // ---- extended options if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTEOPTRAIDSTRIDE, &temp64)==0) strlcatf(options, sizeof(options), " -E stride=%ld ", (long)temp64); if ((dico_get_u64(d, 0, FSYSHEADKEY_FSEXTEOPTRAIDSTRIPEWIDTH, &temp64)==0) && e2fstoolsver>=PROGVER(1,40,7)) strlcatf(options, sizeof(options), " -E stripe-width=%ld ", (long)temp64); // ---- execute mke2fs msgprintf(MSG_VERB2, "exec: %s\n", command); if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "%s %s %s", progname, partition, options)!=0 || exitst!=0) { errprintf("command [%s] failed with return status=%d\n", command, exitst); ret=-1; goto extfs_mkfs_cleanup; } // ---- use tune2fs to set the other advanced options memset(options, 0, sizeof(options)); if (dico_get_string(d, 0, FSYSHEADKEY_FSUUID, buffer, sizeof(buffer))==0 && strlen(buffer)==36) strlcatf(options, sizeof(options), " -U %s ", buffer); if (dico_get_string(d, 0, FSYSHEADKEY_FSEXTDEFMNTOPT, buffer, sizeof(buffer))==0 && strlen(buffer)>0) strlcatf(options, sizeof(options), " -o %s ", buffer); if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFSCKMAXMNTCOUNT, &temp64)==0) strlcatf(options, sizeof(options), " -c %ld ", (long)temp64); if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFSCKCHECKINTERVAL, &temp64)==0) strlcatf(options, sizeof(options), " -i %ldd ", (long)(temp64/86400L)); if (options[0]) { if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "tune2fs %s %s", partition, options)!=0 || exitst!=0) { errprintf("command [%s] failed with return status=%d\n", command, exitst); ret=-1; goto extfs_mkfs_cleanup; } // run e2fsck to workaround an tune2fs bug in e2fsprogs < 1.41.4 on ext4 // http://article.gmane.org/gmane.comp.file-systems.ext4/11181 if (extfstype==EXTFSTYPE_EXT4 && e2fstoolsver<PROGVER(1,41,4)) { if ( ((res=exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "e2fsck -fy %s", partition))!=0) || ((exitst!=0) && (exitst!=1)) ) { errprintf("command [%s] failed with return status=%d\n", command, exitst); ret=-1; goto extfs_mkfs_cleanup; } } } extfs_mkfs_cleanup: strlist_destroy(&strfeatures); return ret; }