Fix Coverity CIDs: 1220259 1364687 (and discarded 1220496) and added more checks...
[claws.git] / src / plugins / archive / libarchive_archive.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2016 Michael Rasmussen and the Claws Mail Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #  include "config.h"
21 #include "claws-features.h"
22 #endif
23
24 #include <glib.h>
25 #include <glib/gi18n.h>
26
27 #include "libarchive_archive.h"
28
29 #ifndef _TEST
30 #       include "archiver.h"
31 #       include "utils.h"
32 #       include "mainwindow.h"
33 #   include "folder.h"
34 #endif
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38
39 #include <archive.h>
40 #include <archive_entry.h>
41 #include <fcntl.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <dirent.h>
47 #include <glib.h>
48 #include <libgen.h>
49
50 #define READ_BLOCK_SIZE 10240
51
52 struct file_info {
53         char* path;
54         char* name;
55 };
56
57 static GSList* msg_trash_list = NULL;
58 static GSList* file_list = NULL;
59 static gboolean stop_action = FALSE;
60
61 #ifdef _TEST
62 static int permissions = 0;
63 #endif
64
65 static void free_msg_trash(MsgTrash* trash) {
66     if (trash) {
67         debug_print("Freeing files in %s\n", folder_item_get_name(trash->item));
68         if (trash->msgs) {
69             g_slist_free(trash->msgs);
70         }
71         g_free(trash);
72     }
73 }
74
75 MsgTrash* new_msg_trash(FolderItem* item) {
76     MsgTrash* msg_trash;
77     FolderType  type;
78
79     g_return_val_if_fail(item != NULL, NULL);
80
81     /* FolderType must be F_MH, F_MBOX, F_MAILDIR or F_IMAP */
82     type = item->folder->klass->type;
83     if (!(type == F_MH || type == F_MBOX || 
84             type == F_MAILDIR || type == F_IMAP))
85        return NULL; 
86     msg_trash = g_new0(MsgTrash, 1);
87     msg_trash->item = item;
88     msg_trash->msgs = NULL;
89     msg_trash_list = g_slist_prepend(msg_trash_list, msg_trash);
90     
91     return msg_trash;
92     }
93
94 void archive_free_archived_files() {
95     MsgTrash* mt = NULL;
96     gint    res;
97     GSList* l = NULL;
98    
99     for (l = msg_trash_list; l; l = g_slist_next(l)) {
100         mt = (MsgTrash *) l->data;
101         debug_print("Trashing messages in folder: %s\n", 
102                 folder_item_get_name(mt->item));
103         res = folder_item_remove_msgs(mt->item, mt->msgs);
104         debug_print("Result was %d\n", res);
105         free_msg_trash(mt);
106     }
107     g_slist_free(msg_trash_list);
108     msg_trash_list = NULL;
109 }
110
111 void archive_add_msg_mark(MsgTrash* trash, MsgInfo* msg) {
112     g_return_if_fail(trash != NULL || msg != NULL);
113     debug_print("Marking msg #%d for removal\n", msg->msgnum);
114     trash->msgs = g_slist_prepend(trash->msgs, msg);
115 }
116
117 static void free_all(GDate* date, gchar** parts) {
118     if (date)
119         g_date_free(date);
120     if (parts)
121         g_strfreev(parts);
122 }
123
124 static gboolean is_iso_string(gchar** items) {
125     int i = -1;
126     gchar* item;
127
128     while (*items) {
129         i++;
130         item = *items++;
131         debug_print("Date part %d: %s\n", i, item);
132         switch(i) {
133             case 0:
134                 if (strlen(item) != 4)
135                     return FALSE;
136                 break;
137             case 1:
138             case 2:
139                 if (strlen(item) != 2)
140                     return FALSE;
141                 break;
142             default:
143                 return FALSE;
144         }
145     }
146     debug_print("Leaving\n");
147     return (i == 2);
148 }
149
150 static GDate* iso2GDate(const gchar* date) {
151     GDate*  gdate;
152     gchar** parts = NULL;
153     int     i;
154
155     g_return_val_if_fail(date != NULL, NULL);
156
157     gdate = g_date_new();
158     parts = g_strsplit(date, "-", 3);
159     if (!parts)
160         return NULL;
161     if (! is_iso_string(parts))
162         return NULL;
163     for (i = 0; i < 3; i++) {
164         int t = atoi(parts[i]);
165         switch (i) {
166             case 0: 
167                 if (t < 1 || t > 9999) {
168                     free_all(gdate, parts);
169                     return NULL;
170                 }
171                 g_date_set_year(gdate, t);
172                 break;
173             case 1:
174                 if (t < 1 || t > 12) {
175                     free_all(gdate, parts);
176                     return NULL;
177                 }
178                 g_date_set_month(gdate, t);
179                 break;
180             case 2:
181                 if (t < 1 || t > 31) {
182                     free_all(gdate, parts);
183                     return NULL;
184                 }
185                 g_date_set_day(gdate, t);
186                 break;
187         }
188     }
189     g_strfreev(parts);
190     return gdate;
191 }
192
193 gboolean before_date(time_t msg_mtime, const gchar* before) {
194     gchar*      pos = NULL;
195     GDate*      date;
196     GDate*      file_t;
197     gboolean    res;
198
199     debug_print("Cut-off date: %s\n", before);
200     if ((date = iso2GDate(before)) == NULL) {
201         g_warning("Bad date format: %s", before);
202         return FALSE;
203     }
204
205     file_t = g_date_new();
206     g_date_set_time_t(file_t, msg_mtime);
207
208     if (debug_get_mode()) {
209         pos = g_new0(char, 100);
210         g_date_strftime(pos, 100, "%F", file_t);
211         fprintf(stderr, "File date: %s\n", pos);
212         g_free(pos);
213     }
214
215     if (! g_date_valid(file_t)) {
216         g_warning("Invalid msg date");
217         return FALSE;
218     }
219
220     res = (g_date_compare(file_t, date) >= 0) ? FALSE : TRUE;
221     g_date_free(file_t);
222     return res;
223 }
224    
225 static void archive_free_file_info(struct file_info* file) {
226         if (! file)
227                 return;
228         if (file->path)
229                 g_free(file->path);
230         if (file->name)
231                 g_free(file->name);
232         g_free(file);
233         file = NULL;
234 }
235
236 void stop_archiving() {
237         debug_print("stop action set to true\n");
238         stop_action = TRUE;
239 }
240
241 void archive_free_file_list(gboolean md5, gboolean rename) {
242         struct file_info* file = NULL;
243         gchar* path = NULL;
244
245         debug_print("freeing file list\n");
246         if (! file_list)
247                 return;
248         while (file_list) {
249                 file = (struct file_info *) file_list->data;
250                 if (!rename && md5 && g_str_has_suffix(file->name, ".md5")) {
251                         path = g_strdup_printf("%s/%s", file->path, file->name);
252                         debug_print("unlinking %s\n", path);
253                         g_unlink(path);
254                         g_free(path);
255                 }
256                 if (rename) {
257                         path = g_strdup_printf("%s/%s", file->path, file->name);
258                         debug_print("unlinking %s\n", path);
259                         g_unlink(path);
260                         g_free(path);
261                 }
262                 archive_free_file_info(file);
263                 file_list->data = NULL;
264                 file_list = g_slist_next(file_list);
265         }
266         if (file_list) {
267                 g_slist_free(file_list);
268                 file_list = NULL;
269         }
270 }
271
272 static struct file_info* archive_new_file_info() {
273         struct file_info* new_file_info = malloc(sizeof(struct file_info));
274
275         new_file_info->path = NULL;
276         new_file_info->name = NULL;
277         return new_file_info;
278 }
279
280 static void archive_add_to_list(struct file_info* file) {
281         if (! file)
282                 return;
283         file_list = g_slist_prepend(file_list, (gpointer) file);
284 }
285
286 static gchar* strip_leading_dot_slash(gchar* path) {
287         if (path && strlen(path) > 1 && path[0] == '.' && path[1] == '/')
288                 return g_strdup(&(path[2]));
289
290         return g_strdup(path);
291 }
292
293 static gchar* get_full_path(struct file_info* file) {
294         char* path = malloc(PATH_MAX);
295
296         if (file->path && *(file->path))
297                 sprintf(path, "%s/%s", file->path, file->name);
298         else
299                 sprintf(path, "%s", file->name);
300         return path;
301 }
302
303 #ifdef _TEST
304 static gchar* strip_leading_slash(gchar* path) {
305         gchar* stripped = path;
306         gchar* result = NULL;
307
308         if (stripped && stripped[0] == '/') {
309                 ++stripped;
310                 result = g_strdup(stripped);
311         }
312         else
313                 result = g_strdup(path);
314         return result;
315 }
316
317 static int archive_get_permissions() {
318         return permissions;
319 }
320
321
322 void archive_set_permissions(int perm) {
323         permissions = perm;
324 }
325
326 static int archive_copy_data(struct archive* in, struct archive* out) {
327         const void* buf;
328         size_t size;
329         off_t offset;
330         int res = ARCHIVE_OK;
331
332         while (res == ARCHIVE_OK) {
333                 res = archive_read_data_block(in, &buf, &size, &offset);
334                 if (res == ARCHIVE_OK) {
335                         res = archive_write_data_block(out, buf, size, offset);
336                 }
337         }
338         return (res == ARCHIVE_EOF) ? ARCHIVE_OK : res;
339 }
340 #endif
341
342 void archive_add_file(gchar* path) {
343         struct file_info* file;
344         gchar* filename = NULL;
345
346         g_return_if_fail(path != NULL);
347
348 #ifndef _TEST
349         debug_print("add %s to list\n", path);
350 #endif
351         filename = g_strrstr_len(path, strlen(path), "/");
352         if (! filename)
353                 g_warning("no filename in path '%s'", path);
354         g_return_if_fail(filename != NULL);
355
356         filename++;
357         file = archive_new_file_info();
358         file->name = g_strdup(filename);
359         file->path = strip_leading_dot_slash(dirname(path));
360         archive_add_to_list(file);
361 }
362
363 GSList* archive_get_file_list() {
364         return file_list;
365 }
366
367 #ifdef _TEST
368 const gchar* archive_extract(const char* archive_name, int flags) {
369         struct archive* in;
370         struct archive* out;
371         struct archive_entry* entry;
372         int res = ARCHIVE_OK;
373         gchar* buf = NULL;
374         const char* result == NULL;
375
376         g_return_val_if_fail(archive_name != NULL, ARCHIVE_FATAL);
377
378         fprintf(stdout, "%s: extracting\n", archive_name);
379         in = archive_read_new();
380         if ((res = archive_read_support_format_tar(in)) == ARCHIVE_OK) {
381                 if ((res = archive_read_support_compression_gzip(in)) == ARCHIVE_OK) {
382 #if ARCHIVE_VERSION_NUMBER < 3000000
383                         if ((res = archive_read_open_file(
384 #else
385                         if ((res = archive_read_open_filename(
386 #endif
387                                 in, archive_name, READ_BLOCK_SIZE)) != ARCHIVE_OK) {
388                                 g_warning("%s: %s", archive_name, archive_error_string(in));
389                                 result = archive_error_string(in);
390                         }
391                         else {
392                                 out = archive_write_disk_new();
393                                 if ((res = archive_write_disk_set_options(
394                                                                 out, flags)) == ARCHIVE_OK) {
395                                         res = archive_read_next_header(in, &entry);
396                                         while (res == ARCHIVE_OK) {
397                                                 res = archive_write_header(out, entry);
398                                                 if (res != ARCHIVE_OK) {
399                                                         g_warning("%s", archive_error_string(out));
400                                                         /* skip this file an continue */
401                                                         res = ARCHIVE_OK;
402                                                 }
403                                                 else {
404                                                         res = archive_copy_data(in, out);
405                                                         if (res != ARCHIVE_OK) {
406                                                                 g_warning("%s", archive_error_string(in));
407                                                                 /* skip this file an continue */
408                                                                 res = ARCHIVE_OK;
409                                                         }
410                                                         else
411                                                                 res = archive_read_next_header(in, &entry);
412                                                 }
413                                         }
414                                         if (res == ARCHIVE_EOF)
415                                                 res = ARCHIVE_OK;
416                                         if (res != ARCHIVE_OK) {
417                                                 gchar *e = archive_error_string(in);
418                                                 g_warning("%s: %s", archive_name, e? e: "unknown error");
419                                                 result = e;
420                                         }
421                                 }
422                                 else
423                                         result = archive_error_string(out);
424                                 archive_read_close(in);
425                         }
426 #if ARCHIVE_VERSION_NUMBER < 3000000
427                         archive_read_finish(in);
428 #else
429                         archive_read_free(in);
430 #endif
431                 }
432                 else
433                         result = archive_error_string(in);
434         }
435         else
436                 result = archive_error_string(in);
437         return result;
438 }
439 #endif
440
441 const gchar* archive_create(const char* archive_name, GSList* files,
442                         COMPRESS_METHOD method, ARCHIVE_FORMAT format) {
443         struct archive* arch;
444         struct archive_entry* entry;
445         char* buf = NULL;
446         ssize_t len;
447         int fd;
448         struct stat st;
449         struct file_info* file;
450         gchar* filename = NULL;
451         gchar* msg = NULL;
452
453 #ifndef _TEST
454         gint num = 0;
455         gint total = g_slist_length (files);
456 #endif
457
458         g_return_val_if_fail(files != NULL, "No files for archiving");
459
460         debug_print("File: %s\n", archive_name);
461         arch = archive_write_new();
462         switch (method) {
463                 case GZIP:
464 #if ARCHIVE_VERSION_NUMBER < 3000000
465                         if (archive_write_set_compression_gzip(arch) != ARCHIVE_OK)
466 #else
467                         if (archive_write_add_filter_gzip(arch) != ARCHIVE_OK)
468 #endif
469                                 return archive_error_string(arch);
470                         break;
471                 case BZIP2:
472 #if ARCHIVE_VERSION_NUMBER < 3000000
473                         if (archive_write_set_compression_bzip2(arch) != ARCHIVE_OK)
474 #else
475                         if (archive_write_add_filter_bzip2(arch) != ARCHIVE_OK)
476 #endif
477                                 return archive_error_string(arch);
478                         break;
479                 case COMPRESS:
480 #if ARCHIVE_VERSION_NUMBER < 3000000
481                         if (archive_write_set_compression_compress(arch) != ARCHIVE_OK)
482 #else
483                         if (archive_write_add_filter_compress(arch) != ARCHIVE_OK)
484 #endif
485                                 return archive_error_string(arch);
486                         break;
487 #if ARCHIVE_VERSION_NUMBER >= 2006990
488                 case LZMA:
489 #if ARCHIVE_VERSION_NUMBER < 3000000
490                         if (archive_write_set_compression_lzma(arch) != ARCHIVE_OK)
491 #else
492                         if (archive_write_add_filter_lzma(arch) != ARCHIVE_OK)
493 #endif
494                                 return archive_error_string(arch);
495                         break;
496                 case XZ:
497 #if ARCHIVE_VERSION_NUMBER < 3000000
498                         if (archive_write_set_compression_xz(arch) != ARCHIVE_OK)
499 #else
500                         if (archive_write_add_filter_xz(arch) != ARCHIVE_OK)
501 #endif
502                                 return archive_error_string(arch);
503                         break;
504 #endif
505 #if ARCHIVE_VERSION_NUMBER >= 3000000
506                 case LZIP:
507                         if (archive_write_add_filter_lzip(arch) != ARCHIVE_OK)
508                                 return archive_error_string(arch);
509                         break;
510 #endif
511 #if ARCHIVE_VERSION_NUMBER >= 3001000
512                 case LRZIP:
513                         if (archive_write_add_filter_lrzip(arch) != ARCHIVE_OK)
514                                 return archive_error_string(arch);
515                         break;
516                 case LZOP:
517                         if (archive_write_add_filter_lzop(arch) != ARCHIVE_OK)
518                                 return archive_error_string(arch);
519                         break;
520                 case GRZIP:
521                         if (archive_write_add_filter_grzip(arch) != ARCHIVE_OK)
522                                 return archive_error_string(arch);
523                         break;
524 #endif
525 #if ARCHIVE_VERSION_NUMBER >= 3001900
526                 case LZ4:
527                         if (archive_write_add_filter_lz4(arch) != ARCHIVE_OK)
528                                 return archive_error_string(arch);
529                         break;
530 #endif
531                 case NO_COMPRESS:
532 #if ARCHIVE_VERSION_NUMBER < 3000000
533                         if (archive_write_set_compression_none(arch) != ARCHIVE_OK)
534 #else
535                         if (archive_write_add_filter_none(arch) != ARCHIVE_OK)
536 #endif
537                                 return archive_error_string(arch);
538                         break;
539         }
540         switch (format) {
541                 case TAR:
542                         if (archive_write_set_format_ustar(arch) != ARCHIVE_OK)
543                                 return archive_error_string(arch);
544                         break;
545                 case SHAR:
546                         if (archive_write_set_format_shar(arch) != ARCHIVE_OK)
547                                 return archive_error_string(arch);
548                         break;
549                 case PAX:
550                         if (archive_write_set_format_pax(arch) != ARCHIVE_OK)
551                                 return archive_error_string(arch);
552                         break;
553                 case CPIO:
554                         if (archive_write_set_format_cpio(arch) != ARCHIVE_OK)
555                                 return archive_error_string(arch);
556                         break;
557                 case NO_FORMAT:
558                         return "Missing archive format";
559         }
560 #if ARCHIVE_VERSION_NUMBER < 3000000
561         if (archive_write_open_file(arch, archive_name) != ARCHIVE_OK)
562 #else
563         if (archive_write_open_filename(arch, archive_name) != ARCHIVE_OK)
564 #endif
565                 return archive_error_string(arch);
566
567         while (files && ! stop_action) {
568 #ifndef _TEST
569                 set_progress_print_all(num++, total, 30);
570 #endif
571                 file = (struct file_info *) files->data;
572                 if (!file)
573                         continue;
574                 filename = get_full_path(file);
575                 /* libarchive will crash if instructed to add archive to it self */
576                 if (g_utf8_collate(archive_name, filename) == 0) {
577                         g_warning("%s: not dumping to '%s'", archive_name, filename);
578 #ifndef _TEST
579                         debug_print("%s: not dumping to '%s'\n", archive_name, filename);
580 #endif
581                 }
582                 else {
583 #ifndef _TEST
584                         debug_print("Adding: %s\n", filename);
585                         msg = g_strdup_printf("%s", filename);
586                         set_progress_file_label(msg);
587                         g_free(msg);
588 #endif
589                         entry = archive_entry_new();
590                         if ((fd = open(filename, O_RDONLY)) == -1) {
591                                 perror("open file");
592                         }
593                         else {
594                                 if (lstat(filename, &st) == -1) {
595                                         perror("lstat file");
596                                 } else {
597                                         archive_entry_copy_stat(entry, &st);
598                                         archive_entry_set_pathname(entry, filename);
599                                         if (S_ISLNK(st.st_mode)) {
600                                                 if ((buf = malloc(PATH_MAX + 1)) != NULL) {
601                                                         if ((len = readlink(filename, buf, PATH_MAX)) < 0)
602                                                                 perror("error in readlink");
603                                                         else
604                                                                 buf[len] = '\0';
605                                                         archive_entry_set_symlink(entry, buf);
606                                                         g_free(buf);
607                                                         archive_entry_set_size(entry, 0);
608                                                         archive_write_header(arch, entry);
609                                                 }
610                                         }
611                                         else {
612                                                 if (archive_write_header(arch, entry) != ARCHIVE_OK)
613                                                         g_warning("%s", archive_error_string(arch));
614                                                 if ((buf = malloc(READ_BLOCK_SIZE)) != NULL) {
615                                                         len = read(fd, buf, READ_BLOCK_SIZE);
616                                                         while (len > 0) {
617                                                                 if (archive_write_data(arch, buf, len) == -1)
618                                                                         g_warning("%s", archive_error_string(arch));
619                                                                 memset(buf, 0, READ_BLOCK_SIZE);
620                                                                 len = read(fd, buf, READ_BLOCK_SIZE);
621                                                         }
622                                                         g_free(buf);
623                                                 }
624                                         }
625                                 }
626                                 close(fd);
627                                 archive_entry_free(entry);
628                         }
629                 }
630                 g_free(filename);
631                 files = g_slist_next(files);
632         }
633 #ifndef _TEST
634         if (stop_action)
635                 unlink(archive_name);
636         stop_action = FALSE;
637 #endif
638         archive_write_close(arch);
639 #if ARCHIVE_VERSION_NUMBER < 3000000
640         archive_write_finish(arch);
641 #else
642         archive_write_free(arch);
643 #endif
644         return NULL;
645 }
646
647 #ifdef _TEST
648 void archive_scan_folder(const char* dir) {
649         GStatBuf st;
650         DIR* root;
651         struct dirent* ent;
652         gchar cwd[PATH_MAX];
653         gchar path[PATH_MAX];
654         
655         getcwd(cwd, PATH_MAX);
656
657         if (g_stat(dir, &st) == -1)
658                 return;
659         if (! S_ISDIR(st.st_mode))
660                 return;
661         if (!(root = opendir(dir)))
662                 return;
663         chdir(dir);
664
665         while ((ent = readdir(root)) != NULL) {
666                 if (strcmp(".", ent->d_name) == 0 || strcmp("..", ent->d_name) == 0)
667                         continue;
668                 g_stat(ent->d_name, &st);
669                 sprintf(path, "%s/%s", dir, ent->d_name);
670                 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
671                         archive_add_file(path);
672                 }
673                 else if (S_ISDIR(st.st_mode)) {
674                         archive_scan_folder(path);
675                 }
676         }
677         chdir(cwd);
678         closedir(root);
679 }
680
681 int main(int argc, char** argv) {
682         char* archive = NULL;
683         char buf[PATH_MAX];
684         int pid;
685         int opt;
686         int perm = ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME |
687                 ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_SECURE_SYMLINKS;
688         gchar cwd[PATH_MAX];
689         gboolean remove = FALSE;
690         const char *p = NULL;
691         int res;
692
693         getcwd(cwd, PATH_MAX);
694
695         while (*++argv && **argv == '-') {
696                 p = *argv + 1;
697
698                 while ((opt = *p++) != '\0') {
699                         switch(opt) {
700                                 case 'a':
701                                         if (*p != '\0')
702                                                 archive = (char *) p;
703                                         else
704                                                 archive = *++argv;
705                                         p += strlen(p);
706                                         break;
707                                 case 'r':
708                                         remove = TRUE;
709                                         break;
710                         }
711                 }
712         }
713         if (! archive) {
714                 fprintf(stderr, "Missing archive name!\n");
715                 return EXIT_FAILURE;
716         }
717         if (!*argv) {
718                 fprintf(stderr, "Expected arguments after options!\n");
719                 return EXIT_FAILURE;
720         }
721         
722         while (*argv) {
723                 archive_scan_folder(*argv++);
724                 res = archive_create(archive, file_list);
725                 if (res != ARCHIVE_OK) {
726                         fprintf(stderr, "%s: Creating archive failed\n", archive);
727                         return EXIT_FAILURE;
728                 }
729         }
730         pid = (int) getpid();
731         sprintf(buf, "/tmp/%d", pid);
732         fprintf(stdout, "Creating: %s\n", buf);
733         mkdir(buf, 0700);
734         chdir(buf);
735         if (strcmp(dirname(archive), ".") == 0) 
736                 sprintf(buf, "%s/%s", cwd, basename(archive));
737         else
738                 sprintf(buf, "%s", archive);
739         archive_extract(buf, perm);
740         chdir(cwd);
741         if (remove) {
742                 sprintf(buf, "rm -rf /tmp/%d", pid);
743                 fprintf(stdout, "Executing: %s\n", buf);
744                 system(buf);
745         }
746         archive_free_list(file_list);
747         return EXIT_SUCCESS;
748 }
749 #endif