1 |
commit: 01b7a90b59097201a3316ee10f2cb512a1db852d |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri Jan 31 10:47:48 2020 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Fri Jan 31 10:47:48 2020 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=01b7a90b |
7 |
|
8 |
qsize: don't count hardlinked files double, #11 |
9 |
|
10 |
While ensuring hardlinked files are counted only once, also report on |
11 |
the amount of real unique files, if different from file count. |
12 |
|
13 |
This is an alternative take to the work of Jan Ziak. |
14 |
|
15 |
Closes: PR #11 |
16 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
17 |
|
18 |
qsize.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++---------------- |
19 |
1 file changed, 49 insertions(+), 16 deletions(-) |
20 |
|
21 |
diff --git a/qsize.c b/qsize.c |
22 |
index aa5e1d1..1a1b40e 100644 |
23 |
--- a/qsize.c |
24 |
+++ b/qsize.c |
25 |
@@ -93,7 +93,10 @@ struct qsize_opt_state { |
26 |
const char *fmt; |
27 |
bool need_full_atom:1; |
28 |
|
29 |
- size_t num_all_files, num_all_nonfiles, num_all_ignored; |
30 |
+ set *uniq_files; |
31 |
+ size_t num_all_files; |
32 |
+ size_t num_all_nonfiles; |
33 |
+ size_t num_all_ignored; |
34 |
uint64_t num_all_bytes; |
35 |
}; |
36 |
|
37 |
@@ -107,6 +110,11 @@ qsize_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
38 |
char *savep; |
39 |
size_t num_files, num_nonfiles, num_ignored; |
40 |
uint64_t num_bytes; |
41 |
+ struct stat st; |
42 |
+ bool ok = false; |
43 |
+ char ikey[2 * (sizeof(size_t) * 2) + 1]; /* hex rep */ |
44 |
+ size_t cur_uniq = cnt_set(state->uniq_files); |
45 |
+ bool isuniq; |
46 |
|
47 |
if ((line = tree_pkg_meta_get(pkg_ctx, CONTENTS)) == NULL) |
48 |
return EXIT_SUCCESS; |
49 |
@@ -115,8 +123,8 @@ qsize_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
50 |
for (; (line = strtok_r(line, "\n", &savep)) != NULL; line = NULL) { |
51 |
contents_entry *e; |
52 |
regex_t *regex; |
53 |
- int ok = 0; |
54 |
|
55 |
+ ok = false; |
56 |
e = contents_parse_line(line); |
57 |
if (!e) |
58 |
continue; |
59 |
@@ -124,21 +132,27 @@ qsize_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
60 |
array_for_each(state->ignore_regexp, i, regex) { |
61 |
if (!regexec(regex, e->name, 0, NULL, 0)) { |
62 |
num_ignored++; |
63 |
- ok = 1; |
64 |
+ ok = true; |
65 |
} |
66 |
} |
67 |
if (ok) |
68 |
continue; |
69 |
|
70 |
if (e->type == CONTENTS_OBJ || e->type == CONTENTS_SYM) { |
71 |
- struct stat st; |
72 |
- ++num_files; |
73 |
- if (!fstatat(pkg_ctx->cat_ctx->ctx->portroot_fd, |
74 |
- e->name + 1, &st, AT_SYMLINK_NOFOLLOW)) |
75 |
- num_bytes += |
76 |
- state->fs_size ? st.st_blocks * S_BLKSIZE : st.st_size; |
77 |
- } else |
78 |
- ++num_nonfiles; |
79 |
+ num_files++; |
80 |
+ if (fstatat(pkg_ctx->cat_ctx->ctx->portroot_fd, |
81 |
+ e->name + 1, &st, AT_SYMLINK_NOFOLLOW) == 0) |
82 |
+ { |
83 |
+ snprintf(ikey, sizeof(ikey), "%zx%zx", |
84 |
+ (size_t)st.st_dev, (size_t)st.st_ino); |
85 |
+ add_set_unique(ikey, state->uniq_files, &isuniq); |
86 |
+ if (isuniq) |
87 |
+ num_bytes += |
88 |
+ state->fs_size ? st.st_blocks * S_BLKSIZE : st.st_size; |
89 |
+ } |
90 |
+ } else { |
91 |
+ num_nonfiles++; |
92 |
+ } |
93 |
} |
94 |
state->num_all_bytes += num_bytes; |
95 |
state->num_all_files += num_files; |
96 |
@@ -146,10 +160,19 @@ qsize_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
97 |
state->num_all_ignored += num_ignored; |
98 |
|
99 |
if (!state->summary_only) { |
100 |
+ char uniqbuf[32]; |
101 |
+ |
102 |
+ cur_uniq = cnt_set(state->uniq_files) - cur_uniq; |
103 |
atom = tree_get_atom(pkg_ctx, state->need_full_atom); |
104 |
- printf("%s: %zu files, %zu non-files, ", |
105 |
+ |
106 |
+ if (cur_uniq != num_files) |
107 |
+ snprintf(uniqbuf, sizeof(uniqbuf), " (%zu unique)", cur_uniq); |
108 |
+ else |
109 |
+ uniqbuf[0] = '\0'; |
110 |
+ |
111 |
+ printf("%s: %zu files%s, %zu non-files, ", |
112 |
atom_format(state->fmt, atom), |
113 |
- num_files, num_nonfiles); |
114 |
+ num_files, uniqbuf, num_nonfiles); |
115 |
if (num_ignored) |
116 |
printf("%zu names-ignored, ", num_ignored); |
117 |
printf("%s %s\n", |
118 |
@@ -177,10 +200,11 @@ int qsize_main(int argc, char **argv) |
119 |
.disp_units = 0, |
120 |
.str_disp_units = NULL, |
121 |
.ignore_regexp = ignore_regexp, |
122 |
- .num_all_bytes = 0, |
123 |
+ .uniq_files = create_set(), |
124 |
.num_all_files = 0, |
125 |
.num_all_nonfiles = 0, |
126 |
.num_all_ignored = 0, |
127 |
+ .num_all_bytes = 0, |
128 |
.need_full_atom = false, |
129 |
.fmt = NULL, |
130 |
}; |
131 |
@@ -238,8 +262,16 @@ int qsize_main(int argc, char **argv) |
132 |
} |
133 |
|
134 |
if (state.summary) { |
135 |
- printf(" %sTotals%s: %zu files, %zu non-files, ", BOLD, NORM, |
136 |
- state.num_all_files, state.num_all_nonfiles); |
137 |
+ char uniqbuf[32]; |
138 |
+ size_t uniq_files = cnt_set(state.uniq_files); |
139 |
+ |
140 |
+ if (uniq_files != state.num_all_files) |
141 |
+ snprintf(uniqbuf, sizeof(uniqbuf), " (%zu unique)", uniq_files); |
142 |
+ else |
143 |
+ uniqbuf[0] = '\0'; |
144 |
+ |
145 |
+ printf(" %sTotals%s: %zu files%s, %zu non-files, ", BOLD, NORM, |
146 |
+ state.num_all_files, uniqbuf, state.num_all_nonfiles); |
147 |
if (state.num_all_ignored) |
148 |
printf("%zu names-ignored, ", state.num_all_ignored); |
149 |
printf("%s %s\n", |
150 |
@@ -252,6 +284,7 @@ int qsize_main(int argc, char **argv) |
151 |
atom_implode(atom); |
152 |
xarrayfree_int(state.atoms); |
153 |
xarrayfree(state.ignore_regexp); |
154 |
+ free_set(state.uniq_files); |
155 |
|
156 |
return ret; |
157 |
} |