Permit file objects in python header constructor
[platform/upstream/rpm.git] / build / parseSpec.c
index 833eae0..3c5349d 100644 (file)
 #define SKIPSPACE(s) { while (*(s) && risspace(*(s))) (s)++; }
 #define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; }
 
-/* XXX FIXME: strlen for these is calculated at runtime, preventing const */
-static struct PartRec {
+#define LEN_AND_STR(_tag) (sizeof(_tag)-1), (_tag)
+
+static const struct PartRec {
     int part;
     size_t len;
     const char * token;
-} partList[] = {
-    { PART_PREAMBLE,      0, "%package"},
-    { PART_PREP,          0, "%prep"},
-    { PART_BUILD,         0, "%build"},
-    { PART_INSTALL,       0, "%install"},
-    { PART_CHECK,         0, "%check"},
-    { PART_CLEAN,         0, "%clean"},
-    { PART_PREUN,         0, "%preun"},
-    { PART_POSTUN,        0, "%postun"},
-    { PART_PRETRANS,      0, "%pretrans"},
-    { PART_POSTTRANS,     0, "%posttrans"},
-    { PART_PRE,           0, "%pre"},
-    { PART_POST,          0, "%post"},
-    { PART_FILES,         0, "%files"},
-    { PART_CHANGELOG,     0, "%changelog"},
-    { PART_DESCRIPTION,   0, "%description"},
-    { PART_TRIGGERPOSTUN, 0, "%triggerpostun"},
-    { PART_TRIGGERPREIN,  0, "%triggerprein"},
-    { PART_TRIGGERUN,     0, "%triggerun"},
-    { PART_TRIGGERIN,     0, "%triggerin"},
-    { PART_TRIGGERIN,     0, "%trigger"},
-    { PART_VERIFYSCRIPT,  0, "%verifyscript"},
+} const partList[] = {
+    { PART_PREAMBLE,      LEN_AND_STR("%package")},
+    { PART_PREP,          LEN_AND_STR("%prep")},
+    { PART_BUILD,         LEN_AND_STR("%build")},
+    { PART_INSTALL,       LEN_AND_STR("%install")},
+    { PART_CHECK,         LEN_AND_STR("%check")},
+    { PART_CLEAN,         LEN_AND_STR("%clean")},
+    { PART_PREUN,         LEN_AND_STR("%preun")},
+    { PART_POSTUN,        LEN_AND_STR("%postun")},
+    { PART_PRETRANS,      LEN_AND_STR("%pretrans")},
+    { PART_POSTTRANS,     LEN_AND_STR("%posttrans")},
+    { PART_PRE,           LEN_AND_STR("%pre")},
+    { PART_POST,          LEN_AND_STR("%post")},
+    { PART_FILES,         LEN_AND_STR("%files")},
+    { PART_CHANGELOG,     LEN_AND_STR("%changelog")},
+    { PART_DESCRIPTION,   LEN_AND_STR("%description")},
+    { PART_TRIGGERPOSTUN, LEN_AND_STR("%triggerpostun")},
+    { PART_TRIGGERPREIN,  LEN_AND_STR("%triggerprein")},
+    { PART_TRIGGERUN,     LEN_AND_STR("%triggerun")},
+    { PART_TRIGGERIN,     LEN_AND_STR("%triggerin")},
+    { PART_TRIGGERIN,     LEN_AND_STR("%trigger")},
+    { PART_VERIFYSCRIPT,  LEN_AND_STR("%verifyscript")},
     {0, 0, 0}
 };
 
-/**
- */
-static inline void initParts(struct PartRec *p)
-{
-    for (; p->token != NULL; p++)
-       p->len = strlen(p->token);
-}
-
 rpmParseState isPart(const char *line)
 {
-    struct PartRec *p;
+    const 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))
@@ -139,7 +129,7 @@ static int copyNextLineFromOFI(rpmSpec spec, OFI_t *ofi)
        to = spec->lbufPtr ? spec->lbufPtr : spec->lbuf;
        from = ofi->readPtr;
        ch = ' ';
-       while (*from && ch != '\n')
+       while (from && *from && ch != '\n')
            ch = *to++ = *from++;
        spec->lbufPtr = to;
        *to++ = '\0';
@@ -299,29 +289,29 @@ int readLine(rpmSpec spec, int strip)
     SKIPSPACE(s);
 
     match = -1;
-    if (!spec->readStack->reading && !strncmp("%if", s, sizeof("%if")-1)) {
+    if (!spec->readStack->reading && rstreqn("%if", s, sizeof("%if")-1)) {
        match = 0;
-    } else if (! strncmp("%ifarch", s, sizeof("%ifarch")-1)) {
+    } 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 (! strncmp("%ifnarch", s, sizeof("%ifnarch")-1)) {
+    } 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 (! strncmp("%ifos", s, sizeof("%ifos")-1)) {
+    } 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 (! strncmp("%ifnos", s, sizeof("%ifnos")-1)) {
+    } 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 (! strncmp("%if", s, sizeof("%if")-1)) {
+    } else if (rstreqn("%if", s, sizeof("%if")-1)) {
        s += 3;
         match = parseExpressionBoolean(spec, s);
        if (match < 0) {
@@ -330,7 +320,7 @@ int readLine(rpmSpec spec, int strip)
                        ofi->fileName, ofi->lineNum, match);
            return PART_ERROR;
        }
-    } else if (! strncmp("%else", s, sizeof("%else")-1)) {
+    } else if (rstreqn("%else", s, sizeof("%else")-1)) {
        s += 5;
        if (! spec->readStack->next) {
            /* Got an else with no %if ! */
@@ -342,7 +332,7 @@ int readLine(rpmSpec spec, int strip)
        spec->readStack->reading =
            spec->readStack->next->reading && ! spec->readStack->reading;
        spec->line[0] = '\0';
-    } else if (! strncmp("%endif", s, sizeof("%endif")-1)) {
+    } else if (rstreqn("%endif", s, sizeof("%endif")-1)) {
        s += 6;
        if (! spec->readStack->next) {
            /* Got an end with no %if ! */
@@ -355,7 +345,7 @@ int readLine(rpmSpec spec, int strip)
        spec->readStack = spec->readStack->next;
        free(rl);
        spec->line[0] = '\0';
-    } else if (! strncmp("%include", s, sizeof("%include")-1)) {
+    } else if (rstreqn("%include", s, sizeof("%include")-1)) {
        char *fileName, *endFileName, *p;
 
        s += 8;
@@ -424,28 +414,14 @@ int parseSpec(rpmts ts, const char *specFile, const char *rootDir,
     /* Set up a new Spec structure with no packages. */
     spec = newSpec();
 
-    /*
-     * Note: rpmGetPath should guarantee a "canonical" path. That means
-     * that the following pathologies should be weeded out:
-     *          //bin//sh
-     *          //usr//bin/
-     *          /.././../usr/../bin//./sh (XXX FIXME: dots not handled yet)
-     */
     spec->specFile = rpmGetPath(specFile, NULL);
     spec->fileStack = newOpenFileInfo();
     spec->fileStack->fileName = xstrdup(spec->specFile);
+    /* If buildRoot not specified, use default %{buildroot} */
     if (buildRoot) {
-       if (*buildRoot == '\0') {
-           rpmlog(RPMLOG_ERR, _("BuildRoot couldn't be empty\n"));
-           goto errxit;
-       }
-       if (!strcmp(buildRoot, "/")) {
-           rpmlog(RPMLOG_ERR, _("BuildRoot can not be \"/\"\n"));
-           goto errxit;
-        }
-       spec->gotBuildRoot = 1;
        spec->buildRoot = xstrdup(buildRoot);
-       addMacro(spec->macros, "buildroot", NULL, buildRoot, RMIL_SPEC);
+    } else {
+       spec->buildRoot = rpmGetPath("%{?buildroot:%{buildroot}}", NULL);
     }
     addMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC);
     spec->recursing = recursing;
@@ -465,7 +441,6 @@ int parseSpec(rpmts ts, const char *specFile, const char *rootDir,
     /* in the spec's line buffer.  Except for parsePreamble(),   */
     /* which handles the initial entry into a spec file.         */
     
-       /* LCL: parsePart is modified @*/
     while (parsePart != PART_NONE) {
        int goterror = 0;
        switch (parsePart) {
@@ -531,7 +506,6 @@ int parseSpec(rpmts ts, const char *specFile, const char *rootDir,
 
            closeSpec(spec);
 
-           /* LCL: sizeof(spec->BASpecs[0]) -nullderef whine here */
            spec->BASpecs = xcalloc(spec->BACount, sizeof(*spec->BASpecs));
            index = 0;
            if (spec->BANames != NULL)
@@ -580,7 +554,13 @@ int parseSpec(rpmts ts, const char *specFile, const char *rootDir,
            return 0;
        }
     }
-       /* LCL: parsePart is modified @*/
+
+    if (spec->clean == NULL) {
+       char *body = rpmExpand("%{?buildroot: %{__rm} -rf %{buildroot}}", NULL);
+       spec->clean = newStringBuf();
+       appendLineStringBuf(spec->clean, body);
+       free(body);
+    }
 
     /* Check for description in each package and add arch and os */
   {
@@ -590,14 +570,16 @@ int parseSpec(rpmts ts, const char *specFile, const char *rootDir,
 
     for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
        if (!headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) {
-           const char * name;
-           (void) headerNVR(pkg->header, &name, NULL, NULL);
-           rpmlog(RPMLOG_ERR, _("Package has no %%description: %s\n"), name);
+           rpmlog(RPMLOG_ERR, _("Package has no %%description: %s\n"),
+                  headerGetString(pkg->header, RPMTAG_NAME));
            goto errxit;
        }
 
        headerPutString(pkg->header, RPMTAG_OS, os);
-       headerPutString(pkg->header, RPMTAG_ARCH, arch);
+       /* noarch subpackages already have arch set here, leave it alone */
+       if (!headerIsEntry(pkg->header, RPMTAG_ARCH)) {
+           headerPutString(pkg->header, RPMTAG_ARCH, arch);
+       }
        headerPutString(pkg->header, RPMTAG_PLATFORM, platform);
 
        pkg->ds = rpmdsThis(pkg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);