1 |
commit: 704d05c0829aaf03abb95273308116786046b891 |
2 |
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon Feb 22 18:28:25 2016 +0000 |
4 |
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
5 |
CommitDate: Mon Feb 22 18:28:25 2016 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=704d05c0 |
7 |
|
8 |
qsize: rework code to use vdb callbacks |
9 |
|
10 |
This helps reduce some of the boiler plate code for vdb walking. |
11 |
There should be no real functional changes. |
12 |
|
13 |
qsize.c | 268 +++++++++++++++++++++++++++++++++++----------------------------- |
14 |
1 file changed, 145 insertions(+), 123 deletions(-) |
15 |
|
16 |
diff --git a/qsize.c b/qsize.c |
17 |
index 2df2fce..db00247 100644 |
18 |
--- a/qsize.c |
19 |
+++ b/qsize.c |
20 |
@@ -31,37 +31,143 @@ static const char * const qsize_opts_help[] = { |
21 |
}; |
22 |
#define qsize_usage(ret) usage(ret, QSIZE_FLAGS, qsize_long_opts, qsize_opts_help, lookup_applet_idx("qsize")) |
23 |
|
24 |
-int qsize_main(int argc, char **argv) |
25 |
+struct qsize_opt_state { |
26 |
+ array_t *atoms; |
27 |
+ char **argv; |
28 |
+ char search_all; |
29 |
+ char fs_size; |
30 |
+ char summary; |
31 |
+ char summary_only; |
32 |
+ size_t disp_units; |
33 |
+ const char *str_disp_units; |
34 |
+ array_t *ignore_regexp; |
35 |
+ |
36 |
+ size_t buflen; |
37 |
+ char *buf; |
38 |
+ |
39 |
+ size_t num_all_files, num_all_nonfiles, num_all_ignored; |
40 |
+ uint64_t num_all_bytes; |
41 |
+}; |
42 |
+ |
43 |
+_q_static int qsize_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv) |
44 |
{ |
45 |
- q_vdb_ctx *ctx; |
46 |
- q_vdb_cat_ctx *cat_ctx; |
47 |
- q_vdb_pkg_ctx *pkg_ctx; |
48 |
+ struct qsize_opt_state *state = priv; |
49 |
+ const char *catname = pkg_ctx->cat_ctx->name; |
50 |
+ const char *pkgname = pkg_ctx->name; |
51 |
size_t i; |
52 |
- char fs_size = 0, summary = 0, summary_only = 0; |
53 |
- size_t num_all_files, num_all_nonfiles, num_all_ignored; |
54 |
+ depend_atom *atom; |
55 |
+ FILE *fp; |
56 |
size_t num_files, num_nonfiles, num_ignored; |
57 |
- uint64_t num_all_bytes, num_bytes; |
58 |
- size_t disp_units = 0; |
59 |
- const char *str_disp_units = NULL; |
60 |
- size_t buflen; |
61 |
- char *buf; |
62 |
+ uint64_t num_bytes; |
63 |
+ bool showit = false; |
64 |
+ |
65 |
+ /* see if this cat/pkg is requested */ |
66 |
+ if (array_cnt(state->atoms)) { |
67 |
+ depend_atom *qatom; |
68 |
+ |
69 |
+ snprintf(state->buf, state->buflen, "%s/%s", catname, pkgname); |
70 |
+ qatom = atom_explode(state->buf); |
71 |
+ array_for_each(state->atoms, i, atom) |
72 |
+ if (atom_compare(atom, qatom) == EQUAL) { |
73 |
+ showit = true; |
74 |
+ break; |
75 |
+ } |
76 |
+ atom_implode(qatom); |
77 |
+ } else |
78 |
+ showit = true; |
79 |
+ if (!showit) |
80 |
+ return EXIT_SUCCESS; |
81 |
+ |
82 |
+ if ((fp = q_vdb_pkg_fopenat_ro(pkg_ctx, "CONTENTS")) == NULL) |
83 |
+ return EXIT_SUCCESS; |
84 |
+ |
85 |
+ num_ignored = num_files = num_nonfiles = num_bytes = 0; |
86 |
+ while (getline(&state->buf, &state->buflen, fp) != -1) { |
87 |
+ contents_entry *e; |
88 |
+ regex_t *regex; |
89 |
+ int ok = 0; |
90 |
+ |
91 |
+ e = contents_parse_line(state->buf); |
92 |
+ if (!e) |
93 |
+ continue; |
94 |
+ |
95 |
+ array_for_each(state->ignore_regexp, i, regex) |
96 |
+ if (!regexec(regex, state->buf, 0, NULL, 0)) { |
97 |
+ num_ignored += 1; |
98 |
+ ok = 1; |
99 |
+ } |
100 |
+ if (ok) |
101 |
+ continue; |
102 |
+ |
103 |
+ if (e->type == CONTENTS_OBJ || e->type == CONTENTS_SYM) { |
104 |
+ struct stat st; |
105 |
+ ++num_files; |
106 |
+ if (!fstatat(pkg_ctx->cat_ctx->ctx->portroot_fd, e->name + 1, &st, AT_SYMLINK_NOFOLLOW)) |
107 |
+ num_bytes += (state->fs_size ? st.st_blocks * S_BLKSIZE : st.st_size); |
108 |
+ } else |
109 |
+ ++num_nonfiles; |
110 |
+ } |
111 |
+ fclose(fp); |
112 |
+ state->num_all_bytes += num_bytes; |
113 |
+ state->num_all_files += num_files; |
114 |
+ state->num_all_nonfiles += num_nonfiles; |
115 |
+ state->num_all_ignored += num_ignored; |
116 |
+ |
117 |
+ if (!state->summary_only) { |
118 |
+ printf("%s%s/%s%s%s: %'zu files, %'zu non-files, ", BOLD, |
119 |
+ catname, BLUE, pkgname, NORM, |
120 |
+ num_files, num_nonfiles); |
121 |
+ if (num_ignored) |
122 |
+ printf("%'zu names-ignored, ", num_ignored); |
123 |
+ if (state->disp_units) |
124 |
+ printf("%s %s\n", |
125 |
+ make_human_readable_str(num_bytes, 1, state->disp_units), |
126 |
+ state->str_disp_units); |
127 |
+ else |
128 |
+ printf("%'"PRIu64"%s%"PRIu64" KiB\n", |
129 |
+ num_bytes / KILOBYTE, |
130 |
+ decimal_point, |
131 |
+ ((num_bytes % KILOBYTE) * 1000) / KILOBYTE); |
132 |
+ } |
133 |
+ |
134 |
+ return EXIT_SUCCESS; |
135 |
+} |
136 |
+ |
137 |
+int qsize_main(int argc, char **argv) |
138 |
+{ |
139 |
+ size_t i; |
140 |
+ int ret; |
141 |
+ DECLARE_ARRAY(ignore_regexp); |
142 |
depend_atom *atom; |
143 |
DECLARE_ARRAY(atoms); |
144 |
- DECLARE_ARRAY(ignore_regexp); |
145 |
+ struct qsize_opt_state state = { |
146 |
+ .atoms = atoms, |
147 |
+ .search_all = 0, |
148 |
+ .fs_size = 0, |
149 |
+ .summary = 0, |
150 |
+ .summary_only = 0, |
151 |
+ .disp_units = 0, |
152 |
+ .str_disp_units = NULL, |
153 |
+ .ignore_regexp = ignore_regexp, |
154 |
+ .num_all_bytes = 0, |
155 |
+ .num_all_files = 0, |
156 |
+ .num_all_nonfiles = 0, |
157 |
+ .num_all_ignored = 0, |
158 |
+ }; |
159 |
|
160 |
while ((i = GETOPT_LONG(QSIZE, qsize, "")) != -1) { |
161 |
switch (i) { |
162 |
COMMON_GETOPTS_CASES(qsize) |
163 |
- case 'f': fs_size = 1; break; |
164 |
- case 's': summary = 1; break; |
165 |
- case 'S': summary = summary_only = 1; break; |
166 |
- case 'm': disp_units = MEGABYTE; str_disp_units = "MiB"; break; |
167 |
- case 'k': disp_units = KILOBYTE; str_disp_units = "KiB"; break; |
168 |
- case 'b': disp_units = 1; str_disp_units = "bytes"; break; |
169 |
+ case 'f': state.fs_size = 1; break; |
170 |
+ case 's': state.summary = 1; break; |
171 |
+ case 'S': state.summary = state.summary_only = 1; break; |
172 |
+ case 'm': state.disp_units = MEGABYTE; state.str_disp_units = "MiB"; break; |
173 |
+ case 'k': state.disp_units = KILOBYTE; state.str_disp_units = "KiB"; break; |
174 |
+ case 'b': state.disp_units = 1; state.str_disp_units = "bytes"; break; |
175 |
case 'i': { |
176 |
regex_t regex; |
177 |
xregcomp(®ex, optarg, REG_EXTENDED|REG_NOSUB); |
178 |
- xarraypush(ignore_regexp, ®ex, sizeof(regex)); |
179 |
+ xarraypush(state.ignore_regexp, ®ex, sizeof(regex)); |
180 |
break; |
181 |
} |
182 |
} |
183 |
@@ -74,121 +180,37 @@ int qsize_main(int argc, char **argv) |
184 |
if (!atom) |
185 |
warn("invalid atom: %s", argv[i]); |
186 |
else |
187 |
- xarraypush_ptr(atoms, atom); |
188 |
+ xarraypush_ptr(state.atoms, atom); |
189 |
} |
190 |
|
191 |
- num_all_bytes = num_all_files = num_all_nonfiles = num_all_ignored = 0; |
192 |
- |
193 |
- buflen = _Q_PATH_MAX; |
194 |
- buf = xmalloc(buflen); |
195 |
- |
196 |
- ctx = q_vdb_open(); |
197 |
- if (!ctx) |
198 |
- return EXIT_FAILURE; |
199 |
- |
200 |
- /* open /var/db/pkg */ |
201 |
- while ((cat_ctx = q_vdb_next_cat(ctx))) { |
202 |
- /* open the cateogry */ |
203 |
- const char *catname = cat_ctx->name; |
204 |
- while ((pkg_ctx = q_vdb_next_pkg(cat_ctx))) { |
205 |
- const char *pkgname = pkg_ctx->name; |
206 |
- FILE *fp; |
207 |
- bool showit = false; |
208 |
- |
209 |
- /* see if this cat/pkg is requested */ |
210 |
- if (array_cnt(atoms)) { |
211 |
- depend_atom *qatom; |
212 |
- |
213 |
- snprintf(buf, buflen, "%s/%s", catname, pkgname); |
214 |
- qatom = atom_explode(buf); |
215 |
- array_for_each(atoms, i, atom) |
216 |
- if (atom_compare(atom, qatom) == EQUAL) { |
217 |
- showit = true; |
218 |
- break; |
219 |
- } |
220 |
- atom_implode(qatom); |
221 |
- } else |
222 |
- showit = true; |
223 |
- if (!showit) |
224 |
- goto next_pkg; |
225 |
- |
226 |
- if ((fp = q_vdb_pkg_fopenat_ro(pkg_ctx, "CONTENTS")) == NULL) |
227 |
- goto next_pkg; |
228 |
- |
229 |
- num_ignored = num_files = num_nonfiles = num_bytes = 0; |
230 |
- while (getline(&buf, &buflen, fp) != -1) { |
231 |
- contents_entry *e; |
232 |
- regex_t *regex; |
233 |
- int ok = 0; |
234 |
- |
235 |
- e = contents_parse_line(buf); |
236 |
- if (!e) |
237 |
- continue; |
238 |
- |
239 |
- array_for_each(ignore_regexp, i, regex) |
240 |
- if (!regexec(regex, buf, 0, NULL, 0)) { |
241 |
- num_ignored += 1; |
242 |
- ok = 1; |
243 |
- } |
244 |
- if (ok) |
245 |
- continue; |
246 |
- |
247 |
- if (e->type == CONTENTS_OBJ || e->type == CONTENTS_SYM) { |
248 |
- struct stat st; |
249 |
- ++num_files; |
250 |
- if (!fstatat(ctx->portroot_fd, e->name + 1, &st, AT_SYMLINK_NOFOLLOW)) |
251 |
- num_bytes += (fs_size ? st.st_blocks * S_BLKSIZE : st.st_size); |
252 |
- } else |
253 |
- ++num_nonfiles; |
254 |
- } |
255 |
- fclose(fp); |
256 |
- num_all_bytes += num_bytes; |
257 |
- num_all_files += num_files; |
258 |
- num_all_nonfiles += num_nonfiles; |
259 |
- num_all_ignored += num_ignored; |
260 |
- |
261 |
- if (!summary_only) { |
262 |
- printf("%s%s/%s%s%s: %'zu files, %'zu non-files, ", BOLD, |
263 |
- catname, BLUE, pkgname, NORM, |
264 |
- num_files, num_nonfiles); |
265 |
- if (num_ignored) |
266 |
- printf("%'zu names-ignored, ", num_ignored); |
267 |
- if (disp_units) |
268 |
- printf("%s %s\n", |
269 |
- make_human_readable_str(num_bytes, 1, disp_units), |
270 |
- str_disp_units); |
271 |
- else |
272 |
- printf("%'"PRIu64"%s%"PRIu64" KiB\n", |
273 |
- num_bytes / KILOBYTE, |
274 |
- decimal_point, |
275 |
- ((num_bytes % KILOBYTE) * 1000) / KILOBYTE); |
276 |
- } |
277 |
+ state.buflen = _Q_PATH_MAX; |
278 |
+ state.buf = xmalloc(state.buflen); |
279 |
|
280 |
- next_pkg: |
281 |
- q_vdb_close_pkg(pkg_ctx); |
282 |
- } |
283 |
- } |
284 |
+ ret = q_vdb_foreach_pkg(qsize_cb, &state, NULL); |
285 |
|
286 |
- if (summary) { |
287 |
+ if (state.summary) { |
288 |
printf(" %sTotals%s: %'zu files, %'zu non-files, ", BOLD, NORM, |
289 |
- num_all_files, num_all_nonfiles); |
290 |
- if (num_all_ignored) |
291 |
- printf("%'zu names-ignored, ", num_all_ignored); |
292 |
- if (disp_units) |
293 |
+ state.num_all_files, state.num_all_nonfiles); |
294 |
+ if (state.num_all_ignored) |
295 |
+ printf("%'zu names-ignored, ", state.num_all_ignored); |
296 |
+ if (state.disp_units) |
297 |
printf("%s %s\n", |
298 |
- make_human_readable_str(num_all_bytes, 1, disp_units), |
299 |
- str_disp_units); |
300 |
+ make_human_readable_str(state.num_all_bytes, 1, state.disp_units), |
301 |
+ state.str_disp_units); |
302 |
else |
303 |
printf("%'"PRIu64"%s%"PRIu64" MiB\n", |
304 |
- num_all_bytes / MEGABYTE, |
305 |
+ state.num_all_bytes / MEGABYTE, |
306 |
decimal_point, |
307 |
- ((num_all_bytes % MEGABYTE) * 1000) / MEGABYTE); |
308 |
+ ((state.num_all_bytes % MEGABYTE) * 1000) / MEGABYTE); |
309 |
} |
310 |
- array_for_each(atoms, i, atom) |
311 |
+ |
312 |
+ array_for_each(state.atoms, i, atom) |
313 |
atom_implode(atom); |
314 |
- xarrayfree_int(atoms); |
315 |
- xarrayfree(ignore_regexp); |
316 |
- return EXIT_SUCCESS; |
317 |
+ xarrayfree_int(state.atoms); |
318 |
+ xarrayfree(state.ignore_regexp); |
319 |
+ free(state.buf); |
320 |
+ |
321 |
+ return ret; |
322 |
} |
323 |
|
324 |
#else |