Missed some unlinks() when scripts failed
[platform/upstream/rpm.git] / build / build.c
1 #include "config.h"
2
3 #ifdef HAVE_ALLOCA_A
4 #include <alloca.h>
5 #endif
6
7 #include <sys/types.h>
8 #include <sys/wait.h>
9 #include <sys/stat.h>
10 #include <stdlib.h>
11
12 #include "misc.h"
13 #include "spec.h"
14 #include "build.h"
15 #include "lib/misc.h"
16 #include "lib/messages.h"
17 #include "rpmlib.h"
18 #include "pack.h"
19 #include "files.h"
20
21 static void doRmSource(Spec spec);
22 static int writeVars(Spec spec, FILE *f);
23
24 int buildSpec(Spec spec, int what, int test)
25 {
26     int x, rc;
27
28     if (!spec->inBuildArchitectures && spec->buildArchitectureCount) {
29         /* When iterating over buildArchitectures, do the source    */
30         /* packaging on the first run, and skip RMSOURCE altogether */
31         x = 0;
32         while (x < spec->buildArchitectureCount) {
33             if ((rc = buildSpec(spec->buildArchitectureSpecs[x],
34                                 (what & ~RPMBUILD_RMSOURCE) |
35                                 (x ? 0 : (what & RPMBUILD_PACKAGESOURCE)),
36                                 test))) {
37                 return rc;
38             }
39             x++;
40         }
41     } else {
42         if (what & RPMBUILD_PREP) {
43             if ((rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test))) {
44                 return rc;
45             }
46         }
47         if (what & RPMBUILD_BUILD) {
48             if ((rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test))) {
49                 return rc;
50             }
51         }
52         if (what & RPMBUILD_INSTALL) {
53             if ((rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test))) {
54                 return rc;
55             }
56         }
57
58         if (what & RPMBUILD_PACKAGESOURCE) {
59             if ((rc = processSourceFiles(spec))) {
60                 return rc;
61             }
62         }
63
64         if ((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
65             (what & RPMBUILD_FILECHECK)) {
66             if ((rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL))) {
67                 return rc;
68             }
69         }
70
71         if (what & RPMBUILD_PACKAGESOURCE && !test) {
72             if ((rc = packageSources(spec))) {
73                 return rc;
74             }
75         }
76         if (what & RPMBUILD_PACKAGEBINARY && !test) {
77             if ((rc = packageBinaries(spec))) {
78                 return rc;
79             }
80         }
81         
82         if (what & RPMBUILD_CLEAN) {
83             if ((rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test))) {
84                 return rc;
85             }
86         }
87         if (what & RPMBUILD_RMBUILD) {
88             if ((rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test))) {
89                 return rc;
90             }
91         }
92     }
93
94     if (what & RPMBUILD_RMSOURCE) {
95         doRmSource(spec);
96     }
97
98     return 0;
99 }
100
101 int doScript(Spec spec, int what, char *name, StringBuf sb, int test)
102 {
103     int fd;
104     FILE *f;
105     char *scriptName;
106     int pid;
107     int status;
108     char *buildShell;
109     
110     switch (what) {
111       case RPMBUILD_PREP:
112         name = "%prep";
113         sb = spec->prep;
114         break;
115       case RPMBUILD_BUILD:
116         name = "%build";
117         sb = spec->build;
118         break;
119       case RPMBUILD_INSTALL:
120         name = "%install";
121         sb = spec->install;
122         break;
123       case RPMBUILD_CLEAN:
124         name = "%clean";
125         sb = spec->clean;
126         break;
127       case RPMBUILD_RMBUILD:
128         name = "--clean";
129         break;
130       case RPMBUILD_STRINGBUF:
131         break;
132     }
133     if ((what != RPMBUILD_RMBUILD) && !sb) {
134         return 0;
135     }
136     
137     if (makeTempFile(NULL, &scriptName, &fd)) {
138         rpmError(RPMERR_SCRIPT, "Unable to open temp file");
139         return RPMERR_SCRIPT;
140     }
141     f = fdopen(fd, "w");
142     
143     if (writeVars(spec, f)) {
144         fclose(f);
145         unlink(scriptName);
146         FREE(scriptName);
147         return RPMERR_SCRIPT;
148     }
149     
150     fprintf(f, rpmIsVerbose() ? "set -x\n\n" : "exec > /dev/null\n\n");
151     fprintf(f, "umask 022\n");
152     fprintf(f, "cd %s\n", rpmGetVar(RPMVAR_BUILDDIR));
153     if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD) {
154         if (spec->buildSubdir) {
155             fprintf(f, "cd %s\n", spec->buildSubdir);
156         }
157     }
158     if (what == RPMBUILD_RMBUILD) {
159         if (spec->buildSubdir) {
160             fprintf(f, "rm -rf %s\n", spec->buildSubdir);
161         }
162     } else {
163         fprintf(f, "%s", getStringBuf(sb));
164     }
165     fprintf(f, "\nexit 0\n");
166     
167     fclose(f);
168     chmod(scriptName, 0600);
169
170     if (test) {
171         FREE(scriptName);
172         return 0;
173     }
174     
175     rpmMessage(RPMMESS_NORMAL, "Executing: %s\n", name);
176     if (!(pid = fork())) {
177         buildShell = rpmGetVar(RPMVAR_BUILDSHELL);
178         execl(buildShell, buildShell, "-e", scriptName, scriptName, NULL);
179         rpmError(RPMERR_SCRIPT, "Exec of %s failed (%s)",
180                  scriptName, name);
181         unlink(scriptName);
182         FREE(scriptName);
183         return RPMERR_SCRIPT;
184     }
185     wait(&status);
186     if (! WIFEXITED(status) || WEXITSTATUS(status)) {
187         rpmError(RPMERR_SCRIPT, "Bad exit status from %s (%s)",
188                  scriptName, name);
189         unlink(scriptName);
190         FREE(scriptName);
191         return RPMERR_SCRIPT;
192     }
193     
194     unlink(scriptName);
195     FREE(scriptName);
196
197     return 0;
198 }
199
200 static int writeVars(Spec spec, FILE *f)
201 {
202     char *arch, *os, *s;
203     
204     rpmGetArchInfo(&arch, NULL);
205     rpmGetOsInfo(&os, NULL);
206
207     fprintf(f, "RPM_SOURCE_DIR=\"%s\"\n", rpmGetVar(RPMVAR_SOURCEDIR));
208     fprintf(f, "RPM_BUILD_DIR=\"%s\"\n", rpmGetVar(RPMVAR_BUILDDIR));
209     fprintf(f, "RPM_DOC_DIR=\"%s\"\n", spec->docDir);
210     fprintf(f, "RPM_OPT_FLAGS=\"%s\"\n", rpmGetVar(RPMVAR_OPTFLAGS));
211     fprintf(f, "RPM_ARCH=\"%s\"\n", arch);
212     fprintf(f, "RPM_OS=\"%s\"\n", os);
213     fprintf(f, "export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_DOC_DIR "
214             "RPM_OPT_FLAGS RPM_ARCH RPM_OS\n");
215
216     if (spec->buildRoot) {
217         fprintf(f, "RPM_BUILD_ROOT=\"%s\"\n", spec->buildRoot);
218         fprintf(f, "export RPM_BUILD_ROOT\n");
219         /* This could really be checked internally */
220         fprintf(f, "if [ -z \"$RPM_BUILD_ROOT\" -o -z \"`echo $RPM_BUILD_ROOT | sed -e 's#/##g'`\" ]; then\n");
221         fprintf(f, "  echo 'Warning: Spec contains BuildRoot: tag that is either empty or is set to \"/\"'\n");
222         fprintf(f, "  exit 1\n");
223         fprintf(f, "fi\n");
224     }
225
226     headerGetEntry(spec->packages->header, RPMTAG_NAME,
227                    NULL, (void **)&s, NULL);
228     fprintf(f, "RPM_PACKAGE_NAME=\"%s\"\n", s);
229     headerGetEntry(spec->packages->header, RPMTAG_VERSION,
230                    NULL, (void **)&s, NULL);
231     fprintf(f, "RPM_PACKAGE_VERSION=\"%s\"\n", s);
232     headerGetEntry(spec->packages->header, RPMTAG_RELEASE,
233                    NULL, (void **)&s, NULL);
234     fprintf(f, "RPM_PACKAGE_RELEASE=\"%s\"\n", s);
235     fprintf(f, "export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION "
236             "RPM_PACKAGE_RELEASE\n");
237     
238     return 0;
239 }
240
241 static void doRmSource(Spec spec)
242 {
243     struct Source *p;
244     Package pkg;
245     char buf[BUFSIZ];
246     
247     unlink(spec->specFile);
248
249     p = spec->sources;
250     while (p) {
251         if (! (p->flags & RPMBUILD_ISNO)) {
252             sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), p->source);
253             unlink(buf);
254         }
255         p = p->next;
256     }
257
258     pkg = spec->packages;
259     while (pkg) {
260         p = pkg->icon;
261         while (p) {
262             if (! (p->flags & RPMBUILD_ISNO)) {
263                 sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), p->source);
264                 unlink(buf);
265             }
266             p = p->next;
267         }
268         pkg = pkg->next;
269     }
270 }