]>
Commit | Line | Data |
---|---|---|
221cc3ce MT |
1 | /*############################################################################# |
2 | # # | |
3 | # Pakfire - The IPFire package management system # | |
4 | # Copyright (C) 2014 Pakfire development team # | |
5 | # # | |
6 | # This program is free software: you can redistribute it and/or modify # | |
7 | # it under the terms of the GNU General Public License as published by # | |
8 | # the Free Software Foundation, either version 3 of the License, or # | |
9 | # (at your option) any later version. # | |
10 | # # | |
11 | # This program is distributed in the hope that it will be useful, # | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
14 | # GNU General Public License for more details. # | |
15 | # # | |
16 | # You should have received a copy of the GNU General Public License # | |
17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
18 | # # | |
19 | #############################################################################*/ | |
20 | ||
d03fa9a3 MT |
21 | #include <errno.h> |
22 | #include <stdlib.h> | |
d5d7737f | 23 | #include <sys/queue.h> |
d03fa9a3 | 24 | |
3a9677db MT |
25 | #include <archive.h> |
26 | ||
517708c8 MT |
27 | // Enable legacy logging |
28 | #define PAKFIRE_LEGACY_LOGGING | |
29 | ||
221cc3ce MT |
30 | #include <pakfire/file.h> |
31 | #include <pakfire/filelist.h> | |
bd261c01 | 32 | #include <pakfire/i18n.h> |
3a9677db | 33 | #include <pakfire/logging.h> |
883b3be9 | 34 | #include <pakfire/pakfire.h> |
9f953e68 | 35 | #include <pakfire/private.h> |
76c59d9f | 36 | #include <pakfire/progress.h> |
d973a13d | 37 | #include <pakfire/string.h> |
221cc3ce MT |
38 | #include <pakfire/util.h> |
39 | ||
d5d7737f MT |
40 | struct pakfire_filelist_element { |
41 | TAILQ_ENTRY(pakfire_filelist_element) nodes; | |
42 | ||
43 | struct pakfire_file* file; | |
44 | }; | |
45 | ||
1bbbfb9e | 46 | struct pakfire_filelist { |
88b4d102 | 47 | struct pakfire_ctx* ctx; |
ac4c607b | 48 | struct pakfire* pakfire; |
d03fa9a3 MT |
49 | int nrefs; |
50 | ||
d5d7737f | 51 | TAILQ_HEAD(entries, pakfire_filelist_element) files; |
78d8a62a MT |
52 | }; |
53 | ||
ac4c607b | 54 | PAKFIRE_EXPORT int pakfire_filelist_create(struct pakfire_filelist** list, struct pakfire* pakfire) { |
1bbbfb9e | 55 | struct pakfire_filelist* l = calloc(1, sizeof(*l)); |
d03fa9a3 MT |
56 | if (!l) |
57 | return -ENOMEM; | |
58 | ||
88b4d102 MT |
59 | // Store a reference to the context |
60 | l->ctx = pakfire_ctx(pakfire); | |
61 | ||
883b3be9 | 62 | l->pakfire = pakfire_ref(pakfire); |
d03fa9a3 MT |
63 | l->nrefs = 1; |
64 | ||
d5d7737f MT |
65 | // Initialise files |
66 | TAILQ_INIT(&l->files); | |
67 | ||
d03fa9a3 MT |
68 | *list = l; |
69 | return 0; | |
70 | } | |
71 | ||
1bbbfb9e | 72 | static void pakfire_filelist_free(struct pakfire_filelist* list) { |
d03fa9a3 | 73 | pakfire_filelist_clear(list); |
883b3be9 | 74 | pakfire_unref(list->pakfire); |
88b4d102 MT |
75 | if (list->ctx) |
76 | pakfire_ctx_unref(list->ctx); | |
f0d6233d | 77 | free(list); |
221cc3ce MT |
78 | } |
79 | ||
1bbbfb9e | 80 | PAKFIRE_EXPORT struct pakfire_filelist* pakfire_filelist_ref(struct pakfire_filelist* list) { |
d03fa9a3 MT |
81 | list->nrefs++; |
82 | ||
83 | return list; | |
84 | } | |
85 | ||
1bbbfb9e | 86 | PAKFIRE_EXPORT struct pakfire_filelist* pakfire_filelist_unref(struct pakfire_filelist* list) { |
d03fa9a3 MT |
87 | if (--list->nrefs > 0) |
88 | return list; | |
89 | ||
90 | pakfire_filelist_free(list); | |
91 | return NULL; | |
92 | } | |
93 | ||
94ff3014 | 94 | PAKFIRE_EXPORT size_t pakfire_filelist_length(struct pakfire_filelist* list) { |
d5d7737f MT |
95 | struct pakfire_filelist_element* element = NULL; |
96 | size_t size = 0; | |
97 | ||
98 | TAILQ_FOREACH(element, &list->files, nodes) | |
99 | size++; | |
100 | ||
101 | return size; | |
d03fa9a3 MT |
102 | } |
103 | ||
c258ca9b | 104 | size_t pakfire_filelist_total_size(struct pakfire_filelist* list) { |
d5d7737f | 105 | struct pakfire_filelist_element* element = NULL; |
c258ca9b MT |
106 | size_t size = 0; |
107 | ||
d5d7737f MT |
108 | TAILQ_FOREACH(element, &list->files, nodes) |
109 | size += pakfire_file_get_size(element->file); | |
c258ca9b MT |
110 | |
111 | return size; | |
112 | } | |
113 | ||
1bbbfb9e | 114 | PAKFIRE_EXPORT int pakfire_filelist_is_empty(struct pakfire_filelist* list) { |
d5d7737f | 115 | return TAILQ_EMPTY(&list->files); |
5e9463ec MT |
116 | } |
117 | ||
1bbbfb9e | 118 | PAKFIRE_EXPORT void pakfire_filelist_clear(struct pakfire_filelist* list) { |
d5d7737f MT |
119 | struct pakfire_filelist_element* element = NULL; |
120 | ||
121 | while (!TAILQ_EMPTY(&list->files)) { | |
122 | // Fetch the first element | |
123 | element = TAILQ_FIRST(&list->files); | |
221cc3ce | 124 | |
d5d7737f MT |
125 | // Remove it from the list |
126 | TAILQ_REMOVE(&list->files, element, nodes); | |
221cc3ce | 127 | |
d5d7737f MT |
128 | // Dereference the file |
129 | pakfire_file_unref(element->file); | |
221cc3ce | 130 | |
d5d7737f MT |
131 | // Free it all |
132 | free(element); | |
133 | } | |
221cc3ce MT |
134 | } |
135 | ||
1bbbfb9e | 136 | PAKFIRE_EXPORT struct pakfire_file* pakfire_filelist_get(struct pakfire_filelist* list, size_t index) { |
d5d7737f MT |
137 | struct pakfire_filelist_element* element = NULL; |
138 | ||
139 | // Fetch the first element | |
140 | element = TAILQ_FIRST(&list->files); | |
141 | ||
142 | while (element && index--) | |
143 | element = TAILQ_NEXT(element, nodes); | |
d03fa9a3 | 144 | |
420db400 MT |
145 | if (!element) |
146 | return NULL; | |
147 | ||
d5d7737f | 148 | return pakfire_file_ref(element->file); |
221cc3ce MT |
149 | } |
150 | ||
2f88682d | 151 | PAKFIRE_EXPORT int pakfire_filelist_add(struct pakfire_filelist* list, struct pakfire_file* file) { |
d5d7737f MT |
152 | struct pakfire_filelist_element* element = NULL; |
153 | struct pakfire_filelist_element* e = NULL; | |
9a6e3e2d | 154 | |
d5d7737f MT |
155 | // Allocate a new element |
156 | element = calloc(1, sizeof *element); | |
157 | if (!element) { | |
158 | ERROR(list->pakfire, "Could not allocate a new filelist element: %m\n"); | |
159 | return 1; | |
221cc3ce | 160 | } |
d03fa9a3 | 161 | |
d5d7737f MT |
162 | // Reference the file |
163 | element->file = pakfire_file_ref(file); | |
d03fa9a3 | 164 | |
d5d7737f MT |
165 | // Fetch the last element |
166 | e = TAILQ_LAST(&list->files, entries); | |
5e9463ec | 167 | |
d5d7737f MT |
168 | // Skip all elements that are "greater than" the element we want to add |
169 | while (e) { | |
f0bd0a4b | 170 | if (pakfire_file_cmp(e->file, file) <= 0) |
d5d7737f MT |
171 | break; |
172 | ||
173 | e = TAILQ_PREV(e, entries, nodes); | |
174 | } | |
2b04f43c | 175 | |
d5d7737f MT |
176 | // If we found an element on the list, we will append after it, |
177 | // otherwise we add right at the start. | |
178 | if (e) | |
179 | TAILQ_INSERT_AFTER(&list->files, e, element, nodes); | |
180 | else | |
181 | TAILQ_INSERT_HEAD(&list->files, element, nodes); | |
182 | ||
183 | return 0; | |
2b04f43c MT |
184 | } |
185 | ||
79fdf091 MT |
186 | static int pakfire_filelist_remove(struct pakfire_filelist* list, struct pakfire_file* file) { |
187 | struct pakfire_filelist_element* element = NULL; | |
188 | ||
189 | TAILQ_FOREACH(element, &list->files, nodes) { | |
190 | if (element->file == file) { | |
191 | // Remove the element from the list | |
192 | TAILQ_REMOVE(&list->files, element, nodes); | |
193 | ||
194 | // Free the element | |
195 | pakfire_file_unref(element->file); | |
196 | free(element); | |
197 | ||
198 | return 0; | |
199 | } | |
200 | } | |
201 | ||
202 | return 0; | |
203 | } | |
204 | ||
205 | static int __pakfire_filelist_remove_one( | |
206 | struct pakfire* pakfire, struct pakfire_file* file, void* data) { | |
207 | struct pakfire_filelist* list = (struct pakfire_filelist*)data; | |
208 | ||
209 | // Remove the file from the given filelist | |
210 | return pakfire_filelist_remove(list, file); | |
211 | } | |
212 | ||
213 | int pakfire_filelist_remove_all( | |
214 | struct pakfire_filelist* list, struct pakfire_filelist* removees) { | |
a3f3c077 | 215 | return pakfire_filelist_walk(removees, __pakfire_filelist_remove_one, list, 0); |
5e9463ec MT |
216 | } |
217 | ||
677f2a67 MT |
218 | static int pakfire_filelist_match_patterns(const char* path, |
219 | const char** patterns, const int flags) { | |
220 | char buffer[PATH_MAX]; | |
221 | int r; | |
f0456138 | 222 | |
677f2a67 MT |
223 | // Check inputs |
224 | if (!path || !patterns) | |
225 | return -EINVAL; | |
226 | ||
227 | for (const char** pattern = patterns; *pattern; pattern++) { | |
228 | // Try to find a simple match | |
229 | if (pakfire_path_match(*pattern, path)) | |
230 | return 1; | |
231 | ||
232 | // If requested perform extended matching | |
233 | if (flags & PAKFIRE_FILELIST_EXTENDED_MATCHING) { | |
234 | // / matches everything | |
235 | if (strcmp(*pattern, "/") == 0) | |
236 | return 1; | |
237 | ||
238 | // Try to match any sub-directories and files | |
239 | r = pakfire_string_format(buffer, "%s/**", *pattern); | |
240 | if (r) | |
241 | return 1; | |
242 | ||
243 | if (pakfire_path_match(buffer, path)) | |
244 | return 1; | |
245 | } | |
246 | } | |
f0456138 | 247 | |
677f2a67 | 248 | // No match |
f0456138 MT |
249 | return 0; |
250 | } | |
251 | ||
66450e63 MT |
252 | struct pakfire_filelist_matches { |
253 | const char* root; | |
254 | const char** includes; | |
255 | const char** excludes; | |
677f2a67 | 256 | const int flags; |
66450e63 | 257 | }; |
70aabbfd | 258 | |
66450e63 MT |
259 | static int pakfire_filelist_scan_filter(struct archive* archive, void* p, |
260 | struct archive_entry* entry) { | |
261 | const struct pakfire_filelist_matches* matches = p; | |
f0456138 | 262 | |
66450e63 MT |
263 | // Descend if possible |
264 | if (archive_read_disk_can_descend(archive)) | |
265 | archive_read_disk_descend(archive); | |
f0456138 | 266 | |
66450e63 MT |
267 | // Fetch the path |
268 | const char* path = archive_entry_pathname(entry); | |
04fbda35 | 269 | |
66450e63 MT |
270 | // Make the path relative to the root |
271 | path = pakfire_path_relpath(matches->root, path); | |
04fbda35 | 272 | |
66450e63 MT |
273 | // Skip the root |
274 | if (!path || !*path) | |
275 | return 0; | |
70aabbfd | 276 | |
6f1c578b MT |
277 | // Should we skip any directories? |
278 | if (matches->flags & PAKFIRE_FILELIST_NO_DIRECTORIES) { | |
279 | mode_t filetype = archive_entry_filetype(entry); | |
280 | ||
281 | if (filetype == S_IFDIR) | |
282 | return 0; | |
283 | } | |
284 | ||
66450e63 | 285 | // Skip excludes |
677f2a67 MT |
286 | if (matches->excludes && |
287 | pakfire_filelist_match_patterns(path, matches->excludes, matches->flags)) | |
66450e63 | 288 | return 0; |
70aabbfd | 289 | |
66450e63 | 290 | // Skip what is not included |
677f2a67 MT |
291 | if (matches->includes && |
292 | !pakfire_filelist_match_patterns(path, matches->includes, matches->flags)) | |
66450e63 | 293 | return 0; |
70aabbfd | 294 | |
677f2a67 MT |
295 | // Store the new path |
296 | archive_entry_set_pathname(entry, path); | |
297 | ||
66450e63 | 298 | return 1; |
70aabbfd MT |
299 | } |
300 | ||
1bbbfb9e | 301 | int pakfire_filelist_scan(struct pakfire_filelist* list, const char* root, |
677f2a67 | 302 | const char** includes, const char** excludes, int flags) { |
31a1df67 | 303 | struct archive* reader = NULL; |
7b57bb4b MT |
304 | struct pakfire_file* file = NULL; |
305 | struct archive_entry* entry = NULL; | |
66450e63 MT |
306 | struct pakfire_filelist_matches matches = { |
307 | .root = root, | |
308 | .includes = includes, | |
309 | .excludes = excludes, | |
677f2a67 | 310 | .flags = flags, |
66450e63 | 311 | }; |
7b57bb4b MT |
312 | int r = 1; |
313 | ||
86f7f0ce MT |
314 | // Root must be absolute |
315 | if (!pakfire_path_is_absolute(root)) { | |
316 | errno = EINVAL; | |
317 | return 1; | |
318 | } | |
319 | ||
70aabbfd MT |
320 | DEBUG(list->pakfire, "Scanning %s...\n", root); |
321 | ||
48d07bbd MT |
322 | if (includes) { |
323 | DEBUG(list->pakfire, " Includes:\n"); | |
324 | ||
325 | for (const char** include = includes; *include; include++) | |
326 | DEBUG(list->pakfire, " %s\n", *include); | |
327 | } | |
328 | ||
329 | if (excludes) { | |
330 | DEBUG(list->pakfire, " Excludes:\n"); | |
331 | ||
332 | for (const char** exclude = excludes; *exclude; exclude++) | |
333 | DEBUG(list->pakfire, " %s\n", *exclude); | |
334 | } | |
335 | ||
31a1df67 MT |
336 | // Check if the path exists |
337 | if (!pakfire_path_exists(root)) { | |
338 | DEBUG(list->pakfire, "Path to scan (%s) does not exist\n", root); | |
339 | r = 0; | |
340 | goto ERROR; | |
341 | } | |
342 | ||
66450e63 | 343 | // Create a new disk reader |
31a1df67 | 344 | reader = pakfire_make_archive_disk_reader(list->pakfire, 1); |
3a9677db | 345 | if (!reader) |
7b57bb4b | 346 | goto ERROR; |
3a9677db | 347 | |
66450e63 MT |
348 | // Start reading from here |
349 | r = archive_read_disk_open(reader, root); | |
350 | if (r) { | |
351 | ERROR(list->pakfire, "Could not open %s: %s\n", root, | |
352 | archive_error_string(reader)); | |
3a9677db | 353 | goto ERROR; |
66450e63 | 354 | } |
3a9677db | 355 | |
66450e63 MT |
356 | // Configure filter function |
357 | r = archive_read_disk_set_metadata_filter_callback(reader, | |
358 | pakfire_filelist_scan_filter, &matches); | |
359 | if (r) { | |
360 | ERROR(list->pakfire, "Could not set filter callback: %s\n", | |
361 | archive_error_string(reader)); | |
362 | goto ERROR; | |
363 | } | |
3a9677db | 364 | |
66450e63 MT |
365 | // Walk through all files |
366 | for (;;) { | |
367 | r = archive_read_next_header(reader, &entry); | |
3a9677db | 368 | |
66450e63 MT |
369 | // Handle the return code |
370 | switch (r) { | |
371 | // Fall through if everything is okay | |
372 | case ARCHIVE_OK: | |
373 | break; | |
3a9677db | 374 | |
66450e63 MT |
375 | // Return OK when we reached the end of the archive |
376 | case ARCHIVE_EOF: | |
377 | r = 0; | |
3a9677db MT |
378 | goto ERROR; |
379 | ||
66450e63 MT |
380 | // Raise any other errors |
381 | default: | |
382 | ERROR(list->pakfire, "Could not read next file: %s\n", | |
383 | archive_error_string(reader)); | |
384 | goto ERROR; | |
3a9677db MT |
385 | } |
386 | ||
387 | // Create file | |
7b57bb4b | 388 | r = pakfire_file_create_from_archive_entry(&file, list->pakfire, entry); |
3a9677db MT |
389 | if (r) |
390 | goto ERROR; | |
391 | ||
3a9677db | 392 | // Append it to the list |
2f88682d | 393 | r = pakfire_filelist_add(list, file); |
3a9677db MT |
394 | if (r) { |
395 | pakfire_file_unref(file); | |
396 | goto ERROR; | |
397 | } | |
06066cb1 MT |
398 | |
399 | pakfire_file_unref(file); | |
3a9677db MT |
400 | } |
401 | ||
3a9677db | 402 | ERROR: |
31a1df67 MT |
403 | if (reader) |
404 | archive_read_free(reader); | |
3a9677db MT |
405 | |
406 | return r; | |
407 | } | |
4140a923 | 408 | |
1bbbfb9e | 409 | int pakfire_filelist_contains(struct pakfire_filelist* list, const char* pattern) { |
d5d7737f MT |
410 | struct pakfire_filelist_element* element = NULL; |
411 | ||
4140a923 MT |
412 | if (!pattern) { |
413 | errno = EINVAL; | |
414 | return -1; | |
415 | } | |
416 | ||
d5d7737f MT |
417 | TAILQ_FOREACH(element, &list->files, nodes) { |
418 | const char* path = pakfire_file_get_path(element->file); | |
4140a923 MT |
419 | if (!path) |
420 | return -1; | |
421 | ||
b76073b9 | 422 | if (pakfire_path_match(pattern, path)) |
4140a923 MT |
423 | return 1; |
424 | } | |
425 | ||
426 | return 0; | |
427 | } | |
5b0b3dc2 | 428 | |
c258ca9b | 429 | int pakfire_filelist_walk(struct pakfire_filelist* list, |
a3f3c077 | 430 | pakfire_filelist_walk_callback callback, void* data, int flags) { |
76c59d9f | 431 | struct pakfire_progress* progress = NULL; |
d5d7737f | 432 | struct pakfire_filelist_element* element = NULL; |
c258ca9b MT |
433 | int r = 0; |
434 | ||
76c59d9f | 435 | // Show progress when iterating over the filelist |
73c6c3da | 436 | if (flags & PAKFIRE_FILELIST_SHOW_PROGRESS) { |
88b4d102 | 437 | r = pakfire_progress_create(&progress, list->ctx, |
15d74456 | 438 | PAKFIRE_PROGRESS_SHOW_PERCENTAGE|PAKFIRE_PROGRESS_SHOW_ETA, NULL); |
76c59d9f MT |
439 | if (r) |
440 | goto ERROR; | |
441 | ||
442 | // Set title | |
443 | r = pakfire_progress_set_title(progress, "%s", _("Processing Files...")); | |
73c6c3da MT |
444 | if (r) |
445 | goto ERROR; | |
446 | ||
447 | const size_t length = pakfire_filelist_length(list); | |
448 | ||
76c59d9f MT |
449 | // Start progress |
450 | r = pakfire_progress_start(progress, length); | |
451 | if (r) | |
452 | goto ERROR; | |
73c6c3da MT |
453 | } |
454 | ||
c258ca9b | 455 | // Call the callback once for every element on the list |
d5d7737f | 456 | TAILQ_FOREACH(element, &list->files, nodes) { |
76c59d9f MT |
457 | // Increment the progress |
458 | if (progress) | |
459 | pakfire_progress_increment(progress, 1); | |
73c6c3da | 460 | |
c258ca9b | 461 | // Call the callback |
d5d7737f | 462 | r = callback(list->pakfire, element->file, data); |
c258ca9b MT |
463 | if (r) |
464 | break; | |
465 | } | |
466 | ||
73c6c3da | 467 | // Done! |
76c59d9f MT |
468 | if (progress) { |
469 | r = pakfire_progress_finish(progress); | |
470 | if (r) | |
471 | goto ERROR; | |
472 | } | |
73c6c3da MT |
473 | |
474 | ERROR: | |
475 | // Finish progress | |
76c59d9f MT |
476 | if (progress) |
477 | pakfire_progress_unref(progress); | |
73c6c3da | 478 | |
c258ca9b MT |
479 | return r; |
480 | } | |
481 | ||
9cfb8bb8 | 482 | static int __pakfire_filelist_dump( |
f7f44921 MT |
483 | struct pakfire* pakfire, struct pakfire_file* file, void* data) { |
484 | int* flags = (int*)data; | |
9cfb8bb8 | 485 | |
f7f44921 | 486 | char* s = pakfire_file_dump(file, *flags); |
9cfb8bb8 | 487 | if (s) { |
f7f44921 | 488 | INFO(pakfire, "%s\n", s); |
9cfb8bb8 MT |
489 | free(s); |
490 | } | |
491 | ||
492 | return 0; | |
493 | } | |
494 | ||
f7f44921 | 495 | int pakfire_filelist_dump(struct pakfire_filelist* list, int flags) { |
a3f3c077 | 496 | return pakfire_filelist_walk(list, __pakfire_filelist_dump, &flags, 0); |
9cfb8bb8 MT |
497 | } |
498 | ||
bd261c01 MT |
499 | /* |
500 | Verifies all files on the filelist | |
501 | */ | |
502 | int pakfire_filelist_verify(struct pakfire_filelist* list, struct pakfire_filelist* errors) { | |
d5d7737f | 503 | struct pakfire_filelist_element* element = NULL; |
76c59d9f | 504 | struct pakfire_progress* progress = NULL; |
c0b051bb | 505 | int status; |
bd261c01 MT |
506 | int r; |
507 | ||
94ff3014 | 508 | const size_t length = pakfire_filelist_length(list); |
d5d7737f MT |
509 | |
510 | DEBUG(list->pakfire, "Verifying filelist (%zu file(s))...\n", length); | |
bd261c01 | 511 | |
76c59d9f | 512 | // Setup progress |
88b4d102 | 513 | r = pakfire_progress_create(&progress, list->ctx, |
15d74456 | 514 | PAKFIRE_PROGRESS_SHOW_PERCENTAGE|PAKFIRE_PROGRESS_SHOW_ETA, NULL); |
bd261c01 MT |
515 | if (r) |
516 | goto ERROR; | |
517 | ||
76c59d9f MT |
518 | // Add title |
519 | r = pakfire_progress_set_title(progress, "%s", _("Verifying Files...")); | |
bd261c01 MT |
520 | if (r) |
521 | goto ERROR; | |
522 | ||
76c59d9f MT |
523 | // Start the progress indicator |
524 | r = pakfire_progress_start(progress, length); | |
bd261c01 MT |
525 | if (r) |
526 | goto ERROR; | |
527 | ||
528 | // Iterate over the entire list | |
d5d7737f | 529 | TAILQ_FOREACH(element, &list->files, nodes) { |
bd261c01 | 530 | // Verify the file |
d5d7737f | 531 | r = pakfire_file_verify(element->file, &status); |
c0b051bb MT |
532 | if (r) |
533 | goto ERROR; | |
534 | ||
535 | // If the verification failed, we append it to the errors list | |
536 | if (status) { | |
bd261c01 | 537 | // Append the file to the error list |
2f88682d | 538 | r = pakfire_filelist_add(errors, element->file); |
bd261c01 MT |
539 | if (r) |
540 | goto ERROR; | |
541 | } | |
542 | ||
76c59d9f MT |
543 | // Increment progress |
544 | r = pakfire_progress_increment(progress, 1); | |
bd261c01 MT |
545 | if (r) |
546 | goto ERROR; | |
547 | } | |
548 | ||
549 | // Finish | |
76c59d9f | 550 | r = pakfire_progress_finish(progress); |
bd261c01 MT |
551 | if (r) |
552 | goto ERROR; | |
553 | ||
554 | ERROR: | |
76c59d9f MT |
555 | if (progress) |
556 | pakfire_progress_unref(progress); | |
bd261c01 MT |
557 | |
558 | return r; | |
559 | } | |
2a838122 | 560 | |
9274236e | 561 | int pakfire_filelist_cleanup(struct pakfire_filelist* list, int flags) { |
d5d7737f | 562 | struct pakfire_filelist_element* element = NULL; |
2a838122 MT |
563 | int r; |
564 | ||
90a9a801 MT |
565 | // Nothing to do if the filelist is empty |
566 | if (pakfire_filelist_is_empty(list)) | |
567 | return 0; | |
568 | ||
2a838122 | 569 | // Walk through the list backwards |
d5d7737f | 570 | TAILQ_FOREACH_REVERSE(element, &list->files, entries, nodes) { |
9274236e | 571 | r = pakfire_file_cleanup(element->file, flags); |
2a838122 MT |
572 | if (r) |
573 | return r; | |
574 | } | |
575 | ||
576 | return 0; | |
577 | } | |
34dd7fbf MT |
578 | |
579 | static int __pakfire_filelist_matches_class(struct pakfire* pakfire, | |
580 | struct pakfire_file* file, void* p) { | |
581 | int* class = (int*)p; | |
582 | ||
583 | return pakfire_file_matches_class(file, *class); | |
584 | } | |
585 | ||
586 | /* | |
587 | Returns true if any file on the list matches class | |
588 | */ | |
589 | int pakfire_filelist_matches_class(struct pakfire_filelist* list, int class) { | |
a3f3c077 | 590 | return pakfire_filelist_walk(list, __pakfire_filelist_matches_class, &class, 0); |
34dd7fbf | 591 | } |