2 * Prints out following information in same format as %dump for builder:
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
19 * -3: url http://rpm5.org/
21 * $ rpm-specdump qemu.spec
23 * h PACKAGE_VERSION 0.9.0
24 * h PACKAGE_RELEASE 60k
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
35 * s SOURCEURL1 http://fabrice.bellard.free.fr/qemu/kqemu-1.3.0pre11.tar.gz
36 * s SOURCEURL0 http://fabrice.bellard.free.fr/qemu/qemu-0.9.0.tar.gz
38 * And with NoSource: 1, NoSource: 2
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
48 * $ rpm-specdump ZendDebugger.spec
49 * h PACKAGE_NAME ZendDebugger
50 * h PACKAGE_VERSION 5.2.10
51 * h PACKAGE_RELEASE 0.4
52 * s SOURCEURL1 http://downloads.zend.com/pdt/server-debugger/ZendDebugger-5.2.10-linux-glibc23-x86_64.tar.gz
54 * s SOURCEURL0 http://downloads.zend.com/pdt/server-debugger/ZendDebugger-5.2.10-linux-glibc21-i386.tar.gz
58 * gcc -lrpm -I/usr/include/rpm -lrpmbuild rpm-specdump.c -o rpm-specdump
60 * Version 0.1, 2008-01-23
61 * - initial version, based on getdeps.c
78 #include <sys/types.h>
81 #define RPM_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
83 #define RPM_VERSION_CODE RPM_VERSION(RPM_FORMAT_VERSION, RPM_MAJOR_VERSION, RPM_MINOR_VERSION)
87 #if RPM_VERSION_CODE < RPM_VERSION(5,4,0)
90 #if RPM_VERSION_CODE < RPM_VERSION(5,0,0)
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
104 #if !defined(EXIT_FAILURE)
105 # define EXIT_FAILURE 1
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 },
132 char const ** values;
137 char const * specfile;
141 int32_t const * flags;
143 char const ** version;
148 writeStr(int fd, char const *cmd)
150 (void)write(fd, cmd, strlen(cmd));
153 #define WRITE_MSG(FD,X) (void)(write(FD,X,sizeof(X)-1))
154 #define WRITE_STR(FD,X) writeStr(FD,X)
157 showHelp(int fd, char const *cmd, int res)
159 char tmp[strlen(cmd)+1];
162 WRITE_MSG(fd, "Usage: ");
163 WRITE_STR(fd, basename(tmp));
165 " [--define '<macro> <value>']* [--with[out] <key>]* [--chroot <dir>]\n"
166 " [--target <target>] [--rcfile <rcfile>] [--] <specfile>\n");
171 addDefine(struct Arguments *args, char const *val)
173 register size_t c = args->macros.cnt;
174 if (args->macros.reserved <= c) {
175 args->macros.reserved *= 2;
176 args->macros.reserved += 1;
178 args->macros.values = realloc(args->macros.values,
179 args->macros.reserved * sizeof(char const *));
180 if (args->macros.values==0) {
186 args->macros.values[c] = strdup(val);
191 setWithMacro(struct Arguments *args,
192 char const *name, char const *prefix, size_t prefix_len)
194 size_t len = strlen(name);
195 char tmp[2*len + 2*prefix_len + sizeof("__ ---")];
198 // set '_<prefix>_<name>'
200 memcpy(ptr, prefix, prefix_len); ptr += prefix_len;
202 memcpy(ptr, name, len); ptr += len;
205 // append ' --<prefix>-<name>'
208 memcpy(ptr, prefix, prefix_len); ptr += prefix_len;
210 memcpy(ptr, name, len); ptr += len;
213 addDefine(args, tmp);
218 parseArgs(struct Arguments *args, int argc, char *argv[])
221 int c = getopt_long(argc, argv, "", CMDLINE_OPTIONS, 0);
224 case 'h' : showHelp(1, argv[0], 0); break;
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;
234 WRITE_MSG(2, "Try '");
235 WRITE_STR(2, argv[0]);
236 WRITE_MSG(2, " --help\" for more information.\n");
241 if (optind+1!=argc) {
242 write(2, "No/too much specfile(s) given; aborting\n", 40);
246 if (args->gid==(gid_t)(-1))
247 args->gid = args->uid;
249 args->specfile = argv[optind];
253 setMacros(char const * const *macros, size_t cnt)
256 for (i=0; i<cnt; ++i)
257 rpmDefineMacro(rpmGlobalMacroContext, macros[i], 0);
260 int main(int argc, char *argv[])
262 struct Arguments args = { 0,0,0,-1,-1, {0,0,0}, 0 };
265 addDefine(&args, "patch %{nil}");
267 // instead of requiring rpm-build, we include some "builtin" macros
268 addDefine(&args, "bcond_without() %{expand:%%{!?_without_%{1}:%%global with_%{1} 1}}");
269 addDefine(&args, "bcond_with() %{expand:%%{?_with_%{1}:%%global with_%{1} 1}}");
270 addDefine(&args, "with() %{expand:%%{?with_%{1}:1}%%{!?with_%{1}:0}}");
271 addDefine(&args, "without() %{expand:%%{?with_%{1}:0}%%{!?with_%{1}:1}}");
273 // include macros.perl, etc
274 addDefine(&args, "include() %{nil}");
276 parseArgs(&args, argc, argv);
278 if ((args.chroot && chroot(args.chroot)==-1) ||
279 (args.uid!=(uid_t)(-1) && (setgroups(0,0) ==-1 || getgroups(0,0)!=0)) ||
280 (args.gid!=(gid_t)(-1) && (setgid(args.gid)==-1 || getgid()!=args.gid)) ||
281 (args.uid!=(uid_t)(-1) && (setuid(args.uid)==-1 || getuid()!=args.uid))) {
283 perror("chroot/setuid/setgid()");
287 rpmReadConfigFiles(args.rcfile, args.target);
288 setMacros(args.macros.values, args.macros.cnt);
290 rpmts ts = rpmtsCreate();
291 if (parseSpec(ts, args.specfile, NULL, 0, NULL, NULL, 1, 1, 0) != 0) {
297 // here starts the code for builder
298 const char *name = NULL, *version = NULL, *release = NULL, *summary = NULL, *url = NULL;
300 initSourceHeader(s, NULL);
301 Header h = s->sourceHeader;
303 #if RPM_VERSION_CODE < RPM_VERSION(5,0,0)
305 headerGetEntryMinMemory(h, RPMTAG_NAME, NULL, (void *)&name, NULL) == 0 ||
306 headerGetEntryMinMemory(h, RPMTAG_VERSION, NULL, (void *)&version, NULL) == 0 ||
307 headerGetEntryMinMemory(h, RPMTAG_RELEASE, NULL, (void *)&release, NULL) == 0
309 fprintf(stderr, "NVR query failed\n");
318 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
319 he->tag = (rpmTag) RPMTAG_NAME;
320 rc = headerGet(h, he, 0);
322 fprintf(stderr, "Name (NVR) query failed\n");
325 name = (char *)he->p.ptr;
327 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
328 he->tag = (rpmTag) RPMTAG_VERSION;
329 rc = headerGet(h, he, 0);
331 fprintf(stderr, "Version (NVR) query failed\n");
334 version = (char *)he->p.ptr;
336 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
337 he->tag = (rpmTag) RPMTAG_RELEASE;
338 rc = headerGet(h, he, 0);
340 fprintf(stderr, "Release (NVR) query failed\n");
343 release = (char *)he->p.ptr;
345 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
346 he->tag = (rpmTag) RPMTAG_SUMMARY;
347 rc = headerGet(h, he, 0);
349 fprintf(stderr, "Summary query failed\n");
352 summary = (char *)he->p.ptr;
354 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
355 he->tag = (rpmTag) RPMTAG_URL;
356 rc = headerGet(h, he, 0);
358 // URL field is not required
359 url = (char *)he->p.ptr;
364 printf("h PACKAGE_NAME %s\n", name);
365 printf("h PACKAGE_VERSION %s\n", version);
366 printf("h PACKAGE_RELEASE %s\n", release);
368 printf("h PACKAGE_SUMMARY %s\n", summary);
369 printf("h url %s\n", url);
371 struct Source *ps = s->sources;
373 const char *type = (ps->flags & RPMFILE_SOURCE) ? "SOURCE" : "PATCH";
374 printf("s %sURL%d %s\n", type, ps->num, ps->fullSource);
375 if (ps->flags & RPMFILE_GHOST) {
376 printf("s nosource %d\n", ps->num);
381 const char *arch = rpmExpand("%{_target_cpu}", NULL);
382 printf("m _target_cpu %s\n", arch);