]> git.pld-linux.org Git - packages/rpm-specdump.git/blame - rpm-specdump.c
- drop support for rpm older than 4.4.9
[packages/rpm-specdump.git] / rpm-specdump.c
CommitLineData
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
108static struct option const
109CMDLINE_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
123struct 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
140struct DepSet {
141 int32_t const * flags;
142 char const ** name;
143 char const ** version;
144 ssize_t cnt;
145};
146
147inline static void
148writeStr(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
156static void
157showHelp(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
170static void
171addDefine(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
190static void
191setWithMacro(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
217static void
218parseArgs(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
252static void
253setMacros(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
260int main(int argc, char *argv[])
261{
262struct Arguments args = { 0,0,0,-1,-1, {0,0,0}, 0 };
263Spec s;
264
22c309c5 265 addDefine(&args, "patch %{nil}");
0cf659b5
ER
266
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}}");
272
273 // include macros.perl, etc
274 addDefine(&args, "include() %{nil}");
275
70252337
ER
276 parseArgs(&args, argc, argv);
277
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))) {
282
283 perror("chroot/setuid/setgid()");
284 return EXIT_FAILURE;
285 }
286
287 rpmReadConfigFiles(args.rcfile, args.target);
288 setMacros(args.macros.values, args.macros.cnt);
289
290 rpmts ts = rpmtsCreate();
0d9e3461 291 if (parseSpec(ts, args.specfile, NULL, 0, NULL, NULL, 1, 1, 0) != 0) {
70252337
ER
292 return EXIT_FAILURE;
293 }
294
295 s = rpmtsSpec(ts);
3e262c69
ER
296
297 // here starts the code for builder
846d963b 298 const char *name = NULL, *version = NULL, *release = NULL, *summary = NULL, *url = NULL;
70252337 299
4eb1bd11 300 initSourceHeader(s, NULL);
ca058888 301 Header h = s->sourceHeader;
70252337 302
8e46eae6 303#if RPM_VERSION_CODE < RPM_VERSION(5,0,0)
70252337
ER
304 if (
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
308 ) {
c4820126 309 fprintf(stderr, "NVR query failed\n");
70252337
ER
310 return EXIT_FAILURE;
311 }
312
8e46eae6
AM
313#else
314 {
315 HE_t he;
316 int rc;
8551a535 317
8e46eae6
AM
318 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
319 he->tag = (rpmTag) RPMTAG_NAME;
320 rc = headerGet(h, he, 0);
321 if (!rc) {
322 fprintf(stderr, "Name (NVR) query failed\n");
323 return EXIT_FAILURE;
324 }
325 name = (char *)he->p.ptr;
326
327 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
328 he->tag = (rpmTag) RPMTAG_VERSION;
329 rc = headerGet(h, he, 0);
330 if (!rc) {
331 fprintf(stderr, "Version (NVR) query failed\n");
332 return EXIT_FAILURE;
333 }
334 version = (char *)he->p.ptr;
335
336 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
337 he->tag = (rpmTag) RPMTAG_RELEASE;
338 rc = headerGet(h, he, 0);
339 if (!rc) {
340 fprintf(stderr, "Release (NVR) query failed\n");
341 return EXIT_FAILURE;
342 }
343 release = (char *)he->p.ptr;
8551a535
ER
344
345 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
346 he->tag = (rpmTag) RPMTAG_SUMMARY;
347 rc = headerGet(h, he, 0);
348 if (!rc) {
349 fprintf(stderr, "Summary query failed\n");
350 return EXIT_FAILURE;
351 }
352 summary = (char *)he->p.ptr;
846d963b
ER
353
354 he = (HE_s*)memset(alloca(sizeof(*he)), 0, sizeof(*he));
355 he->tag = (rpmTag) RPMTAG_URL;
356 rc = headerGet(h, he, 0);
357 if (rc) {
358 // URL field is not required
359 url = (char *)he->p.ptr;
360 }
8e46eae6
AM
361 }
362#endif
363
70252337
ER
364 printf("h PACKAGE_NAME %s\n", name);
365 printf("h PACKAGE_VERSION %s\n", version);
366 printf("h PACKAGE_RELEASE %s\n", release);
70252337 367
8551a535 368 printf("h PACKAGE_SUMMARY %s\n", summary);
846d963b 369 printf("h url %s\n", url);
8551a535 370
70252337
ER
371 struct Source *ps = s->sources;
372 while (ps) {
373 const char *type = (ps->flags & RPMFILE_SOURCE) ? "SOURCE" : "PATCH";
afa4a282 374 printf("s %sURL%d %s\n", type, ps->num, ps->fullSource);
70252337
ER
375 if (ps->flags & RPMFILE_GHOST) {
376 printf("s nosource %d\n", ps->num);
377 }
378 ps = ps->next;
379 }
380
3e31d4b4
ER
381 const char *arch = rpmExpand("%{_target_cpu}", NULL);
382 printf("m _target_cpu %s\n", arch);
383
70252337
ER
384 return(0);
385}
This page took 0.127097 seconds and 4 git commands to generate.