]> git.pld-linux.org Git - packages/rpm-getdeps.git/blob - getdeps.c
571df0fbf51139dec81644072a273c1b96f99e76
[packages/rpm-getdeps.git] / getdeps.c
1 // $Id$    --*- c -*--
2
3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
8 //  
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //  
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 // version 0.0.7, 2003-11-21
19 //    * made it compilable with non-C99 compilers
20 //
21 // version 0.0.6, 2003-11-21
22 //    * added rpm-4.0.4 compatibility (define RPM404 macro)
23 //
24 // version 0.0.5, 2003-11-21
25 //    * added '--uid' and '--gid' options
26 //    * use macros for option-ids
27 //
28 // version 0.0.4, 2003-11-19
29 //    * set 'force' flag on parseSpec() to ignore missing sources & patches
30 //
31 // version 0.0.3, 2003-11-19
32 //    * fixed buffer-overflow in '--with[out]' statements
33 //
34 // version 0.0.2, 2003-11-19
35 //    * big rewrite; implemented nearly the full functionality
36 //
37 // version 0.0.1, 2003-11-19
38 //    * initial version
39
40
41 #define _GNU_SOURCE
42
43 #ifdef HAVE_CONFIG_H
44 #  include <config.h>
45 #endif
46
47 #include <getopt.h>
48 #include <stdbool.h>
49 #include <string.h>
50 #include <assert.h>
51 #include <unistd.h>
52 #include <sys/time.h>
53 #include <sys/types.h>
54
55 #include <rpmbuild.h>
56 #include <rpmlib.h>
57 #include <header.h>
58
59 #ifndef RPM404
60 #  include <rpmts.h>
61 #endif
62
63 #define ARG_WITH        1024
64 #define ARG_WITHOUT     1025
65 #define ARG_DEFINE      1026
66 #define ARG_TARGET      1027
67 #define ARG_RCFILE      1028
68 #define ARG_CHROOT      1029
69 #define ARG_UID         1030
70 #define ARG_GID         1031
71
72 static struct option const
73 CMDLINE_OPTIONS[] = {
74   { "help",     no_argument,  0, 'h' },
75   { "version",  no_argument,  0, 'v' },
76   { "with",     required_argument, 0, ARG_WITH    },
77   { "without",  required_argument, 0, ARG_WITHOUT },
78   { "define",   required_argument, 0, ARG_DEFINE  },
79   { "target",   required_argument, 0, ARG_TARGET  },
80   { "rcfile",   required_argument, 0, ARG_RCFILE  },
81   { "chroot",   required_argument, 0, ARG_CHROOT  },
82   { "uid",      required_argument, 0, ARG_UID },
83   { "gid",      required_argument, 0, ARG_GID },
84   { 0,0,0,0 }
85 };
86
87 struct Arguments
88 {
89     char const *        target;
90     char const *        rcfile;
91     char const *        chroot;
92     uid_t               uid;
93     gid_t               gid;
94     
95     struct {
96         char const **   values;
97         size_t          cnt;
98         size_t          reserved;
99     }                   macros;
100
101     char const *        specfile;
102 };
103
104 struct DepSet {
105     int32_t const *     flags;
106     char const **       name;
107     char const **       version;
108     ssize_t             cnt;
109 };
110
111 inline static void 
112 writeStr(int fd, char const *cmd)
113 {
114   (void)write(fd, cmd, strlen(cmd));
115 }
116
117 #define WRITE_MSG(FD,X)         (void)(write(FD,X,sizeof(X)-1))
118 #define WRITE_STR(FD,X)         writeStr(FD,X)
119
120 static void
121 showHelp(int fd, char const *cmd, int res)
122 {
123   char          tmp[strlen(cmd)+1];
124   strcpy(tmp, cmd);
125   
126   WRITE_MSG(fd, "Usage:  ");
127   WRITE_STR(fd, basename(tmp));
128   WRITE_MSG(fd,
129             " [--define '<macro> <value>']* [--with[out] <key>]* [--chroot <dir>]\n"
130             "                [--target <target>] [--rcfile <rcfile>] [--] <specfile>\n");
131   exit(res);
132 }
133
134 static void
135 addDefine(struct Arguments *args, char const *val)
136 {
137   register size_t       c = args->macros.cnt;
138   if (args->macros.reserved <= c) {
139     args->macros.reserved *= 2;
140     args->macros.reserved += 1;
141   
142     args->macros.values = realloc(args->macros.values,
143                                   args->macros.reserved * sizeof(char const *));
144     if (args->macros.values==0) {
145       perror("realloc()");
146       exit(1);
147     }
148   }
149
150   args->macros.values[c] = strdup(val);
151   ++args->macros.cnt;
152 }
153
154 static void
155 setWithMacro(struct Arguments *args,
156              char const *name, char const *prefix, size_t prefix_len)
157 {
158   size_t        len = strlen(name);
159   char          tmp[2*len + 2*prefix_len + sizeof("__ ---")];
160   char *        ptr = tmp;
161
162   // set '_<prefix>_<name>'
163   *ptr++ = '_';
164   memcpy(ptr, prefix, prefix_len); ptr += prefix_len;
165   *ptr++ = '_';
166   memcpy(ptr, name,   len);        ptr += len;
167   *ptr++ = ' ';
168
169   // append ' --<prefix>-<name>'
170   *ptr++ = '-';
171   *ptr++ = '-';
172   memcpy(ptr, prefix, prefix_len); ptr += prefix_len;
173   *ptr++ = '-';
174   memcpy(ptr, name,   len);        ptr += len;
175   *ptr   = '\0';
176
177   addDefine(args, tmp);
178 }
179
180
181 static void
182 parseArgs(struct Arguments *args, int argc, char *argv[])
183 {
184   while (1) {
185     int         c = getopt_long(argc, argv, "", CMDLINE_OPTIONS, 0);
186     if (c==-1) break;
187     switch (c) {
188       case 'h'          :  showHelp(1, argv[0], 0);
189       case ARG_TARGET   :  args->target = optarg; break;
190       case ARG_RCFILE   :  args->rcfile = optarg; break;
191       case ARG_CHROOT   :  args->chroot = optarg; break;
192       case ARG_UID      :  args->uid    = atoi(optarg); break;
193       case ARG_GID      :  args->gid    = atoi(optarg); break;
194       case ARG_DEFINE   :  addDefine(args, optarg); break;
195       case ARG_WITH     :  setWithMacro(args, optarg, "with",    4); break;
196       case ARG_WITHOUT  :  setWithMacro(args, optarg, "without", 7); break;
197       default:
198         WRITE_MSG(2, "Try '");
199         WRITE_STR(2, argv[0]);
200         WRITE_MSG(2, " --help\" for more information.\n");
201         exit(1);
202     }
203   }
204
205   if (optind+1!=argc) {
206     write(2, "No/too much specfile(s) given; aborting\n", 40);
207     exit(1);
208   }
209
210   if (args->gid==(gid_t)(-1))
211     args->gid = args->uid;
212
213   args->specfile = argv[optind];
214 }
215
216 static void
217 setMacros(char const * const *macros, size_t cnt)
218 {
219   size_t        i;
220   for (i=0; i<cnt; ++i)
221     rpmDefineMacro(rpmGlobalMacroContext, macros[i], 0);
222 }
223
224 static void
225 printDepSet(struct DepSet const *set, char const *prefix)
226 {
227   ssize_t       i;
228   for (i=0; i<set->cnt; ++i)
229     printf("%s%08x %s %s\n", prefix, set->flags[i], set->name[i], set->version[i]);
230 }
231
232 static void
233 evaluateHeader(Header h)
234 {
235   int32_t               cnt[3];
236   struct DepSet         buildreqs = { 0,0,0,0 };
237   struct DepSet         conflicts = { 0,0,0,0 };
238
239   if (headerGetEntry(h, RPMTAG_REQUIREFLAGS,    0, (void**)&buildreqs.flags,   cnt+0) &&
240       headerGetEntry(h, RPMTAG_REQUIRENAME,     0, (void**)&buildreqs.name,    cnt+1) &&
241       headerGetEntry(h, RPMTAG_REQUIREVERSION,  0, (void**)&buildreqs.version, cnt+2)) {
242     assert(cnt[0]==cnt[1] && cnt[1]==cnt[2]);
243     buildreqs.cnt = cnt[0];
244   }
245
246   if (headerGetEntry(h, RPMTAG_CONFLICTFLAGS,   0, (void**)&conflicts.flags,   cnt+0) &&
247       headerGetEntry(h, RPMTAG_CONFLICTNAME,    0, (void**)&conflicts.name,    cnt+1) &&
248       headerGetEntry(h, RPMTAG_CONFLICTVERSION, 0, (void**)&conflicts.version, cnt+2)) {
249     assert(cnt[0]==cnt[1] && cnt[1]==cnt[2]);
250     conflicts.cnt = cnt[0];
251   }
252
253   printDepSet(&buildreqs, "+ ");
254   printDepSet(&conflicts, "- ");
255 }
256
257 int main(int argc, char *argv[])
258 {
259   struct Arguments      args = { 0,0,0,-1,-1, {0,0,0}, 0 };
260   Spec                  s;
261
262   parseArgs(&args, argc, argv);
263
264   if ((args.chroot           && chroot(args.chroot)==-1) ||
265       (args.uid!=(uid_t)(-1) && (setgroups(0,0)  ==-1 || getgroups(0,0)!=0))  ||
266       (args.gid!=(gid_t)(-1) && (setgid(args.gid)==-1 || getgid()!=args.gid)) ||
267       (args.uid!=(uid_t)(-1) && (setuid(args.uid)==-1 || getuid()!=args.uid))) {
268     perror("chroot/setuid/setgid()");
269     return EXIT_FAILURE;
270   }
271   
272   rpmReadConfigFiles(args.rcfile, args.target);
273   setMacros(args.macros.values, args.macros.cnt);
274
275
276 #ifndef RPM404
277   rpmts                 ts = rpmtsCreate();
278   if (parseSpec(ts, args.specfile, 0,0, 1, 0,0, 1,1)!=0) {
279     return EXIT_FAILURE;
280   }
281   
282   s = rpmtsSpec(ts);
283 #else
284   if (parseSpec(&s, args.specfile, 0,0, 1, 0,0, 1,1)!=0) {
285     return EXIT_FAILURE;
286   }
287 #endif
288
289   evaluateHeader(s->buildRestrictions);
290 }
291
292 /// Local Variables:
293 /// compile-command: "make getdeps LDFLAGS='-lrpm       -lrpmbuild'       CFLAGS='-I/usr/include/rpm       -Wall -W -pedantic --std=c99 -g3 -O0'"
294 /// compile-commandX: "make getdeps LDFLAGS='-lrpm-4.0.4 -lrpmbuild-4.0.4 -lrpmio-4.0.4 -lrpmdb-4.0.4 -lpopt' CFLAGS='-I/usr/include/rpm-4.0.4 -Wall -W -pedantic --std=c99 -g3 -O0 -DRPM404'"
295 /// End:
This page took 0.080413 seconds and 2 git commands to generate.