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; }
static void copyNextLineFinish(rpmSpec spec, int strip) { char *last; char ch; /* Find next line in expanded line buffer */ spec->line = last = spec->nextline; ch = ' '; while (*spec->nextline && ch != '\n') { ch = *spec->nextline++; if (!risspace(ch)) last = spec->nextline; } /* Save 1st char of next line in order to terminate current line. */ if (*spec->nextline != '\0') { spec->nextpeekc = *spec->nextline; *spec->nextline = '\0'; } if (strip & STRIP_COMMENTS) handleComments(spec->line); if (strip & STRIP_TRAILINGSPACE) *last = '\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) { 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; }
rpmRC rpmpluginsAddPlugin(rpmPlugins plugins, const char *type, const char *name) { char *path; char *options; rpmRC rc = RPMRC_FAIL; path = rpmExpand("%{?__", type, "_", name, "}", NULL); if (!path || rstreq(path, "")) { rpmlog(RPMLOG_ERR, _("Failed to expand %%__%s_%s macro\n"), type, name); goto exit; } /* split the options from the path */ #define SKIPSPACE(s) { while (*(s) && risspace(*(s))) (s)++; } #define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; } options = path; SKIPNONSPACE(options); if (risspace(*options)) { *options = '\0'; options++; SKIPSPACE(options); } if (*options == '\0') { options = NULL; } rc = rpmpluginsAdd(plugins, name, path, options); exit: _free(path); return rc; }
static int findPreambleTag(rpmSpec spec,rpmTagVal * tag, const char ** macro, char * lang) { PreambleRec p; char *s; for (p = preambleList; p->token != NULL; p++) { if (!(p->token && !rstrncasecmp(spec->line, p->token, p->len))) continue; if (p->deprecated) { rpmlog(RPMLOG_WARNING, _("line %d: %s is deprecated: %s\n"), spec->lineNum, p->token, spec->line); } break; } if (p == NULL || p->token == NULL) return 1; s = spec->line + p->len; SKIPSPACE(s); switch (p->type) { default: case 0: /* Unless this is a source or a patch, a ':' better be next */ if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) { if (*s != ':') return 1; } *lang = '\0'; break; case 1: /* Parse optional ( <token> ). */ case 2: if (*s == ':') { /* Type 1 is multilang, 2 is qualifiers with no defaults */ strcpy(lang, (p->type == 1) ? RPMBUILD_DEFAULT_LANG : ""); break; } if (*s != '(') return 1; s++; SKIPSPACE(s); while (!risspace(*s) && *s != ')') *lang++ = *s++; *lang = '\0'; SKIPSPACE(s); if (*s != ')') return 1; s++; SKIPSPACE(s); if (*s != ':') return 1; break; } *tag = p->tag; if (macro) *macro = p->token; return 0; }
static inline char * findLastChar(char * s) { char *res = s; while (*s != '\0') { if (! risspace(*s)) res = s; s++; } return res; }
int isPart(const char *line) { const struct PartRec *p; for (p = partList; p->token != NULL; p++) { char c; if (rstrncasecmp(line, p->token, p->len)) continue; c = *(line + p->len); if (c == '\0' || risspace(c)) break; } return (p->token ? p->part : PART_NONE); }
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; }
rpmParseState isPart(const char *line) { struct PartRec *p; if (partList[0].len == 0) initParts(partList); for (p = partList; p->token != NULL; p++) { char c; if (rstrncasecmp(line, p->token, p->len)) continue; c = *(line + p->len); if (c == '\0' || risspace(c)) break; } return (p->token ? p->part : PART_NONE); }
static void dbConfigure(rpmDbiTagVal rpmtag, struct dbConfig_s *cfg, struct dbiConfig_s *dbicfg) { char *dbOpts; dbOpts = rpmExpand("%{_dbi_config_", rpmTagGetName(rpmtag), "}", NULL); if (!(dbOpts && *dbOpts && *dbOpts != '%')) { dbOpts = _free(dbOpts); dbOpts = rpmExpand("%{_dbi_config}", NULL); if (!(dbOpts && *dbOpts && *dbOpts != '%')) { dbOpts = _free(dbOpts); } } /* Parse the options for the database element(s). */ if (dbOpts && *dbOpts && *dbOpts != '%') { char *o, *oe; char *p, *pe; memset(&staticdbicfg, 0, sizeof(staticdbicfg)); /*=========*/ for (o = dbOpts; o && *o; o = oe) { const struct poptOption *opt; const char * tok; unsigned int argInfo; /* Skip leading white space. */ while (*o && risspace(*o)) o++; /* Find and terminate next key=value pair. Save next start point. */ for (oe = o; oe && *oe; oe++) { if (risspace(*oe)) break; if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/')) break; } if (oe && *oe) *oe++ = '\0'; if (*o == '\0') continue; /* Separate key from value, save value start (if any). */ for (pe = o; pe && *pe && *pe != '='; pe++) {}; p = (pe ? *pe++ = '\0', pe : NULL); /* Skip over negation at start of token. */ for (tok = o; *tok == '!'; tok++) {}; /* Find key in option table. */ for (opt = rdbOptions; opt->longName != NULL; opt++) { if (!rstreq(tok, opt->longName)) continue; break; } if (opt->longName == NULL) { rpmlog(RPMLOG_ERR, _("unrecognized db option: \"%s\" ignored.\n"), o); continue; } /* Toggle the flags for negated tokens, if necessary. */ argInfo = opt->argInfo; if (argInfo == POPT_BIT_SET && *o == '!' && ((tok - o) % 2)) argInfo = POPT_BIT_CLR; /* Save value in template as appropriate. */ switch (argInfo & POPT_ARG_MASK) { case POPT_ARG_NONE: (void) poptSaveInt((int *)opt->arg, argInfo, 1L); break; case POPT_ARG_VAL: (void) poptSaveInt((int *)opt->arg, argInfo, (long)opt->val); break; case POPT_ARG_STRING: { char ** t = opt->arg; if (t) { /* FIX: opt->arg annotation in popt.h */ *t = _free(*t); *t = xstrdup( (p ? p : "") ); } } break; case POPT_ARG_INT: case POPT_ARG_LONG: { long aLong = strtol(p, &pe, 0); if (pe) { if (!rstrncasecmp(pe, "Mb", 2)) aLong *= 1024 * 1024; else if (!rstrncasecmp(pe, "Kb", 2)) aLong *= 1024; else if (*pe != '\0') { rpmlog(RPMLOG_ERR, _("%s has invalid numeric value, skipped\n"), opt->longName); continue; } } if ((argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) { if (aLong == LONG_MIN || aLong == LONG_MAX) { rpmlog(RPMLOG_ERR, _("%s has too large or too small long value, skipped\n"), opt->longName); continue; } (void) poptSaveLong((long *)opt->arg, argInfo, aLong); break; } else { if (aLong > INT_MAX || aLong < INT_MIN) { rpmlog(RPMLOG_ERR, _("%s has too large or too small integer value, skipped\n"), opt->longName); continue; } (void) poptSaveInt((int *)opt->arg, argInfo, aLong); } } break; default: break; } } /*=========*/ } dbOpts = _free(dbOpts); if (cfg) { *cfg = staticcfg; /* structure assignment */ /* Throw in some defaults if configuration didn't set any */ if (!cfg->db_mmapsize) cfg->db_mmapsize = 16 * 1024 * 1024; if (!cfg->db_cachesize) cfg->db_cachesize = 8 * 1024 * 1024; } if (dbicfg) { *dbicfg = staticdbicfg; } }
static void rpmcliAllArgCallback( poptContext con, enum poptCallbackReason reason, const struct poptOption * opt, const char * arg, const void * data) { /* XXX avoid accidental collisions with POPT_BIT_SET for flags */ if (opt->arg == NULL) switch (opt->val) { case 'q': rpmSetVerbosity(RPMLOG_WARNING); break; case 'v': rpmIncreaseVerbosity(); break; case POPT_PREDEFINE: (void) rpmDefineMacro(NULL, arg, RMIL_CMDLINE); break; case 'D': { char *s, *t; /* XXX Convert '-' in macro name to underscore, skip leading %. */ s = t = xstrdup(arg); while (*t && !risspace(*t)) { if (*t == '-') *t = '_'; t++; } t = s; if (*t == '%') t++; /* XXX Predefine macro if not initialized yet. */ if (rpmcliInitialized < 0) (void) rpmDefineMacro(NULL, t, RMIL_CMDLINE); rpmcliConfigured(); (void) rpmDefineMacro(NULL, t, RMIL_CMDLINE); (void) rpmDefineMacro(rpmCLIMacroContext, t, RMIL_CMDLINE); free(s); break; } case 'E': rpmcliConfigured(); { char *val = rpmExpand(arg, NULL); fprintf(stdout, "%s\n", val); free(val); } break; case POPT_DBPATH: rpmcliConfigured(); addMacro(NULL, "_dbpath", NULL, arg, RMIL_CMDLINE); break; case POPT_SHOWVERSION: printVersion(stdout); exit(EXIT_SUCCESS); break; case POPT_SHOWRC: rpmcliConfigured(); (void) rpmShowRC(stdout); exit(EXIT_SUCCESS); break; case POPT_QUERYTAGS: rpmDisplayQueryTags(stdout); exit(EXIT_SUCCESS); break; case RPMCLI_POPT_NODIGEST: rpmcliQueryFlags |= VERIFY_DIGEST; break; case RPMCLI_POPT_NOSIGNATURE: rpmcliQueryFlags |= VERIFY_SIGNATURE; break; case RPMCLI_POPT_NOHDRCHK: rpmcliQueryFlags |= VERIFY_HDRCHK; break; } }
/** * Add %changelog section to header. * @param h header * @param sb changelog strings * @return RPMRC_OK on success */ static rpmRC addChangelog(Header h, StringBuf sb) { char *s; int i; time_t time; time_t lastTime = 0; time_t trimtime = rpmExpandNumeric("%{?_changelog_trimtime}"); char *date, *name, *text, *next; s = getStringBuf(sb); /* skip space */ SKIPSPACE(s); while (*s != '\0') { if (*s != '*') { rpmlog(RPMLOG_ERR, _("%%changelog entries must start with *\n")); return RPMRC_FAIL; } /* find end of line */ date = s; while(*s && *s != '\n') s++; if (! *s) { rpmlog(RPMLOG_ERR, _("incomplete %%changelog entry\n")); return RPMRC_FAIL; } *s = '\0'; text = s + 1; /* 4 fields of date */ date++; s = date; for (i = 0; i < 4; i++) { SKIPSPACE(s); SKIPNONSPACE(s); } SKIPSPACE(date); if (dateToTimet(date, &time)) { rpmlog(RPMLOG_ERR, _("bad date in %%changelog: %s\n"), date); return RPMRC_FAIL; } if (lastTime && lastTime < time) { rpmlog(RPMLOG_ERR, _("%%changelog not in descending chronological order\n")); return RPMRC_FAIL; } lastTime = time; /* skip space to the name */ SKIPSPACE(s); if (! *s) { rpmlog(RPMLOG_ERR, _("missing name in %%changelog\n")); return RPMRC_FAIL; } /* name */ name = s; while (*s != '\0') s++; while (s > name && risspace(*s)) { *s-- = '\0'; } if (s == name) { rpmlog(RPMLOG_ERR, _("missing name in %%changelog\n")); return RPMRC_FAIL; } /* text */ SKIPSPACE(text); if (! *text) { rpmlog(RPMLOG_ERR, _("no description in %%changelog\n")); return RPMRC_FAIL; } /* find the next leading '*' (or eos) */ s = text; do { s++; } while (*s && (*(s-1) != '\n' || *s != '*')); next = s; s--; /* backup to end of description */ while ((s > text) && risspace(*s)) { *s-- = '\0'; } if ( !trimtime || time >= trimtime ) { addChangelogEntry(h, time, name, text); } else break; s = next; } return RPMRC_OK; }
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; }
/** * @param state expression parser state */ static int rdToken(ParseState state) { int token; Value v = NULL; char *p = state->p; /* Skip whitespace before the next token. */ while (*p && risspace(*p)) p++; switch (*p) { case '\0': token = TOK_EOF; p--; break; case '+': token = TOK_ADD; break; case '-': token = TOK_MINUS; break; case '*': token = TOK_MULTIPLY; break; case '/': token = TOK_DIVIDE; break; case '(': token = TOK_OPEN_P; break; case ')': token = TOK_CLOSE_P; break; case '=': if (p[1] == '=') { token = TOK_EQ; p++; } else { rpmlog(RPMLOG_ERR, _("syntax error while parsing ==\n")); return -1; } break; case '!': if (p[1] == '=') { token = TOK_NEQ; p++; } else token = TOK_NOT; break; case '<': if (p[1] == '=') { token = TOK_LE; p++; } else token = TOK_LT; break; case '>': if (p[1] == '=') { token = TOK_GE; p++; } else token = TOK_GT; break; case '&': if (p[1] == '&') { token = TOK_LOGICAL_AND; p++; } else { rpmlog(RPMLOG_ERR, _("syntax error while parsing &&\n")); return -1; } break; case '|': if (p[1] == '|') { token = TOK_LOGICAL_OR; p++; } else { rpmlog(RPMLOG_ERR, _("syntax error while parsing ||\n")); return -1; } break; default: if (risdigit(*p)) { char *temp; size_t ts; for (ts=1; p[ts] && risdigit(p[ts]); ts++); temp = xmalloc(ts+1); memcpy(temp, p, ts); p += ts-1; temp[ts] = '\0'; token = TOK_INTEGER; v = valueMakeInteger(atoi(temp)); free(temp); } else if (risalpha(*p)) { char *temp; size_t ts; for (ts=1; p[ts] && (risalnum(p[ts]) || p[ts] == '_'); ts++); temp = xmalloc(ts+1); memcpy(temp, p, ts); p += ts-1; temp[ts] = '\0'; token = TOK_IDENTIFIER; v = valueMakeString(temp); } else if (*p == '\"') { char *temp; size_t ts; p++; for (ts=0; p[ts] && p[ts] != '\"'; ts++); temp = xmalloc(ts+1); memcpy(temp, p, ts); p += ts-1; temp[ts] = '\0'; p++; token = TOK_STRING; v = valueMakeString( rpmExpand(temp, NULL) ); free(temp); } else { rpmlog(RPMLOG_ERR, _("parse error in expression\n")); return -1; } } state->p = p + 1; state->nextToken = token; state->tokenValue = v; DEBUG(printf("rdToken: \"%s\" (%d)\n", prToken(token), token)); DEBUG(valueDump("rdToken:", state->tokenValue, stdout)); return 0; }