1 |
commit: f05c78008b1754a79e31e793a67d07ed8f5d11bc |
2 |
Author: sbesl <sambesselink <AT> planet <DOT> nl> |
3 |
AuthorDate: Fri Aug 9 22:31:57 2019 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Sep 29 12:13:18 2019 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=f05c7800 |
7 |
|
8 |
Make qfile also check the prune lib registry |
9 |
|
10 |
Modifications by Fabian Groffen <grobian <AT> gentoo.org>: |
11 |
- indentation fixes |
12 |
- declarations go on top |
13 |
- no C99 features |
14 |
- adapt style to 0.80 release |
15 |
|
16 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
17 |
|
18 |
qfile.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
19 |
1 file changed, 103 insertions(+), 2 deletions(-) |
20 |
|
21 |
diff --git a/qfile.c b/qfile.c |
22 |
index bc5c9ac..63b47da 100644 |
23 |
--- a/qfile.c |
24 |
+++ b/qfile.c |
25 |
@@ -20,7 +20,7 @@ |
26 |
#include "rmspace.h" |
27 |
#include "tree.h" |
28 |
|
29 |
-#define QFILE_FLAGS "F:doRx:S" COMMON_FLAGS |
30 |
+#define QFILE_FLAGS "F:doRx:SP" COMMON_FLAGS |
31 |
static struct option const qfile_long_opts[] = { |
32 |
{"format", a_argument, NULL, 'F'}, |
33 |
{"slots", no_argument, NULL, 'S'}, |
34 |
@@ -28,6 +28,7 @@ static struct option const qfile_long_opts[] = { |
35 |
{"dir", no_argument, NULL, 'd'}, |
36 |
{"orphans", no_argument, NULL, 'o'}, |
37 |
{"exclude", a_argument, NULL, 'x'}, |
38 |
+ {"skip-plibreg",no_argument, NULL, 'P'}, |
39 |
COMMON_LONG_OPTS |
40 |
}; |
41 |
static const char * const qfile_opts_help[] = { |
42 |
@@ -37,6 +38,7 @@ static const char * const qfile_opts_help[] = { |
43 |
"Also match directories for single component arguments", |
44 |
"List orphan files", |
45 |
"Don't look in package <arg> (used with --orphans)", |
46 |
+ "Don't look in the prunelib registry", |
47 |
COMMON_OPTS_HELP |
48 |
}; |
49 |
#define qfile_usage(ret) usage(ret, QFILE_FLAGS, qfile_long_opts, qfile_opts_help, NULL, lookup_applet_idx("qfile")) |
50 |
@@ -53,6 +55,7 @@ typedef struct { |
51 |
char **dirnames; |
52 |
char **realdirnames; |
53 |
short *non_orphans; |
54 |
+ int *results; |
55 |
} qfile_args_t; |
56 |
|
57 |
struct qfile_opt_state { |
58 |
@@ -69,10 +72,88 @@ struct qfile_opt_state { |
59 |
bool basename; |
60 |
bool orphans; |
61 |
bool assume_root_prefix; |
62 |
+ bool skip_plibreg; |
63 |
const char *format; |
64 |
bool need_full_atom; |
65 |
}; |
66 |
|
67 |
+/* |
68 |
+ * As a final step, check if file is in the plib_reg |
69 |
+ */ |
70 |
+static int qfile_check_plibreg(void *priv) |
71 |
+{ |
72 |
+ struct qfile_opt_state *state = priv; |
73 |
+ |
74 |
+ char fn_plibreg[_Q_PATH_MAX]; |
75 |
+ int fd_plibreg; |
76 |
+ FILE *fp_plibreg; |
77 |
+ struct stat cst; |
78 |
+ |
79 |
+ char file[_Q_PATH_MAX]; |
80 |
+ char *line = NULL; |
81 |
+ size_t len = 0; |
82 |
+ int found = 0; |
83 |
+ int i; |
84 |
+ |
85 |
+ qfile_args_t *args = &state->args; |
86 |
+ char **base_names = args->basenames; |
87 |
+ char **dir_names = args->dirnames; |
88 |
+ short *non_orphans = args->non_orphans; |
89 |
+ int *results = args->results; |
90 |
+ |
91 |
+ /* Open plibreg */ |
92 |
+ snprintf(fn_plibreg, _Q_PATH_MAX, "%s%s", |
93 |
+ CONFIG_EPREFIX, "var/lib/portage/preserved_libs_registry"); |
94 |
+ fp_plibreg = NULL; |
95 |
+ fd_plibreg = open(fn_plibreg, O_RDONLY|O_CLOEXEC, 0); |
96 |
+ if (fd_plibreg == -1) |
97 |
+ return 0; |
98 |
+ if (fstat(fd_plibreg, &cst)) { |
99 |
+ close(fd_plibreg); |
100 |
+ return 0; |
101 |
+ } |
102 |
+ if ((fp_plibreg = fdopen(fd_plibreg, "r")) == NULL) { |
103 |
+ close(fd_plibreg); |
104 |
+ return 0; |
105 |
+ } |
106 |
+ |
107 |
+ for (i = 0; i < args->length; i++) { |
108 |
+ if (base_names[i] == NULL) |
109 |
+ continue; |
110 |
+ if (non_orphans && non_orphans[i]) |
111 |
+ continue; |
112 |
+ if (results[i] == 1) |
113 |
+ continue; |
114 |
+ |
115 |
+ if (dir_names[i] != NULL) |
116 |
+ snprintf(file, sizeof(file), "%s/%s", dir_names[i], base_names[i]); |
117 |
+ else |
118 |
+ snprintf(file, sizeof(file), "%s", base_names[i]); |
119 |
+ |
120 |
+ while (getline(&line, &len, fp_plibreg) != -1) |
121 |
+ if (strstr(line, file) != NULL) { |
122 |
+ found++; |
123 |
+ if (!quiet) |
124 |
+ printf("%splib_registry%s\n", BLUE, NORM); |
125 |
+ else |
126 |
+ printf("%splib_registry%s: %s\n", BLUE, NORM, file); |
127 |
+ } |
128 |
+ } |
129 |
+ |
130 |
+ if (line) |
131 |
+ free(line); |
132 |
+ |
133 |
+ return found; |
134 |
+} |
135 |
+ |
136 |
+/* |
137 |
+ * 1. Do package exclusion tests |
138 |
+ * 2. Run through CONTENTS file, perform tests and fail-by-continue |
139 |
+ * 3. On success bump and return retvalue 'found' |
140 |
+ * |
141 |
+ * We assume the people calling us have chdir(/var/db/pkg) and so |
142 |
+ * we use relative paths throughout here. |
143 |
+ */ |
144 |
static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
145 |
{ |
146 |
struct qfile_opt_state *state = priv; |
147 |
@@ -88,6 +169,7 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
148 |
char **dir_names = args->dirnames; |
149 |
char **real_dir_names = args->realdirnames; |
150 |
short *non_orphans = args->non_orphans; |
151 |
+ int *results = args->results; |
152 |
int found = 0; |
153 |
|
154 |
/* If exclude_pkg is not NULL, check it. We are looking for files |
155 |
@@ -116,6 +198,7 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
156 |
if (fp == NULL) |
157 |
goto qlist_done; |
158 |
|
159 |
+ /* Run through CONTENTS file */ |
160 |
while (getline(&state->buf, &state->buflen, fp) != -1) { |
161 |
size_t dirname_len; |
162 |
contents_entry *e; |
163 |
@@ -224,6 +307,9 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
164 |
} else { |
165 |
non_orphans[i] = 1; |
166 |
} |
167 |
+ |
168 |
+ /* Success */ |
169 |
+ results[i] = 1; |
170 |
found++; |
171 |
} |
172 |
} |
173 |
@@ -250,6 +336,7 @@ static void destroy_qfile_args(qfile_args_t *qfile_args) |
174 |
free(qfile_args->dirnames); |
175 |
free(qfile_args->realdirnames); |
176 |
free(qfile_args->non_orphans); |
177 |
+ free(qfile_args->results); |
178 |
|
179 |
memset(qfile_args, 0, sizeof(qfile_args_t)); |
180 |
} |
181 |
@@ -268,6 +355,7 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st |
182 |
char **basenames = NULL; |
183 |
char **dirnames = NULL; |
184 |
char **realdirnames = NULL; |
185 |
+ int *results = NULL; |
186 |
char tmppath[_Q_PATH_MAX]; |
187 |
char abspath[_Q_PATH_MAX]; |
188 |
|
189 |
@@ -279,6 +367,7 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st |
190 |
basenames = xcalloc(argc, sizeof(char*)); |
191 |
dirnames = xcalloc(argc, sizeof(char*)); |
192 |
realdirnames = xcalloc(argc, sizeof(char*)); |
193 |
+ results = xcalloc(argc, sizeof(int)); |
194 |
|
195 |
for (i = 0; i < argc; ++i) { |
196 |
/* Record basename, but if it is ".", ".." or "/" */ |
197 |
@@ -375,6 +464,7 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st |
198 |
args->dirnames = dirnames; |
199 |
args->realdirnames = realdirnames; |
200 |
args->length = argc; |
201 |
+ args->results = results; |
202 |
|
203 |
if (state->orphans) |
204 |
args->non_orphans = xcalloc(argc, sizeof(short)); |
205 |
@@ -390,6 +480,7 @@ int qfile_main(int argc, char **argv) |
206 |
.basename = false, |
207 |
.orphans = false, |
208 |
.assume_root_prefix = false, |
209 |
+ .skip_plibreg = false, |
210 |
.format = NULL, |
211 |
}; |
212 |
int i, nb_of_queries, found = 0; |
213 |
@@ -403,6 +494,7 @@ int qfile_main(int argc, char **argv) |
214 |
case 'd': state.basename = true; break; |
215 |
case 'o': state.orphans = true; break; |
216 |
case 'R': state.assume_root_prefix = true; break; |
217 |
+ case 'P': state.skip_plibreg = true; break; |
218 |
case 'x': |
219 |
if (state.exclude_pkg) |
220 |
err("--exclude can only be used once."); |
221 |
@@ -471,7 +563,8 @@ int qfile_main(int argc, char **argv) |
222 |
|
223 |
/* Prepare the qfile(...) arguments structure */ |
224 |
nb_of_queries = prepare_qfile_args(argc, (const char **) argv, &state); |
225 |
- /* Now do the actual `qfile` checking */ |
226 |
+ |
227 |
+ /* Now do the actual `qfile` checking by looking at CONTENTS of all pkgs */ |
228 |
if (nb_of_queries > 0) { |
229 |
tree_ctx *vdb = tree_open_vdb(portroot, portvdb); |
230 |
if (vdb != NULL) { |
231 |
@@ -480,6 +573,14 @@ int qfile_main(int argc, char **argv) |
232 |
} |
233 |
} |
234 |
|
235 |
+ /* Also check the prune lib registry. |
236 |
+ * But only for files we otherwise couldn't account for. If we'd |
237 |
+ * check plib_reg for all files, we would get duplicate messages for |
238 |
+ * files that were re-added to CONTENTS files after a version |
239 |
+ * upgrade (which are also recorded in plib_reg). */ |
240 |
+ if (nb_of_queries > 0 && !state.skip_plibreg) |
241 |
+ found += qfile_check_plibreg(&state); |
242 |
+ |
243 |
if (state.args.non_orphans) { |
244 |
/* display orphan files */ |
245 |
for (i = 0; i < state.args.length; i++) { |