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