Contents of /trunk/mkinitrd-magellan/busybox/archival/libunarchive/data_extract_all.c
Parent Directory | Revision Log
Revision 816 -
(show annotations)
(download)
Fri Apr 24 18:33:46 2009 UTC (15 years ago) by niro
File MIME type: text/plain
File size: 4364 byte(s)
Fri Apr 24 18:33:46 2009 UTC (15 years ago) by niro
File MIME type: text/plain
File size: 4364 byte(s)
-updated to busybox-1.13.4
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
4 | */ |
5 | |
6 | #include "libbb.h" |
7 | #include "unarchive.h" |
8 | |
9 | void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) |
10 | { |
11 | file_header_t *file_header = archive_handle->file_header; |
12 | int dst_fd; |
13 | int res; |
14 | |
15 | if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { |
16 | char *name = xstrdup(file_header->name); |
17 | bb_make_directory(dirname(name), -1, FILEUTILS_RECUR); |
18 | free(name); |
19 | } |
20 | |
21 | /* Check if the file already exists */ |
22 | if (archive_handle->ah_flags & ARCHIVE_EXTRACT_UNCONDITIONAL) { |
23 | /* Remove the entry if it exists */ |
24 | if (((file_header->mode & S_IFMT) != S_IFDIR) |
25 | && (unlink(file_header->name) == -1) |
26 | && (errno != ENOENT) |
27 | ) { |
28 | bb_perror_msg_and_die("cannot remove old file %s", |
29 | file_header->name); |
30 | } |
31 | } |
32 | else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) { |
33 | /* Remove the existing entry if its older than the extracted entry */ |
34 | struct stat statbuf; |
35 | if (lstat(file_header->name, &statbuf) == -1) { |
36 | if (errno != ENOENT) { |
37 | bb_perror_msg_and_die("cannot stat old file"); |
38 | } |
39 | } |
40 | else if (statbuf.st_mtime <= file_header->mtime) { |
41 | if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { |
42 | bb_error_msg("%s not created: newer or " |
43 | "same age file exists", file_header->name); |
44 | } |
45 | data_skip(archive_handle); |
46 | return; |
47 | } |
48 | else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) { |
49 | bb_perror_msg_and_die("cannot remove old file %s", |
50 | file_header->name); |
51 | } |
52 | } |
53 | |
54 | /* Handle hard links separately |
55 | * We identified hard links as regular files of size 0 with a symlink */ |
56 | if (S_ISREG(file_header->mode) && (file_header->link_target) |
57 | && (file_header->size == 0) |
58 | ) { |
59 | /* hard link */ |
60 | res = link(file_header->link_target, file_header->name); |
61 | if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { |
62 | bb_perror_msg("cannot create %slink " |
63 | "from %s to %s", "hard", |
64 | file_header->name, |
65 | file_header->link_target); |
66 | } |
67 | } else { |
68 | /* Create the filesystem entry */ |
69 | switch (file_header->mode & S_IFMT) { |
70 | case S_IFREG: { |
71 | /* Regular file */ |
72 | dst_fd = xopen3(file_header->name, O_WRONLY | O_CREAT | O_EXCL, |
73 | file_header->mode); |
74 | bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size); |
75 | close(dst_fd); |
76 | break; |
77 | } |
78 | case S_IFDIR: |
79 | res = mkdir(file_header->name, file_header->mode); |
80 | if ((res == -1) |
81 | && (errno != EISDIR) /* btw, Linux doesn't return this */ |
82 | && (errno != EEXIST) |
83 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
84 | ) { |
85 | bb_perror_msg("cannot make dir %s", file_header->name); |
86 | } |
87 | break; |
88 | case S_IFLNK: |
89 | /* Symlink */ |
90 | res = symlink(file_header->link_target, file_header->name); |
91 | if ((res == -1) |
92 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
93 | ) { |
94 | bb_perror_msg("cannot create %slink " |
95 | "from %s to %s", "sym", |
96 | file_header->name, |
97 | file_header->link_target); |
98 | } |
99 | break; |
100 | case S_IFSOCK: |
101 | case S_IFBLK: |
102 | case S_IFCHR: |
103 | case S_IFIFO: |
104 | res = mknod(file_header->name, file_header->mode, file_header->device); |
105 | if ((res == -1) |
106 | && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
107 | ) { |
108 | bb_perror_msg("cannot create node %s", file_header->name); |
109 | } |
110 | break; |
111 | default: |
112 | bb_error_msg_and_die("unrecognized file type"); |
113 | } |
114 | } |
115 | |
116 | if (!(archive_handle->ah_flags & ARCHIVE_NOPRESERVE_OWN)) { |
117 | #if ENABLE_FEATURE_TAR_UNAME_GNAME |
118 | uid_t uid = file_header->uid; |
119 | gid_t gid = file_header->gid; |
120 | |
121 | if (file_header->uname) { |
122 | struct passwd *pwd = getpwnam(file_header->uname); |
123 | if (pwd) uid = pwd->pw_uid; |
124 | } |
125 | if (file_header->gname) { |
126 | struct group *grp = getgrnam(file_header->gname); |
127 | if (grp) gid = grp->gr_gid; |
128 | } |
129 | lchown(file_header->name, uid, gid); |
130 | #else |
131 | lchown(file_header->name, file_header->uid, file_header->gid); |
132 | #endif |
133 | } |
134 | if ((file_header->mode & S_IFMT) != S_IFLNK) { |
135 | /* uclibc has no lchmod, glibc is even stranger - |
136 | * it has lchmod which seems to do nothing! |
137 | * so we use chmod... */ |
138 | if (!(archive_handle->ah_flags & ARCHIVE_NOPRESERVE_PERM)) { |
139 | chmod(file_header->name, file_header->mode); |
140 | } |
141 | /* same for utime */ |
142 | if (archive_handle->ah_flags & ARCHIVE_PRESERVE_DATE) { |
143 | struct utimbuf t; |
144 | t.actime = t.modtime = file_header->mtime; |
145 | utime(file_header->name, &t); |
146 | } |
147 | } |
148 | } |