]> git.pld-linux.org Git - packages/rpm-specdump.git/blame - rpm-specdump.c
- drop support for rpm < 4.5
[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 };
97634434
JR
263#if RPM_VERSION_CODE < RPM_VERSION(5,0,0)
264rpmSpec s;
265#else
70252337 266Spec 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}
This page took 0.112053 seconds and 4 git commands to generate.