static void printFileInfo(const char * name, rpm_loff_t size, unsigned short mode, unsigned int mtime, unsigned short rdev, unsigned int nlink, const char * owner, const char * group, const char * linkto) { char sizefield[21]; char ownerfield[8+1], groupfield[8+1]; char timefield[100]; time_t when = mtime; /* important if sizeof(int32_t) ! sizeof(time_t) */ struct tm * tm; static time_t now; char * perms = rpmPermsString(mode); char *link = NULL; /* On first call, grab snapshot of now */ if (now == 0) now = time(NULL); rstrlcpy(ownerfield, owner, sizeof(ownerfield)); rstrlcpy(groupfield, group, sizeof(groupfield)); /* this is normally right */ snprintf(sizefield, sizeof(sizefield), "%20" PRIu64, size); /* this knows too much about dev_t */ if (S_ISLNK(mode)) { rasprintf(&link, "%s -> %s", name, linkto); } else if (S_ISCHR(mode)) { perms[0] = 'c'; snprintf(sizefield, sizeof(sizefield), "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff), ((unsigned)rdev & 0xff)); } else if (S_ISBLK(mode)) {
static int rpmLeadFromHeader(Header h, struct rpmlead_s *l) { if (h != NULL) { int archnum, osnum; char * nevr = headerGetAsString(h, RPMTAG_NEVR); /* FIXME: should grab these from header instead (RhBug:717898) */ rpmGetArchInfo(NULL, &archnum); rpmGetOsInfo(NULL, &osnum); memset(l, 0, sizeof(*l)); l->major = 3; l->minor = 0; l->archnum = archnum; l->osnum = osnum; l->signature_type = RPMSIGTYPE_HEADERSIG; l->type = (headerIsSource(h) ? 1 : 0); memcpy(l->magic, lead_magic, sizeof(l->magic)); rstrlcpy(l->name, nevr, sizeof(l->name)); free(nevr); } return (h != NULL); }
/* Callback for the rich dependency parser. We use this to do check for invalid * characters and to build a normailzed version of the dependency */ static rpmRC parseRCPOTRichCB(void *cbdata, rpmrichParseType type, const char *n, int nl, const char *e, int el, rpmsenseFlags sense, rpmrichOp op, char **emsg) { struct parseRCPOTRichData *data = cbdata; StringBuf sb = data->sb; rpmRC rc = RPMRC_OK; if (type == RPMRICH_PARSE_ENTER) { appendStringBuf(sb, "("); } else if (type == RPMRICH_PARSE_LEAVE) { appendStringBuf(sb, ")"); } else if (type == RPMRICH_PARSE_SIMPLE) { char *N = xmalloc(nl + 1); char *EVR = NULL; rstrlcpy(N, n, nl + 1); appendStringBuf(sb, N); if (el) { char rel[6], *rp = rel; EVR = xmalloc(el + 1); rstrlcpy(EVR, e, el + 1); *rp++ = ' '; if (sense & RPMSENSE_LESS) *rp++ = '<'; if (sense & RPMSENSE_GREATER) *rp++ = '>'; if (sense & RPMSENSE_EQUAL) *rp++ = '='; *rp++ = ' '; *rp = 0; appendStringBuf(sb, rel); appendStringBuf(sb, EVR); } rc = checkDep(data->spec, N, EVR, emsg); _free(N); _free(EVR); } else if (type == RPMRICH_PARSE_OP) { appendStringBuf(sb, " "); appendStringBuf(sb, rpmrichOpStr(op)); appendStringBuf(sb, " "); } return rc; }
/* * Format sigcheck result for output, appending the message spew to buf and * bad/missing keyids to keyprob. * * In verbose mode, just dump it all. Otherwise ok signatures * are dumped lowercase, bad sigs uppercase and for PGP/GPG * if misssing/untrusted key it's uppercase in parenthesis * and stash the key id as <SIGTYPE>#<keyid>. Pfft. */ static void formatResult(rpmTagVal sigtag, rpmRC sigres, const char *result, char **keyprob, char **buf) { char *msg = NULL; if (rpmIsVerbose()) { rasprintf(&msg, " %s\n", result); } else { /* Check for missing / untrusted keys in result. */ const char *signame = sigtagname(sigtag, (sigres != RPMRC_OK)); if (sigres == RPMRC_NOKEY || sigres == RPMRC_NOTTRUSTED) { const char *tempKey = strstr(result, "ey ID"); if (tempKey) { char keyid[sizeof(pgpKeyID_t) + 1]; rstrlcpy(keyid, tempKey + 6, sizeof(keyid)); rstrscat(keyprob, " ", signame, "#", keyid, NULL); } } rasprintf(&msg, (*keyprob ? "(%s) " : "%s "), signame); } rstrcat(buf, msg); free(msg); }
static void compressFilelist(Header h) { struct rpmtd_s fileNames; char ** dirNames; const char ** baseNames; uint32_t * dirIndexes; rpm_count_t count; int i; int dirIndex = -1; /* * This assumes the file list is already sorted, and begins with a * single '/'. That assumption isn't critical, but it makes things go * a bit faster. */ if (headerIsEntry(h, RPMTAG_DIRNAMES)) { headerDel(h, RPMTAG_OLDFILENAMES); return; /* Already converted. */ } if (!headerGet(h, RPMTAG_OLDFILENAMES, &fileNames, HEADERGET_MINMEM)) return; count = rpmtdCount(&fileNames); if (count < 1) return; dirNames = xmalloc(sizeof(*dirNames) * count); /* worst case */ baseNames = xmalloc(sizeof(*dirNames) * count); dirIndexes = xmalloc(sizeof(*dirIndexes) * count); /* HACK. Source RPM, so just do things differently */ { const char *fn = rpmtdGetString(&fileNames); if (fn && *fn != '/') { dirIndex = 0; dirNames[dirIndex] = xstrdup(""); while ((i = rpmtdNext(&fileNames)) >= 0) { dirIndexes[i] = dirIndex; baseNames[i] = rpmtdGetString(&fileNames); } goto exit; } } /* * XXX EVIL HACK, FIXME: * This modifies (and then restores) a const string from rpmtd * through basename retrieved from strrchr() which silently * casts away const on return. */ while ((i = rpmtdNext(&fileNames)) >= 0) { char ** needle; char savechar; char * baseName; size_t len; char *filename = (char *) rpmtdGetString(&fileNames); /* HACK HACK */ if (filename == NULL) /* XXX can't happen */ continue; baseName = strrchr(filename, '/') + 1; len = baseName - filename; needle = dirNames; savechar = *baseName; *baseName = '\0'; if (dirIndex < 0 || (needle = bsearch(&filename, dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) { char *s = xmalloc(len + 1); rstrlcpy(s, filename, len + 1); dirIndexes[i] = ++dirIndex; dirNames[dirIndex] = s; } else dirIndexes[i] = needle - dirNames; *baseName = savechar; baseNames[i] = baseName; } exit: if (count > 0) { headerPutUint32(h, RPMTAG_DIRINDEXES, dirIndexes, count); headerPutStringArray(h, RPMTAG_BASENAMES, baseNames, count); headerPutStringArray(h, RPMTAG_DIRNAMES, (const char **) dirNames, dirIndex + 1); } rpmtdFreeData(&fileNames); for (i = 0; i <= dirIndex; i++) { free(dirNames[i]); } free(dirNames); free(baseNames); free(dirIndexes); headerDel(h, RPMTAG_OLDFILENAMES); }
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; }
rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, int index, rpmsenseFlags tagflags) { const char *r, *re, *v, *ve; char *emsg = NULL; char * N = NULL, * EVR = NULL; rpmTagVal nametag = RPMTAG_NOT_FOUND; rpmsenseFlags Flags; rpmds *pdsp = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ switch (tagN) { default: case RPMTAG_REQUIREFLAGS: nametag = RPMTAG_REQUIRENAME; tagflags |= RPMSENSE_ANY; break; case RPMTAG_RECOMMENDFLAGS: nametag = RPMTAG_RECOMMENDNAME; break; case RPMTAG_SUGGESTFLAGS: nametag = RPMTAG_SUGGESTNAME; break; case RPMTAG_SUPPLEMENTFLAGS: nametag = RPMTAG_SUPPLEMENTNAME; break; case RPMTAG_ENHANCEFLAGS: nametag = RPMTAG_ENHANCENAME; 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; break; case RPMTAG_BUILDCONFLICTS: nametag = RPMTAG_CONFLICTNAME; break; case RPMTAG_FILETRIGGERIN: nametag = RPMTAG_FILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERIN; break; case RPMTAG_FILETRIGGERUN: nametag = RPMTAG_FILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERUN; break; case RPMTAG_FILETRIGGERPOSTUN: nametag = RPMTAG_FILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERPOSTUN; break; case RPMTAG_TRANSFILETRIGGERIN: nametag = RPMTAG_TRANSFILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERIN; break; case RPMTAG_TRANSFILETRIGGERUN: nametag = RPMTAG_TRANSFILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERUN; break; case RPMTAG_TRANSFILETRIGGERPOSTUN: nametag = RPMTAG_TRANSFILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERPOSTUN; break; } for (r = field; *r != '\0'; r = re) { SKIPWHITE(r); if (*r == '\0') break; Flags = (tagflags & ~RPMSENSE_SENSEMASK); if (r[0] == '(') { struct parseRCPOTRichData data; if (nametag != RPMTAG_REQUIRENAME && nametag != RPMTAG_CONFLICTNAME && nametag != RPMTAG_RECOMMENDNAME && nametag != RPMTAG_SUPPLEMENTNAME && nametag != RPMTAG_SUGGESTNAME && nametag != RPMTAG_ENHANCENAME) { rasprintf(&emsg, _("No rich dependencies allowed for this type")); goto exit; } data.spec = spec; data.sb = newStringBuf(); if (rpmrichParse(&r, &emsg, parseRCPOTRichCB, &data) != RPMRC_OK) { freeStringBuf(data.sb); goto exit; } if (addReqProv(pkg, nametag, getStringBuf(data.sb), NULL, Flags | RPMSENSE_RICH, index)) { rasprintf(&emsg, _("invalid dependency")); freeStringBuf(data.sb); goto exit; } freeStringBuf(data.sb); re = r; continue; } re = r; SKIPNONWHITE(re); N = xmalloc((re-r) + 1); rstrlcpy(N, r, (re-r) + 1); /* Parse EVR */ EVR = NULL; 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) { rpmsenseFlags sense = rpmParseDSFlags(v, ve - v); if (sense) { Flags |= sense; /* now parse EVR */ v = ve; SKIPWHITE(v); ve = v; SKIPNONWHITE(ve); if (*v == '\0' || ve == v) { rasprintf(&emsg, _("Version required")); goto exit; } EVR = xmalloc((ve-v) + 1); rstrlcpy(EVR, v, (ve-v) + 1); re = ve; /* ==> next token after EVR string starts here */ } } /* check that dependency is well-formed */ if (checkDep(spec, N, EVR, &emsg)) goto exit; if (nametag == RPMTAG_FILETRIGGERNAME || nametag == RPMTAG_TRANSFILETRIGGERNAME) { if (N[0] != '/') { rasprintf(&emsg, _("Only absolute paths are allowed in " "file triggers")); } } /* Deny more "normal" triggers fired by the same pakage. File triggers are ok */ pdsp = packageDependencies(pkg, nametag); rpmdsInit(*pdsp); if (nametag == RPMTAG_TRIGGERNAME) { while (rpmdsNext(*pdsp) >= 0) { if (rstreq(rpmdsN(*pdsp), N) && ((rpmdsFlags(*pdsp) & tagflags))) { rasprintf(&emsg, _("Trigger fired by the same package " "is already defined in spec file")); goto exit; } } } if (addReqProv(pkg, nametag, N, EVR, Flags, index)) { rasprintf(&emsg, _("invalid dependency")); goto exit; } N = _free(N); EVR = _free(EVR); } rc = RPMRC_OK; exit: if (emsg) { int lvl = (rc == RPMRC_OK) ? RPMLOG_WARNING : RPMLOG_ERR; /* Automatic dependencies don't relate to spec lines */ if (tagflags & (RPMSENSE_FIND_REQUIRES|RPMSENSE_FIND_PROVIDES)) { rpmlog(lvl, "%s: %s\n", emsg, r); } else { rpmlog(lvl, _("line %d: %s: %s\n"), spec->lineNum, emsg, spec->line); } free(emsg); } _free(N); _free(EVR); return rc; }