static retvalue parse_architectures(/*@out@*/struct atomlist *atoms, const char **pp, const struct filebeingparsed *fbp, int column) { const char *p = *pp; retvalue r; atomlist_init(atoms); do { const char *startp, *endp; atom_t atom; 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 != '*' && *p != '?') p++; if (*p == '*' || *p == '?') { errorcol(fbp, column + (int)(p - *pp), "Wildcards are not allowed in architectures!"); return RET_ERROR; } if (*p == '\0') { errorcol(fbp, column + (int)(p - *pp), "closing \"'\" expected!"); return RET_ERROR; } assert (*p == '\''); endp = p; p++; atom = architecture_find_l(startp, endp - startp); if (!atom_defined(atom)) { errorcol(fbp, column + (int)(startp-*pp), "Unknown architecture '%.*s'! (Did you mistype?)", (int)(endp-startp), startp); return RET_ERROR; } r = atomlist_add_uniq(atoms, atom); 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; }
static retvalue parsearchitecture(enum term_comparison c, const char *value, size_t len, struct compare_with *v) { if (c == tc_none) { fprintf(stderr, "Error: $Architecture is always defined, it does not make sense without parameter\n" "to compare against!\n"); return RET_ERROR; } if (c != tc_equal && c != tc_notequal) { v->pointer = strndup(value, len); if (FAILEDTOALLOC(v->pointer)) return RET_ERROR_OOM; return RET_OK; } v->number = architecture_find_l(value, len); if (atom_defined(v->number)) return RET_OK; fprintf(stderr, "Unknown architecture '%.*s' in formula (must be listed in conf/distributions to be known)!\n", (int)len, value); return RET_ERROR; }
retvalue changes_parsefileline(const char *fileline, /*@out@*/filetype *result_type, /*@out@*/char **result_basename, /*@out@*/struct hash_data *hash_p, /*@out@*/struct hash_data *size_p, /*@out@*/char **result_section, /*@out@*/char **result_priority, /*@out@*/architecture_t *result_architecture, /*@out@*/char **result_name) { const char *p, *md5start, *md5end; const char *sizestart, *sizeend; const char *sectionstart, *sectionend; const char *priostart, *prioend; const char *filestart, *nameend, *fileend; const char *archstart, *archend; const char *versionstart; filetype type; char *section, *priority, *basefilename, *name; architecture_t architecture; size_t l; bool checkfilename = false; p = fileline; while (*p !='\0' && xisspace(*p)) p++; md5start = p; while ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f')) p++; if (*p == '\0') { fprintf(stderr, "Missing md5sum in '%s'!\n", fileline); return RET_ERROR; } if (!xisspace(*p)) { fprintf(stderr, "Malformed md5 hash in '%s'!\n", fileline); return RET_ERROR; } md5end = p; while (*p !='\0' && xisspace(*p)) p++; while (*p == '0' && p[1] >= '0' && p[1] <= '9') p++; sizestart = p; while (*p >= '0' && *p <= '9') p++; if (*p == '\0') { fprintf(stderr, "Missing size (second argument) in '%s'!\n", fileline); return RET_ERROR; } if (!xisspace(*p)) { fprintf(stderr, "Malformed size (second argument) in '%s'!\n", fileline); return RET_ERROR; } sizeend = p; while (*p !='\0' && xisspace(*p)) p++; sectionstart = p; while (*p !='\0' && !xisspace(*p)) p++; sectionend = p; while (*p !='\0' && xisspace(*p)) p++; priostart = p; while (*p !='\0' && !xisspace(*p)) p++; prioend = p; while (*p !='\0' && xisspace(*p)) p++; filestart = p; while (*p !='\0' && !xisspace(*p)) p++; fileend = p; while (*p !='\0' && xisspace(*p)) p++; if (*p != '\0') { fprintf(stderr, "Unexpected sixth argument in '%s'!\n", fileline); return RET_ERROR; } if (*md5start == '\0' || *sizestart == '\0' || *sectionstart == '\0' || *priostart == '\0' || *filestart == '\0') { fprintf(stderr, "Wrong number of arguments in '%s' (5 expected)!\n", fileline); return RET_ERROR; } if ((sectionend - sectionstart == 6 && strncmp(sectionstart, "byhand", 6) == 0) || (sectionend - sectionstart > 4 && strncmp(sectionstart, "raw-", 4) == 0)) { section = strndup(sectionstart, sectionend - sectionstart); priority = strndup(priostart, prioend - priostart); basefilename = strndup(filestart, fileend - filestart); if (FAILEDTOALLOC(section) || FAILEDTOALLOC(priority) || FAILEDTOALLOC(basefilename)) { free(section); free(priority); free(basefilename); return RET_ERROR_OOM; } hash_p->start = md5start; hash_p->len = md5end - md5start; size_p->start = sizestart; size_p->len = sizeend - sizestart; *result_section = section; *result_priority = priority; *result_basename = basefilename; *result_architecture = atom_unknown; *result_name = NULL; *result_type = fe_BYHAND; return RET_OK; } p = filestart; while (*p != '\0' && *p != '_' && !xisspace(*p)) p++; if (*p != '_') { if (*p == '\0') fprintf(stderr, "No underscore found in file name in '%s'!\n", fileline); else fprintf(stderr, "Unexpected character '%c' in file name in '%s'!\n", *p, fileline); return RET_ERROR; } nameend = p; p++; versionstart = p; /* changing 3.0 format to now also allow _ in source files * makes this parsing quite more ugly... */ while (*p !='\0' && !xisspace(*p)) p++; l = p - versionstart; /* identify the binary types (they have no compression * and will need a _ */ if (l >= 4 && memcmp(p-4, ".deb", 4) == 0) type = fe_DEB; else if (l >= 5 && memcmp(p-5, ".udeb", 5) == 0) type = fe_UDEB; else type = fe_UNKNOWN; if (type != fe_UNKNOWN) { /* a _ should separate the version from the rest */ p = versionstart; names_overversion(&p, true); if (*p != '\0' && *p != '_') { fprintf(stderr, "Unexpected character '%c' in file name within '%s'!\n", *p, fileline); return RET_ERROR; } if (*p != '_') { fprintf(stderr, "Cannot cope with .[u]deb filename not containing an underscore (in '%s')!", fileline); return RET_ERROR; } p++; archstart = p; if (type == fe_DEB) archend = versionstart + l - 4; else { assert (type == fe_UDEB); archend = versionstart + l - 5; } if (archend - archstart == 6 && strncmp(archstart, "source", 6) == 0) { fprintf(stderr, "Architecture 'source' not allowed for .[u]debs ('%s')!\n", filestart); return RET_ERROR; } } else { enum compression c; const char *eoi; /* without those, it gets more complicated. * It's not .deb or .udeb, so most likely a * source file (or perhaps a log (reprepro extension)) */ /* if it uses a known compression, things are easy, * so try this first: */ c = compression_by_suffix(versionstart, &l); p = versionstart + l; archstart = "source"; archend = archstart + 6; if (l > 9 && strncmp(p-9, ".orig.tar", 9) == 0) { type = fe_ORIG; eoi = p - 9; } else if (l > 4 && strncmp(p-4, ".tar", 4) == 0) { type = fe_TAR; eoi = p - 4; } else if (l > 5 && strncmp(p-5, ".diff", 5) == 0) { type = fe_DIFF; eoi = p - 5; } else if (l > 4 && strncmp(p-4, ".dsc", 4) == 0 && c == c_none) { type = fe_DSC; eoi = p - 4; } else if (l > 4 && strncmp(p-4, ".git", 4) == 0 && c == c_none) { type = fe_ALTSRC; eoi = p - 4; } else if (l > 4 && strncmp(p-4, ".log", 4) == 0) { type = fe_LOG; eoi = p - 4; } else if (l > 6 && strncmp(p-6, ".build", 6) == 0) { type = fe_LOG; eoi = p - 6; } if (type != fe_UNKNOWN) { /* check for a proper version */ p = versionstart; names_overversion(&p, true); if (p >= eoi) { /* all well */ } else if (type == fe_TAR) { /* a tar might be a component with ugly * data between .orig- and the .tar.c */ const char *o = strstr(versionstart, ".orig-"); if (o == NULL || o > eoi) { fprintf(stderr, "Unexpected character '%c' in file name within '%s'!\n", *p, fileline); return RET_ERROR; } checkfilename = true; } else if (type == fe_LOG) { if (*p == '_') { archstart = p + 1; archend = eoi; checkfilename = true; } else { fprintf(stderr, "Unexpected character '%c' in file name within '%s'!\n", *p, fileline); } } else { fprintf(stderr, "Unexpected character '%c' in file name within '%s'!\n", *p, fileline); return RET_ERROR; } } else { /* everything else is assumed to be source */ checkfilename = true; fprintf(stderr, "Unknown file type: '%s', assuming source format...\n", fileline); } } section = strndup(sectionstart, sectionend - sectionstart); priority = strndup(priostart, prioend - priostart); basefilename = strndup(filestart, fileend - filestart); // TODO: this does not make much sense for log files, as they might // list multiple.. architecture = architecture_find_l(archstart, archend - archstart); name = strndup(filestart, nameend - filestart); if (FAILEDTOALLOC(section) || FAILEDTOALLOC(priority) || FAILEDTOALLOC(basefilename) || FAILEDTOALLOC(name)) { free(section); free(priority); free(basefilename); free(name); return RET_ERROR_OOM; } if (checkfilename || !atom_defined(architecture)) { retvalue r; /* as we no longer run properversion over the whole * rest of the string, at least make sure nothing evil * is in this name */ r = properfilename(basefilename); if (!RET_IS_OK(r)) { assert (r != RET_NOTHING); free(section); free(priority); free(basefilename); free(name); return r; } } hash_p->start = md5start; hash_p->len = md5end - md5start; size_p->start = sizestart; size_p->len = sizeend - sizestart; *result_section = section; *result_priority = priority; *result_basename = basefilename; *result_architecture = architecture; *result_name = name; *result_type = type; return RET_OK; }