Patch from Konstantin Isakov <ikm@pisem.net>:
[oweals/busybox.git] / archival / libunarchive / data_extract_all.c
1 #include <sys/types.h>
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <utime.h>
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include "libbb.h"
10 #include "unarchive.h"
11
12 extern void data_extract_all(archive_handle_t *archive_handle)
13 {
14         file_header_t *file_header = archive_handle->file_header;
15         int dst_fd;
16         int res;
17
18         if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) {
19                 char *name = strdup(file_header->name);
20                 make_directory (dirname(name), 0777, FILEUTILS_RECUR);
21                 free(name);
22         }                  
23
24         /* Create the file */
25         switch(file_header->mode & S_IFMT) {
26                 case S_IFREG: {
27 #ifdef CONFIG_CPIO
28                         if (file_header->link_name) {
29                                 /* hard link */
30                                 res = link(file_header->link_name, file_header->name);
31                                 if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
32                                         perror_msg("Couldnt create hard link");
33                                 }
34                         } else
35 #endif
36                         {
37                                 /* Regular file */
38                                 dst_fd = xopen(file_header->name, O_WRONLY | O_CREAT);
39                                 copy_file_chunk_fd(archive_handle->src_fd, dst_fd, file_header->size);
40                                 close(dst_fd);
41                         }
42                         break;
43                 }
44                 case S_IFDIR:
45                         res = mkdir(file_header->name, file_header->mode);
46                         if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
47                                 perror_msg("extract_archive: %s", file_header->name);
48                         }
49                         break;
50                 case S_IFLNK:
51                         /* Symlink */
52                         res = symlink(file_header->link_name, file_header->name);
53                         if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
54                                 perror_msg("Cannot create symlink from %s to '%s'", file_header->name, file_header->link_name);
55                         }
56                         break;
57                 case S_IFSOCK:
58                 case S_IFBLK:
59                 case S_IFCHR:
60                 case S_IFIFO:
61                         res = mknod(file_header->name, file_header->mode, file_header->device);
62                         if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
63                                 perror_msg("Cannot create node %s", file_header->name);
64                         }
65                         break;
66         }
67
68         chmod(file_header->name, file_header->mode);
69         chown(file_header->name, file_header->uid, file_header->gid);
70
71         if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
72                 struct utimbuf t;
73                 t.actime = t.modtime = file_header->mtime;
74                 utime(file_header->name, &t);
75         }
76 }