/[gentoo-projects]/portage-utils/main.c
Gentoo

Contents of /portage-utils/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.89 - (show annotations) (download) (as text)
Tue Jan 3 15:40:53 2006 UTC (7 years, 4 months ago) by solar
Branch: MAIN
Changes since 1.88: +9 -2 lines
File MIME type: text/x-csrc
- update PORTAGE_BINHOST/CONFIG_PROTECT/PKGDIR handling. It is cleaner now but I still have much more work todo.

1 /*
2 * Copyright 2005 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/portage-utils/main.c,v 1.88 2006/01/02 23:33:00 solar Exp $
5 *
6 * Copyright 2005 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2005 Mike Frysinger - <vapier@gentoo.org>
8 */
9
10 #define _GNU_SOURCE
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #include <time.h>
19 #include <sys/time.h>
20 #include <ctype.h>
21 #include <dirent.h>
22 #include <getopt.h>
23 #include <regex.h>
24 #include <errno.h>
25 #include <libgen.h>
26 #include <limits.h>
27 #include <assert.h>
28
29 /* make sure our buffers are as big as they can be */
30 #if PATH_MAX > _POSIX_PATH_MAX
31 # define _Q_PATH_MAX PATH_MAX
32 #else
33 # define _Q_PATH_MAX _POSIX_PATH_MAX
34 #endif
35
36 /* prototypes and such */
37 static char eat_file(const char *file, char *buf, const size_t bufsize);
38 int rematch(const char *, const char *, int);
39 static char *rmspace(char *);
40
41 void initialize_portage_env(void);
42 void initialize_ebuild_flat(void);
43 void reinitialize_ebuild_flat(void);
44 void reinitialize_as_needed(void);
45 void cleanup(void);
46 int lookup_applet_idx(const char *);
47
48 /* variables to control runtime behavior */
49 static char exact = 0;
50 static int found = 0;
51 static int verbose = 0;
52 static int quiet = 0;
53 static char reinitialize = 0;
54
55 static char portdir[_Q_PATH_MAX] = "/usr/portage";
56 static char portarch[20] = "";
57 static char portvdb[] = "var/db/pkg";
58 static char portcachedir[] = "metadata/cache";
59 static char portroot[_Q_PATH_MAX] = "/";
60 static char config_protect[_Q_PATH_MAX] = "/etc/";
61
62 char binhost[512] = ""; // "ftp://tinderbox.x86.dev.gentoo.org/default-linux/x86/2005.1/All";
63 char pkgdir[512] = ""; // /usr/portage/packages/
64 char port_tmpdir[512] = "/var/tmp/portage/portage-pkg/";
65
66
67 #define _q_unused_ __attribute__((__unused__))
68
69
70 #ifndef BUFSIZE
71 # define BUFSIZE 8192
72 #endif
73
74 /* helper functions for showing errors */
75 static const char *argv0;
76
77 #ifdef EBUG
78 # include <sys/resource.h>
79
80 # define DBG(fmt, args...) warnf(fmt , ## args)
81 # define IF_DEBUG(x) x
82 void init_coredumps(void);
83 void init_coredumps(void)
84 {
85 struct rlimit rl;
86 rl.rlim_cur = RLIM_INFINITY;
87 rl.rlim_max = RLIM_INFINITY;
88 setrlimit(RLIMIT_CORE, &rl);
89 }
90 #else
91 # define DBG(fmt, args...)
92 # define IF_DEBUG(x)
93 #endif
94
95 /* include common library code */
96 #include "libq/libq.c"
97
98 void no_colors(void);
99 void no_colors() {
100 BOLD = NORM = BLUE = DKBLUE = CYAN = GREEN = MAGENTA = RED = YELLOW = WHITE = "";
101 }
102
103
104 /* include common applet defs */
105 #include "applets.h"
106
107 /* Common usage for all applets */
108 #define COMMON_FLAGS "vqChV"
109 #define a_argument required_argument
110 #define COMMON_LONG_OPTS \
111 {"verbose", no_argument, NULL, 'v'}, \
112 {"quiet", no_argument, NULL, 'q'}, \
113 {"nocolor", no_argument, NULL, 'C'}, \
114 {"help", no_argument, NULL, 'h'}, \
115 {"version", no_argument, NULL, 'V'}, \
116 {NULL, no_argument, NULL, 0x0}
117 #define COMMON_OPTS_HELP \
118 "Make a lot of noise", \
119 "Tighter output; suppress warnings", \
120 "Don't output color", \
121 "Print this help and exit", \
122 "Print version and exit", \
123 NULL
124 #define COMMON_GETOPTS_CASES(applet) \
125 case 'v': ++verbose; break; \
126 case 'q': ++quiet; stderr = freopen("/dev/null", "w", stderr); break; \
127 case 'V': version_barf( applet ## _rcsid ); break; \
128 case 'h': applet ## _usage(EXIT_SUCCESS); break; \
129 case 'C': no_colors(); break; \
130 default: applet ## _usage(EXIT_FAILURE); break;
131
132 #define GETOPT_LONG(A, a, ex) \
133 getopt_long(argc, argv, ex A ## _FLAGS, a ## _long_opts, NULL)
134 /* display usage and exit */
135 static void usage(int status, const char *flags, struct option const opts[],
136 const char *help[], int blabber)
137 {
138 unsigned long i;
139 if (blabber == 0) {
140 printf("%sUsage:%s %sq%s %s<applet> [arguments]...%s\n\n", GREEN,
141 NORM, YELLOW, NORM, DKBLUE, NORM);
142 printf("%sCurrently defined applets:%s\n", GREEN, NORM);
143 for (i = 0; applets[i].desc; ++i)
144 printf(" %s%8s%s %s%-16s%s%s:%s %s\n",
145 YELLOW, applets[i].name, NORM,
146 DKBLUE, applets[i].opts, NORM,
147 RED, NORM, applets[i].desc);
148 } else {
149 printf("%sUsage:%s %s%s%s %s%s%s %s:%s %s\n", GREEN, NORM,
150 YELLOW, applets[blabber].name, NORM,
151 DKBLUE, applets[blabber].opts, NORM,
152 RED, NORM, applets[blabber].desc);
153 }
154 printf("\n%sOptions:%s -[%s]\n", GREEN, NORM, flags);
155 for (i = 0; opts[i].name; ++i) {
156 assert(help[i] != NULL); /* this assert is a life saver when adding new applets. */
157 if (opts[i].has_arg == no_argument)
158 printf(" -%c, --%-15s%s*%s %s\n", opts[i].val,
159 opts[i].name, RED, NORM, help[i]);
160 else
161 printf(" -%c, --%-8s %s<arg>%s %s*%s %s\n", opts[i].val,
162 opts[i].name, DKBLUE, NORM, RED, NORM, help[i]);
163 }
164 exit(status);
165 }
166 static void version_barf(const char *Id)
167 {
168 #ifndef VERSION
169 # define VERSION "cvs"
170 #endif
171 printf("portage-utils-%s: compiled on %s\n%s\n"
172 "%s written for Gentoo by <solar and vapier @ gentoo.org>\n",
173 VERSION, __DATE__, Id, argv0);
174 exit(EXIT_SUCCESS);
175 }
176
177 static char eat_file(const char *file, char *buf, const size_t bufsize)
178 {
179 FILE *f;
180 struct stat s;
181 char ret = 0;
182
183 if ((f = fopen(file, "r")) == NULL)
184 return ret;
185
186 memset(buf, 0x00, bufsize);
187 if (fstat(fileno(f), &s) != 0)
188 goto close_and_ret;
189 if (s.st_size) {
190 if (bufsize < (size_t)s.st_size)
191 goto close_and_ret;
192 if (fread(buf, 1, s.st_size, f) != (size_t)s.st_size)
193 goto close_and_ret;
194 } else {
195 if (fread(buf, 1, bufsize, f) == 0)
196 goto close_and_ret;
197 }
198
199 ret = 1;
200 close_and_ret:
201 fclose(f);
202 return ret;
203 }
204
205 int rematch(const char *regex, const char *match, int cflags)
206 {
207 regex_t preg;
208 int ret;
209
210 if ((match == NULL) || (regex == NULL))
211 return EXIT_FAILURE;
212
213 if ((ret = regcomp(&preg, regex, cflags))) {
214 char err[256];
215 if (regerror(ret, &preg, err, sizeof(err)))
216 warnf("regcomp failed: %s", err);
217 else
218 warnf("regcomp failed");
219 return EXIT_FAILURE;
220 }
221 ret = regexec(&preg, match, 0, NULL, 0);
222 regfree(&preg);
223
224 return ret;
225 }
226
227 /* removes adjacent extraneous white space */
228 static char *remove_extra_space(char *str);
229 static char *remove_extra_space(char *str)
230 {
231 char *p, c = ' ';
232 size_t len, pos = 0;
233 char *buf;
234
235 if (str == NULL)
236 return NULL;
237 len = strlen(str);
238 buf = (char*)xmalloc(len+1);
239 memset(buf, 0, len+1);
240 for (p = str; *p != 0; ++p) {
241 if (!isspace(*p)) c = *p; else {
242 if (c == ' ') continue;
243 c = ' ';
244 }
245 buf[pos] = c;
246 pos++;
247 }
248 if (pos > 0 && buf[pos-1] == ' ') buf[pos-1] = '\0';
249 strcpy(str, buf);
250 free(buf);
251 return str;
252 }
253
254 void makeargv(char *string, int *argc, char ***argv);
255 void makeargv(char *string, int *argc, char ***argv) {
256 int curc = 2;
257 char *q, *p, *str;
258 (*argv) = (char **) malloc(sizeof(char **) * curc);
259
260 *argc = 1;
261 (*argv)[0] = xstrdup(argv0);
262 q = xstrdup(string);
263 str = q;
264
265 remove_extra_space(str);
266 rmspace(str);
267
268 while (str) {
269 if ((p = strchr(str, ' ')) != NULL)
270 *(p++) = '\0';
271
272 if (*argc == curc) {
273 curc *= 2;
274 (*argv) = (char **) realloc(*argv, sizeof(char **) * curc);
275 }
276 (*argv)[*argc] = xstrdup(str);
277 (*argc)++;
278 str = p;
279 }
280 free(q);
281 }
282
283 #if 0
284 /* helper func for scanning the vdb */
285 struct dirent *q_vdb_get_next_dir(DIR *dir);
286 struct dirent *q_vdb_get_next_dir(DIR *dir)
287 {
288 /* search for a category directory */
289 struct dirent *ret;
290
291 next_entry:
292 ret = readdir(dir);
293 if (ret == NULL) {
294 closedir(dir);
295 return NULL;
296 }
297
298 if (ret->d_name[0] == '.' || ret->d_name[0] == '-')
299 goto next_entry;
300 if (strchr(ret->d_name, '-') == NULL)
301 goto next_entry;
302
303 return ret;
304 }
305 #endif
306 /*
307 * Parse a line of CONTENTS file and provide access to the individual fields
308 */
309 typedef enum {
310 CONTENTS_DIR, CONTENTS_OBJ, CONTENTS_SYM
311 } contents_type;
312 typedef struct {
313 contents_type type;
314 char *_data;
315 char *name;
316 char *sym_target;
317 char *digest;
318 char *mtime_str;
319 long mtime;
320 } contents_entry;
321
322 contents_entry *contents_parse_line(char *line);
323 contents_entry *contents_parse_line(char *line)
324 {
325 static contents_entry e;
326 char *p;
327
328 if (!line || !*line || *line == '\n')
329 return NULL;
330
331 /* chop trailing newline */
332 if ((p = strrchr(line, '\n')) != NULL)
333 *p = '\0';
334
335 memset(&e, 0x00, sizeof(e));
336 e._data = line;
337
338 if (!strncmp(e._data, "obj ", 4))
339 e.type = CONTENTS_OBJ;
340 else if (!strncmp(e._data, "dir ", 4))
341 e.type = CONTENTS_DIR;
342 else if (!strncmp(e._data, "sym ", 4))
343 e.type = CONTENTS_SYM;
344 else
345 return NULL;
346
347 e.name = e._data + 4;
348
349 switch (e.type) {
350 /* dir /bin */
351 case CONTENTS_DIR:
352 break;
353
354 /* obj /bin/bash 62ed51c8b23866777552643ec57614b0 1120707577 */
355 case CONTENTS_OBJ:
356 if ((e.mtime_str = strrchr(e.name, ' ')) == NULL)
357 return NULL;
358 *e.mtime_str++ = '\0';
359 if ((e.digest = strrchr(e.name, ' ')) == NULL)
360 return NULL;
361 *e.digest++ = '\0';
362 break;
363
364 /* sym /bin/sh -> bash 1120707577 */
365 case CONTENTS_SYM:
366 if ((e.mtime_str = strrchr(e.name, ' ')) == NULL)
367 return NULL;
368 *e.mtime_str++ = '\0';
369 if ((e.sym_target = strstr(e.name, " -> ")) == NULL)
370 return NULL;
371 *e.sym_target = '\0';
372 e.sym_target += 4;
373 break;
374 }
375
376 if (e.mtime_str) {
377 e.mtime = strtol(e.mtime_str, NULL, 10);
378 if (e.mtime == LONG_MAX) {
379 e.mtime = 0;
380 e.mtime_str = NULL;
381 }
382 }
383
384 return &e;
385 }
386
387 void initialize_portage_env(void)
388 {
389 char nocolor = 0;
390 int i, f;
391 struct stat st;
392 FILE *fp;
393 char buf[BUFSIZE], *s, *p;
394
395 char profile[_Q_PATH_MAX], portage_file[_Q_PATH_MAX];
396 const char *files[] = {portage_file, "/etc/make.globals", "/etc/make.conf"};
397 typedef enum { _Q_BOOL, _Q_STR } var_types;
398 struct {
399 const char *name;
400 const size_t name_len;
401 const var_types type;
402 char *value;
403 const size_t value_len;
404 } vars_to_read[] = {
405 {"ARCH", 4, _Q_STR, portarch, sizeof(portarch)},
406 {"CONFIG_PROTECT", 14, _Q_STR, config_protect, sizeof(config_protect)},
407 {"NOCOLOR", 7, _Q_BOOL, &nocolor, 1},
408 {"PORTDIR", 7, _Q_STR, portdir, sizeof(portdir)},
409 {"PORTAGE_BINHOST", 15, _Q_STR, binhost, sizeof(binhost)},
410 {"PKGDIR", 6, _Q_STR, pkgdir, sizeof(pkgdir)},
411 {"ROOT", 4, _Q_STR, portroot, sizeof(portroot)}
412 };
413
414 f = 0;
415 if (readlink("/etc/make.profile", profile, sizeof(profile)) == -1)
416 strcpy(profile, "/etc/make.profile");
417 do {
418 if (f == 0)
419 snprintf(portage_file, sizeof(portage_file), "%s/make.defaults", profile);
420 IF_DEBUG(printf("profile %s\n", files[f]));
421
422 if ((fp=fopen(files[f], "r")) != NULL) {
423 while (fgets(buf, sizeof(buf), fp) != NULL) {
424 rmspace(buf);
425 if (*buf == '#' || *buf == '\0')
426 continue;
427 for (i=0; i<ARR_SIZE(vars_to_read); ++i) {
428 if (buf[vars_to_read[i].name_len] != '=' && buf[vars_to_read[i].name_len] != ' ')
429 continue;
430 if (strncmp(buf, vars_to_read[i].name, vars_to_read[i].name_len))
431 continue;
432
433 /* make sure we handle spaces between the varname, the =, and the value:
434 * VAR=val VAR = val VAR="val"
435 */
436 s = buf + vars_to_read[i].name_len;
437 if ((p = strchr(s, '=')) != NULL)
438 s = p + 1;
439 while (isspace(*s))
440 ++s;
441 if (*s == '"' || *s == '\'') {
442 ++s;
443 s[strlen(s)-1] = '\0';
444 }
445
446 switch (vars_to_read[i].type) {
447 case _Q_BOOL: *vars_to_read[i].value = 1; break;
448 case _Q_STR: strncpy(vars_to_read[i].value, s, vars_to_read[i].value_len); break;
449 }
450 }
451 }
452 fclose(fp);
453 }
454
455 if (f > 0) {
456 if (++f < ARR_SIZE(files))
457 continue;
458 else
459 break;
460 }
461
462 /* everything below here is to figure out what the next parent is */
463 snprintf(portage_file, sizeof(portage_file), "%s/parent", profile);
464 if (stat(portage_file, &st) == 0) {
465 eat_file(portage_file, buf, sizeof(buf));
466 rmspace(buf);
467 portage_file[strlen(portage_file)-7] = '\0';
468 snprintf(profile, sizeof(profile), "%s/%s", portage_file, buf);
469 } else {
470 f = 1;
471 }
472 } while (1);
473
474 /* finally, check the env */
475 for (i=0; i<ARR_SIZE(vars_to_read); ++i) {
476 s = getenv(vars_to_read[i].name);
477 if (s != NULL) {
478 switch (vars_to_read[i].type) {
479 case _Q_BOOL: *vars_to_read[i].value = 1; break;
480 case _Q_STR: strncpy(vars_to_read[i].value, s, vars_to_read[i].value_len); break;
481 }
482 }
483 IF_DEBUG(
484 printf("%s = ", vars_to_read[i].name);
485 switch (vars_to_read[i].type) {
486 case _Q_BOOL: printf("%i\n", *vars_to_read[i].value); break;
487 case _Q_STR: puts(vars_to_read[i].value); break;
488 }
489 )
490 }
491
492 if (nocolor)
493 no_colors();
494 }
495
496
497
498 /* The logic for ebuild.x should be moved into /var/cache */
499 /* and allow for user defined --cache files */
500 enum {
501 CACHE_EBUILD = 1,
502 CACHE_METADATA = 2
503 };
504
505 int filter_hidden(const struct dirent *dentry);
506 int filter_hidden(const struct dirent *dentry)
507 {
508 if (dentry->d_name[0] == '.')
509 return 0;
510 return 1;
511 }
512
513 #define CACHE_EBUILD_FILE ".ebuild.x"
514 #define CACHE_METADATA_FILE ".metadata.x"
515 const char *initialize_flat(int cache_type);
516 const char *initialize_flat(int cache_type)
517 {
518 struct dirent **category, **pn, **eb;
519 struct stat st;
520 struct timeval start, finish;
521 static const char *cache_file;
522 char *p;
523 int a, b, c, d, e, i;
524 int frac, secs, count;
525 FILE *fp;
526
527 a = b = c = d = e = i = 0;
528 count = frac = secs = 0;
529
530 cache_file = (cache_type == CACHE_EBUILD ? CACHE_EBUILD_FILE : CACHE_METADATA_FILE);
531
532 if (chdir(portdir) != 0) {
533 warnp("chdir to PORTDIR '%s' failed", portdir);
534 goto ret;
535 }
536
537 if (cache_type == CACHE_METADATA && chdir(portcachedir) != 0) {
538 warnp("chdir to portage cache '%s/%s' failed", portdir, portcachedir);
539 goto ret;
540 }
541
542 if ((stat(cache_file, &st)) != (-1))
543 if (st.st_size == 0)
544 unlink(cache_file);
545
546 /* assuming --sync is used with --delete this will get recreated after every merge */
547 if (access(cache_file, R_OK) == 0)
548 goto ret;
549
550 warn("Updating ebuild %scache ... ", cache_type == CACHE_EBUILD ? "" : "meta" );
551
552 unlink(cache_file);
553 if (errno != ENOENT) {
554 warnfp("unlinking '%s/%s' failed", portdir, cache_file);
555 goto ret;
556 }
557
558 if ((fp = fopen(cache_file, "w")) == NULL) {
559 warnfp("opening '%s/%s' failed", portdir, cache_file);
560 goto ret;
561 }
562
563 gettimeofday(&start, NULL);
564
565 if ((a = scandir(".", &category, filter_hidden, alphasort)) < 0)
566 goto ret;
567
568 for (i = 0 ; i < a; i++) {
569 stat(category[i]->d_name, &st);
570 if (!S_ISDIR(st.st_mode))
571 continue;
572 if (strchr(category[i]->d_name, '-') == NULL)
573 continue;
574
575 if ((b = scandir(category[i]->d_name, &pn, filter_hidden, alphasort)) < 0)
576 continue;
577 for (c = 0; c < b; c++) {
578 char de[_Q_PATH_MAX];
579
580 snprintf(de, sizeof(de), "%s/%s", category[i]->d_name, pn[c]->d_name);
581
582 if (stat(de, &st) < 0)
583 continue;
584
585 switch (cache_type) {
586 case CACHE_EBUILD:
587 if (!S_ISDIR(st.st_mode))
588 continue;
589 break;
590 case CACHE_METADATA:
591 if (S_ISREG(st.st_mode))
592 fprintf(fp, "%s\n", de);
593 continue;
594 break;
595 }
596 if ((e = scandir(de, &eb, filter_hidden, alphasort)) < 0)
597 continue;
598 for (d = 0 ; d < e; d++) {
599 if ((p = rindex(eb[d]->d_name, '.')) != NULL)
600 if (strcmp(p, ".ebuild") == 0) {
601 count++;
602 fprintf(fp, "%s/%s/%s\n", category[i]->d_name, pn[c]->d_name, eb[d]->d_name);
603 }
604 }
605 while(d--) free(eb[d]);
606 free(eb);
607 }
608 while(b--) free(pn[b]);
609 free(pn);
610 }
611 fclose(fp);
612 while(a--) free(category[a]);
613 free(category);
614
615 gettimeofday(&finish, NULL);
616 if (start.tv_usec > finish.tv_usec) {
617 finish.tv_usec += 1000000;
618 finish.tv_sec--;
619
620 }
621 frac = (finish.tv_usec - start.tv_usec);
622 secs = (finish.tv_sec - start.tv_sec);
623 if (secs < 0) secs = 0;
624 if (frac < 0) frac = 0;
625 warn("Finished %u entries in %d.%06d seconds", count, secs, frac);
626 ret:
627 return cache_file;
628 }
629 #define initialize_ebuild_flat() initialize_flat(CACHE_EBUILD)
630 #define initialize_metadata_flat() initialize_flat(CACHE_METADATA)
631
632 void reinitialize_ebuild_flat(void)
633 {
634 if ((chdir(portdir)) != 0) {
635 warnp("chdir to PORTDIR '%s' failed", portdir);
636 return;
637 }
638 unlink(CACHE_EBUILD_FILE);
639 initialize_ebuild_flat();
640 }
641
642 void reinitialize_as_needed(void)
643 {
644 if (reinitialize)
645 reinitialize_ebuild_flat();
646 }
647
648 typedef struct {
649 char *_data;
650 char *DEPEND; /* line 1 */
651 char *RDEPEND;
652 char *SLOT;
653 char *SRC_URI;
654 char *RESTRICT; /* line 5 */
655 char *HOMEPAGE;
656 char *LICENSE;
657 char *DESCRIPTION;
658 char *KEYWORDS;
659 char *INHERITED; /* line 10 */
660 char *IUSE;
661 char *CDEPEND;
662 char *PDEPEND;
663 char *PROVIDE; /* line 14 */
664 depend_atom *atom;
665 } portage_cache;
666
667 void cache_free(portage_cache *cache);
668 portage_cache *cache_read_file(const char *file);
669 portage_cache *cache_read_file(const char *file)
670 {
671 struct stat s;
672 char *ptr;
673 FILE *f;
674 portage_cache *ret = NULL;
675 size_t len;
676
677 if ((f = fopen(file, "r")) == NULL)
678 goto err;
679
680 if (fstat(fileno(f), &s) != 0)
681 goto err;
682 len = sizeof(*ret) + s.st_size + 1;
683 ret = xmalloc(len);
684 memset(ret, 0x00, len);
685 #if 0
686 { /* This is the expected format of portage-2.0 cache code NAME=var */
687 /* at any time ferringb might decide to add new entries. CDEPEND= will be no more */
688 char buf[BUFSIZ];
689 while ((fgets(buf, sizeof(buf), f)) != NULL) {
690 if ((ptr = strrchr(buf, '\n')) != NULL)
691 *ptr = 0;
692
693 if ((strncmp(buf, "DEPEND=", 7)) == 0)
694 ret->DEPEND = xstrdup(buf + 7);
695
696 if ((strncmp(buf, "DESCRIPTION=", 12)) == 0)
697 ret->DESCRIPTION = xstrdup(buf + 12);
698 #if 0
699 if ((strncmp(buf, "EAPI=", 5)) == 0)
700 warnf("EAPI=%s", buf + 5);
701 #endif
702 if ((strncmp(buf, "HOMEPAGE=", 9)) == 0)
703 ret->HOMEPAGE = xstrdup(buf + 9);
704
705 if ((strncmp(buf, "INHERITED=", 10)) == 0)
706 ret->INHERITED = xstrdup(buf + 10);
707
708 if ((strncmp(buf, "IUSE=", 4)) == 0)
709 ret->IUSE = xstrdup(buf + 4);
710
711 if ((strncmp(buf, "KEYWORDS=", 9)) == 0)
712 ret->KEYWORDS = xstrdup(buf + 9);
713
714 if ((strncmp(buf, "LICENSE=", 8)) == 0)
715 ret->LICENSE = xstrdup(buf + 8);
716
717 if ((strncmp(buf, "PDEPEND=", 8)) == 0)
718 ret->PDEPEND = xstrdup(buf + 8);
719
720 if ((strncmp(buf, "PROVIDE=", 8)) == 0)
721 ret->PROVIDE = xstrdup(buf + 8);
722
723 if ((strncmp(buf, "RDEPEND=", 8)) == 0)
724 ret->RDEPEND = xstrdup(buf + 8);
725
726 if ((strncmp(buf, "RESTRICT=", 9)) == 0)
727 ret->RESTRICT = xstrdup(buf + 9);
728
729 if ((strncmp(buf, "SLOT=", 5)) == 0)
730 ret->SLOT = xstrdup(buf + 5);
731
732 if ((strncmp(buf, "SRC_URI=", 8)) == 0)
733 ret->SRC_URI = xstrdup(buf + 8);
734 }
735 rewind(f);
736 }
737 #endif
738 ptr = (char*)ret;
739 ret->_data = ptr + sizeof(*ret);
740 if ((off_t)fread(ret->_data, 1, s.st_size, f) != s.st_size)
741 goto err;
742
743 ret->atom = atom_explode(file);
744 ret->DEPEND = ret->_data;
745 #define next_line(curr, next) \
746 if ((ptr = strchr(ret->curr, '\n')) == NULL) { \
747 warn("Invalid cache file '%s'", file); \
748 goto err; \
749 } \
750 ret->next = ptr+1; \
751 *ptr = '\0';
752 next_line(DEPEND, RDEPEND)
753 next_line(RDEPEND, SLOT)
754 next_line(SLOT, SRC_URI)
755 next_line(SRC_URI, RESTRICT)
756 next_line(RESTRICT, HOMEPAGE)
757 next_line(HOMEPAGE, LICENSE)
758 next_line(LICENSE, DESCRIPTION)
759 next_line(DESCRIPTION, KEYWORDS)
760 next_line(KEYWORDS, INHERITED)
761 next_line(INHERITED, IUSE)
762 next_line(IUSE, CDEPEND)
763 next_line(CDEPEND, PDEPEND)
764 next_line(PDEPEND, PROVIDE)
765 #undef next_line
766 ptr = strchr(ptr+1, '\n');
767 *ptr = '\0';
768
769 fclose(f);
770
771 return ret;
772
773 err:
774 if (ret) cache_free(ret);
775 return NULL;
776 }
777
778 void cache_dump(portage_cache *cache);
779 void cache_dump(portage_cache *cache)
780 {
781 if (!cache)
782 errf("Cache is empty !");
783
784 printf("DEPEND : %s\n", cache->DEPEND);
785 printf("RDEPEND : %s\n", cache->RDEPEND);
786 printf("SLOT : %s\n", cache->SLOT);
787 printf("SRC_URI : %s\n", cache->SRC_URI);
788 printf("RESTRICT : %s\n", cache->RESTRICT);
789 printf("HOMEPAGE : %s\n", cache->HOMEPAGE);
790 printf("LICENSE : %s\n", cache->LICENSE);
791 printf("DESCRIPTION: %s\n", cache->DESCRIPTION);
792 printf("KEYWORDS : %s\n", cache->KEYWORDS);
793 printf("INHERITED : %s\n", cache->INHERITED);
794 printf("IUSE : %s\n", cache->IUSE);
795 printf("CDEPEND : %s\n", cache->CDEPEND);
796 printf("PDEPEND : %s\n", cache->PDEPEND);
797 printf("PROVIDE : %s\n", cache->PROVIDE);
798 if (!cache->atom) return;
799 printf("CATEGORY : %s\n", cache->atom->CATEGORY);
800 printf("PN : %s\n", cache->atom->PN);
801 printf("PV : %s\n", cache->atom->PV);
802 printf("PVR : %s\n", cache->atom->PVR);
803 }
804
805 void cache_free(portage_cache *cache)
806 {
807 if (!cache)
808 errf("Cache is empty !");
809 atom_implode(cache->atom);
810 free(cache);
811 }
812
813 #ifdef SOLAR_WAS_HERE
814 depend_atom **get_vdb_atoms(void);
815 depend_atom **get_vdb_atoms(void) {
816 int cfd, j;
817 int dfd, i;
818
819 char buf[_Q_PATH_MAX];
820
821 struct dirent **cat;
822 struct dirent **pf;
823
824 depend_atom *atom = NULL;
825
826 if (chdir(portroot))
827 errp("could not chdir(%s) for ROOT", portroot);
828
829 if (chdir(portvdb) != 0)
830 return NULL;
831
832 memset(buf, 0, sizeof(buf));
833 /* scan the cat first */
834 if ((cfd = scandir(".", &cat, filter_hidden, alphasort)) < 0)
835 return NULL;
836
837 for (j = 0; j < cfd ; j++) {
838 if (cat[j]->d_name[0] == '-')
839 continue;
840 if (chdir(cat[j]->d_name) != 0)
841 continue;
842 if ((dfd = scandir(".", &pf, filter_hidden, alphasort)) < 0) {
843 chdir("..");
844 continue;
845 }
846 for (i = 0; i < dfd; i++) {
847 if (pf[i]->d_name[0] == '-')
848 continue;
849 snprintf(buf, sizeof(buf), "%s/%s", cat[j]->d_name, pf[i]->d_name);
850 atom = atom_explode(buf);
851 printf("%s %s %s", atom->CATEGORY, atom->PN, atom->PV);
852 if (verbose || atom->PR_int)
853 printf(" r%i", atom->PR_int);
854 putchar('\n');
855 atom_implode(atom);
856
857 }
858 chdir("..");
859 while(dfd--) free(pf[dfd]);
860 }
861
862 /* cleanup */
863 if (cfd) while(cfd--) free(cat[cfd]);
864
865 return NULL;
866 }
867 #endif
868
869 #include "q.c"
870 #include "qcheck.c"
871 #include "qdepends.c"
872 #include "qfile.c"
873 #include "qlist.c"
874 #include "qlop.c"
875 #include "qsearch.c"
876 #include "qsize.c"
877 #include "qmerge.c"
878 #include "qtbz2.c"
879 #include "quse.c"
880 #include "qxpak.c"
881 #include "qpkg.c"
882 #include "qgrep.c"
883 #include "qatom.c"
884
885 #if 0
886 queue *resolve_vdb_virtuals();
887 queue *resolve_vdb_virtuals() {
888 DIR *dir, *dirp;
889 struct dirent *dentry_cat, *dentry_pkg;
890 char buf[BUFSIZE];
891 depend_atom *atom;
892
893 chdir("/");
894
895 /* now try to run through vdb and locate matches for user inputs */
896 if ((dir = opendir(portvdb)) == NULL)
897 return virtuals;
898
899 /* scan all the categories */
900 while ((dentry_cat = q_vdb_get_next_dir(dir)) != NULL) {
901 snprintf(buf, sizeof(buf), "%s/%s", portvdb, dentry_cat->d_name);
902 if ((dirp = opendir(buf)) == NULL)
903 continue;
904
905 /* scan all the packages in this category */
906 while ((dentry_pkg = q_vdb_get_next_dir(dirp)) != NULL) {
907 FILE *fp;
908 char *p;
909 /* see if user wants any of these packages */
910 snprintf(buf, sizeof(buf), "%s/%s/%s/PROVIDE", portvdb, dentry_cat->d_name, dentry_pkg->d_name);
911 if ((fp = fopen(buf, "r")) != NULL) {
912 fgets(buf, sizeof(buf), fp);
913
914 if ((p = strrchr(buf, '\n')) != NULL)
915 *p = 0;
916
917 rmspace(buf);
918
919 if (*buf) {
920 int ok = 0;
921 char *v, *tmp = xstrdup(buf);
922 snprintf(buf, sizeof(buf), "%s/%s", dentry_cat->d_name, dentry_pkg->d_name);
923
924 atom = atom_explode(buf);
925 if (!atom) {
926 warn("could not explode '%s'", buf);
927 continue;
928 }
929 sprintf(buf, "%s/%s", atom->CATEGORY, atom->PN);
930 if ((v = virtual(tmp, virtuals)) != NULL) {
931 IF_DEBUG(fprintf(stderr, "%s provided by %s (removing)\n", tmp, v));
932 virtuals = del_set(tmp, virtuals, &ok);
933 }
934 virtuals = add_set(tmp, buf, virtuals);
935 IF_DEBUG(fprintf(stderr, "%s provided by %s/%s (adding)\n", tmp, atom->CATEGORY, dentry_pkg->d_name));
936 free(tmp);
937 atom_implode(atom);
938 }
939 fclose(fp);
940 }
941 }
942 }
943 return virtuals;
944 }
945 #endif
946
947 void cleanup() {
948 reinitialize_as_needed();
949 free_sets(virtuals);
950 }
951
952 int main(int argc, char **argv)
953 {
954 IF_DEBUG(init_coredumps());
955 argv0 = argv[0];
956 #if 0
957 if (ttyname(1) == NULL)
958 no_colors();
959 #endif
960 initialize_portage_env();
961 atexit(cleanup);
962 optind = 0;
963 return q_main(argc, argv);
964 }

  ViewVC Help
Powered by ViewVC 1.1.13