1 |
vapier 11/03/02 09:16:22 |
2 |
|
3 |
Modified: .depend qmerge.c |
4 |
Log: |
5 |
rewrite merging logic so that we can upgrade in place without doing a full unmerge followed by a full merge |
6 |
|
7 |
Revision Changes Path |
8 |
1.42 portage-utils/.depend |
9 |
|
10 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/.depend?rev=1.42&view=markup |
11 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/.depend?rev=1.42&content-type=text/plain |
12 |
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/.depend?r1=1.41&r2=1.42 |
13 |
|
14 |
Index: .depend |
15 |
=================================================================== |
16 |
RCS file: /var/cvsroot/gentoo-projects/portage-utils/.depend,v |
17 |
retrieving revision 1.41 |
18 |
retrieving revision 1.42 |
19 |
diff -u -r1.41 -r1.42 |
20 |
--- .depend 23 Feb 2011 22:58:51 -0000 1.41 |
21 |
+++ .depend 2 Mar 2011 09:16:22 -0000 1.42 |
22 |
@@ -3,7 +3,7 @@ |
23 |
libq/hash_fd.c libq/md5_sha1_sum.c libq/human_readable.c libq/rmspace.c \ |
24 |
libq/which.c libq/compat.c libq/copy_file.c libq/safe_io.c libq/xchdir.c \ |
25 |
libq/xgetcwd.c libq/xmkdir.c libq/xreadlink.c libq/xsystem.c \ |
26 |
- libq/atom_explode.c libq/atom_compare.c libq/basename.c \ |
27 |
+ libq/atom_explode.c libq/atom_compare.c libq/basename.c libq/profile.c \ |
28 |
libq/vdb_get_next_dir.c libq/virtuals.c applets.h include_applets.h q.c \ |
29 |
qcheck.c qdepends.c qfile.c qlist.c qlop.c qsearch.c qsize.c qtbz2.c \ |
30 |
quse.c qxpak.c qpkg.c qgrep.c qatom.c qmerge.c qcache.c qglsa.c |
31 |
|
32 |
|
33 |
|
34 |
1.106 portage-utils/qmerge.c |
35 |
|
36 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?rev=1.106&view=markup |
37 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?rev=1.106&content-type=text/plain |
38 |
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?r1=1.105&r2=1.106 |
39 |
|
40 |
Index: qmerge.c |
41 |
=================================================================== |
42 |
RCS file: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v |
43 |
retrieving revision 1.105 |
44 |
retrieving revision 1.106 |
45 |
diff -u -r1.105 -r1.106 |
46 |
--- qmerge.c 2 Mar 2011 03:51:01 -0000 1.105 |
47 |
+++ qmerge.c 2 Mar 2011 09:16:22 -0000 1.106 |
48 |
@@ -1,7 +1,7 @@ |
49 |
/* |
50 |
* Copyright 2005-2010 Gentoo Foundation |
51 |
* Distributed under the terms of the GNU General Public License v2 |
52 |
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v 1.105 2011/03/02 03:51:01 solar Exp $ |
53 |
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v 1.106 2011/03/02 09:16:22 vapier Exp $ |
54 |
* |
55 |
* Copyright 2005-2010 Ned Ludd - <solar@g.o> |
56 |
* Copyright 2005-2010 Mike Frysinger - <vapier@g.o> |
57 |
@@ -55,7 +55,7 @@ |
58 |
COMMON_OPTS_HELP |
59 |
}; |
60 |
|
61 |
-static const char qmerge_rcsid[] = "$Id: qmerge.c,v 1.105 2011/03/02 03:51:01 solar Exp $"; |
62 |
+static const char qmerge_rcsid[] = "$Id: qmerge.c,v 1.106 2011/03/02 09:16:22 vapier Exp $"; |
63 |
#define qmerge_usage(ret) usage(ret, QMERGE_FLAGS, qmerge_long_opts, qmerge_opts_help, lookup_applet_idx("qmerge")) |
64 |
|
65 |
char search_pkgs = 0; |
66 |
@@ -95,70 +95,36 @@ |
67 |
|
68 |
typedef struct llist_char_t llist_char; |
69 |
|
70 |
-int interactive_rename(const char *, const char *, struct pkg_t *); |
71 |
-void fetch(const char *, const char *); |
72 |
-char *best_version(const char *, const char *); |
73 |
-void pkg_fetch(int, depend_atom *, struct pkg_t *); |
74 |
-void pkg_merge(int, depend_atom *, struct pkg_t *); |
75 |
-int pkg_unmerge(const char *, const char *); |
76 |
-int unlink_empty(char *); |
77 |
-void print_Pkg(int, struct pkg_t *); |
78 |
-int pkg_verify_checksums(char *, struct pkg_t *, depend_atom *, int strict, int display); |
79 |
-char *find_binpkg(const char *); |
80 |
+_q_static void pkg_fetch(int, const depend_atom *, const struct pkg_t *); |
81 |
+_q_static void pkg_merge(int, const depend_atom *, const struct pkg_t *); |
82 |
+_q_static int pkg_unmerge(const char *, const char *, queue *); |
83 |
+_q_static struct pkg_t *grab_binpkg_info(const char *); |
84 |
+_q_static char *find_binpkg(const char *); |
85 |
|
86 |
-struct pkg_t *grab_binpkg_info(const char *); |
87 |
- |
88 |
-static int q_unlink_q(char *path, const char *func, int line) |
89 |
+_q_static int q_unlink_q(const char *path, const char *func, int line) |
90 |
{ |
91 |
- if ((strcmp(path, "/bin/sh") == 0) || (strcmp(path, BUSYBOX) == 0)) { |
92 |
- warn("Oh hell no: unlink(%s) from %s line %d", path, func, line); |
93 |
- return 1; |
94 |
- } |
95 |
+ int ret; |
96 |
+ char *d; |
97 |
+ |
98 |
if (pretend) |
99 |
return 0; |
100 |
- return unlink(path); |
101 |
-} |
102 |
|
103 |
-#define unlink_q(path) q_unlink_q(path, __FUNCTION__, __LINE__) |
104 |
- |
105 |
-/* rewrite using copyfile() utime() stat(), lstat(), read() and perms. */ |
106 |
-int interactive_rename(const char *src, const char *dst, struct pkg_t *pkg) |
107 |
-{ |
108 |
- FILE *fp; |
109 |
- char *p; |
110 |
- int ret; |
111 |
- char buf[1024]; |
112 |
- struct stat st; |
113 |
- char check_interactive = interactive; |
114 |
+ ret = unlink(path); |
115 |
+ if (ret) |
116 |
+ return ret; |
117 |
|
118 |
- if (check_interactive && (stat(dst, &st) != -1)) { |
119 |
- snprintf(buf, sizeof(buf), "qfile -Cqev %s 2>/dev/null", dst); |
120 |
- if ((fp = popen(buf, "r")) != NULL) { |
121 |
- buf[0] = '\0'; |
122 |
- if (fgets(buf, sizeof(buf), fp) != NULL) |
123 |
- if ((p = strchr(buf, '\n')) != NULL) { |
124 |
- *p = 0; |
125 |
- p = xstrdup(buf); |
126 |
- snprintf(buf, sizeof(buf), "%s/%s", pkg->CATEGORY, pkg->PF); |
127 |
- if (strcmp(buf, p) == 0) |
128 |
- check_interactive = 0; |
129 |
- else |
130 |
- warn("%s owns %s", p, dst); |
131 |
- free(p); |
132 |
- } |
133 |
- pclose(fp); |
134 |
- } |
135 |
+ d = strrchr(path, '/'); |
136 |
+ if (d) { |
137 |
+ *d = '\0'; |
138 |
+ rmdir_r(path); |
139 |
} |
140 |
- snprintf(buf, sizeof(buf), BUSYBOX " mv %s %s %s", check_interactive ? "-i" : "", src, dst); |
141 |
- ret = (system(buf) << 8); |
142 |
- if (ret == 0) { |
143 |
- qprintf("%s>>>%s %s\n", GREEN, NORM, dst); |
144 |
- } else |
145 |
- warn("%s!!!%s %s ret=%d", RED, NORM, dst, ret); |
146 |
+ |
147 |
return ret; |
148 |
} |
149 |
|
150 |
-void fetch(const char *destdir, const char *src) |
151 |
+#define unlink_q(path) q_unlink_q(path, __FUNCTION__, __LINE__) |
152 |
+ |
153 |
+_q_static void fetch(const char *destdir, const char *src) |
154 |
{ |
155 |
char buf[BUFSIZ]; |
156 |
|
157 |
@@ -169,18 +135,47 @@ |
158 |
if (getenv("FETCHCOMMAND") != NULL) { |
159 |
snprintf(buf, sizeof(buf), "(export DISTDIR='%s' URI='%s/%s'; %s)", |
160 |
destdir, binhost, src, getenv("FETCHCOMMAND")); |
161 |
+ xsystem(buf); |
162 |
} else |
163 |
#endif |
164 |
{ |
165 |
- snprintf(buf, sizeof(buf), "%s " BUSYBOX " wget %s -P %s %s/%s", (force_download || install) ? "" : pretend ? "echo " : "", |
166 |
- (quiet ? "-q" : ""), destdir, binhost, src); |
167 |
+ pid_t p; |
168 |
+ int status; |
169 |
+ |
170 |
+ const char *prog = (force_download || install) ? "wget" : pretend ? "echo" : "wget"; |
171 |
+ char *argv[] = { |
172 |
+ xstrdup(prog), |
173 |
+ xstrdup("-c"), |
174 |
+ xstrdup("-P"), |
175 |
+ xstrdup(destdir), |
176 |
+ buf, |
177 |
+ quiet ? xstrdup("-q") : NULL, |
178 |
+ NULL, |
179 |
+ }; |
180 |
+ snprintf(buf, sizeof(buf), "%s/%s", binhost, src); |
181 |
+ |
182 |
+ p = vfork(); |
183 |
+ if (p == 0) |
184 |
+ _exit(execvp(prog, argv)); |
185 |
+ |
186 |
+ free(argv[0]); |
187 |
+ free(argv[1]); |
188 |
+ free(argv[2]); |
189 |
+ free(argv[3]); |
190 |
+ free(argv[5]); |
191 |
+ |
192 |
+ waitpid(p, &status, 0); |
193 |
+#if 0 |
194 |
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) |
195 |
+ return; |
196 |
+#endif |
197 |
} |
198 |
- xsystem(buf); |
199 |
+ |
200 |
fflush(stdout); |
201 |
fflush(stderr); |
202 |
} |
203 |
|
204 |
-static void qmerge_initialize(void) |
205 |
+_q_static void qmerge_initialize(void) |
206 |
{ |
207 |
if (strlen(BUSYBOX)) |
208 |
if (access(BUSYBOX, X_OK) != 0) |
209 |
@@ -196,9 +191,9 @@ |
210 |
errf("PORTAGE_BINHOST= does not appear to be valid"); |
211 |
|
212 |
if (!search_pkgs && !pretend) { |
213 |
- if (access(pkgdir, R_OK|W_OK|X_OK) != 0) |
214 |
- errf("Wrong perms on PKGDIR='%s'", pkgdir); |
215 |
- mkdir(port_tmpdir, 0755); |
216 |
+ if (mkdir_p(pkgdir, 0755)) |
217 |
+ errp("could not setup PKGDIR: %s", pkgdir); |
218 |
+ mkdir_p(port_tmpdir, 0755); |
219 |
} |
220 |
|
221 |
xchdir(port_tmpdir); |
222 |
@@ -216,29 +211,67 @@ |
223 |
} |
224 |
} |
225 |
|
226 |
-char *best_version(const char *CATEGORY, const char *PN) |
227 |
+_q_static char *best_version(const char *CATEGORY, const char *PN) |
228 |
{ |
229 |
- static char buf[1024]; |
230 |
+ /* XXX: The qlist code should be refactored to avoid this fork and I/O */ |
231 |
+ static char buf[4096]; |
232 |
+ ssize_t rret; |
233 |
+ int status, pipefd[2]; |
234 |
+ pid_t p; |
235 |
FILE *fp; |
236 |
- char *p; |
237 |
|
238 |
- /* if defined(EBUG) this spits out incorrect versions. */ |
239 |
- snprintf(buf, sizeof(buf), "qlist -CIev '%s%s%s' 2>/dev/null | tr '\n' ' '", |
240 |
- (CATEGORY != NULL ? CATEGORY : ""), (CATEGORY != NULL ? "/" : ""), PN); |
241 |
+ buf[0] = '\0'; |
242 |
+ if (pipe(pipefd)) |
243 |
+ return buf; |
244 |
|
245 |
- if ((fp = popen(buf, "r")) == NULL) |
246 |
- return NULL; |
247 |
+ snprintf(buf, sizeof(buf), "%s%s%s", (CATEGORY != NULL ? CATEGORY : ""), |
248 |
+ (CATEGORY != NULL ? "/" : ""), PN); |
249 |
|
250 |
- buf[0] = '\0'; |
251 |
- if (fgets(buf, sizeof(buf), fp) != NULL) |
252 |
- if ((p = strchr(buf, '\n')) != NULL) |
253 |
- *p = 0; |
254 |
- pclose(fp); |
255 |
- rmspace(buf); |
256 |
- return (char *) buf; |
257 |
+ fflush(stdout); |
258 |
+ |
259 |
+ switch ((p = fork())) { |
260 |
+ /* Stupid -Cv screws up global state */ |
261 |
+ case 0: { |
262 |
+ fclose(stdout); |
263 |
+ close(pipefd[0]); |
264 |
+ if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) |
265 |
+ exit(1); |
266 |
+ stdout = fdopen(pipefd[1], "w"); |
267 |
+ if (!stdout) |
268 |
+ exit(1); |
269 |
+ run_applet_l("qlist", "-CIev", buf, NULL); |
270 |
+ exit(0); |
271 |
+ } |
272 |
+ default: |
273 |
+ close(pipefd[1]); |
274 |
+ waitpid(p, &status, 0); |
275 |
+ } |
276 |
+ |
277 |
+ fp = fdopen(pipefd[0], "r"); |
278 |
+ if (!fp) { |
279 |
+ close(pipefd[0]); |
280 |
+ return buf; |
281 |
+ } |
282 |
+ |
283 |
+ rret = fread(buf, 1, sizeof(buf), fp); |
284 |
+ if (rret > 0) { |
285 |
+ char *s; |
286 |
+ |
287 |
+ buf[rret] = '\0'; |
288 |
+ |
289 |
+ s = buf; |
290 |
+ while ((s = strchr(s, '\n')) != NULL) |
291 |
+ *s = ' '; |
292 |
+ rmspace(buf); |
293 |
+ } |
294 |
+ |
295 |
+ /* takes care of close(pipefd[0]) */ |
296 |
+ fclose(fp); |
297 |
+ |
298 |
+ return buf; |
299 |
} |
300 |
|
301 |
-static int |
302 |
+_q_static int |
303 |
config_protected(const char *buf, int cp_argc, char **cp_argv, |
304 |
int cpm_argc, char **cpm_argv) |
305 |
{ |
306 |
@@ -264,7 +297,7 @@ |
307 |
return 0; |
308 |
} |
309 |
|
310 |
-static void crossmount_rm(const char *fname, const struct stat st) |
311 |
+_q_static void crossmount_rm(const char *fname, const struct stat st) |
312 |
{ |
313 |
struct stat lst; |
314 |
|
315 |
@@ -312,8 +345,8 @@ |
316 |
} |
317 |
} |
318 |
|
319 |
-char *atom2str(depend_atom *atom, char *buf, size_t size); |
320 |
-char *atom2str(depend_atom *atom, char *buf, size_t size) |
321 |
+_q_static char * |
322 |
+atom2str(const depend_atom *atom, char *buf, size_t size) |
323 |
{ |
324 |
if (atom->PR_int) |
325 |
snprintf(buf, size, "%s-%s-r%i", atom->PN, atom->PV, atom->PR_int); |
326 |
@@ -322,8 +355,8 @@ |
327 |
return buf; |
328 |
} |
329 |
|
330 |
-char qprint_tree_node(int level, depend_atom *atom, struct pkg_t *pkg); |
331 |
-char qprint_tree_node(int level, depend_atom *atom, struct pkg_t *pkg) |
332 |
+_q_static char |
333 |
+qprint_tree_node(int level, const depend_atom *atom, const struct pkg_t *pkg) |
334 |
{ |
335 |
char buf[1024]; |
336 |
char *p; |
337 |
@@ -386,40 +419,57 @@ |
338 |
return c; |
339 |
} |
340 |
|
341 |
-static void pkg_run_func(const char *vdb_path, const char *phases, const char *func) |
342 |
+_q_static void pkg_run_func(const char *vdb_path, const char *phases, const char *func) |
343 |
{ |
344 |
+ const char *phase; |
345 |
char *script; |
346 |
|
347 |
/* This assumes no func is a substring of another func. |
348 |
* Today, that assumption is valid for all funcs ... |
349 |
* The phases are the func with the "pkg_" chopped off. */ |
350 |
- if (strstr(phases, func + 4) == NULL) |
351 |
+ phase = func + 4; |
352 |
+ if (strstr(phases, phase) == NULL) { |
353 |
+ qprintf("--- %s\n", func); |
354 |
return; |
355 |
+ } |
356 |
|
357 |
qprintf(">>> %s\n", func); |
358 |
|
359 |
xasprintf(&script, |
360 |
/* Provide funcs required by the PMS */ |
361 |
+ "EBUILD_PHASE=%3$s\n" |
362 |
"debug-print() { :; }\n" |
363 |
"debug-print-function() { :; }\n" |
364 |
"debug-print-section() { :; }\n" |
365 |
+ /* Not quite right */ |
366 |
+ "has_version() { qlist -ICq -e '$1' >/dev/null; }\n" |
367 |
"use() { useq \"$@\"; }\n" |
368 |
"useq() { hasq $1 $USE; }\n" |
369 |
"has() { hasq \"$@\"; }\n" |
370 |
"hasq() { local h=$1; shift; case \" $* \" in *\" $h \"*) return 0;; *) return 1;; esac; }\n" |
371 |
+ "elog() { printf ' * %%b\\n' \"$*\"; }\n" |
372 |
+ "einfo() { elog \"$@\"; }\n" |
373 |
+ "ewarn() { elog \"$@\"; }\n" |
374 |
+ "eerror() { elog \"$@\"; }\n" |
375 |
+ "die() { eerror \"$@\"; exit 1; }\n" |
376 |
+ "ebegin() { printf ' * %%b ...' \"$*\"; }\n" |
377 |
+ "eend() { local r=${1:-$?}; [ $r -eq 0 ] && echo '[ ok ]' || echo '[ !! ]'; return $r; }\n" |
378 |
/* Unpack the env if need be */ |
379 |
"[ -e '%1$s/environment' ] || { bzip2 -dc '%1$s/environment.bz2' > '%1$s/environment' || exit 1; }\n" |
380 |
/* Load the env and run the func */ |
381 |
- ". %1$s/environment && %2$s", |
382 |
- vdb_path, func); |
383 |
+ ". '%1$s/environment' && %2$s\n" |
384 |
+ /* Ignore func return values (not exit values) */ |
385 |
+ ":", |
386 |
+ vdb_path, func, phase); |
387 |
xsystembash(script); |
388 |
free(script); |
389 |
} |
390 |
|
391 |
/* Copy one tree (the single package) to another tree (ROOT) */ |
392 |
-static int merge_tree_at(int fd_src, const char *src, int fd_dst, const char *dst, |
393 |
- FILE *contents, char **cpathp, int iargc, char **iargv, |
394 |
- int cp_argc, char **cp_argv, int cpm_argc, char **cpm_argv) |
395 |
+_q_static int |
396 |
+merge_tree_at(int fd_src, const char *src, int fd_dst, const char *dst, |
397 |
+ FILE *contents, queue **objs, char **cpathp, int iargc, char **iargv, |
398 |
+ int cp_argc, char **cp_argv, int cpm_argc, char **cpm_argv) |
399 |
{ |
400 |
int i, ret, subfd_src, subfd_dst; |
401 |
DIR *dir; |
402 |
@@ -458,7 +508,7 @@ |
403 |
/* Build up the full path for this entry */ |
404 |
nlen = strlen(name); |
405 |
if (mnlen < nlen) { |
406 |
- cpath = *cpathp = realloc(*cpathp, nlen + clen + 2); |
407 |
+ cpath = *cpathp = xrealloc(*cpathp, clen + 1 + nlen + 1); |
408 |
mnlen = nlen; |
409 |
} |
410 |
strcpy(cpath + clen + 1, name); |
411 |
@@ -489,13 +539,21 @@ |
412 |
/* XXX: update times of dir ? */ |
413 |
} |
414 |
|
415 |
+#if 0 /* We filter out "dir" as it's generally unnecessary cruft */ |
416 |
/* syntax: dir dirname */ |
417 |
fprintf(contents, "dir %s\n", cpath); |
418 |
+ *objs = add_set(cpath, "", *objs); |
419 |
qprintf("%s>>>%s %s%s%s/\n", GREEN, NORM, DKBLUE, cpath, NORM); |
420 |
+#endif |
421 |
|
422 |
/* Copy all of these contents */ |
423 |
- merge_tree_at(subfd_src, name, subfd_dst, name, contents, cpathp, |
424 |
+ merge_tree_at(subfd_src, name, subfd_dst, name, contents, objs, cpathp, |
425 |
iargc, iargv, cp_argc, cp_argv, cpm_argc, cpm_argv); |
426 |
+ cpath = *cpathp; |
427 |
+ mnlen = 0; |
428 |
+ |
429 |
+ /* In case we didn't install anything, prune the empty dir */ |
430 |
+ unlinkat(subfd_dst, name, AT_REMOVEDIR); |
431 |
} |
432 |
|
433 |
/* Migrate a file */ |
434 |
@@ -531,10 +589,11 @@ |
435 |
dname = name; |
436 |
qprintf("%s>>>%s %s\n", GREEN, NORM, cpath); |
437 |
} |
438 |
+ *objs = add_set(cpath, "", *objs); |
439 |
|
440 |
/* First try fast path -- src/dst are same device */ |
441 |
- if (renameat(subfd_src, dname, subfd_dst, name)) |
442 |
- ; |
443 |
+ if (renameat(subfd_src, dname, subfd_dst, name) == 0) |
444 |
+ continue; |
445 |
|
446 |
/* Fall back to slow path -- manual read/write */ |
447 |
fd_srcf = openat(subfd_src, name, O_RDONLY|O_CLOEXEC); |
448 |
@@ -605,6 +664,7 @@ |
449 |
/* syntax: sym src -> dst mtime */ |
450 |
fprintf(contents, "sym %s -> %s %lu\n", cpath, sym, (unsigned long)st.st_mtime); |
451 |
qprintf("%s>>>%s %s%s -> %s%s\n", GREEN, NORM, CYAN, cpath, sym, NORM); |
452 |
+ *objs = add_set(cpath, "", *objs); |
453 |
|
454 |
/* Make it in the dest tree */ |
455 |
if (symlinkat(sym, subfd_dst, name)) { |
456 |
@@ -630,6 +690,8 @@ |
457 |
} |
458 |
} |
459 |
|
460 |
+ ret = 0; |
461 |
+ |
462 |
done: |
463 |
close(subfd_src); |
464 |
close(subfd_dst); |
465 |
@@ -638,8 +700,9 @@ |
466 |
} |
467 |
|
468 |
/* Copy one tree (the single package) to another tree (ROOT) */ |
469 |
-static int merge_tree(const char *src, const char *dst, FILE *contents, |
470 |
- int iargc, char **iargv) |
471 |
+_q_static int |
472 |
+merge_tree(const char *src, const char *dst, FILE *contents, |
473 |
+ queue **objs, int iargc, char **iargv) |
474 |
{ |
475 |
int ret; |
476 |
int cp_argc, cpm_argc; |
477 |
@@ -654,7 +717,7 @@ |
478 |
makeargv(config_protect_mask, &cpm_argc, &cpm_argv); |
479 |
|
480 |
cpath = xstrdup(""); |
481 |
- ret = merge_tree_at(AT_FDCWD, src, AT_FDCWD, dst, contents, &cpath, |
482 |
+ ret = merge_tree_at(AT_FDCWD, src, AT_FDCWD, dst, contents, objs, &cpath, |
483 |
iargc, iargv, cp_argc, cp_argv, cpm_argc, cpm_argv); |
484 |
free(cpath); |
485 |
|
486 |
@@ -665,17 +728,16 @@ |
487 |
} |
488 |
|
489 |
/* oh shit getting into pkg mgt here. FIXME: write a real dep resolver. */ |
490 |
-void pkg_merge(int level, depend_atom *atom, struct pkg_t *pkg) |
491 |
+_q_static void |
492 |
+pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg) |
493 |
{ |
494 |
+ queue *objs; |
495 |
FILE *fp, *contents; |
496 |
char buf[1024], phases[128]; |
497 |
- char tarball[255]; |
498 |
- char *p; |
499 |
+ char *tbz2, *p; |
500 |
int i; |
501 |
char **ARGV; |
502 |
int ARGC; |
503 |
- const char *saved_argv0 = argv0; |
504 |
- int ret, saved_optind = optind; |
505 |
struct stat st; |
506 |
char c; |
507 |
char **iargv; |
508 |
@@ -696,6 +758,8 @@ |
509 |
*/ |
510 |
|
511 |
if (pkg->RDEPEND[0] && follow_rdepends) { |
512 |
+ const char *rdepend; |
513 |
+ |
514 |
IF_DEBUG(fprintf(stderr, "\n+Parent: %s/%s\n", pkg->CATEGORY, pkg->PF)); |
515 |
IF_DEBUG(fprintf(stderr, "+Depstring: %s\n", pkg->RDEPEND)); |
516 |
|
517 |
@@ -703,11 +767,12 @@ |
518 |
if (strncmp(pkg->RDEPEND, "|| ", 3) == 0) { |
519 |
if (verbose) |
520 |
qfprintf(stderr, "fix this rdepend hack %s\n", pkg->RDEPEND); |
521 |
- strcpy(pkg->RDEPEND, ""); |
522 |
- } |
523 |
+ rdepend = ""; |
524 |
+ } else |
525 |
+ rdepend = pkg->RDEPEND; |
526 |
/* </hack> */ |
527 |
|
528 |
- makeargv(pkg->RDEPEND, &ARGC, &ARGV); |
529 |
+ makeargv(rdepend, &ARGC, &ARGV); |
530 |
/* Walk the rdepends here. Merging what need be. */ |
531 |
for (i = 1; i < ARGC; i++) { |
532 |
depend_atom *subatom, *ratom; |
533 |
@@ -720,6 +785,7 @@ |
534 |
case '=': |
535 |
if (verbose) |
536 |
qfprintf(stderr, "Unhandled depstring %s\n", name); |
537 |
+ case '\0': |
538 |
break; |
539 |
default: |
540 |
if (*name == '~') { |
541 |
@@ -731,7 +797,6 @@ |
542 |
struct pkg_t *subpkg; |
543 |
char *resolved = NULL; |
544 |
|
545 |
- dep = NULL; |
546 |
dep = find_binpkg(name); |
547 |
|
548 |
if (strncmp(name, "virtual/", 8) == 0) { |
549 |
@@ -785,11 +850,11 @@ |
550 |
if (pretend) |
551 |
return; |
552 |
|
553 |
- xchdir(port_tmpdir); |
554 |
- |
555 |
- mkdir(pkg->PF, 0755); |
556 |
- /* mkdir(pkg->PF, 0710); */ |
557 |
- xchdir(pkg->PF); |
558 |
+ /* Set up our temp dir to unpack this stuff */ |
559 |
+ xasprintf(&p, "%s/qmerge/%s", port_tmpdir, pkg->PF); |
560 |
+ mkdir_p(p, 0755); |
561 |
+ xchdir(p); |
562 |
+ free(p); |
563 |
|
564 |
/* Doesn't actually remove $PWD, just everything under it */ |
565 |
rm_rf("."); |
566 |
@@ -798,144 +863,147 @@ |
567 |
* tarball directly rather than unpacking it first. */ |
568 |
|
569 |
/* split the tbz and xpak data */ |
570 |
- snprintf(tarball, sizeof(tarball), "%s.tbz2", pkg->PF); |
571 |
- snprintf(buf, sizeof(buf), "%s/%s/%s", pkgdir, pkg->CATEGORY, tarball); |
572 |
- unlink(tarball); |
573 |
- if (symlink(buf, tarball)) |
574 |
- errp("symlink(%s, %s) failed", buf, tarball); |
575 |
+ xasprintf(&tbz2, "%s/%s/%s.tbz2", pkgdir, pkg->CATEGORY, pkg->PF); |
576 |
+ assert(run_applet_l("qtbz2", "-s", tbz2, NULL) == 0); |
577 |
+ |
578 |
mkdir("vdb", 0755); |
579 |
- mkdir("image", 0755); |
580 |
+ sprintf(tbz2, "%s.xpak", pkg->PF); |
581 |
+ assert(run_applet_l("qxpak", "-d", "vdb", "-x", tbz2, NULL) == 0); |
582 |
|
583 |
- /* unpack the tarball using our internal qxpak */ |
584 |
- ARGC = 3; |
585 |
- ARGV = xmalloc(sizeof(*ARGV) * ARGC); |
586 |
- ARGV[0] = (char *)"qtbz2"; |
587 |
- ARGV[1] = (char *)"-s"; |
588 |
- ARGV[2] = tarball; |
589 |
- argv0 = ARGV[0]; |
590 |
- optind = 0; |
591 |
- assert(qtbz2_main(ARGC, ARGV) == 0); |
592 |
- argv0 = saved_argv0; |
593 |
- optind = saved_optind; |
594 |
- free(ARGV); |
595 |
- |
596 |
- /* list and extract vdb files from the xpak */ |
597 |
- snprintf(buf, sizeof(buf), "qxpak -d %s/%s/vdb -x %s.xpak `qxpak -l %s.xpak`", |
598 |
- port_tmpdir, pkg->PF, pkg->PF, pkg->PF); |
599 |
- xsystem(buf); |
600 |
+ free(tbz2); |
601 |
|
602 |
/* extrct the binary package data */ |
603 |
+ mkdir("image", 0755); |
604 |
snprintf(buf, sizeof(buf), BUSYBOX " tar -jx%sf %s.tar.bz2 -C image/", ((verbose > 1) ? "v" : ""), pkg->PF); |
605 |
xsystem(buf); |
606 |
fflush(stdout); |
607 |
|
608 |
+ eat_file("vdb/DEFINED_PHASES", phases, sizeof(phases)); |
609 |
+ pkg_run_func("vdb", phases, "pkg_preinst"); |
610 |
+ |
611 |
+ /* XXX: kill this off */ |
612 |
+ xchdir("image"); |
613 |
+ |
614 |
+ if (stat(".", &st) == -1) |
615 |
+ err("Cant stat pwd"); |
616 |
+ |
617 |
+ /* Initialize INSTALL_MASK and common stuff */ |
618 |
+ makeargv(install_mask, &iargc, &iargv); |
619 |
+ /* XXX: Would be better if INSTALL_MASK deleted from image/ |
620 |
+ * so we didn't have to parse it while doing merge_tree() */ |
621 |
+ install_mask_pwd(iargc, iargv, st); |
622 |
+ |
623 |
+ if (strstr(features, "noinfo")) rm_rf("./usr/share/info"); |
624 |
+ if (strstr(features, "noman" )) rm_rf("./usr/share/man"); |
625 |
+ if (strstr(features, "nodoc" )) rm_rf("./usr/share/doc"); |
626 |
+ |
627 |
+ /* we dont care about the return code */ |
628 |
+ rmdir("./usr/share"); |
629 |
+ |
630 |
+ /* XXX: Once we kill xchdir(image), this can die too */ |
631 |
+ xchdir(".."); |
632 |
+ |
633 |
+ if ((contents = fopen("vdb/CONTENTS", "w")) == NULL) |
634 |
+ errf("come on wtf?"); |
635 |
+ objs = NULL; |
636 |
+ merge_tree("image", portroot, contents, &objs, iargc, iargv); |
637 |
+ fclose(contents); |
638 |
+ |
639 |
+ freeargv(iargc, iargv); |
640 |
+ |
641 |
+ /* run postinst */ |
642 |
+ pkg_run_func("vdb", phases, "pkg_postinst"); |
643 |
+ |
644 |
+ /* XXX: hmm, maybe we'll want to strip more ? */ |
645 |
+ unlink("vdb/environment"); |
646 |
+ |
647 |
+ /* FIXME */ /* move unmerging to around here ? */ |
648 |
/* check for an already installed pkg */ |
649 |
snprintf(buf, sizeof(buf), "%s/%s", atom->CATEGORY, pkg->PF); |
650 |
|
651 |
- /* Unmerge the other versions */ |
652 |
+ /* Unmerge any stray pieces from the older version which we didn't replace */ |
653 |
p = best_version(atom->CATEGORY, atom->PN); |
654 |
if (*p) { |
655 |
+ /* XXX: Should see about merging with unmerge_packages() */ |
656 |
makeargv(p, &ARGC, &ARGV); |
657 |
for (i = 1; i < ARGC; i++) { |
658 |
- char pf[126]; |
659 |
+ int ret, u; |
660 |
+ const char *pn; |
661 |
+ char *pf; |
662 |
char *slot = NULL; |
663 |
- char u; |
664 |
|
665 |
- strncpy(pf, ARGV[i], sizeof(pf)); |
666 |
+ pf = ARGV[i]; |
667 |
switch ((ret = atom_compare_str(buf, pf))) { |
668 |
- case ERROR: break; |
669 |
- case NOT_EQUAL: break; |
670 |
+ case ERROR: |
671 |
+ case NOT_EQUAL: |
672 |
+ continue; |
673 |
case NEWER: |
674 |
case OLDER: |
675 |
case EQUAL: |
676 |
u = 1; |
677 |
- slot = grab_vdb_item("SLOT", atom->CATEGORY, basename(pf)); |
678 |
+ pn = basename(pf); |
679 |
+ slot = grab_vdb_item("SLOT", atom->CATEGORY, pn); |
680 |
if (pkg->SLOT[0] && slot) { |
681 |
if (strcmp(pkg->SLOT, slot) != 0) |
682 |
u = 0; |
683 |
} |
684 |
/* We need to really set this unmerge pending after we look at contents of the new pkg */ |
685 |
if (u) |
686 |
- pkg_unmerge(atom->CATEGORY, basename(pf)); |
687 |
- break; |
688 |
+ break; |
689 |
+ continue; |
690 |
default: |
691 |
warn("no idea how we reached here."); |
692 |
- break; |
693 |
+ continue; |
694 |
} |
695 |
- qprintf("%s+++%s %s %s %s\n", GREEN, NORM, buf, booga[ret], ARGV[i]); |
696 |
+ |
697 |
+ qprintf("%s+++%s %s %s %s\n", GREEN, NORM, buf, booga[ret], pf); |
698 |
+ |
699 |
+ pkg_unmerge(atom->CATEGORY, pn, objs); |
700 |
} |
701 |
freeargv(ARGC, ARGV); |
702 |
} |
703 |
|
704 |
- xchdir("image"); |
705 |
- |
706 |
- eat_file("../vdb/DEFINED_PHASES", phases, sizeof(phases)); |
707 |
- pkg_run_func("../vdb", phases, "pkg_preinst"); |
708 |
- |
709 |
- if (stat(".", &st) == -1) |
710 |
- err("Cant stat pwd"); |
711 |
- |
712 |
- /* Initialize INSTALL_MASK and common stuff */ |
713 |
- makeargv(install_mask, &iargc, &iargv); |
714 |
- install_mask_pwd(iargc, iargv, st); |
715 |
- |
716 |
- if (strstr(features, "noinfo")) rm_rf("./usr/share/info"); |
717 |
- if (strstr(features, "noman" )) rm_rf("./usr/share/man"); |
718 |
- if (strstr(features, "nodoc" )) rm_rf("./usr/share/doc"); |
719 |
- |
720 |
- /* we dont care about the return code */ |
721 |
- rmdir("./usr/share"); |
722 |
- |
723 |
- if ((contents = fopen("../vdb/CONTENTS", "w")) == NULL) |
724 |
- errf("come on wtf?"); |
725 |
- |
726 |
- merge_tree(".", portroot, contents, iargc, iargv); |
727 |
- |
728 |
- fclose(contents); |
729 |
- |
730 |
- freeargv(iargc, iargv); |
731 |
- |
732 |
- xchdir(port_tmpdir); |
733 |
- xchdir(pkg->PF); |
734 |
- |
735 |
- /* run postinst */ |
736 |
- pkg_run_func("./vdb", phases, "pkg_postinst"); |
737 |
- |
738 |
- /* FIXME */ /* move unmerging to around here ? */ |
739 |
- /* not perfect when a version is already installed */ |
740 |
- snprintf(buf, sizeof(buf), "%s/var/db/pkg/%s/", portroot, pkg->CATEGORY); |
741 |
- if (access(buf, R_OK|W_OK|X_OK) != 0) |
742 |
- mkdir_p(buf, 0755); |
743 |
- strncat(buf, pkg->PF, sizeof(buf)-strlen(buf)-1); |
744 |
- if (access(buf, X_OK) == 0) { |
745 |
- /* we need to compare CONTENTS in it and remove any file not provided by our CONTENTS */ |
746 |
- rm_rf(buf); |
747 |
+ /* Clean up the package state */ |
748 |
+ while (objs) { |
749 |
+ queue *q = objs; |
750 |
+ objs = q->next; |
751 |
+ free(q->name); |
752 |
+ free(q->item); |
753 |
+ free(q); |
754 |
} |
755 |
|
756 |
+ /* Update the magic counter */ |
757 |
if ((fp = fopen("vdb/COUNTER", "w")) != NULL) { |
758 |
fputs("0", fp); |
759 |
fclose(fp); |
760 |
} |
761 |
+ |
762 |
/* move the local vdb copy to the final place */ |
763 |
- interactive_rename("vdb", buf, pkg); |
764 |
+ snprintf(buf, sizeof(buf), "%s%s/%s/", portroot, portvdb, pkg->CATEGORY); |
765 |
+ mkdir_p(buf, 0755); |
766 |
+ strcat(buf, pkg->PF); |
767 |
+ if (rename("vdb", buf)) { |
768 |
+ xasprintf(&p, "mv vdb '%s'", buf); |
769 |
+ xsystem(p); |
770 |
+ free(p); |
771 |
+ } |
772 |
|
773 |
- snprintf(buf, sizeof(buf), "%s.tar.bz2", pkg->PF); |
774 |
- unlink_q(buf); |
775 |
- xchdir(port_tmpdir); |
776 |
+ /* clean up our local temp dir */ |
777 |
+ xchdir(".."); |
778 |
rm_rf(pkg->PF); |
779 |
- |
780 |
- snprintf(buf, sizeof(buf), "%s/%s.tbz2", pkgdir, pkg->PF); |
781 |
- unlink(buf); |
782 |
+ /* don't care about return */ |
783 |
+ rmdir("../qmerge"); |
784 |
|
785 |
printf("%s>>>%s %s%s%s/%s%s%s\n", YELLOW, NORM, WHITE, atom->CATEGORY, NORM, CYAN, atom->PN, NORM); |
786 |
} |
787 |
|
788 |
-int pkg_unmerge(const char *cat, const char *pkgname) |
789 |
+_q_static int |
790 |
+pkg_unmerge(const char *cat, const char *pkgname, queue *keep) |
791 |
{ |
792 |
size_t buflen; |
793 |
char *buf, *vdb_path, phases[128]; |
794 |
FILE *fp; |
795 |
- int ret, fd, vdb_fd; |
796 |
+ int ret, fd, vdb_fd, portroot_fd; |
797 |
int cp_argc, cpm_argc; |
798 |
char **cp_argv, **cpm_argv; |
799 |
llist_char *dirs = NULL; |
800 |
@@ -943,7 +1011,7 @@ |
801 |
ret = 1; |
802 |
buf = NULL; |
803 |
vdb_path = NULL; |
804 |
- vdb_fd = fd = -1; |
805 |
+ vdb_fd = portroot_fd = fd = -1; |
806 |
|
807 |
if ((strchr(pkgname, ' ') != NULL) || (strchr(cat, ' ') != NULL)) { |
808 |
qfprintf(stderr, "%s!!!%s '%s' '%s' (ambiguous name) specify fully-qualified pkgs\n", RED, NORM, cat, pkgname); |
809 |
@@ -956,9 +1024,17 @@ |
810 |
if (pretend == 100) |
811 |
return 0; |
812 |
|
813 |
+ /* Get a handle to the root to play with */ |
814 |
+ portroot_fd = open(portroot, O_RDONLY | O_CLOEXEC); |
815 |
+ if (portroot_fd == -1) { |
816 |
+ warnp("unable to read %s", portroot); |
817 |
+ goto done; |
818 |
+ } |
819 |
+ |
820 |
/* Get a handle on the vdb path which we'll use everywhere else */ |
821 |
- xasprintf(&vdb_path, "%s/%s/%s/%s/", portroot, portvdb, cat, pkgname); |
822 |
- vdb_fd = open(vdb_path, O_RDONLY | O_CLOEXEC); |
823 |
+ /* Note: This vdb_path must be absolute since we use it in pkg_run_func() */ |
824 |
+ xasprintf(&vdb_path, "%s%s/%s/%s/", portroot, portvdb, cat, pkgname); |
825 |
+ vdb_fd = openat(portroot_fd, vdb_path, O_RDONLY | O_CLOEXEC); |
826 |
if (vdb_fd == -1) { |
827 |
warnp("unable to read %s", vdb_path); |
828 |
goto done; |
829 |
@@ -988,66 +1064,84 @@ |
830 |
makeargv(config_protect_mask, &cpm_argc, &cpm_argv); |
831 |
|
832 |
while (getline(&buf, &buflen, fp) != -1) { |
833 |
+ queue *q; |
834 |
contents_entry *e; |
835 |
char zing[20]; |
836 |
int protected = 0; |
837 |
- struct stat lst; |
838 |
- char dst[_Q_PATH_MAX]; |
839 |
+ struct stat st; |
840 |
|
841 |
e = contents_parse_line(buf); |
842 |
- if (!e) continue; |
843 |
- snprintf(dst, sizeof(dst), "%s%s", portroot, e->name); |
844 |
+ if (!e) |
845 |
+ continue; |
846 |
+ |
847 |
protected = config_protected(e->name, cp_argc, cp_argv, cpm_argc, cpm_argv); |
848 |
snprintf(zing, sizeof(zing), "%s%s%s", protected ? YELLOW : GREEN, protected ? "***" : "<<<" , NORM); |
849 |
|
850 |
+ /* This should never happen ... */ |
851 |
+ assert(e->name[0] == '/' && e->name[1] != '/'); |
852 |
+ |
853 |
/* Should we remove in order symlinks,objects,dirs ? */ |
854 |
switch (e->type) { |
855 |
case CONTENTS_DIR: |
856 |
if (!protected) { |
857 |
/* since the dir contains files, we remove it later */ |
858 |
llist_char *list = xmalloc(sizeof(llist_char)); |
859 |
- list->data = xstrdup(dst); |
860 |
+ list->data = xstrdup(e->name); |
861 |
list->next = dirs; |
862 |
dirs = list; |
863 |
} |
864 |
- break; |
865 |
+ continue; |
866 |
+ |
867 |
case CONTENTS_OBJ: |
868 |
- if (!protected) |
869 |
- unlink_q(dst); |
870 |
- qprintf("%s %s\n", zing, dst); |
871 |
break; |
872 |
+ |
873 |
case CONTENTS_SYM: |
874 |
- if (protected) |
875 |
- break; |
876 |
- if (e->name[0] != '/') |
877 |
- break; |
878 |
- if (e->sym_target[0] != '/') { |
879 |
- if (lstat(dst, &lst) != -1) { |
880 |
- if (S_ISLNK(lst.st_mode)) { |
881 |
- qprintf("%s %s%s -> %s%s\n", zing, CYAN, dst, e->sym_target, NORM); |
882 |
- unlink_q(dst); |
883 |
- break; |
884 |
- } |
885 |
- } else { |
886 |
- warnp("lstat failed for %s -> '%s'", dst, e->sym_target); |
887 |
- } |
888 |
- warn("!!! %s -> %s", e->name, e->sym_target); |
889 |
- break; |
890 |
- } |
891 |
- if (lstat(dst, &lst) != -1) { |
892 |
- if (S_ISLNK(lst.st_mode)) { |
893 |
- qprintf("%s %s%s -> %s%s\n", zing, CYAN, dst, e->sym_target, NORM); |
894 |
- unlink_q(dst); |
895 |
- } else { |
896 |
- warn("%s is not a symlink", dst); |
897 |
- } |
898 |
- } else { |
899 |
- warnp("lstat failed for '%s' -> %s", dst, e->sym_target); |
900 |
+ if (fstatat(portroot_fd, e->name + 1, &st, AT_SYMLINK_NOFOLLOW)) { |
901 |
+ warnp("stat failed for %s -> '%s'", e->name, e->sym_target); |
902 |
+ continue; |
903 |
} |
904 |
+ |
905 |
+ /* Hrm, if it isn't a symlink anymore, then leave it be */ |
906 |
+ if (!S_ISLNK(st.st_mode)) |
907 |
+ continue; |
908 |
+ |
909 |
break; |
910 |
+ |
911 |
default: |
912 |
- warn("%s???%s %s%s%s (%d)", RED, NORM, WHITE, dst, NORM, e->type); |
913 |
+ warn("%s???%s %s%s%s (%d)", RED, NORM, WHITE, e->name, NORM, e->type); |
914 |
+ continue; |
915 |
+ } |
916 |
+ |
917 |
+ if (protected) { |
918 |
+ qprintf("%s %s\n", zing, e->name); |
919 |
+ continue; |
920 |
+ } |
921 |
+ |
922 |
+ /* See if this was updated */ |
923 |
+ q = keep; |
924 |
+ while (q) { |
925 |
+ if (!strcmp(q->name, e->name)) { |
926 |
+ /* XXX: could remove this from the queue */ |
927 |
+ strcpy(zing, "---"); |
928 |
+ q = NULL; |
929 |
break; |
930 |
+ } |
931 |
+ q = q->next; |
932 |
+ } |
933 |
+ |
934 |
+ /* No match, so unmerge it */ |
935 |
+ if (!quiet) |
936 |
+ printf("%s %s\n", zing, e->name); |
937 |
+ if (!keep || q) { |
938 |
+ char *p; |
939 |
+ |
940 |
+ unlinkat(portroot_fd, e->name + 1, 0); |
941 |
+ |
942 |
+ p = strrchr(e->name, '/'); |
943 |
+ if (p) { |
944 |
+ *p = '\0'; |
945 |
+ rmdir_r_at(portroot_fd, e->name + 1); |
946 |
+ } |
947 |
} |
948 |
} |
949 |
|
950 |
@@ -1060,7 +1154,7 @@ |
951 |
char *dir = list->data; |
952 |
int rm; |
953 |
|
954 |
- rm = pretend ? -1 : rmdir(dir); |
955 |
+ rm = pretend ? -1 : rmdir_r_at(portroot_fd, dir + 1); |
956 |
qprintf("%s%s%s %s%s%s/\n", rm ? YELLOW : GREEN, rm ? "---" : "<<<", |
957 |
NORM, DKBLUE, dir, NORM); |
958 |
|
959 |
@@ -1079,15 +1173,10 @@ |
960 |
pkg_run_func(vdb_path, phases, "pkg_postrm"); |
961 |
|
962 |
/* Finally delete the vdb entry */ |
963 |
- rm_rf(vdb_path); |
964 |
+ rm_rf_at(portroot_fd, vdb_path); |
965 |
|
966 |
/* And prune any empty vdb dirs */ |
967 |
- dir = strrchr(vdb_path, '/'); |
968 |
- *dir = '\0'; |
969 |
- rmdir(vdb_path); |
970 |
- dir = strrchr(vdb_path, '/'); |
971 |
- *dir = '\0'; |
972 |
- rmdir(vdb_path); |
973 |
+ rmdir_r_at(portroot_fd, vdb_path); |
974 |
} |
975 |
|
976 |
ret = 0; |
977 |
@@ -1096,13 +1185,15 @@ |
978 |
close(fd); |
979 |
if (vdb_fd != -1) |
980 |
close(vdb_fd); |
981 |
+ if (portroot_fd != -1) |
982 |
+ close(portroot_fd); |
983 |
free(buf); |
984 |
free(vdb_path); |
985 |
|
986 |
return ret; |
987 |
} |
988 |
|
989 |
-int unlink_empty(char *buf) |
990 |
+_q_static int unlink_empty(const char *buf) |
991 |
{ |
992 |
struct stat st; |
993 |
if (stat(buf, &st) != -1) |
994 |
@@ -1111,7 +1202,7 @@ |
995 |
return -1; |
996 |
} |
997 |
|
998 |
-static int match_pkg(queue *ll, struct pkg_t *pkg) |
999 |
+_q_static int match_pkg(queue *ll, const struct pkg_t *pkg) |
1000 |
{ |
1001 |
depend_atom *atom; |
1002 |
char buf[255], buf2[255]; |
1003 |
@@ -1154,7 +1245,9 @@ |
1004 |
return match; |
1005 |
} |
1006 |
|
1007 |
-int pkg_verify_checksums(char *fname, struct pkg_t *pkg, depend_atom *atom, int strict, int display) |
1008 |
+_q_static int |
1009 |
+pkg_verify_checksums(char *fname, const struct pkg_t *pkg, const depend_atom *atom, |
1010 |
+ int strict, int display) |
1011 |
{ |
1012 |
char *hash = NULL; |
1013 |
int ret = 0; |
1014 |
@@ -1197,7 +1290,8 @@ |
1015 |
return ret; |
1016 |
} |
1017 |
|
1018 |
-static void pkg_process(queue *todo, struct pkg_t *pkg) |
1019 |
+_q_static |
1020 |
+void pkg_process(queue *todo, const struct pkg_t *pkg) |
1021 |
{ |
1022 |
queue *ll; |
1023 |
depend_atom *atom; |
1024 |
@@ -1221,11 +1315,10 @@ |
1025 |
atom_implode(atom); |
1026 |
} |
1027 |
|
1028 |
-void pkg_fetch(int level, depend_atom *atom, struct pkg_t *pkg) |
1029 |
+_q_static void |
1030 |
+pkg_fetch(int level, const depend_atom *atom, const struct pkg_t *pkg) |
1031 |
{ |
1032 |
- char savecwd[_POSIX_PATH_MAX]; |
1033 |
- char buf[255], str[255]; |
1034 |
- memset(str, 0, sizeof(str)); |
1035 |
+ char buf[_Q_PATH_MAX], str[_Q_PATH_MAX]; |
1036 |
|
1037 |
/* qmerge -pv patch */ |
1038 |
if (pretend) { |
1039 |
@@ -1242,6 +1335,8 @@ |
1040 |
snprintf(str, sizeof(str), "%s/%s", pkgdir, pkg->CATEGORY); |
1041 |
mkdir(str, 0755); |
1042 |
|
1043 |
+ /* XXX: should do a size check here for partial downloads */ |
1044 |
+ |
1045 |
if (force_download && (access(buf, R_OK) == 0) && (pkg->SHA1[0] || pkg->MD5[0])) { |
1046 |
if (pkg_verify_checksums(buf, pkg, atom, 0, 0) != 0) |
1047 |
unlink(buf); |
1048 |
@@ -1251,7 +1346,7 @@ |
1049 |
warn("No checksum data for %s", buf); |
1050 |
return; |
1051 |
} else { |
1052 |
- if (pkg_verify_checksums(buf, pkg, atom, qmerge_strict, 1) == 0) { |
1053 |
+ if (pkg_verify_checksums(buf, pkg, atom, qmerge_strict, !quiet) == 0) { |
1054 |
pkg_merge(0, atom, pkg); |
1055 |
return; |
1056 |
} |
1057 |
@@ -1282,25 +1377,16 @@ |
1058 |
fflush(stderr); |
1059 |
return; |
1060 |
} |
1061 |
- xgetcwd(savecwd, sizeof(savecwd)); |
1062 |
- xchdir(pkgdir); |
1063 |
- if (chdir("All/") == 0) { |
1064 |
- snprintf(buf, sizeof(buf), "%s.tbz2", pkg->PF); |
1065 |
- snprintf(str, sizeof(str), "../%s/%s.tbz2", atom->CATEGORY, pkg->PF); |
1066 |
- unlink(buf); |
1067 |
- if (symlink(str, buf)) |
1068 |
- errp("symlink(%s, %s) failed", str, buf); |
1069 |
- } |
1070 |
- xchdir(savecwd); |
1071 |
|
1072 |
snprintf(buf, sizeof(buf), "%s/%s/%s.tbz2", pkgdir, atom->CATEGORY, pkg->PF); |
1073 |
- if (pkg_verify_checksums(buf, pkg, atom, qmerge_strict, 1) == 0) { |
1074 |
+ if (pkg_verify_checksums(buf, pkg, atom, qmerge_strict, !quiet) == 0) { |
1075 |
pkg_merge(0, atom, pkg); |
1076 |
return; |
1077 |
} |
1078 |
} |
1079 |
|
1080 |
-void print_Pkg(int full, struct pkg_t *pkg) |
1081 |
+_q_static void |
1082 |
+print_Pkg(int full, struct pkg_t *pkg) |
1083 |
{ |
1084 |
char *p = NULL; |
1085 |
char buf[512]; |
1086 |
@@ -1358,10 +1444,13 @@ |
1087 |
atom_implode(atom); |
1088 |
} |
1089 |
|
1090 |
-static int unmerge_packages(queue *todo) |
1091 |
+_q_static int |
1092 |
+unmerge_packages(queue *todo) |
1093 |
{ |
1094 |
depend_atom *atom; |
1095 |
char *p; |
1096 |
+ int i, argc; |
1097 |
+ char **argv; |
1098 |
|
1099 |
while (todo) { |
1100 |
char buf[512]; |
1101 |
@@ -1372,11 +1461,18 @@ |
1102 |
p = best_version(NULL, todo->name); |
1103 |
if (!*p) |
1104 |
goto next; |
1105 |
- if ((atom = atom_explode(p)) == NULL) |
1106 |
- goto next; |
1107 |
- atom2str(atom, buf, sizeof(buf)); |
1108 |
- pkg_unmerge(atom->CATEGORY, buf); |
1109 |
- atom_implode(atom); |
1110 |
+ |
1111 |
+ makeargv(p, &argc, &argv); |
1112 |
+ for (i = 1; i < argc; ++i) { |
1113 |
+ if ((atom = atom_explode(argv[i])) == NULL) |
1114 |
+ continue; |
1115 |
+ if (atom->CATEGORY) { |
1116 |
+ atom2str(atom, buf, sizeof(buf)); |
1117 |
+ pkg_unmerge(atom->CATEGORY, buf, NULL); |
1118 |
+ } |
1119 |
+ atom_implode(atom); |
1120 |
+ } |
1121 |
+ freeargv(argc, argv); |
1122 |
|
1123 |
next: |
1124 |
todo = todo->next; |
1125 |
@@ -1385,7 +1481,8 @@ |
1126 |
return 0; |
1127 |
} |
1128 |
|
1129 |
-struct pkg_t *grab_binpkg_info(const char *name) |
1130 |
+_q_static struct pkg_t * |
1131 |
+grab_binpkg_info(const char *name) |
1132 |
{ |
1133 |
FILE *fp; |
1134 |
char buf[BUFSIZ]; |
1135 |
@@ -1490,7 +1587,8 @@ |
1136 |
return rpkg; |
1137 |
} |
1138 |
|
1139 |
-char *find_binpkg(const char *name) |
1140 |
+_q_static char * |
1141 |
+find_binpkg(const char *name) |
1142 |
{ |
1143 |
FILE *fp; |
1144 |
char buf[BUFSIZ]; |
1145 |
@@ -1572,7 +1670,8 @@ |
1146 |
return best_match; |
1147 |
} |
1148 |
|
1149 |
-static int parse_packages(queue *todo) |
1150 |
+_q_static int |
1151 |
+parse_packages(queue *todo) |
1152 |
{ |
1153 |
FILE *fp; |
1154 |
size_t buflen; |
1155 |
@@ -1670,7 +1769,8 @@ |
1156 |
return 0; |
1157 |
} |
1158 |
|
1159 |
-static queue *qmerge_add_set_atom(char *satom, queue *set) |
1160 |
+_q_static queue * |
1161 |
+qmerge_add_set_atom(char *satom, queue *set) |
1162 |
{ |
1163 |
char *p; |
1164 |
const char *slot; |
1165 |
@@ -1684,30 +1784,22 @@ |
1166 |
return add_set(satom, slot, set); |
1167 |
} |
1168 |
|
1169 |
-static queue *qmerge_add_set_file(const char *file, queue *set) |
1170 |
+_q_static queue * |
1171 |
+qmerge_add_set_file(const char *dir, const char *file, queue *set) |
1172 |
{ |
1173 |
FILE *fp; |
1174 |
size_t buflen; |
1175 |
- char *buf; |
1176 |
- const char *fname; |
1177 |
+ char *buf, *fname; |
1178 |
|
1179 |
/* Find the file to read */ |
1180 |
- if (*portroot && strcmp(portroot, "/") != 0) { |
1181 |
- size_t len, flen; |
1182 |
- char *f; |
1183 |
- |
1184 |
- len = strlen(portroot); |
1185 |
- flen = strlen(file) + 1; |
1186 |
- fname = f = alloca(len + flen); |
1187 |
- memcpy(f, portroot, len); |
1188 |
- memcpy(f + len, file, flen); |
1189 |
- } else |
1190 |
- fname = file; |
1191 |
+ xasprintf(&fname, "%s%s/%s", portroot, dir, file); |
1192 |
|
1193 |
if ((fp = fopen(fname, "r")) == NULL) { |
1194 |
warnp("unable to read set file %s", fname); |
1195 |
+ free(fname); |
1196 |
return NULL; |
1197 |
} |
1198 |
+ free(fname); |
1199 |
|
1200 |
/* Load each entry */ |
1201 |
buf = NULL; |
1202 |
@@ -1722,17 +1814,48 @@ |
1203 |
return set; |
1204 |
} |
1205 |
|
1206 |
-static queue *qmerge_add_set(char *buf, queue *set) |
1207 |
+_q_static void * |
1208 |
+qmerge_add_set_system(void *data, char *buf, FILE *fp) |
1209 |
+{ |
1210 |
+ queue *set = data; |
1211 |
+ char *s; |
1212 |
+ |
1213 |
+ s = strchr(buf, '#'); |
1214 |
+ if (s) |
1215 |
+ *s = '\0'; |
1216 |
+ rmspace(buf); |
1217 |
+ |
1218 |
+ s = buf; |
1219 |
+ if (*s == '*') |
1220 |
+ set = add_set(s + 1, "", set); |
1221 |
+ else if (s[0] == '-' && s[1] == '*') { |
1222 |
+ int ok; |
1223 |
+ set = del_set(s + 2, set, &ok); |
1224 |
+ } |
1225 |
+ |
1226 |
+ return set; |
1227 |
+} |
1228 |
+ |
1229 |
+/* XXX: note, this doesn't handle more complicated set files like |
1230 |
+ * the portage .ini files in /usr/share/portage/sets/ */ |
1231 |
+/* XXX: this code does not combine duplicate dependencies */ |
1232 |
+_q_static queue * |
1233 |
+qmerge_add_set(char *buf, queue *set) |
1234 |
{ |
1235 |
if (strcmp(buf, "world") == 0) |
1236 |
- return qmerge_add_set_file("/var/lib/portage/world", set); |
1237 |
- if (strcmp(buf, "all") == 0) |
1238 |
+ return qmerge_add_set_file("/var/lib/portage", "world", set); |
1239 |
+ else if (strcmp(buf, "all") == 0) |
1240 |
return get_vdb_atoms(0); |
1241 |
- /* XXX: Should load custom sets here */ |
1242 |
- return qmerge_add_set_atom(buf, set); |
1243 |
+ else if (strcmp(buf, "system") == 0) |
1244 |
+ return q_profile_walk("packages", qmerge_add_set_system, set); |
1245 |
+ else if (buf[0] == '@') |
1246 |
+ return qmerge_add_set_file("/etc/portage", buf+1, set); |
1247 |
+ else |
1248 |
+ return qmerge_add_set_atom(buf, set); |
1249 |
} |
1250 |
|
1251 |
-static int qmerge_run(queue *todo) |
1252 |
+_q_static int |
1253 |
+qmerge_run(queue *todo) |
1254 |
{ |
1255 |
if (uninstall) |
1256 |
return unmerge_packages(todo); |