add %setup and %patch handling
authormarc <devnull@localhost>
Wed, 27 Dec 1995 16:54:54 +0000 (16:54 +0000)
committermarc <devnull@localhost>
Wed, 27 Dec 1995 16:54:54 +0000 (16:54 +0000)
add "really_exec" flag to execPart()

CVS patchset: 91
CVS date: 1995/12/27 16:54:54

build/build.c

index 01390bb..c83a7b9 100644 (file)
@@ -8,6 +8,9 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <limits.h>
 
 #include "build.h"
 #include "header.h"
@@ -18,6 +21,7 @@
 #include "messages.h"
 #include "stringbuf.h"
 #include "var.h"
+#include "misc.h"
 #include "pack.h"
 
 struct Script {
@@ -25,13 +29,20 @@ struct Script {
     FILE *file;
 };
 
-struct Script *openScript(Spec spec);
+struct Script *openScript(Spec spec, int builddir);
 void writeScript(struct Script *script, char *s);
 int execScript(struct Script *script);
 void freeScript(struct Script *script);
-int execPart(Spec s, char *sb, char *name);
+int execPart(Spec s, char *sb, char *name, int builddir);
+static int doSetupMacro(Spec spec, StringBuf sb, char *line);
+static int doPatchMacro(Spec spec, StringBuf sb, char *line);
+static char *do_untar(Spec spec, int c);
+static char *do_patch(Spec spec, int c, int strip, char *dashb);
+int isCompressed(char *file);
 
-struct Script *openScript(Spec spec)
+static char build_subdir[1024];
+
+struct Script *openScript(Spec spec, int builddir)
 {
     struct Script *script = malloc(sizeof(struct Script));
     struct PackageRec *main_package = spec->packages;
@@ -68,6 +79,12 @@ struct Script *openScript(Spec spec)
     fprintf(script->file, "RPM_PACKAGE_RELEASE=\"%s\"\n", s);
 
     fprintf(script->file, "\ncd %s\n\n", getVar(RPMVAR_BUILDDIR));
+    if (builddir) {
+       /* Need to cd to the actual build directory. */
+       /* Note that this means we have to parse the */
+       /* %prep section even if we aren't using it. */
+       fprintf(script->file, "cd %s\n\n", build_subdir);
+    }
 
     return script;
 }
@@ -109,36 +126,404 @@ void freeScript(struct Script *script)
     free(script);
 }
 
-int execPart(Spec s, char *sb, char *name)
+int execPart(Spec s, char *sb, char *name, int builddir)
 {
     struct Script *script;
 
-    script = openScript(s);
+    message(MESS_DEBUG, "RUNNING: %s\n", name);
+    script = openScript(s, builddir);
     writeScript(script, sb);
     execScript(script);
     freeScript(script);
     return 0;
 }
 
-int execPrep(Spec s)
+static int doSetupMacro(Spec spec, StringBuf sb, char *line)
+{
+    char *s, *s1, *version;
+    int opt_a, opt_b, opt_c, opt_D, opt_T;
+    char *opt_n;
+    char buf[1024];
+
+    opt_a = opt_b = -1;
+    opt_c = opt_T = opt_D = 0;
+    opt_n = NULL;
+    
+    strtok(line, " \t\n");  /* remove %setup */
+    while ((s = strtok(NULL, " \t\n"))) {
+       if (!strcmp(s, "-c")) {
+           opt_c = 1;
+       } else if (!strcmp(s, "-T")) {
+           opt_T = 1;
+       } else if (!strcmp(s, "-D")) {
+           opt_D = 1;
+       } else if (!strcmp(s, "-n")) {
+           /* dir name */
+           opt_n = strtok(NULL, " \t\n");
+           if (! opt_n) {
+               error(RPMERR_BADSPEC, "Need arg to %%setup -n");
+               return(RPMERR_BADSPEC);
+           }
+       } else if (!strcmp(s, "-a")) {
+           s = strtok(NULL, " \t\n");
+           if (! s) {
+               error(RPMERR_BADSPEC, "Need arg to %%setup -a");
+               return(RPMERR_BADSPEC);
+           }
+           s1 = NULL;
+           opt_a = strtoul(s, &s1, 10);
+           if ((*s1) || (s1 == s) || (opt_a == ULONG_MAX)) {
+               error(RPMERR_BADSPEC, "Bad arg to %%setup -a: %s", s);
+               return(RPMERR_BADSPEC);
+           }
+       } else if (!strcmp(s, "-b")) {
+           s = strtok(NULL, " \t\n");
+           if (! s) {
+               error(RPMERR_BADSPEC, "Need arg to %%setup -b");
+               return(RPMERR_BADSPEC);
+           }
+           s1 = NULL;
+           opt_b = strtoul(s, &s1, 10);
+           if ((*s1) || (s1 == s) || (opt_b == ULONG_MAX)) {
+               error(RPMERR_BADSPEC, "Bad arg to %%setup -b: %s", s);
+               return(RPMERR_BADSPEC);
+           }
+       } else {
+           error(RPMERR_BADSPEC, "Bad arg to %%setup: %s", s);
+           return(RPMERR_BADSPEC);
+       }
+    }
+
+    /* All args parsed */
+#if 0
+    printf("a = %d\n", opt_a);
+    printf("b = %d\n", opt_b);
+    printf("c = %d\n", opt_c);
+    printf("T = %d\n", opt_T);
+    printf("D = %d\n", opt_D);
+    printf("n = %s\n", opt_n);
+#endif
+
+    if (opt_n) {
+       strcpy(build_subdir, opt_n);
+    } else {
+       strcpy(build_subdir, spec->name);
+       strcat(build_subdir, "-");
+       /* We should already have a version field */
+       getEntry(spec->packages->header, RPMTAG_VERSION, NULL,
+                (void *) &version, NULL);
+       strcat(build_subdir, version);
+    }
+    
+    /* cd to the build dir */
+    sprintf(buf, "cd %s", getVar(RPMVAR_BUILDDIR));
+    appendLineStringBuf(sb, buf);
+    
+    /* delete any old sources */
+    if (! opt_D) {
+       sprintf(buf, "rm -rf %s", build_subdir);
+       appendLineStringBuf(sb, buf);
+    }
+
+    /* if necessary, create and cd into the proper dir */
+    if (opt_c) {
+       sprintf(buf, "mkdir -p %s\ncd %s", build_subdir, build_subdir);
+       appendLineStringBuf(sb, buf);
+    }
+
+    /* do the default action */
+    if ((! opt_c) && (! opt_T)) {
+       s = do_untar(spec, 0);
+       if (! s) {
+           return 1;
+       }
+       appendLineStringBuf(sb, s);
+    }
+
+    /* do any before action */
+    if (opt_b > -1) {
+       s = do_untar(spec, opt_b);
+       if (! s) {
+           return 1;
+       }
+       appendLineStringBuf(sb, s);
+    }
+    
+    /* cd into the build subdir */
+    if (opt_c) {
+       sprintf(buf, "cd %s", build_subdir);
+       appendLineStringBuf(sb, buf);
+    }
+
+    if (opt_c && (! opt_T)) {
+       s = do_untar(spec, 0);
+       if (! s) {
+           return 1;
+       }
+       appendLineStringBuf(sb, s);
+    }
+    
+    /* do any after action */
+    if (opt_a > -1) {
+       s = do_untar(spec, opt_a);
+       if (! s) {
+           return 1;
+       }
+       appendLineStringBuf(sb, s);
+    }
+
+    /* clean up permissions etc */
+    sprintf(buf, "cd %s/%s", getVar(RPMVAR_BUILDDIR), build_subdir);
+    appendLineStringBuf(sb, buf);
+    /* XXX - should check if root here first */
+    strcpy(buf, "chown -R root.root .");
+    appendLineStringBuf(sb, buf);
+    strcpy(buf, "chmod -R a+rX,g-w,o-w .");
+    appendLineStringBuf(sb, buf);
+    
+    return 0;
+}
+
+int isCompressed(char *file)
+{
+    int fd;
+    unsigned char magic[4];
+
+    fd = open(file, O_RDONLY);
+    read(fd, magic, 4);
+    close(fd);
+
+    if (((magic[0] == 0037) && (magic[1] == 0213)) ||  /* gzip */
+       ((magic[0] == 0037) && (magic[1] == 0236)) ||  /* old gzip */
+       ((magic[0] == 0037) && (magic[1] == 0036)) ||  /* pack */
+       ((magic[0] == 0037) && (magic[1] == 0240)) ||  /* SCO lzh */
+       ((magic[0] == 0037) && (magic[1] == 0235)) ||  /* compress */
+       ((magic[0] == 0120) && (magic[1] == 0113) &&
+        (magic[2] == 0003) && (magic[3] == 0004))     /* pkzip */
+       ) {
+       return 1;
+    }
+
+    return 0;
+}
+
+static char *do_untar(Spec spec, int c)
+{
+    static char buf[1024];
+    static char file[1024];
+    char *s, *taropts;
+    struct sources *sp;
+
+    s = NULL;
+    sp = spec->sources;
+    while (sp) {
+       if ((sp->ispatch == 0) && (sp->num == c)) {
+           s = sp->source;
+           break;
+       }
+       sp = sp->next;
+    }
+    if (! s) {
+       error(RPMERR_BADSPEC, "No source number %d", c);
+       return NULL;
+    }
+
+    sprintf(file, "%s/%s", getVar(RPMVAR_SOURCEDIR), s);
+    taropts = (isVerbose() ? "-xvvf" : "-xf");
+    
+    if (isCompressed(file)) {
+       sprintf(buf,
+               "gzip -dc %s | tar %s -\n"
+               "if [ $? -ne 0 ]; then\n"
+               "  exit $?\n"
+               "fi",
+               file, taropts);
+    } else {
+       sprintf(buf, "tar %s %s", taropts, file);
+    }
+
+    return buf;
+}
+
+static char *do_patch(Spec spec, int c, int strip, char *db)
+{
+    static char buf[1024];
+    static char file[1024];
+    static char dashb[1024];
+    char *s;
+    struct sources *sp;
+
+    s = NULL;
+    sp = spec->sources;
+    while (sp) {
+       if ((sp->ispatch == 1) && (sp->num == c)) {
+           s = sp->source;
+           break;
+       }
+       sp = sp->next;
+    }
+    if (! s) {
+       error(RPMERR_BADSPEC, "No patch number %d", c);
+       return NULL;
+    }
+
+    sprintf(file, "%s/%s", getVar(RPMVAR_SOURCEDIR), s);
+
+    if (db) {
+       sprintf(dashb, "-b %s", db);
+    } else {
+       strcpy(dashb, "");
+    }
+    
+    if (isCompressed(file)) {
+       sprintf(buf,
+               "gzip -dc %s | patch -p%d %s -s\n"
+               "if [ $? -ne 0 ]; then\n"
+               "  exit $?\n"
+               "fi",
+               file, strip, dashb);
+    } else {
+       sprintf(buf, "patch -p%d %s -s < %s", strip, dashb, file);
+    }
+
+    return buf;
+}
+
+static int doPatchMacro(Spec spec, StringBuf sb, char *line)
+{
+    char *opt_b;
+    int opt_P, opt_p;
+    char *s, *s1;
+    char buf[1024];
+    int patch_nums[1024];  /* XXX - we can only handle 1024 patches! */
+    int patch_index, x;
+
+    opt_P = opt_p = 0;
+    opt_b = NULL;
+    patch_index = 0;
+
+    if (! index(" \t\n", line[6])) {
+       /* %patchN */
+       sprintf(buf, "%%patch -P %s", line + 6);
+    } else {
+       strcpy(buf, line);
+    }
+    
+    strtok(buf, " \t\n");  /* remove %patch */
+    while ((s = strtok(NULL, " \t\n"))) {
+       if (!strcmp(s, "-P")) {
+           opt_P = 1;
+       } else if (!strcmp(s, "-b")) {
+           /* orig suffix */
+           opt_b = strtok(NULL, " \t\n");
+           if (! opt_b) {
+               error(RPMERR_BADSPEC, "Need arg to %%patch -b");
+               return(RPMERR_BADSPEC);
+           }
+       } else if (!strncmp(s, "-p", 2)) {
+           /* unfortunately, we must support -pX */
+           if (! index(" \t\n", s[2])) {
+               s = s + 2;
+           } else {
+               s = strtok(NULL, " \t\n");
+               if (! s) {
+                   error(RPMERR_BADSPEC, "Need arg to %%patch -p");
+                   return(RPMERR_BADSPEC);
+               }
+           }
+           s1 = NULL;
+           opt_p = strtoul(s, &s1, 10);
+           if ((*s1) || (s1 == s) || (opt_p == ULONG_MAX)) {
+               error(RPMERR_BADSPEC, "Bad arg to %%patch -p: %s", s);
+               return(RPMERR_BADSPEC);
+           }
+       } else {
+           /* Must be a patch num */
+           if (patch_index == 1024) {
+               error(RPMERR_BADSPEC, "Too many patches!");
+               return(RPMERR_BADSPEC);
+           }
+           s1 = NULL;
+           patch_nums[patch_index] = strtoul(s, &s1, 10);
+           if ((*s1) || (s1 == s) || (patch_nums[patch_index] == ULONG_MAX)) {
+               error(RPMERR_BADSPEC, "Bad arg to %%patch: %s", s);
+               return(RPMERR_BADSPEC);
+           }
+           patch_index++;
+       }
+    }
+
+    /* All args processed */
+
+    if (! opt_P) {
+       s = do_patch(spec, 0, opt_p, opt_b);
+       if (! s) {
+           return 1;
+       }
+       appendLineStringBuf(sb, s);
+    }
+
+    x = 0;
+    while (x < patch_index) {
+       s = do_patch(spec, patch_nums[x], opt_p, opt_b);
+       if (! s) {
+           return 1;
+       }
+       appendLineStringBuf(sb, s);
+       x++;
+    }
+    
+    return 0;
+}
+
+int execPrep(Spec s, int really_exec)
 {
-    /* XXX Expand %setup and %patch macros here */
-    return execPart(s, getStringBuf(s->prep), "%prep");
+    char **lines, **lines1, *p;
+    StringBuf out;
+    int res;
+
+    out = newStringBuf();
+    
+    p = getStringBuf(s->prep);
+    lines = splitString(p, strlen(p), '\n');
+    lines1 = lines;
+    while (*lines) {
+       if (! strncasecmp(*lines, "%setup", 6)) {
+           if (doSetupMacro(s, out, *lines)) {
+               return 1;
+           }
+       } else if (! strncasecmp(*lines, "%patch", 6)) {
+           if (doPatchMacro(s, out, *lines)) {
+               return 1;
+           }
+       } else {
+           appendLineStringBuf(out, *lines);
+       }
+       lines++;
+    }
+
+    freeSplitString(lines1);
+    res = 0;
+    if (really_exec) {
+       res = execPart(s, getStringBuf(out), "%prep", 0);
+    }
+    freeStringBuf(out);
+    return res;
 }
 
 int execBuild(Spec s)
 {
-    return execPart(s, getStringBuf(s->build), "%build");
+    return execPart(s, getStringBuf(s->build), "%build", 1);
 }
 
 int execInstall(Spec s)
 {
-    return execPart(s, getStringBuf(s->install), "%install");
+    return execPart(s, getStringBuf(s->install), "%install", 1);
 }
 
 int execClean(Spec s)
 {
-    return execPart(s, getStringBuf(s->clean), "%clean");
+    return execPart(s, getStringBuf(s->clean), "%clean", 1);
 }
 
 int verifyList(Spec s)
@@ -155,10 +540,9 @@ int doBuild(Spec s, int flags)
        }
     }
 
-    if (flags & RPMBUILD_PREP) {
-       if (execPrep(s)) {
-           return 1;
-       }
+    /* We always need to parse the %prep section */
+    if (execPrep(s, (flags & RPMBUILD_PREP))) {
+       return 1;
     }
 
     if (flags & RPMBUILD_BUILD) {