Gentoo Archives: gentoo-commits

From: "Mike Frysinger (vapier)" <vapier@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-projects commit in portage-utils: qmerge.c
Date: Mon, 21 Feb 2011 22:03:09
Message-Id: 20110221220259.23A6520054@flycatcher.gentoo.org
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)