]>
Commit | Line | Data |
---|---|---|
70252337 | 1 | /* |
70252337 | 2 | * Prints out following information in same format as %dump for builder: |
3e262c69 ER |
3 | * $ rpmbuild --nodigest --nosignature --nobuild -bp --define 'prep %{echo:dummy: PACKAGE_NAME %{name} }%dump' qemu.spec 2>&1 | awk '$2 ~ /^SOURCEURL/ {print} $2 ~ /^PATCHURL/ {print} $2 ~ /^nosource/ {print} $2 ~ /^PACKAGE_/ {print}' |
4 | * dummy: PACKAGE_NAME qemu ======================== | |
5 | * -2: PACKAGE_RELEASE 60@2.6.16.59_2 | |
6 | * -1: PACKAGE_VERSION 1.3.0pre11 | |
7 | * -3: PATCHURL0 qemu-nostatic.patch | |
8 | * -3: PATCHURL1 qemu-cc.patch | |
9 | * -3: PATCHURL11 qemu-0.7.2-gcc4-opts.patch | |
10 | * -3: PATCHURL13 qemu-dosguest.patch | |
11 | * -3: PATCHURL3 qemu-dot.patch | |
12 | * -3: PATCHURL4 qemu-gcc4_x86.patch | |
13 | * -3: PATCHURL5 qemu-gcc4_ppc.patch | |
14 | * -3: PATCHURL6 qemu-nosdlgui.patch | |
15 | * -3: PATCHURL8 qemu-kde_virtual_workspaces_hack.patch | |
16 | * -3: PATCHURL9 qemu-0.8.0-gcc4-hacks.patch | |
17 | * -3: SOURCEURL0 http://fabrice.bellard.free.fr/qemu/qemu-0.9.0.tar.gz | |
18 | * -3: SOURCEURL1 http://fabrice.bellard.free.fr/qemu/kqemu-1.3.0pre11.tar.gz | |
846d963b | 19 | * -3: url http://rpm5.org/ |
70252337 ER |
20 | * |
21 | * $ rpm-specdump qemu.spec | |
22 | * h PACKAGE_NAME qemu | |
23 | * h PACKAGE_VERSION 0.9.0 | |
24 | * h PACKAGE_RELEASE 60k | |
afa4a282 ER |
25 | * s PATCHURL13 qemu-dosguest.patch |
26 | * s PATCHURL11 qemu-0.7.2-gcc4-opts.patch | |
27 | * s PATCHURL9 qemu-0.8.0-gcc4-hacks.patch | |
28 | * s PATCHURL8 qemu-kde_virtual_workspaces_hack.patch | |
29 | * s PATCHURL6 qemu-nosdlgui.patch | |
30 | * s PATCHURL5 qemu-gcc4_ppc.patch | |
31 | * s PATCHURL4 qemu-gcc4_x86.patch | |
32 | * s PATCHURL3 qemu-dot.patch | |
33 | * s PATCHURL1 qemu-cc.patch | |
34 | * s PATCHURL0 qemu-nostatic.patch | |
70252337 | 35 | * s SOURCEURL1 http://fabrice.bellard.free.fr/qemu/kqemu-1.3.0pre11.tar.gz |
70252337 ER |
36 | * s SOURCEURL0 http://fabrice.bellard.free.fr/qemu/qemu-0.9.0.tar.gz |
37 | * | |
c4820126 ER |
38 | * And with NoSource: 1, NoSource: 2 |
39 | * | |
ebbdedf5 ER |
40 | * $ rpmbuild --nodigest --nosignature --nobuild -bp --define 'prep %{echo:dummy: PACKAGE_NAME %{name} }%dump' ZendDebugger.spec 2>&1 | awk '$2 ~ /^SOURCEURL/ {print} $2 ~ /^PATCHURL/ {print} $2 ~ /^nosource/ {print} $2 ~ /^PACKAGE_/ {print}' |
41 | * dummy: PACKAGE_NAME ZendDebugger ======================== | |
42 | * -2: PACKAGE_RELEASE 0.4 | |
43 | * -1: PACKAGE_VERSION 5.2.10 | |
44 | * -3: SOURCEURL0 http://downloads.zend.com/pdt/server-debugger/ZendDebugger-5.2.10-linux-glibc21-i386.tar.gz | |
45 | * -3: SOURCEURL1 http://downloads.zend.com/pdt/server-debugger/ZendDebugger-5.2.10-linux-glibc23-x86_64.tar.gz | |
46 | * -3: nosource 1 | |
47 | * | |
48 | * $ rpm-specdump ZendDebugger.spec | |
c4820126 ER |
49 | * h PACKAGE_NAME ZendDebugger |
50 | * h PACKAGE_VERSION 5.2.10 | |
51 | * h PACKAGE_RELEASE 0.4 | |
c4820126 ER |
52 | * s SOURCEURL1 http://downloads.zend.com/pdt/server-debugger/ZendDebugger-5.2.10-linux-glibc23-x86_64.tar.gz |
53 | * s nosource 1 | |
c4820126 ER |
54 | * s SOURCEURL0 http://downloads.zend.com/pdt/server-debugger/ZendDebugger-5.2.10-linux-glibc21-i386.tar.gz |
55 | * s nosource 0 | |
56 | * | |
3e262c69 ER |
57 | * Compile with: |
58 | * gcc -lrpm -I/usr/include/rpm -lrpmbuild rpm-specdump.c -o rpm-specdump | |
59 | * | |
70252337 ER |
60 | * Version 0.1, 2008-01-23 |
61 | * - initial version, based on getdeps.c | |
62 | */ | |
63 | ||
70252337 ER |
64 | #define _GNU_SOURCE |
65 | ||
66 | #ifdef HAVE_CONFIG_H | |
67 | # include <config.h> | |
68 | #endif | |
69 | ||
70 | #include <getopt.h> | |
71 | #include <stdbool.h> | |
72 | #include <string.h> | |
73 | #include <assert.h> | |
74 | #include <unistd.h> | |
39a1b19c | 75 | #include <stdint.h> |
70252337 ER |
76 | #include <grp.h> |
77 | #include <sys/time.h> | |
78 | #include <sys/types.h> | |
79 | ||
96ef6911 JR |
80 | // macros from kernel |
81 | #define RPM_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) | |
82 | ||
74900489 | 83 | #define RPM_VERSION_CODE RPM_VERSION(RPM_FORMAT_VERSION, RPM_MAJOR_VERSION, RPM_MINOR_VERSION) |
96ef6911 | 84 | |
010d09dd | 85 | #include <rpmio.h> |
70252337 | 86 | #include <rpmbuild.h> |
96ef6911 | 87 | #if RPM_VERSION_CODE < RPM_VERSION(5,4,0) |
70252337 | 88 | #include <rpmlib.h> |
96ef6911 | 89 | #endif |
8e46eae6 | 90 | #if RPM_VERSION_CODE < RPM_VERSION(5,0,0) |
70252337 | 91 | #include <header.h> |
8e46eae6 | 92 | #endif |
70252337 ER |
93 | #include <rpmts.h> |
94 | ||
95 | #define ARG_WITH 1024 | |
96 | #define ARG_WITHOUT 1025 | |
97 | #define ARG_DEFINE 1026 | |
98 | #define ARG_TARGET 1027 | |
99 | #define ARG_RCFILE 1028 | |
100 | #define ARG_CHROOT 1029 | |
101 | #define ARG_UID 1030 | |
102 | #define ARG_GID 1031 | |
103 | ||
96ef6911 JR |
104 | #if !defined(EXIT_FAILURE) |
105 | # define EXIT_FAILURE 1 | |
106 | #endif | |
107 | ||
70252337 ER |
108 | static struct option const |
109 | CMDLINE_OPTIONS[] = { | |
110 | { "help", no_argument, 0, 'h' }, | |
111 | { "version", no_argument, 0, 'v' }, | |
112 | { "with", required_argument, 0, ARG_WITH }, | |
113 | { "without", required_argument, 0, ARG_WITHOUT }, | |
114 | { "define", required_argument, 0, ARG_DEFINE }, | |
115 | { "target", required_argument, 0, ARG_TARGET }, | |
116 | { "rcfile", required_argument, 0, ARG_RCFILE }, | |
117 | { "chroot", required_argument, 0, ARG_CHROOT }, | |
118 | { "uid", required_argument, 0, ARG_UID }, | |
119 | { "gid", required_argument, 0, ARG_GID }, | |
120 | { 0,0,0,0 } | |
121 | }; | |
122 | ||
123 | struct Arguments | |
124 | { | |
125 | char const * target; | |
126 | char const * rcfile; | |
127 | char const * chroot; | |
128 | uid_t uid; | |
129 | gid_t gid; | |
130 | ||
131 | struct { | |
132 | char const ** values; | |
133 | size_t cnt; | |
134 | size_t reserved; | |
135 | } macros; | |
136 | ||
137 | char const * specfile; | |
138 | }; | |
139 | ||
140 | struct DepSet { | |
141 | int32_t const * flags; | |
142 | char const ** name; | |
143 | char const ** version; | |
144 | ssize_t cnt; | |
145 | }; | |
146 | ||
147 | inline static void | |
148 | writeStr(int fd, char const *cmd) | |
149 | { | |
150 | (void)write(fd, cmd, strlen(cmd)); | |
151 | } | |
152 | ||
153 | #define WRITE_MSG(FD,X) (void)(write(FD,X,sizeof(X)-1)) | |
154 | #define WRITE_STR(FD,X) writeStr(FD,X) | |
155 | ||
156 | static void | |
157 | showHelp(int fd, char const *cmd, int res) | |
158 | { | |
159 | char tmp[strlen(cmd)+1]; | |
160 | strcpy(tmp, cmd); | |
161 | ||
162 | WRITE_MSG(fd, "Usage: "); | |
163 | WRITE_STR(fd, basename(tmp)); | |
164 | WRITE_MSG(fd, | |
165 | " [--define '<macro> <value>']* [--with[out] <key>]* [--chroot <dir>]\n" | |
166 | " [--target <target>] [--rcfile <rcfile>] [--] <specfile>\n"); | |
167 | exit(res); | |
168 | } | |
169 | ||
170 | static void | |
171 | addDefine(struct Arguments *args, char const *val) | |
172 | { | |
173 | register size_t c = args->macros.cnt; | |
174 | if (args->macros.reserved <= c) { | |
175 | args->macros.reserved *= 2; | |
176 | args->macros.reserved += 1; | |
177 | ||
178 | args->macros.values = realloc(args->macros.values, | |
179 | args->macros.reserved * sizeof(char const *)); | |
180 | if (args->macros.values==0) { | |
181 | perror("realloc()"); | |
182 | exit(1); | |
183 | } | |
184 | } | |
185 | ||
186 | args->macros.values[c] = strdup(val); | |
187 | ++args->macros.cnt; | |
188 | } | |
189 | ||
190 | static void | |
191 | setWithMacro(struct Arguments *args, | |
192 | char const *name, char const *prefix, size_t prefix_len) | |
193 | { | |
194 | size_t len = strlen(name); | |
195 | char tmp[2*len + 2*prefix_len + sizeof("__ ---")]; | |
196 | char * ptr = tmp; | |
197 | ||
198 | // set '_<prefix>_<name>' | |
199 | *ptr++ = '_'; | |
200 | memcpy(ptr, prefix, prefix_len); ptr += prefix_len; | |
201 | *ptr++ = '_'; | |
202 | memcpy(ptr, name, len); ptr += len; | |
203 | *ptr++ = ' '; | |
204 | ||
205 | // append ' --<prefix>-<name>' | |
206 | *ptr++ = '-'; | |
207 | *ptr++ = '-'; | |
208 | memcpy(ptr, prefix, prefix_len); ptr += prefix_len; | |
209 | *ptr++ = '-'; | |
210 | memcpy(ptr, name, len); ptr += len; | |
211 | *ptr = '\0'; | |
212 | ||
213 | addDefine(args, tmp); | |
214 | } | |
215 | ||
216 | ||
217 | static void | |
218 | parseArgs(struct Arguments *args, int argc, char *argv[]) | |
219 | { | |
220 | while (1) { | |
221 | int c = getopt_long(argc, argv, "", CMDLINE_OPTIONS, 0); | |
222 | if (c==-1) break; | |
223 | switch (c) { | |
74900489 | 224 | case 'h' : showHelp(1, argv[0], 0); break; |
70252337 ER |
225 | case ARG_TARGET : args->target = optarg; break; |
226 | case ARG_RCFILE : args->rcfile = optarg; break; | |
227 | case ARG_CHROOT : args->chroot = optarg; break; | |
228 | case ARG_UID : args->uid = atoi(optarg); break; | |
229 | case ARG_GID : args->gid = atoi(optarg); break; | |
230 | case ARG_DEFINE : addDefine(args, optarg); break; | |
231 | case ARG_WITH : setWithMacro(args, optarg, "with", 4); break; | |
232 | case ARG_WITHOUT : setWithMacro(args, optarg, "without", 7); break; | |
233 | default: | |
234 | WRITE_MSG(2, "Try '"); | |
235 | WRITE_STR(2, argv[0]); | |
236 | WRITE_MSG(2, " --help\" for more information.\n"); | |
237 | exit(1); | |
238 | } | |
239 | } | |
240 | ||
241 | if (optind+1!=argc) { | |
242 | write(2, "No/too much specfile(s) given; aborting\n", 40); | |
243 | exit(1); | |
244 | } | |
245 | ||
246 | if (args->gid==(gid_t)(-1)) | |
247 | args->gid = args->uid; | |
248 | ||
249 | args->specfile = argv[optind]; | |
250 | } | |
251 | ||
252 | static void | |
253 | setMacros(char const * const *macros, size_t cnt) | |
254 | { | |
255 | size_t i; | |
256 | for (i=0; i<cnt; ++i) | |
257 | rpmDefineMacro(rpmGlobalMacroContext, macros[i], 0); | |
258 | } | |
259 | ||
260 | int main(int argc, char *argv[]) | |
261 | { | |
262 | struct Arguments args = { 0,0,0,-1,-1, {0,0,0}, 0 }; | |
97634434 JR |
263 | #if RPM_VERSION_CODE < RPM_VERSION(5,0,0) |
264 | rpmSpec s; | |
265 | #else | |
70252337 | 266 | Spec s; |
97634434 | 267 | #endif |
70252337 | 268 | |
22c309c5 | 269 | addDefine(&args, "patch %{nil}"); |
0cf659b5 ER |
270 | |
271 | // instead of requiring rpm-build, we include some "builtin" macros | |
272 | addDefine(&args, "bcond_without() %{expand:%%{!?_without_%{1}:%%global with_%{1} 1}}"); | |
273 | addDefine(&args, "bcond_with() %{expand:%%{?_with_%{1}:%%global with_%{1} 1}}"); | |
274 | addDefine(&args, "with() %{expand:%%{?with_%{1}:1}%%{!?with_%{1}:0}}"); | |
275 | addDefine(&args, "without() %{expand:%%{?with_%{1}:0}%%{!?with_%{1}:1}}"); | |
276 | ||
277 | // include macros.perl, etc | |
278 | addDefine(&args, "include() %{nil}"); | |
279 | ||
70252337 ER |
280 | parseArgs(&args, argc, argv); |
281 | ||
282 | if ((args.chroot && chroot(args.chroot)==-1) || | |
283 | (args.uid!=(uid_t)(-1) && (setgroups(0,0) ==-1 || getgroups(0,0)!=0)) || | |
284 | (args.gid!=(gid_t)(-1) && (setgid(args.gid)==-1 || getgid()!=args.gid)) || | |
285 | (args.uid!=(uid_t)(-1) && (setuid(args.uid)==-1 || getuid()!=args.uid))) { | |
286 | ||
287 | perror("chroot/setuid/setgid()"); | |
288 | return EXIT_FAILURE; | |
289 | } | |
290 | ||
291 | rpmReadConfigFiles(args.rcfile, args.target); | |
292 | setMacros(args.macros.values, args.macros.cnt); | |
293 | ||
97634434 JR |
294 | // here starts the code for builder |
295 | const char *name = NULL, *version = NULL, *release = NULL, *summary = NULL, *url = NULL; | |
296 | ||
297 | #if RPM_VERSION_CODE < RPM_VERSION(5,0,0) | |
298 | #define GET_TAG(t) tag = t; rc = headerGet(h, tag, td, 0); | |
299 | #define TAG_VALUE rpmtdGetString(td) | |
300 | s = rpmSpecParse(args.specfile, 0, NULL); | |
301 | Header h = rpmSpecSourceHeader(s); | |
302 | rpmtd td = rpmtdNew(); | |
303 | rpmTagVal tag; | |
304 | #else | |
305 | #define GET_TAG(t) he->tag = (rpmTag)t; he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he)); rc = headerGet(h, he, 0); | |
306 | #define TAG_VALUE (char *)he->p.ptr | |
70252337 | 307 | rpmts ts = rpmtsCreate(); |
0d9e3461 | 308 | if (parseSpec(ts, args.specfile, NULL, 0, NULL, NULL, 1, 1, 0) != 0) { |
70252337 ER |
309 | return EXIT_FAILURE; |
310 | } | |
3e262c69 | 311 | |
97634434 | 312 | s = rpmtsSpec(ts); |
70252337 | 313 | |
ca058888 | 314 | Header h = s->sourceHeader; |
97634434 JR |
315 | HE_t he; |
316 | #endif | |
317 | int rc; | |
70252337 | 318 | |
97634434 JR |
319 | GET_TAG(RPMTAG_NAME); |
320 | if (!rc) { | |
321 | fprintf(stderr, "Name (NVR) query failed\n"); | |
70252337 ER |
322 | return EXIT_FAILURE; |
323 | } | |
97634434 | 324 | name = TAG_VALUE; |
70252337 | 325 | |
97634434 JR |
326 | GET_TAG(RPMTAG_VERSION); |
327 | if (!rc) { | |
328 | fprintf(stderr, "Version (NVR) query failed\n"); | |
329 | return EXIT_FAILURE; | |
330 | } | |
331 | version = TAG_VALUE; | |
332 | ||
333 | GET_TAG(RPMTAG_RELEASE); | |
334 | if (!rc) { | |
335 | fprintf(stderr, "Release (NVR) query failed\n"); | |
336 | return EXIT_FAILURE; | |
337 | } | |
338 | release = TAG_VALUE; | |
339 | ||
340 | GET_TAG(RPMTAG_SUMMARY); | |
341 | if (!rc) { | |
342 | fprintf(stderr, "Summary query failed\n"); | |
343 | return EXIT_FAILURE; | |
344 | } | |
345 | summary = TAG_VALUE; | |
346 | ||
347 | GET_TAG(RPMTAG_URL); | |
348 | if (rc) { | |
349 | // URL field is not required | |
350 | url = TAG_VALUE; | |
8e46eae6 | 351 | } |
8e46eae6 | 352 | |
70252337 ER |
353 | printf("h PACKAGE_NAME %s\n", name); |
354 | printf("h PACKAGE_VERSION %s\n", version); | |
355 | printf("h PACKAGE_RELEASE %s\n", release); | |
70252337 | 356 | |
8551a535 | 357 | printf("h PACKAGE_SUMMARY %s\n", summary); |
846d963b | 358 | printf("h url %s\n", url); |
8551a535 | 359 | |
97634434 JR |
360 | #if RPM_VERSION_CODE < RPM_VERSION(5,0,0) |
361 | rpmSpecSrcIter si = rpmSpecSrcIterInit(s); | |
362 | rpmSpecSrc ps; | |
363 | while ((ps = rpmSpecSrcIterNext(si)) != NULL) { | |
364 | const char *type = (rpmSpecSrcFlags(ps) & RPMBUILD_ISSOURCE) ? "SOURCE" : "PATCH"; | |
365 | printf("s %sURL%d %s\n", type, rpmSpecSrcNum(ps), rpmSpecSrcFilename(ps, 1)); | |
366 | if (rpmSpecSrcFlags(ps) & RPMBUILD_ISNO) { | |
367 | printf("s nosource %d\n", rpmSpecSrcNum(ps)); | |
368 | } | |
369 | } | |
370 | rpmSpecSrcIterFree(si); | |
371 | #else | |
70252337 ER |
372 | struct Source *ps = s->sources; |
373 | while (ps) { | |
374 | const char *type = (ps->flags & RPMFILE_SOURCE) ? "SOURCE" : "PATCH"; | |
afa4a282 | 375 | printf("s %sURL%d %s\n", type, ps->num, ps->fullSource); |
70252337 ER |
376 | if (ps->flags & RPMFILE_GHOST) { |
377 | printf("s nosource %d\n", ps->num); | |
378 | } | |
379 | ps = ps->next; | |
380 | } | |
97634434 | 381 | #endif |
70252337 | 382 | |
3e31d4b4 ER |
383 | const char *arch = rpmExpand("%{_target_cpu}", NULL); |
384 | printf("m _target_cpu %s\n", arch); | |
385 | ||
70252337 ER |
386 | return(0); |
387 | } |