/* * Rough soname sanity filtering: all sane soname's dependencies need to * contain ".so", and normal linkable libraries start with "lib", * everything else is an exception of some sort. The most notable * and common exception is the dynamic linker itself, which we allow * here, the rest can use --no-filter-soname. */ static int skipSoname(const char *soname) { int sane = 0; /* Filter out empty and all-whitespace sonames */ for (const char *s = soname; *s != '\0'; s++) { if (!risspace(*s)) { sane = 1; break; } } if (!sane) return 1; if (filter_soname) { if (!strstr(soname, ".so")) return 1; if (rstreqn(soname, "ld.", 3) || rstreqn(soname, "ld-", 3) || rstreqn(soname, "ld64.", 3) || rstreqn(soname, "ld64-", 3)) return 0; if (rstreqn(soname, "lib", 3)) return 0; else return 1; } return 0; }
/** * Does locale match entry in header i18n table? * * \verbatim * The range [l,le) contains the next locale to match: * ll[_CC][.EEEEE][@dddd] * where * ll ISO language code (in lowercase). * CC (optional) ISO coutnry code (in uppercase). * EEEEE (optional) encoding (not really standardized). * dddd (optional) dialect. * \endverbatim * * @param td header i18n table data, NUL terminated * @param l start of locale to match * @param le end of locale to match * @return 1 on good match, 2 on weak match, 0 on no match */ static int headerMatchLocale(const char *td, const char *l, const char *le) { const char *fe; /* First try a complete match. */ if (strlen(td) == (le-l) && rstreqn(td, l, (le - l))) return 1; /* Next, try stripping optional dialect and matching. */ for (fe = l; fe < le && *fe != '@'; fe++) {}; if (fe < le && rstreqn(td, l, (fe - l))) return 1; /* Next, try stripping optional codeset and matching. */ for (fe = l; fe < le && *fe != '.'; fe++) {}; if (fe < le && rstreqn(td, l, (fe - l))) return 1; /* Finally, try stripping optional country code and matching. */ for (fe = l; fe < le && *fe != '_'; fe++) {}; if (fe < le && rstreqn(td, l, (fe - l))) return 2; return 0; }
int parsePrep(rpmSpec spec) { int nextPart, res, rc; StringBuf sb; char **lines; ARGV_t saveLines = NULL; if (spec->prep != NULL) { rpmlog(RPMLOG_ERR, _("line %d: second %%prep\n"), spec->lineNum); return PART_ERROR; } spec->prep = newStringBuf(); /* There are no options to %prep */ if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { return PART_NONE; } else if (rc < 0) { return PART_ERROR; } sb = newStringBuf(); while (! (nextPart = isPart(spec->line))) { /* Need to expand the macros inline. That way we */ /* can give good line number information on error. */ appendStringBuf(sb, spec->line); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } saveLines = argvSplitString(getStringBuf(sb), "\n", ARGV_NONE); for (lines = saveLines; *lines; lines++) { res = 0; if (rstreqn(*lines, "%setup", sizeof("%setup")-1)) { res = doSetupMacro(spec, *lines); } else if (rstreqn(*lines, "%patch", sizeof("%patch")-1)) { res = doPatchMacro(spec, *lines); } else { appendLineStringBuf(spec->prep, *lines); } if (res && !spec->force) { /* fixup from RPMRC_FAIL do*Macro() codes for now */ nextPart = PART_ERROR; goto exit; } } res = nextPart; exit: argvFree(saveLines); sb = freeStringBuf(sb); return nextPart; }
static rpmRC readIcon(Header h, const char * file) { char *fn = NULL; uint8_t *icon = NULL; FD_t fd = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ off_t size; size_t nb, iconsize; /* XXX use rpmGenPath(rootdir, "%{_sourcedir}/", file) for icon path. */ fn = rpmGetPath("%{_sourcedir}/", file, NULL); fd = Fopen(fn, "r.ufdio"); if (fd == NULL) { rpmlog(RPMLOG_ERR, _("Unable to open icon %s: %s\n"), fn, Fstrerror(fd)); goto exit; } size = fdSize(fd); iconsize = (size >= 0 ? size : (8 * BUFSIZ)); if (iconsize == 0) { rc = RPMRC_OK; /* XXX Eh? */ goto exit; } icon = xmalloc(iconsize + 1); *icon = '\0'; nb = Fread(icon, sizeof(icon[0]), iconsize, fd); if (Ferror(fd) || (size >= 0 && nb != size)) { rpmlog(RPMLOG_ERR, _("Unable to read icon %s: %s\n"), fn, Fstrerror(fd)); goto exit; } if (rstreqn((char*)icon, "GIF", sizeof("GIF")-1)) { headerPutBin(h, RPMTAG_GIF, icon, iconsize); } else if (rstreqn((char*)icon, "/* XPM", sizeof("/* XPM")-1)) { headerPutBin(h, RPMTAG_XPM, icon, iconsize); } else { rpmlog(RPMLOG_ERR, _("Unknown icon type: %s\n"), file); goto exit; } rc = RPMRC_OK; exit: Fclose(fd); free(fn); free(icon); return rc; }
static int parseBits(const char * s, const tokenBits tokbits, rpmsenseFlags * bp) { tokenBits tb; const char * se; rpmsenseFlags bits = RPMSENSE_ANY; int c = 0; int rc = RPMRC_OK; if (s) { while (*s != '\0') { while ((c = *s) && risspace(c)) s++; se = s; while ((c = *se) && risalpha(c)) se++; if (s == se) break; for (tb = tokbits; tb->name; tb++) { if (tb->name != NULL && strlen(tb->name) == (se-s) && rstreqn(tb->name, s, (se-s))) break; } if (tb->name == NULL) { rc = RPMRC_FAIL; break; } bits |= tb->bits; while ((c = *se) && risspace(c)) se++; if (c != ',') break; s = ++se; } } *bp |= bits; return rc; }
rpmsenseFlags rpmParseDSFlags(const char *str, size_t len) { const struct ReqComp *rc; for (rc = ReqComparisons; rc->token != NULL; rc++) if (len == strlen(rc->token) && rstreqn(str, rc->token, len)) return rc->sense; return 0; }
/* * Rough soname sanity filtering: all sane soname's dependencies need to * contain ".so", and normal linkable libraries start with "lib", * everything else is an exception of some sort. The most notable * and common exception is the dynamic linker itself, which we allow * here, the rest can use --no-filter-soname. */ static int skipSoname(const char *soname) { if (filter_soname) { if (!strstr(soname, ".so")) return 1; if (rstreqn(soname, "ld.", 3) || rstreqn(soname, "ld-", 3) || rstreqn(soname, "ld64.", 3) || rstreqn(soname, "ld64-", 3)) return 0; if (rstreqn(soname, "lib", 3)) return 0; else return 1; } return 0; }
/** \ingroup rpmpgp * Return value of an OpenPGP string. * @param vs table of (string,value) pairs * @param s string token to lookup * @param se end-of-string address * @return byte value */ static inline int pgpValTok(pgpValTbl vs, const char * s, const char * se) { do { size_t vlen = strlen(vs->str); if (vlen <= (se-s) && rstreqn(s, vs->str, vlen)) break; } while ((++vs)->val != -1); return vs->val; }
static rpmRC rpmdsParseRichDepCB(void *cbdata, rpmrichParseType type, const char *n, int nl, const char *e, int el, rpmsenseFlags sense, rpmrichOp op, char **emsg) { struct rpmdsParseRichDepData *data = cbdata; rpmds ds = 0; if (type == RPMRICH_PARSE_ENTER) data->depth++; else if (type == RPMRICH_PARSE_LEAVE) { if (--data->depth == 0 && data->dochain && data->rightstart) { /* chain op hack, construct a sub-ds from the right side of the chain */ char *right = xmalloc(n + nl - data->rightstart + 2); right[0] = '('; strncpy(right + 1, data->rightstart, n + nl - data->rightstart); right[n + nl - data->rightstart + 1] = 0; data->rightds = rpmdsFree(data->rightds); ds = singleDS(data->dep->pool, data->dep->tagN, 0, 0, RPMSENSE_RICH | data->depflags, 0, 0, 0); ds->N[0] = rpmstrPoolId(ds->pool, right, 1); ds->EVR[0] = rpmstrPoolId(ds->pool, "", 1); data->rightds = ds; free(right); } } if (data->depth != 1) return RPMRC_OK; /* we're only interested in top-level parsing */ if ((type == RPMRICH_PARSE_SIMPLE || type == RPMRICH_PARSE_LEAVE) && !data->dochain) { if (type == RPMRICH_PARSE_LEAVE) sense = RPMSENSE_RICH; else if (data->dep->tagN == RPMTAG_REQUIRENAME && nl > 7 && rstreqn(n, "rpmlib(", sizeof("rpmlib(")-1)) sense |= RPMSENSE_RPMLIB; ds = singleDS(data->dep->pool, data->dep->tagN, 0, 0, sense | data->depflags, 0, 0, 0); ds->N[0] = rpmstrPoolIdn(ds->pool, n, nl, 1); ds->EVR[0] = rpmstrPoolIdn(ds->pool, e ? e : "", el, 1); if (!data->leftds) data->leftds = ds; else { data->rightds = ds; data->rightstart = n; } } if (type == RPMRICH_PARSE_OP) { if (data->op != RPMRICHOP_SINGLE) data->dochain = 1; /* this is a chained op */ else data->op = op; } return RPMRC_OK; }
urltype urlIsURL(const char * url) { const struct urlstring *us; if (url && *url) { for (us = urlstrings; us->leadin != NULL; us++) { if (!rstreqn(url, us->leadin, strlen(us->leadin))) continue; return us->ret; } if (rstreq(url, "-")) return URL_IS_DASH; } return URL_IS_UNKNOWN; }
static rpmRC parseRichDepOp(const char **dstrp, rpmrichOp *opp, char **emsg) { const char *p = *dstrp, *pe = p; const struct RichOpComp *ro; while (*pe && !risspace(*pe) && *pe != ')') pe++; for (ro = RichOps; ro->token != NULL; ro++) if (pe - p == strlen(ro->token) && rstreqn(p, ro->token, pe - p)) { *opp = ro->op; *dstrp = pe; return RPMRC_OK; } if (emsg) rasprintf(emsg, _("Unknown rich dependency op '%.*s'"), (int)(pe - p), p); return RPMRC_FAIL; }
rpmds rpmdsNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, int flags) { rpmTagVal tagEVR, tagF, tagTi; rpmds ds = NULL; const char * Type; struct rpmtd_s names; if (dsType(tagN, &Type, &tagEVR, &tagF, &tagTi)) goto exit; if (headerGet(h, tagN, &names, HEADERGET_MINMEM)) { struct rpmtd_s evr, flags, tindices; ds = rpmdsCreate(pool, tagN, Type, rpmtdCount(&names), headerGetInstance(h)); ds->N = rpmtdToPool(&names, ds->pool); headerGet(h, tagEVR, &evr, HEADERGET_MINMEM); ds->EVR = rpmtdToPool(&evr, ds->pool); headerGet(h, tagF, &flags, HEADERGET_ALLOC); ds->Flags = flags.data; if (tagTi != RPMTAG_NOT_FOUND) { headerGet(h, tagTi, &tindices, HEADERGET_ALLOC); ds->ti = tindices.data; } /* ensure rpmlib() requires always have RPMSENSE_RPMLIB flag set */ if (tagN == RPMTAG_REQUIRENAME && ds->Flags) { for (int i = 0; i < ds->Count; i++) { if (!(rpmdsFlagsIndex(ds, i) & RPMSENSE_RPMLIB)) { const char *N = rpmdsNIndex(ds, i); if (rstreqn(N, "rpmlib(", sizeof("rpmlib(")-1)) ds->Flags[i] |= RPMSENSE_RPMLIB; } } } rpmtdFreeData(&names); rpmtdFreeData(&evr); /* freeze the pool to save memory, but only if private pool */ if (ds->pool != pool) rpmstrPoolFreeze(ds->pool, 0); } exit: return ds; }
rpmds rpmdsNew(Header h, rpmTagVal tagN, int flags) { rpmTagVal tagEVR, tagF; rpmds ds = NULL; const char * Type; struct rpmtd_s names; headerGetFlags hgflags = HEADERGET_ALLOC|HEADERGET_ARGV; if (dsType(tagN, &Type, &tagEVR, &tagF)) goto exit; if (headerGet(h, tagN, &names, hgflags) && rpmtdCount(&names) > 0) { struct rpmtd_s evr, flags; ds = xcalloc(1, sizeof(*ds)); ds->Type = Type; ds->i = -1; ds->DNEVR = NULL; ds->tagN = tagN; ds->N = names.data; ds->Count = rpmtdCount(&names); ds->nopromote = _rpmds_nopromote; ds->instance = headerGetInstance(h); headerGet(h, tagEVR, &evr, hgflags); ds->EVR = evr.data; headerGet(h, tagF, &flags, hgflags); ds->Flags = flags.data; /* ensure rpmlib() requires always have RPMSENSE_RPMLIB flag set */ if (tagN == RPMTAG_REQUIRENAME && ds->Flags) { for (int i = 0; i < ds->Count; i++) { if (!(ds->Flags[i] & RPMSENSE_RPMLIB) && rstreqn(ds->N[i], "rpmlib(", sizeof("rpmlib(")-1)) ds->Flags[i] |= RPMSENSE_RPMLIB; } } ds = rpmdsLink(ds); } exit: return ds; }
int addReqProv(Package pkg, rpmTagVal tagN, const char * N, const char * EVR, rpmsenseFlags Flags, uint32_t index) { rpmds newds, *dsp = NULL; dsp = packageDependencies(pkg, tagN); /* rpmlib() dependency sanity: only requires permitted, ensure sense bit */ if (rstreqn(N, "rpmlib(", sizeof("rpmlib(")-1)) { if (tagN != RPMTAG_REQUIRENAME) return 1; Flags |= RPMSENSE_RPMLIB; } newds = rpmdsSinglePoolTix(pkg->pool, tagN, N, EVR, rpmSanitizeDSFlags(tagN, Flags), index); rpmdsMerge(dsp, newds); rpmdsFree(newds); return 0; }
int rpmcliImportPubkeys(rpmts ts, ARGV_const_t argv) { int res = 0; for (ARGV_const_t arg = argv; arg && *arg; arg++) { const char *fn = *arg; uint8_t *buf = NULL; ssize_t blen = 0; char *t = NULL; int iorc; /* If arg looks like a keyid, then attempt keyserver retrieve. */ if (rstreqn(fn, "0x", 2)) { const char * s = fn + 2; int i; for (i = 0; *s && isxdigit(*s); s++, i++) {}; if (i == 8 || i == 16) { t = rpmExpand("%{_hkp_keyserver_query}", fn+2, NULL); if (t && *t != '%') fn = t; } } /* Read the file and try to import all contained keys */ iorc = rpmioSlurp(fn, &buf, &blen); if (iorc || buf == NULL || blen < 64) { rpmlog(RPMLOG_ERR, _("%s: import read failed(%d).\n"), fn, iorc); res++; } else { res += doImport(ts, fn, (char *)buf, blen); } free(t); free(buf); } return res; }
void rpmRelocateFileList(rpmRelocation *relocations, int numRelocations, rpmfs fs, Header h) { char ** baseNames; char ** dirNames; uint32_t * dirIndexes; rpm_count_t fileCount, dirCount; int nrelocated = 0; int fileAlloced = 0; char * fn = NULL; int haveRelocatedBase = 0; size_t maxlen = 0; int i, j; struct rpmtd_s bnames, dnames, dindexes, fmodes; if (!addPrefixes(h, relocations, numRelocations)) return; if (rpmIsDebug()) { rpmlog(RPMLOG_DEBUG, "========== relocations\n"); for (i = 0; i < numRelocations; i++) { if (relocations[i].oldPath == NULL) continue; /* XXX can't happen */ if (relocations[i].newPath == NULL) rpmlog(RPMLOG_DEBUG, "%5d exclude %s\n", i, relocations[i].oldPath); else rpmlog(RPMLOG_DEBUG, "%5d relocate %s -> %s\n", i, relocations[i].oldPath, relocations[i].newPath); } } for (i = 0; i < numRelocations; i++) { if (relocations[i].newPath == NULL) continue; size_t len = strlen(relocations[i].newPath); if (len > maxlen) maxlen = len; } headerGet(h, RPMTAG_BASENAMES, &bnames, HEADERGET_MINMEM); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, HEADERGET_ALLOC); headerGet(h, RPMTAG_DIRNAMES, &dnames, HEADERGET_MINMEM); headerGet(h, RPMTAG_FILEMODES, &fmodes, HEADERGET_MINMEM); /* TODO XXX ugh.. use rpmtd iterators & friends instead */ baseNames = bnames.data; dirIndexes = dindexes.data; fileCount = rpmtdCount(&bnames); dirCount = rpmtdCount(&dnames); /* XXX TODO: use rpmtdDup() instead */ dirNames = dnames.data = duparray(dnames.data, dirCount); dnames.flags |= RPMTD_PTR_ALLOCED; /* * For all relocations, we go through sorted file/relocation lists * backwards so that /usr/local relocations take precedence over /usr * ones. */ /* Relocate individual paths. */ for (i = fileCount - 1; i >= 0; i--) { rpmFileTypes ft; int fnlen; size_t len = maxlen + strlen(dirNames[dirIndexes[i]]) + strlen(baseNames[i]) + 1; if (len >= fileAlloced) { fileAlloced = len * 2; fn = xrealloc(fn, fileAlloced); } assert(fn != NULL); /* XXX can't happen */ *fn = '\0'; fnlen = stpcpy( stpcpy(fn, dirNames[dirIndexes[i]]), baseNames[i]) - fn; /* * See if this file path needs relocating. */ /* * XXX FIXME: Would a bsearch of the (already sorted) * relocation list be a good idea? */ for (j = numRelocations - 1; j >= 0; j--) { if (relocations[j].oldPath == NULL) /* XXX can't happen */ continue; len = !rstreq(relocations[j].oldPath, "/") ? strlen(relocations[j].oldPath) : 0; if (fnlen < len) continue; /* * Only subdirectories or complete file paths may be relocated. We * don't check for '\0' as our directory names all end in '/'. */ if (!(fn[len] == '/' || fnlen == len)) continue; if (!rstreqn(relocations[j].oldPath, fn, len)) continue; break; } if (j < 0) continue; rpmtdSetIndex(&fmodes, i); ft = rpmfiWhatis(rpmtdGetNumber(&fmodes)); /* On install, a relocate to NULL means skip the path. */ if (relocations[j].newPath == NULL) { if (ft == XDIR) { /* Start with the parent, looking for directory to exclude. */ for (j = dirIndexes[i]; j < dirCount; j++) { len = strlen(dirNames[j]) - 1; while (len > 0 && dirNames[j][len-1] == '/') len--; if (fnlen != len) continue; if (!rstreqn(fn, dirNames[j], fnlen)) continue; break; } } rpmfsSetAction(fs, i, FA_SKIPNSTATE); rpmlog(RPMLOG_DEBUG, "excluding %s %s\n", ftstring(ft), fn); continue; } /* Relocation on full paths only, please. */ if (fnlen != len) continue; rpmlog(RPMLOG_DEBUG, "relocating %s to %s\n", fn, relocations[j].newPath); nrelocated++; strcpy(fn, relocations[j].newPath); { char * te = strrchr(fn, '/'); if (te) { if (te > fn) te++; /* root is special */ fnlen = te - fn; } else te = fn + strlen(fn); if (!rstreq(baseNames[i], te)) { /* basename changed too? */ if (!haveRelocatedBase) { /* XXX TODO: use rpmtdDup() instead */ bnames.data = baseNames = duparray(baseNames, fileCount); bnames.flags |= RPMTD_PTR_ALLOCED; haveRelocatedBase = 1; } free(baseNames[i]); baseNames[i] = xstrdup(te); } *te = '\0'; /* terminate new directory name */ } /* Does this directory already exist in the directory list? */ for (j = 0; j < dirCount; j++) { if (fnlen != strlen(dirNames[j])) continue; if (!rstreqn(fn, dirNames[j], fnlen)) continue; break; } if (j < dirCount) { dirIndexes[i] = j; continue; } /* Creating new paths is a pita */ dirNames = dnames.data = xrealloc(dnames.data, sizeof(*dirNames) * (dirCount + 1)); dirNames[dirCount] = xstrdup(fn); dirIndexes[i] = dirCount; dirCount++; dnames.count++; } /* Finish off by relocating directories. */ for (i = dirCount - 1; i >= 0; i--) { for (j = numRelocations - 1; j >= 0; j--) { if (relocations[j].oldPath == NULL) /* XXX can't happen */ continue; size_t len = !rstreq(relocations[j].oldPath, "/") ? strlen(relocations[j].oldPath) : 0; if (len && !rstreqn(relocations[j].oldPath, dirNames[i], len)) continue; /* * Only subdirectories or complete file paths may be relocated. We * don't check for '\0' as our directory names all end in '/'. */ if (dirNames[i][len] != '/') continue; if (relocations[j].newPath) { /* Relocate the path */ char *t = NULL; rstrscat(&t, relocations[j].newPath, (dirNames[i] + len), NULL); /* Unfortunately rpmCleanPath strips the trailing slash.. */ (void) rpmCleanPath(t); rstrcat(&t, "/"); rpmlog(RPMLOG_DEBUG, "relocating directory %s to %s\n", dirNames[i], t); free(dirNames[i]); dirNames[i] = t; nrelocated++; } } } /* Save original filenames in header and replace (relocated) filenames. */ if (nrelocated) { saveOrig(h); headerMod(h, &bnames); headerMod(h, &dnames); headerMod(h, &dindexes); } rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); rpmtdFreeData(&fmodes); free(fn); }
int readLine(rpmSpec spec, int strip) { char *s; int match; struct ReadLevelEntry *rl; OFI_t *ofi = spec->fileStack; int rc; if (!restoreFirstChar(spec)) { retry: if ((rc = readLineFromOFI(spec, ofi)) != 0) return rc; /* Copy next file line into the spec line buffer */ rc = copyNextLineFromOFI(spec, ofi); if (rc > 0) { goto retry; } else if (rc < 0) { return PART_ERROR; } } copyNextLineFinish(spec, strip); s = spec->line; SKIPSPACE(s); match = -1; if (!spec->readStack->reading && rstreqn("%if", s, sizeof("%if")-1)) { match = 0; } else if (rstreqn("%ifarch", s, sizeof("%ifarch")-1)) { char *arch = rpmExpand("%{_target_cpu}", NULL); s += 7; match = matchTok(arch, s); arch = _free(arch); } else if (rstreqn("%ifnarch", s, sizeof("%ifnarch")-1)) { char *arch = rpmExpand("%{_target_cpu}", NULL); s += 8; match = !matchTok(arch, s); arch = _free(arch); } else if (rstreqn("%ifos", s, sizeof("%ifos")-1)) { char *os = rpmExpand("%{_target_os}", NULL); s += 5; match = matchTok(os, s); os = _free(os); } else if (rstreqn("%ifnos", s, sizeof("%ifnos")-1)) { char *os = rpmExpand("%{_target_os}", NULL); s += 6; match = !matchTok(os, s); os = _free(os); } else if (rstreqn("%if", s, sizeof("%if")-1)) { s += 3; match = parseExpressionBoolean(spec, s); if (match < 0) { rpmlog(RPMLOG_ERR, _("%s:%d: parseExpressionBoolean returns %d\n"), ofi->fileName, ofi->lineNum, match); return PART_ERROR; } } else if (rstreqn("%else", s, sizeof("%else")-1)) { s += 5; if (! spec->readStack->next) { /* Got an else with no %if ! */ rpmlog(RPMLOG_ERR, _("%s:%d: Got a %%else with no %%if\n"), ofi->fileName, ofi->lineNum); return PART_ERROR; } spec->readStack->reading = spec->readStack->next->reading && ! spec->readStack->reading; spec->line[0] = '\0'; } else if (rstreqn("%endif", s, sizeof("%endif")-1)) { s += 6; if (! spec->readStack->next) { /* Got an end with no %if ! */ rpmlog(RPMLOG_ERR, _("%s:%d: Got a %%endif with no %%if\n"), ofi->fileName, ofi->lineNum); return PART_ERROR; } rl = spec->readStack; spec->readStack = spec->readStack->next; free(rl); spec->line[0] = '\0'; } else if (rstreqn("%include", s, sizeof("%include")-1)) { char *fileName, *endFileName, *p; s += 8; fileName = s; if (! risspace(*fileName)) { rpmlog(RPMLOG_ERR, _("malformed %%include statement\n")); return PART_ERROR; } SKIPSPACE(fileName); endFileName = fileName; SKIPNONSPACE(endFileName); p = endFileName; SKIPSPACE(p); if (*p != '\0') { rpmlog(RPMLOG_ERR, _("malformed %%include statement\n")); return PART_ERROR; } *endFileName = '\0'; forceIncludeFile(spec, fileName); ofi = spec->fileStack; goto retry; } if (match != -1) { rl = xmalloc(sizeof(*rl)); rl->reading = spec->readStack->reading && match; rl->next = spec->readStack; spec->readStack = rl; spec->line[0] = '\0'; } if (! spec->readStack->reading) { spec->line[0] = '\0'; } /* FIX: spec->readStack->next should be dependent */ return 0; }
/** * Skip any files that do not match install policies. * @param ts transaction set * @param files file info set * @param fs file states */ static void skipInstallFiles(const rpmts ts, rpmfiles files, rpmfs fs) { rpm_color_t tscolor = rpmtsColor(ts); rpm_color_t FColor; int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS); int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS); int * drc; char * dff; int dc; int i, j, ix; rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD); if (!noDocs) noDocs = rpmExpandNumeric("%{_excludedocs}"); /* Compute directory refcount, skip directory if now empty. */ dc = rpmfiDC(fi); drc = xcalloc(dc, sizeof(*drc)); dff = xcalloc(dc, sizeof(*dff)); fi = rpmfiInit(fi, 0); while ((i = rpmfiNext(fi)) >= 0) { char ** nsp; const char *flangs; ix = rpmfiDX(fi); drc[ix]++; /* Don't bother with skipped files */ if (XFA_SKIPPING(rpmfsGetAction(fs, i))) { drc[ix]--; dff[ix] = 1; continue; } /* Ignore colored files not in our rainbow. */ FColor = rpmfiFColor(fi); if (tscolor && FColor && !(tscolor & FColor)) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPCOLOR); continue; } /* * Skip net shared paths. * Net shared paths are not relative to the current root (though * they do need to take package relocations into account). */ if (ts->netsharedPaths) { nsp = matchNetsharedpath(ts, fi); if (nsp && *nsp) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPNETSHARED); continue; } } /* * Skip i18n language specific files. */ flangs = (ts->installLangs != NULL) ? rpmfiFLangs(fi) : NULL; if (flangs != NULL && *flangs != '\0') { const char *l, *le; char **lang; for (lang = ts->installLangs; *lang != NULL; lang++) { for (l = flangs; *l != '\0'; l = le) { for (le = l; *le != '\0' && *le != '|'; le++) {}; if ((le-l) > 0 && rstreqn(*lang, l, (le-l))) break; if (*le == '|') le++; /* skip over | */ } if (*l != '\0') break; } if (*lang == NULL) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPNSTATE); continue; } } /* * Skip config files if requested. */ if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPNSTATE); continue; } /* * Skip documentation if requested. */ if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPNSTATE); continue; } } /* Skip (now empty) directories that had skipped files. */ /* Iterate over dirs in reversed order to solve subdirs at first */ for (j = dc - 1; j >= 0; j--) { const char * dn, * bn; size_t dnlen, bnlen; if (drc[j]) continue; /* dir still has files. */ if (!dff[j]) continue; /* dir was not emptied here. */ /* Find parent directory and basename. */ dn = rpmfilesDN(files, j); dnlen = strlen(dn) - 1; bn = dn + dnlen; bnlen = 0; while (bn > dn && bn[-1] != '/') { bnlen++; dnlen--; bn--; } /* If explicitly included in the package, skip the directory. */ fi = rpmfiInit(fi, 0); while ((i = rpmfiNext(fi)) >= 0) { const char * fdn, * fbn; rpm_mode_t fFMode; if (XFA_SKIPPING(rpmfsGetAction(fs, i))) continue; fFMode = rpmfiFMode(fi); if (rpmfiWhatis(fFMode) != XDIR) continue; fdn = rpmfiDN(fi); if (strlen(fdn) != dnlen) continue; if (!rstreqn(fdn, dn, dnlen)) continue; fbn = rpmfiBN(fi); if (strlen(fbn) != bnlen) continue; if (!rstreqn(fbn, bn, bnlen)) continue; rpmlog(RPMLOG_DEBUG, "excluding directory %s\n", dn); rpmfsSetAction(fs, i, FA_SKIPNSTATE); ix = rpmfiDX(fi); /* Decrease count of files for parent directory */ drc[ix]--; /* Mark directory because something was removed from them */ dff[ix] = 1; break; } } free(drc); free(dff); rpmfiFree(fi); }
/** \ingroup payload * Create directory name iterator. * @param fi file info set * @param fs file state set * @param reverse traverse directory names in reverse order? * @return directory name iterator */ static DNLI_t dnlInitIterator(rpmfiles fi, rpmfs fs, int reverse) { DNLI_t dnli; int i, j; int dc; if (fi == NULL) return NULL; dc = rpmfilesDC(fi); dnli = xcalloc(1, sizeof(*dnli)); dnli->fi = fi; dnli->reverse = reverse; dnli->i = (reverse ? dc : 0); if (dc) { dnli->active = xcalloc(dc, sizeof(*dnli->active)); int fc = rpmfilesFC(fi); /* Identify parent directories not skipped. */ for (i = 0; i < fc; i++) if (!XFA_SKIPPING(rpmfsGetAction(fs, i))) dnli->active[rpmfilesDI(fi, i)] = 1; /* Exclude parent directories that are explicitly included. */ for (i = 0; i < fc; i++) { int dil; size_t dnlen, bnlen; if (!S_ISDIR(rpmfilesFMode(fi, i))) continue; dil = rpmfilesDI(fi, i); dnlen = strlen(rpmfilesDN(fi, dil)); bnlen = strlen(rpmfilesBN(fi, i)); for (j = 0; j < dc; j++) { const char * dnl; size_t jlen; if (!dnli->active[j] || j == dil) continue; dnl = rpmfilesDN(fi, j); jlen = strlen(dnl); if (jlen != (dnlen+bnlen+1)) continue; if (!rstreqn(dnl, rpmfilesDN(fi, dil), dnlen)) continue; if (!rstreqn(dnl+dnlen, rpmfilesBN(fi, i), bnlen)) continue; if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0') continue; /* This directory is included in the package. */ dnli->active[j] = 0; break; } } /* Print only once per package. */ if (!reverse) { j = 0; for (i = 0; i < dc; i++) { if (!dnli->active[i]) continue; if (j == 0) { j = 1; rpmlog(RPMLOG_DEBUG, "========== Directories not explicitly included in package:\n"); } rpmlog(RPMLOG_DEBUG, "%10d %s\n", i, rpmfilesDN(fi, i)); } if (j) rpmlog(RPMLOG_DEBUG, "==========\n"); } } return dnli; }
/** * Create (if necessary) directories not explicitly included in package. * @param files file data * @param fs file states * @param plugins rpm plugins handle * @return 0 on success */ static int fsmMkdirs(rpmfiles files, rpmfs fs, rpmPlugins plugins) { DNLI_t dnli = dnlInitIterator(files, fs, 0); struct stat sb; const char *dpath; int dc = rpmfilesDC(files); int rc = 0; int i; int ldnlen = 0; int ldnalloc = 0; char * ldn = NULL; short * dnlx = NULL; dnlx = (dc ? xcalloc(dc, sizeof(*dnlx)) : NULL); if (dnlx != NULL) while ((dpath = dnlNextIterator(dnli)) != NULL) { size_t dnlen = strlen(dpath); char * te, dn[dnlen+1]; dc = dnli->isave; if (dc < 0) continue; dnlx[dc] = dnlen; if (dnlen <= 1) continue; if (dnlen <= ldnlen && rstreq(dpath, ldn)) continue; /* Copy as we need to modify the string */ (void) stpcpy(dn, dpath); /* Assume '/' directory exists, "mkdir -p" for others if non-existent */ for (i = 1, te = dn + 1; *te != '\0'; te++, i++) { if (*te != '/') continue; *te = '\0'; /* Already validated? */ if (i < ldnlen && (ldn[i] == '/' || ldn[i] == '\0') && rstreqn(dn, ldn, i)) { *te = '/'; /* Move pre-existing path marker forward. */ dnlx[dc] = (te - dn); continue; } /* Validate next component of path. */ rc = fsmStat(dn, 1, &sb); /* lstat */ *te = '/'; /* Directory already exists? */ if (rc == 0 && S_ISDIR(sb.st_mode)) { /* Move pre-existing path marker forward. */ dnlx[dc] = (te - dn); } else if (rc == RPMERR_ENOENT) { *te = '\0'; mode_t mode = S_IFDIR | (_dirPerms & 07777); rpmFsmOp op = (FA_CREATE|FAF_UNOWNED); /* Run fsm file pre hook for all plugins */ rc = rpmpluginsCallFsmFilePre(plugins, NULL, dn, mode, op); if (!rc) rc = fsmMkdir(dn, mode); if (!rc) { rc = rpmpluginsCallFsmFilePrepare(plugins, NULL, dn, dn, mode, op); } /* Run fsm file post hook for all plugins */ rpmpluginsCallFsmFilePost(plugins, NULL, dn, mode, op, rc); if (!rc) { rpmlog(RPMLOG_DEBUG, "%s directory created with perms %04o\n", dn, (unsigned)(mode & 07777)); } *te = '/'; } if (rc) break; } if (rc) break; /* Save last validated path. */ if (ldnalloc < (dnlen + 1)) { ldnalloc = dnlen + 100; ldn = xrealloc(ldn, ldnalloc); } if (ldn != NULL) { /* XXX can't happen */ strcpy(ldn, dn); ldnlen = dnlen; } } free(dnlx); free(ldn); dnlFreeIterator(dnli); return rc; }
rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, int index, rpmsenseFlags tagflags) { const char *r, *re, *v, *ve; const char *emsg = NULL; char * N = NULL, * EVR = NULL; rpmTagVal nametag = RPMTAG_NOT_FOUND; rpmsenseFlags Flags; Header h = pkg->header; /* everything except buildrequires go here */ rpmRC rc = RPMRC_FAIL; /* assume failure */ switch (tagN) { default: case RPMTAG_REQUIREFLAGS: nametag = RPMTAG_REQUIRENAME; tagflags |= RPMSENSE_ANY; break; case RPMTAG_PROVIDEFLAGS: nametag = RPMTAG_PROVIDENAME; break; case RPMTAG_OBSOLETEFLAGS: nametag = RPMTAG_OBSOLETENAME; break; case RPMTAG_CONFLICTFLAGS: nametag = RPMTAG_CONFLICTNAME; break; case RPMTAG_ORDERFLAGS: nametag = RPMTAG_ORDERNAME; break; case RPMTAG_PREREQ: /* XXX map legacy PreReq into Requires(pre,preun) */ nametag = RPMTAG_REQUIRENAME; tagflags |= (RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_PREUN); break; case RPMTAG_TRIGGERPREIN: nametag = RPMTAG_TRIGGERNAME; tagflags |= RPMSENSE_TRIGGERPREIN; break; case RPMTAG_TRIGGERIN: nametag = RPMTAG_TRIGGERNAME; tagflags |= RPMSENSE_TRIGGERIN; break; case RPMTAG_TRIGGERPOSTUN: nametag = RPMTAG_TRIGGERNAME; tagflags |= RPMSENSE_TRIGGERPOSTUN; break; case RPMTAG_TRIGGERUN: nametag = RPMTAG_TRIGGERNAME; tagflags |= RPMSENSE_TRIGGERUN; break; case RPMTAG_BUILDPREREQ: case RPMTAG_BUILDREQUIRES: nametag = RPMTAG_REQUIRENAME; tagflags |= RPMSENSE_ANY; h = spec->buildRestrictions; break; case RPMTAG_BUILDCONFLICTS: nametag = RPMTAG_CONFLICTNAME; h = spec->buildRestrictions; break; } for (r = field; *r != '\0'; r = re) { SKIPWHITE(r); if (*r == '\0') break; Flags = (tagflags & ~RPMSENSE_SENSEMASK); /* * Tokens must begin with alphanumeric, _, or /, but we don't know * the spec's encoding so we only check what we can: plain ascii. */ if (isascii(r[0]) && !(risalnum(r[0]) || r[0] == '_' || r[0] == '/')) { emsg = _("Dependency tokens must begin with alpha-numeric, '_' or '/'"); goto exit; } re = r; SKIPNONWHITE(re); N = xmalloc((re-r) + 1); rstrlcpy(N, r, (re-r) + 1); /* Parse EVR */ v = re; SKIPWHITE(v); ve = v; SKIPNONWHITE(ve); re = v; /* ==> next token (if no EVR found) starts here */ /* Check for possible logical operator */ if (ve > v) { const struct ReqComp *rc; for (rc = ReqComparisons; rc->token != NULL; rc++) { if ((ve-v) != strlen(rc->token) || !rstreqn(v, rc->token, (ve-v))) continue; if (r[0] == '/') { emsg = _("Versioned file name not permitted"); goto exit; } Flags |= rc->sense; /* now parse EVR */ v = ve; SKIPWHITE(v); ve = v; SKIPNONWHITE(ve); break; } } if (Flags & RPMSENSE_SENSEMASK) { if (*v == '\0' || ve == v) { emsg = _("Version required"); goto exit; } EVR = xmalloc((ve-v) + 1); rstrlcpy(EVR, v, (ve-v) + 1); if (rpmCharCheck(spec, EVR, ve-v, ".-_+:%{}")) goto exit; re = ve; /* ==> next token after EVR string starts here */ } else EVR = NULL; if (addReqProv(h, nametag, N, EVR, Flags, index)) { emsg = _("invalid dependency"); goto exit; } N = _free(N); EVR = _free(EVR); } rc = RPMRC_OK; exit: if (emsg) { /* Automatic dependencies don't relate to spec lines */ if (tagflags & (RPMSENSE_FIND_REQUIRES|RPMSENSE_FIND_PROVIDES)) { rpmlog(RPMLOG_ERR, "%s: %s\n", emsg, r); } else { rpmlog(RPMLOG_ERR, _("line %d: %s: %s\n"), spec->lineNum, emsg, spec->line); } } free(N); free(EVR); return rc; }
poptContext rpmcliInit(int argc, char *const argv[], struct poptOption * optionsTable) { poptContext optCon; int rc; const char *ctx, *execPath; setprogname(argv[0]); /* Retrofit glibc __progname */ /* XXX glibc churn sanity */ if (__progname == NULL) { if ((__progname = strrchr(argv[0], '/')) != NULL) __progname++; else __progname = argv[0]; } #if defined(ENABLE_NLS) (void) setlocale(LC_ALL, "" ); (void) bindtextdomain(PACKAGE, LOCALEDIR); (void) textdomain(PACKAGE); #endif rpmSetVerbosity(RPMLOG_NOTICE); if (optionsTable == NULL) { /* Read rpm configuration (if not already read). */ rpmcliConfigured(); return NULL; } /* XXX hack to get popt working from build tree wrt lt-foo names */ ctx = rstreqn(__progname, "lt-", 3) ? __progname + 3 : __progname; optCon = poptGetContext(ctx, argc, (const char **)argv, optionsTable, 0); { char *poptfile = rpmGenPath(rpmConfigDir(), LIBRPMALIAS_FILENAME, NULL); (void) poptReadConfigFile(optCon, poptfile); free(poptfile); } (void) poptReadDefaultConfig(optCon, 1); if ((execPath = getenv("RPM_POPTEXEC_PATH")) == NULL) execPath = LIBRPMALIAS_EXECPATH; poptSetExecPath(optCon, execPath, 1); /* Process all options, whine if unknown. */ while ((rc = poptGetNextOpt(optCon)) > 0) { fprintf(stderr, _("%s: option table misconfigured (%d)\n"), __progname, rc); exit(EXIT_FAILURE); } if (rc < -1) { fprintf(stderr, "%s: %s: %s\n", __progname, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); exit(EXIT_FAILURE); } /* Read rpm configuration (if not already read). */ rpmcliConfigured(); if (_debug) { rpmIncreaseVerbosity(); rpmIncreaseVerbosity(); } return optCon; }
int addReqProv(Package pkg, rpmTagVal tagN, const char * N, const char * EVR, rpmsenseFlags Flags, uint32_t index) { rpmTagVal versiontag = 0; rpmTagVal flagtag = 0; rpmTagVal indextag = 0; rpmsenseFlags extra = RPMSENSE_ANY; Header h = pkg->header; /* just a shortcut */ rpmds newds, *dsp = NULL; switch (tagN) { case RPMTAG_PROVIDENAME: versiontag = RPMTAG_PROVIDEVERSION; flagtag = RPMTAG_PROVIDEFLAGS; extra = Flags & RPMSENSE_FIND_PROVIDES; dsp = &pkg->provides; break; case RPMTAG_OBSOLETENAME: versiontag = RPMTAG_OBSOLETEVERSION; flagtag = RPMTAG_OBSOLETEFLAGS; dsp = &pkg->obsoletes; break; case RPMTAG_CONFLICTNAME: versiontag = RPMTAG_CONFLICTVERSION; flagtag = RPMTAG_CONFLICTFLAGS; dsp = &pkg->conflicts; break; case RPMTAG_ORDERNAME: versiontag = RPMTAG_ORDERVERSION; flagtag = RPMTAG_ORDERFLAGS; dsp = &pkg->order; break; case RPMTAG_TRIGGERNAME: versiontag = RPMTAG_TRIGGERVERSION; flagtag = RPMTAG_TRIGGERFLAGS; indextag = RPMTAG_TRIGGERINDEX; extra = Flags & RPMSENSE_TRIGGER; dsp = &pkg->triggers; break; case RPMTAG_REQUIRENAME: default: tagN = RPMTAG_REQUIRENAME; versiontag = RPMTAG_REQUIREVERSION; flagtag = RPMTAG_REQUIREFLAGS; extra = Flags & _ALL_REQUIRES_MASK; dsp = &pkg->requires; } /* rpmlib() dependency sanity: only requires permitted, ensure sense bit */ if (rstreqn(N, "rpmlib(", sizeof("rpmlib(")-1)) { if (tagN != RPMTAG_REQUIRENAME) return 1; extra |= RPMSENSE_RPMLIB; } Flags = (Flags & RPMSENSE_SENSEMASK) | extra; if (EVR == NULL) EVR = ""; newds = rpmdsSinglePool(pkg->pool, tagN, N, EVR, Flags); /* Avoid adding duplicate dependencies. */ if (isNewDep(dsp, newds, h, indextag, index)) { headerPutString(h, tagN, N); headerPutString(h, versiontag, EVR); headerPutUint32(h, flagtag, &Flags, 1); if (indextag) { headerPutUint32(h, indextag, &index, 1); } } rpmdsFree(newds); return 0; }