Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/archival/libunarchive/data_extract_all.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1123 - (hide annotations) (download)
Wed Aug 18 21:56:57 2010 UTC (13 years, 8 months ago) by niro
File MIME type: text/plain
File size: 5698 byte(s)
-updated to busybox-1.17.1
1 niro 532 /* 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 niro 816 void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
10 niro 532 {
11     file_header_t *file_header = archive_handle->file_header;
12     int dst_fd;
13     int res;
14    
15 niro 1123 #if ENABLE_FEATURE_TAR_SELINUX
16     char *sctx = archive_handle->tar__next_file_sctx;
17     if (!sctx)
18     sctx = archive_handle->tar__global_sctx;
19     if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
20     setfscreatecon(sctx);
21     free(archive_handle->tar__next_file_sctx);
22     archive_handle->tar__next_file_sctx = NULL;
23     }
24     #endif
25    
26 niro 816 if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
27 niro 984 char *slash = strrchr(file_header->name, '/');
28     if (slash) {
29     *slash = '\0';
30     bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
31     *slash = '/';
32     }
33 niro 532 }
34    
35 niro 984 if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
36 niro 816 /* Remove the entry if it exists */
37 niro 1123 if (!S_ISDIR(file_header->mode)) {
38     /* Is it hardlink?
39     * We encode hard links as regular files of size 0 with a symlink */
40     if (S_ISREG(file_header->mode)
41     && file_header->link_target
42     && file_header->size == 0
43     ) {
44     /* Ugly special case:
45     * tar cf t.tar hardlink1 hardlink2 hardlink1
46     * results in this tarball structure:
47     * hardlink1
48     * hardlink2 -> hardlink1
49     * hardlink1 -> hardlink1 <== !!!
50     */
51     if (strcmp(file_header->link_target, file_header->name) == 0)
52     goto ret;
53     }
54     /* Proceed with deleting */
55     if (unlink(file_header->name) == -1
56     && errno != ENOENT
57     ) {
58     bb_perror_msg_and_die("can't remove old file %s",
59     file_header->name);
60     }
61 niro 532 }
62     }
63 niro 816 else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
64 niro 532 /* Remove the existing entry if its older than the extracted entry */
65 niro 984 struct stat existing_sb;
66     if (lstat(file_header->name, &existing_sb) == -1) {
67 niro 532 if (errno != ENOENT) {
68 niro 984 bb_perror_msg_and_die("can't stat old file");
69 niro 532 }
70     }
71 niro 984 else if (existing_sb.st_mtime >= file_header->mtime) {
72 niro 816 if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
73 niro 532 bb_error_msg("%s not created: newer or "
74     "same age file exists", file_header->name);
75     }
76     data_skip(archive_handle);
77 niro 1123 goto ret;
78 niro 532 }
79     else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
80 niro 984 bb_perror_msg_and_die("can't remove old file %s",
81 niro 532 file_header->name);
82     }
83     }
84    
85     /* Handle hard links separately
86 niro 1123 * We encode hard links as regular files of size 0 with a symlink */
87 niro 984 if (S_ISREG(file_header->mode)
88     && file_header->link_target
89     && file_header->size == 0
90 niro 532 ) {
91     /* hard link */
92 niro 816 res = link(file_header->link_target, file_header->name);
93     if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
94 niro 984 bb_perror_msg("can't create %slink "
95 niro 816 "from %s to %s", "hard",
96     file_header->name,
97     file_header->link_target);
98 niro 532 }
99 niro 1123 /* Hardlinks have no separate mode/ownership, skip chown/chmod */
100     goto ret;
101     }
102    
103     /* Create the filesystem entry */
104     switch (file_header->mode & S_IFMT) {
105     case S_IFREG: {
106     /* Regular file */
107     int flags = O_WRONLY | O_CREAT | O_EXCL;
108     if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
109     flags = O_WRONLY | O_CREAT | O_TRUNC;
110     dst_fd = xopen3(file_header->name,
111     flags,
112     file_header->mode
113     );
114     bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
115     close(dst_fd);
116     break;
117     }
118     case S_IFDIR:
119     res = mkdir(file_header->name, file_header->mode);
120     if ((res == -1)
121     && (errno != EISDIR) /* btw, Linux doesn't return this */
122     && (errno != EEXIST)
123     && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
124     ) {
125     bb_perror_msg("can't make dir %s", file_header->name);
126 niro 532 }
127 niro 1123 break;
128     case S_IFLNK:
129     /* Symlink */
130     //TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
131     res = symlink(file_header->link_target, file_header->name);
132     if ((res == -1)
133     && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
134     ) {
135     bb_perror_msg("can't create %slink "
136     "from %s to %s", "sym",
137     file_header->name,
138     file_header->link_target);
139 niro 532 }
140 niro 1123 break;
141     case S_IFSOCK:
142     case S_IFBLK:
143     case S_IFCHR:
144     case S_IFIFO:
145     res = mknod(file_header->name, file_header->mode, file_header->device);
146     if ((res == -1)
147     && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
148     ) {
149     bb_perror_msg("can't create node %s", file_header->name);
150     }
151     break;
152     default:
153     bb_error_msg_and_die("unrecognized file type");
154 niro 532 }
155    
156 niro 1123 if (!S_ISLNK(file_header->mode)) {
157     if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
158 niro 984 uid_t uid = file_header->uid;
159     gid_t gid = file_header->gid;
160 niro 1123 #if ENABLE_FEATURE_TAR_UNAME_GNAME
161     if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
162     if (file_header->tar__uname) {
163 niro 984 //TODO: cache last name/id pair?
164 niro 1123 struct passwd *pwd = getpwnam(file_header->tar__uname);
165     if (pwd) uid = pwd->pw_uid;
166     }
167     if (file_header->tar__gname) {
168     struct group *grp = getgrnam(file_header->tar__gname);
169     if (grp) gid = grp->gr_gid;
170     }
171 niro 984 }
172 niro 1123 #endif
173 niro 984 /* GNU tar 1.15.1 uses chown, not lchown */
174     chown(file_header->name, uid, gid);
175 niro 1123 }
176 niro 816 /* uclibc has no lchmod, glibc is even stranger -
177     * it has lchmod which seems to do nothing!
178     * so we use chmod... */
179 niro 984 if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
180 niro 816 chmod(file_header->name, file_header->mode);
181     }
182 niro 984 if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
183     struct timeval t[2];
184    
185     t[1].tv_sec = t[0].tv_sec = file_header->mtime;
186     t[1].tv_usec = t[0].tv_usec = 0;
187     utimes(file_header->name, t);
188 niro 816 }
189 niro 532 }
190 niro 1123
191     ret: ;
192     #if ENABLE_FEATURE_TAR_SELINUX
193     if (sctx) {
194     /* reset the context after creating an entry */
195     setfscreatecon(NULL);
196     }
197     #endif
198 niro 532 }