6 |
#include "libbb.h" |
#include "libbb.h" |
7 |
#include "unarchive.h" |
#include "unarchive.h" |
8 |
|
|
9 |
void data_extract_all(archive_handle_t *archive_handle) |
void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) |
10 |
{ |
{ |
11 |
file_header_t *file_header = archive_handle->file_header; |
file_header_t *file_header = archive_handle->file_header; |
12 |
int dst_fd; |
int dst_fd; |
13 |
int res; |
int res; |
14 |
|
|
15 |
if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) { |
if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { |
16 |
char *name = xstrdup(file_header->name); |
char *name = xstrdup(file_header->name); |
17 |
bb_make_directory(dirname(name), -1, FILEUTILS_RECUR); |
bb_make_directory(dirname(name), -1, FILEUTILS_RECUR); |
18 |
free(name); |
free(name); |
19 |
} |
} |
20 |
|
|
21 |
/* Check if the file already exists */ |
/* Check if the file already exists */ |
22 |
if (archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) { |
if (archive_handle->ah_flags & ARCHIVE_EXTRACT_UNCONDITIONAL) { |
23 |
/* Remove the existing entry if it exists */ |
/* Remove the entry if it exists */ |
24 |
if (((file_header->mode & S_IFMT) != S_IFDIR) |
if (((file_header->mode & S_IFMT) != S_IFDIR) |
25 |
&& (unlink(file_header->name) == -1) |
&& (unlink(file_header->name) == -1) |
26 |
&& (errno != ENOENT) |
&& (errno != ENOENT) |
27 |
) { |
) { |
28 |
bb_perror_msg_and_die("cannot remove old file"); |
bb_perror_msg_and_die("cannot remove old file %s", |
29 |
|
file_header->name); |
30 |
} |
} |
31 |
} |
} |
32 |
else if (archive_handle->flags & ARCHIVE_EXTRACT_NEWER) { |
else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) { |
33 |
/* Remove the existing entry if its older than the extracted entry */ |
/* Remove the existing entry if its older than the extracted entry */ |
34 |
struct stat statbuf; |
struct stat statbuf; |
35 |
if (lstat(file_header->name, &statbuf) == -1) { |
if (lstat(file_header->name, &statbuf) == -1) { |
38 |
} |
} |
39 |
} |
} |
40 |
else if (statbuf.st_mtime <= file_header->mtime) { |
else if (statbuf.st_mtime <= file_header->mtime) { |
41 |
if (!(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) { |
if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { |
42 |
bb_error_msg("%s not created: newer or " |
bb_error_msg("%s not created: newer or " |
43 |
"same age file exists", file_header->name); |
"same age file exists", file_header->name); |
44 |
} |
} |
53 |
|
|
54 |
/* Handle hard links separately |
/* Handle hard links separately |
55 |
* We identified hard links as regular files of size 0 with a symlink */ |
* We identified hard links as regular files of size 0 with a symlink */ |
56 |
if (S_ISREG(file_header->mode) && (file_header->link_name) |
if (S_ISREG(file_header->mode) && (file_header->link_target) |
57 |
&& (file_header->size == 0) |
&& (file_header->size == 0) |
58 |
) { |
) { |
59 |
/* hard link */ |
/* hard link */ |
60 |
res = link(file_header->link_name, file_header->name); |
res = link(file_header->link_target, file_header->name); |
61 |
if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) { |
if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { |
62 |
bb_perror_msg("cannot create hard link"); |
bb_perror_msg("cannot create %slink " |
63 |
|
"from %s to %s", "hard", |
64 |
|
file_header->name, |
65 |
|
file_header->link_target); |
66 |
} |
} |
67 |
} else { |
} else { |
68 |
/* Create the filesystem entry */ |
/* Create the filesystem entry */ |
77 |
} |
} |
78 |
case S_IFDIR: |
case S_IFDIR: |
79 |
res = mkdir(file_header->name, file_header->mode); |
res = mkdir(file_header->name, file_header->mode); |
80 |
if ((errno != EISDIR) && (res == -1) |
if ((res == -1) |
81 |
&& !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET) |
&& (errno != EISDIR) /* btw, Linux doesn't return this */ |
82 |
|
&& (errno != EEXIST) |
83 |
|
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
84 |
) { |
) { |
85 |
bb_perror_msg("extract_archive: %s", file_header->name); |
bb_perror_msg("cannot make dir %s", file_header->name); |
86 |
} |
} |
87 |
break; |
break; |
88 |
case S_IFLNK: |
case S_IFLNK: |
89 |
/* Symlink */ |
/* Symlink */ |
90 |
res = symlink(file_header->link_name, file_header->name); |
res = symlink(file_header->link_target, file_header->name); |
91 |
if ((res == -1) |
if ((res == -1) |
92 |
&& !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET) |
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
93 |
) { |
) { |
94 |
bb_perror_msg("cannot create symlink " |
bb_perror_msg("cannot create %slink " |
95 |
"from %s to '%s'", |
"from %s to %s", "sym", |
96 |
file_header->name, |
file_header->name, |
97 |
file_header->link_name); |
file_header->link_target); |
98 |
} |
} |
99 |
break; |
break; |
100 |
case S_IFSOCK: |
case S_IFSOCK: |
103 |
case S_IFIFO: |
case S_IFIFO: |
104 |
res = mknod(file_header->name, file_header->mode, file_header->device); |
res = mknod(file_header->name, file_header->mode, file_header->device); |
105 |
if ((res == -1) |
if ((res == -1) |
106 |
&& !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET) |
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) |
107 |
) { |
) { |
108 |
bb_perror_msg("cannot create node %s", file_header->name); |
bb_perror_msg("cannot create node %s", file_header->name); |
109 |
} |
} |
113 |
} |
} |
114 |
} |
} |
115 |
|
|
116 |
if (!(archive_handle->flags & ARCHIVE_NOPRESERVE_OWN)) { |
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); |
lchown(file_header->name, file_header->uid, file_header->gid); |
132 |
|
#endif |
133 |
} |
} |
134 |
|
if ((file_header->mode & S_IFMT) != S_IFLNK) { |
135 |
if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) { |
/* uclibc has no lchmod, glibc is even stranger - |
136 |
struct utimbuf t; |
* it has lchmod which seems to do nothing! |
137 |
t.actime = t.modtime = file_header->mtime; |
* so we use chmod... */ |
138 |
utime(file_header->name, &t); |
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 |
} |
} |