1 |
vapier 11/02/21 22:02:59 |
2 |
|
3 |
Modified: qmerge.c |
4 |
Log: |
5 |
add support for CONFIG_PROTECT_MASK when unmerging, as well as running the pkg_{pre,post}rm funcs |
6 |
|
7 |
Revision Changes Path |
8 |
1.100 portage-utils/qmerge.c |
9 |
|
10 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?rev=1.100&view=markup |
11 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?rev=1.100&content-type=text/plain |
12 |
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?r1=1.99&r2=1.100 |
13 |
|
14 |
Index: qmerge.c |
15 |
=================================================================== |
16 |
RCS file: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v |
17 |
retrieving revision 1.99 |
18 |
retrieving revision 1.100 |
19 |
diff -u -r1.99 -r1.100 |
20 |
--- qmerge.c 21 Feb 2011 06:20:24 -0000 1.99 |
21 |
+++ qmerge.c 21 Feb 2011 22:02:59 -0000 1.100 |
22 |
@@ -1,7 +1,7 @@ |
23 |
/* |
24 |
* Copyright 2005-2010 Gentoo Foundation |
25 |
* Distributed under the terms of the GNU General Public License v2 |
26 |
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v 1.99 2011/02/21 06:20:24 vapier Exp $ |
27 |
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v 1.100 2011/02/21 22:02:59 vapier Exp $ |
28 |
* |
29 |
* Copyright 2005-2010 Ned Ludd - <solar@g.o> |
30 |
* Copyright 2005-2010 Mike Frysinger - <vapier@g.o> |
31 |
@@ -55,7 +55,7 @@ |
32 |
COMMON_OPTS_HELP |
33 |
}; |
34 |
|
35 |
-static const char qmerge_rcsid[] = "$Id: qmerge.c,v 1.99 2011/02/21 06:20:24 vapier Exp $"; |
36 |
+static const char qmerge_rcsid[] = "$Id: qmerge.c,v 1.100 2011/02/21 22:02:59 vapier Exp $"; |
37 |
#define qmerge_usage(ret) usage(ret, QMERGE_FLAGS, qmerge_long_opts, qmerge_opts_help, lookup_applet_idx("qmerge")) |
38 |
|
39 |
char search_pkgs = 0; |
40 |
@@ -105,7 +105,6 @@ |
41 |
void pkg_process(int, char **, struct pkg_t *); |
42 |
void print_Pkg(int, struct pkg_t *); |
43 |
int parse_packages(const char *, int, char **); |
44 |
-int config_protected(const char *, int, char **); |
45 |
int match_pkg(const char *, struct pkg_t *); |
46 |
int pkg_verify_checksums(char *, struct pkg_t *, depend_atom *, int strict, int display); |
47 |
int unmerge_packages(int, char **); |
48 |
@@ -129,8 +128,7 @@ |
49 |
return mkdir(dname, mode); |
50 |
} |
51 |
|
52 |
-int q_unlink_q(char *, const char *, int); |
53 |
-int q_unlink_q(char *path, const char *func, int line) |
54 |
+static int q_unlink_q(char *path, const char *func, int line) |
55 |
{ |
56 |
if ((strcmp(path, "/bin/sh") == 0) || (strcmp(path, BUSYBOX) == 0)) { |
57 |
warn("Oh hell no: unlink(%s) from %s line %d", path, func, line); |
58 |
@@ -153,7 +151,7 @@ |
59 |
struct stat st; |
60 |
char check_interactive = interactive; |
61 |
|
62 |
- if (check_interactive && (stat(dst, &st) != (-1))) { |
63 |
+ if (check_interactive && (stat(dst, &st) != -1)) { |
64 |
snprintf(buf, sizeof(buf), "qfile -Cqev %s 2>/dev/null", dst); |
65 |
if ((fp = popen(buf, "r")) != NULL) { |
66 |
buf[0] = '\0'; |
67 |
@@ -260,22 +258,29 @@ |
68 |
return (char *) buf; |
69 |
} |
70 |
|
71 |
-int config_protected(const char *buf, int ARGC, char **ARGV) |
72 |
+static int |
73 |
+config_protected(const char *buf, int cp_argc, char **cp_argv, |
74 |
+ int cpm_argc, char **cpm_argv) |
75 |
{ |
76 |
int i; |
77 |
char dest[_Q_PATH_MAX]; |
78 |
snprintf(dest, sizeof(dest), "%s%s", portroot, buf); |
79 |
|
80 |
- for (i = 1; i < ARGC; i++) |
81 |
- if (strncmp(ARGV[i], buf, strlen(ARGV[i])) == 0) |
82 |
- if ((access(dest, R_OK)) == 0) |
83 |
+ /* Check CONFIG_PROTECT_MASK */ |
84 |
+ for (i = 1; i < cpm_argc; ++i) |
85 |
+ if (strncmp(cpm_argv[i], buf, strlen(cpm_argv[i])) == 0) |
86 |
+ return 0; |
87 |
+ |
88 |
+ /* Check CONFIG_PROTECT */ |
89 |
+ for (i = 1; i < cp_argc; ++i) |
90 |
+ if (strncmp(cp_argv[i], buf, strlen(cp_argv[i])) == 0) |
91 |
+ if (access(dest, R_OK) == 0) |
92 |
return 1; |
93 |
|
94 |
- if (strncmp("/etc", buf, 4) == 0) |
95 |
- if (access(dest, R_OK) == 0) |
96 |
- return 1; |
97 |
+ /* this would probably be bad */ |
98 |
if (strcmp("/bin/sh", buf) == 0) |
99 |
return 1; |
100 |
+ |
101 |
return 0; |
102 |
} |
103 |
|
104 |
@@ -286,7 +291,7 @@ |
105 |
|
106 |
assert(pretend == 0); |
107 |
|
108 |
- if (lstat(buf, &lst) == (-1)) |
109 |
+ if (lstat(buf, &lst) == -1) |
110 |
return; |
111 |
if (lst.st_dev != st.st_dev) { |
112 |
warn("skipping crossmount install masking: %s", buf); |
113 |
@@ -623,7 +628,7 @@ |
114 |
} |
115 |
xchdir("image"); |
116 |
|
117 |
- if (stat("./", &st) == (-1)) |
118 |
+ if (stat("./", &st) == -1) |
119 |
err("Cant stat pwd"); |
120 |
|
121 |
makeargv(install_mask, &iargc, &iargv); |
122 |
@@ -699,7 +704,7 @@ |
123 |
snprintf(line, sizeof(line), "obj %s %s %lu", &buf[1], hash, st.st_mtime); |
124 |
/* /etc /usr/kde/2/share/config /usr/kde/3/share/config /var/qmail/control */ |
125 |
|
126 |
- protected = config_protected(&buf[1], ARGC, ARGV); |
127 |
+ protected = config_protected(&buf[1], ARGC, ARGV, 0, NULL); |
128 |
if (protected) { |
129 |
unsigned char *target_hash = hash_file(dest, HASH_MD5); |
130 |
if (memcmp(target_hash, hash, 16) != 0) { |
131 |
@@ -757,7 +762,7 @@ |
132 |
|
133 |
xgetcwd(pwd, sizeof(pwd)); |
134 |
xchdir(dirname(tmp)); /* tmp gets eatten up now by the dirname call */ |
135 |
- if (lstat(path, &lst) != (-1)) |
136 |
+ if (lstat(path, &lst) != -1) |
137 |
unlink_q(dest); |
138 |
/* if (path[0] != '/') |
139 |
puts("path does not start with /"); |
140 |
@@ -822,12 +827,19 @@ |
141 |
|
142 |
int pkg_unmerge(const char *cat, const char *pkgname) |
143 |
{ |
144 |
- char buf[BUFSIZ]; |
145 |
+ size_t buflen; |
146 |
+ char *buf, *vdb_path; |
147 |
FILE *fp; |
148 |
- int argc; |
149 |
- char **argv; |
150 |
+ int ret, fd, vdb_fd; |
151 |
+ int cp_argc, cpm_argc; |
152 |
+ char **cp_argv, **cpm_argv; |
153 |
llist_char *dirs = NULL; |
154 |
|
155 |
+ ret = 1; |
156 |
+ buf = NULL; |
157 |
+ vdb_path = NULL; |
158 |
+ vdb_fd = fd = -1; |
159 |
+ |
160 |
if ((strchr(pkgname, ' ') != NULL) || (strchr(cat, ' ') != NULL)) { |
161 |
qfprintf(stderr, "%s!!!%s '%s' '%s' (ambiguous name) specify fully-qualified pkgs\n", RED, NORM, cat, pkgname); |
162 |
qfprintf(stderr, "%s!!!%s %s/%s (ambiguous name) specify fully-qualified pkgs\n", RED, NORM, cat, pkgname); |
163 |
@@ -839,16 +851,44 @@ |
164 |
if (pretend == 100) |
165 |
return 0; |
166 |
|
167 |
- snprintf(buf, sizeof(buf), "%s/%s/%s/%s/CONTENTS", portroot, portvdb, cat, pkgname); |
168 |
- |
169 |
- if ((fp = fopen(buf, "r")) == NULL) |
170 |
- return 1; |
171 |
+ /* Get a handle on the vdb path which we'll use everywhere else */ |
172 |
+ xasprintf(&vdb_path, "%s/%s/%s/%s/", portroot, portvdb, cat, pkgname); |
173 |
+ vdb_fd = open(vdb_path, O_RDONLY | O_CLOEXEC); |
174 |
+ if (vdb_fd == -1) { |
175 |
+ warnp("unable to read %s", vdb_path); |
176 |
+ goto done; |
177 |
+ } |
178 |
|
179 |
- argc = 0; |
180 |
- argv = NULL; |
181 |
- makeargv(config_protect, &argc, &argv); |
182 |
+ /* First execute the pkg_prerm step */ |
183 |
+ if (!pretend) { |
184 |
+ qprintf(">>> pkg_prerm\n"); |
185 |
+ xchdir(vdb_path); |
186 |
+ xsystembash( |
187 |
+ "bzip2 -dc environment.bz2 > environment && " |
188 |
+ "pkg_prerm() { :; } && " |
189 |
+ ". ./environment && " |
190 |
+ "pkg_prerm" |
191 |
+ ); |
192 |
+ } |
193 |
+ |
194 |
+ /* Now start removing all the installed files */ |
195 |
+ fd = openat(vdb_fd, "CONTENTS", O_RDONLY | O_CLOEXEC); |
196 |
+ if (fd == -1) { |
197 |
+ warnp("unable to read %s", "CONTENTS"); |
198 |
+ goto done; |
199 |
+ } |
200 |
+ fp = fdopen(fd, "r"); |
201 |
+ if (fp == NULL) |
202 |
+ goto done; |
203 |
+ |
204 |
+ /* XXX: be nice to pull this out of the current func |
205 |
+ * so we don't keep reparsing the same env var |
206 |
+ * when unmerging multiple packages. |
207 |
+ */ |
208 |
+ makeargv(config_protect, &cp_argc, &cp_argv); |
209 |
+ makeargv(config_protect_mask, &cpm_argc, &cpm_argv); |
210 |
|
211 |
- while (fgets(buf, sizeof(buf), fp) != NULL) { |
212 |
+ while (getline(&buf, &buflen, fp) != -1) { |
213 |
contents_entry *e; |
214 |
char zing[20]; |
215 |
int protected = 0; |
216 |
@@ -858,8 +898,9 @@ |
217 |
e = contents_parse_line(buf); |
218 |
if (!e) continue; |
219 |
snprintf(dst, sizeof(dst), "%s%s", portroot, e->name); |
220 |
- protected = config_protected(e->name, argc, argv); |
221 |
+ protected = config_protected(e->name, cp_argc, cp_argv, cpm_argc, cpm_argv); |
222 |
snprintf(zing, sizeof(zing), "%s%s%s", protected ? YELLOW : GREEN, protected ? "***" : "<<<" , NORM); |
223 |
+ |
224 |
/* Should we remove in order symlinks,objects,dirs ? */ |
225 |
switch (e->type) { |
226 |
case CONTENTS_DIR: |
227 |
@@ -870,17 +911,19 @@ |
228 |
list->next = dirs; |
229 |
dirs = list; |
230 |
} |
231 |
- qprintf("%s %s%s%s/\n", zing, DKBLUE, dst, NORM); |
232 |
break; |
233 |
case CONTENTS_OBJ: |
234 |
- if (!protected) unlink_q(dst); |
235 |
+ if (!protected) |
236 |
+ unlink_q(dst); |
237 |
qprintf("%s %s\n", zing, dst); |
238 |
break; |
239 |
case CONTENTS_SYM: |
240 |
- if (protected) break; |
241 |
- if (e->name[0] != '/') break; |
242 |
+ if (protected) |
243 |
+ break; |
244 |
+ if (e->name[0] != '/') |
245 |
+ break; |
246 |
if (e->sym_target[0] != '/') { |
247 |
- if (lstat(dst, &lst) != (-1)) { |
248 |
+ if (lstat(dst, &lst) != -1) { |
249 |
if (S_ISLNK(lst.st_mode)) { |
250 |
qprintf("%s %s%s -> %s%s\n", zing, CYAN, dst, e->sym_target, NORM); |
251 |
unlink_q(dst); |
252 |
@@ -892,7 +935,7 @@ |
253 |
warn("!!! %s -> %s", e->name, e->sym_target); |
254 |
break; |
255 |
} |
256 |
- if (lstat(dst, &lst) != (-1)) { |
257 |
+ if (lstat(dst, &lst) != -1) { |
258 |
if (S_ISLNK(lst.st_mode)) { |
259 |
qprintf("%s %s%s -> %s%s\n", zing, CYAN, dst, e->sym_target, NORM); |
260 |
unlink_q(dst); |
261 |
@@ -910,23 +953,68 @@ |
262 |
} |
263 |
|
264 |
fclose(fp); |
265 |
+ fd = -1; |
266 |
|
267 |
- /* remove all dirs in reverse order */ |
268 |
+ /* Then remove all dirs in reverse order */ |
269 |
while (dirs != NULL) { |
270 |
llist_char *list = dirs; |
271 |
- dirs = dirs->next; |
272 |
- rmdir(list->data); |
273 |
+ char *dir = list->data; |
274 |
+ int rm; |
275 |
+ |
276 |
+ rm = pretend ? -1 : rmdir(dir); |
277 |
+ qprintf("%s%s%s %s%s%s/\n", rm ? YELLOW : GREEN, rm ? "---" : "<<<", |
278 |
+ NORM, DKBLUE, dir, NORM); |
279 |
+ |
280 |
free(list->data); |
281 |
free(list); |
282 |
+ dirs = dirs->next; |
283 |
} |
284 |
|
285 |
- freeargv(argc, argv); |
286 |
+ freeargv(cp_argc, cp_argv); |
287 |
+ freeargv(cpm_argc, cpm_argv); |
288 |
|
289 |
+ /* Then execute the pkg_postrm step */ |
290 |
if (!pretend) { |
291 |
- snprintf(buf, sizeof(buf), BUSYBOX " rm -rf %s/%s/%s/%s", portroot, portvdb, cat, pkgname); |
292 |
- xsystem(buf); |
293 |
+ qprintf(">>> pkg_postrm\n"); |
294 |
+ xsystembash( |
295 |
+ /* "bzip2 -dc environment.bz2 > environment && " */ |
296 |
+ "pkg_postrm() { :; } && " |
297 |
+ ". ./environment && " |
298 |
+ "pkg_postrm" |
299 |
+ ); |
300 |
} |
301 |
- return 1; |
302 |
+ |
303 |
+ if (!pretend) { |
304 |
+ /* Finally delete the vdb entry */ |
305 |
+ DIR *dir; |
306 |
+ struct dirent *de; |
307 |
+ |
308 |
+ dir = fdopendir(vdb_fd); |
309 |
+ if (!dir) |
310 |
+ goto done; |
311 |
+ |
312 |
+ while ((de = readdir(dir)) != NULL) |
313 |
+ unlinkat(vdb_fd, de->d_name, 0); |
314 |
+ |
315 |
+ closedir(dir); |
316 |
+ vdb_fd = -1; |
317 |
+ |
318 |
+ rmdir(vdb_path); |
319 |
+ |
320 |
+ /* XXX: Really only needed because we shell out to qlist and such ... */ |
321 |
+ xchdir("/"); |
322 |
+ } |
323 |
+ |
324 |
+ ret = 0; |
325 |
+ done: |
326 |
+ if (fd != -1) |
327 |
+ close(fd); |
328 |
+ if (vdb_fd != -1) |
329 |
+ close(vdb_fd); |
330 |
+ free(buf); |
331 |
+ free(vdb_path); |
332 |
+ |
333 |
+ return ret; |
334 |
} |
335 |
|
336 |
int unlink_empty(char *buf) |