diff options
-rw-r--r-- | archival/libunarchive/get_header_ar.c | 2 | ||||
-rw-r--r-- | archival/libunarchive/get_header_tar.c | 65 | ||||
-rw-r--r-- | libbb/xfuncs.c | 1 |
3 files changed, 47 insertions, 21 deletions
diff --git a/archival/libunarchive/get_header_ar.c b/archival/libunarchive/get_header_ar.c index b91c6f97d..0d040e30b 100644 --- a/archival/libunarchive/get_header_ar.c +++ b/archival/libunarchive/get_header_ar.c | |||
@@ -88,7 +88,7 @@ char get_header_ar(archive_handle_t *archive_handle) | |||
88 | #endif | 88 | #endif |
89 | } else { | 89 | } else { |
90 | /* short filenames */ | 90 | /* short filenames */ |
91 | typed->name = xstrndup(ar.formatted.name, 16); | 91 | typed->name = xstrndup(ar.formatted.name, 16); |
92 | } | 92 | } |
93 | 93 | ||
94 | typed->name[strcspn(typed->name, " /")] = '\0'; | 94 | typed->name[strcspn(typed->name, " /")] = '\0'; |
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index 68f7b2b9b..0fb14e8e4 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c | |||
@@ -14,9 +14,14 @@ | |||
14 | #include "libbb.h" | 14 | #include "libbb.h" |
15 | #include "unarchive.h" | 15 | #include "unarchive.h" |
16 | 16 | ||
17 | #ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS | 17 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS |
18 | static char *longname = NULL; | 18 | static char *longname; |
19 | static char *linkname = NULL; | 19 | static char *linkname; |
20 | #else | ||
21 | enum { | ||
22 | longname = 0, | ||
23 | linkname = 0, | ||
24 | }; | ||
20 | #endif | 25 | #endif |
21 | 26 | ||
22 | /* NB: _DESTROYS_ str[len] character! */ | 27 | /* NB: _DESTROYS_ str[len] character! */ |
@@ -64,6 +69,11 @@ char get_header_tar(archive_handle_t *archive_handle) | |||
64 | } tar; | 69 | } tar; |
65 | char *cp; | 70 | char *cp; |
66 | int sum, i; | 71 | int sum, i; |
72 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS | ||
73 | int parse_names; | ||
74 | #else | ||
75 | enum { parse_names = 0 }; | ||
76 | #endif | ||
67 | 77 | ||
68 | if (sizeof(tar) != 512) | 78 | if (sizeof(tar) != 512) |
69 | BUG_tar_header_size(); | 79 | BUG_tar_header_size(); |
@@ -93,7 +103,7 @@ char get_header_tar(archive_handle_t *archive_handle) | |||
93 | * 0's are for the old tar format | 103 | * 0's are for the old tar format |
94 | */ | 104 | */ |
95 | if (strncmp(tar.magic, "ustar", 5) != 0) { | 105 | if (strncmp(tar.magic, "ustar", 5) != 0) { |
96 | #ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY | 106 | #if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY |
97 | if (memcmp(tar.magic, "\0\0\0\0", 5) != 0) | 107 | if (memcmp(tar.magic, "\0\0\0\0", 5) != 0) |
98 | #endif | 108 | #endif |
99 | bb_error_msg_and_die("invalid tar magic"); | 109 | bb_error_msg_and_die("invalid tar magic"); |
@@ -111,6 +121,10 @@ char get_header_tar(archive_handle_t *archive_handle) | |||
111 | bb_error_msg_and_die("invalid tar header checksum"); | 121 | bb_error_msg_and_die("invalid tar header checksum"); |
112 | } | 122 | } |
113 | 123 | ||
124 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS | ||
125 | parse_names = (tar.typeflag != 'L' && tar.typeflag != 'K'); | ||
126 | #endif | ||
127 | |||
114 | /* getOctal trashes subsequent field, therefore we call it | 128 | /* getOctal trashes subsequent field, therefore we call it |
115 | * on fields in reverse order */ | 129 | * on fields in reverse order */ |
116 | #define GET_OCTAL(a) getOctal((a), sizeof(a)) | 130 | #define GET_OCTAL(a) getOctal((a), sizeof(a)) |
@@ -119,27 +133,24 @@ char get_header_tar(archive_handle_t *archive_handle) | |||
119 | unsigned major = GET_OCTAL(tar.devmajor); | 133 | unsigned major = GET_OCTAL(tar.devmajor); |
120 | file_header->device = makedev(major, minor); | 134 | file_header->device = makedev(major, minor); |
121 | } | 135 | } |
136 | file_header->link_name = NULL; | ||
137 | if (!linkname && parse_names && tar.linkname[0]) { | ||
138 | /* we trash magic[0] here, it's ok */ | ||
139 | tar.linkname[sizeof(tar.linkname)] = '\0'; | ||
140 | file_header->link_name = xstrdup(tar.linkname); | ||
141 | /* FIXME: what if we have non-link object with link_name? */ | ||
142 | /* Will link_name be free()ed? */ | ||
143 | } | ||
122 | file_header->mtime = GET_OCTAL(tar.mtime); | 144 | file_header->mtime = GET_OCTAL(tar.mtime); |
123 | file_header->size = GET_OCTAL(tar.size); | 145 | file_header->size = GET_OCTAL(tar.size); |
124 | file_header->gid = GET_OCTAL(tar.gid); | 146 | file_header->gid = GET_OCTAL(tar.gid); |
125 | file_header->uid = GET_OCTAL(tar.uid); | 147 | file_header->uid = GET_OCTAL(tar.uid); |
126 | file_header->link_name = !tar.linkname[0] ? NULL : | ||
127 | xstrndup(tar.linkname, sizeof(tar.linkname)); | ||
128 | /* Set bits 0-11 of the files mode */ | 148 | /* Set bits 0-11 of the files mode */ |
129 | file_header->mode = 07777 & GET_OCTAL(tar.mode); | 149 | file_header->mode = 07777 & GET_OCTAL(tar.mode); |
130 | #undef GET_OCTAL | 150 | #undef GET_OCTAL |
131 | 151 | ||
132 | #ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS | 152 | if (!longname && parse_names) { |
133 | if (longname) { | 153 | /* we trash mode[0] here, it's ok */ |
134 | file_header->name = longname; | ||
135 | longname = NULL; | ||
136 | } | ||
137 | else if (linkname) { | ||
138 | file_header->name = linkname; | ||
139 | linkname = NULL; | ||
140 | } else | ||
141 | #endif | ||
142 | { /* we trash mode[0] here, it's ok */ | ||
143 | tar.name[sizeof(tar.name)] = '\0'; | 154 | tar.name[sizeof(tar.name)] = '\0'; |
144 | if (tar.prefix[0]) | 155 | if (tar.prefix[0]) |
145 | file_header->name = concat_path_file(tar.prefix, tar.name); | 156 | file_header->name = concat_path_file(tar.prefix, tar.name); |
@@ -148,6 +159,7 @@ char get_header_tar(archive_handle_t *archive_handle) | |||
148 | } | 159 | } |
149 | 160 | ||
150 | /* Set bits 12-15 of the files mode */ | 161 | /* Set bits 12-15 of the files mode */ |
162 | /* (typeflag was not trashed because chksum does not use getOctal) */ | ||
151 | switch (tar.typeflag) { | 163 | switch (tar.typeflag) { |
152 | /* busybox identifies hard links as being regular files with 0 size and a link name */ | 164 | /* busybox identifies hard links as being regular files with 0 size and a link name */ |
153 | case '1': | 165 | case '1': |
@@ -157,7 +169,7 @@ char get_header_tar(archive_handle_t *archive_handle) | |||
157 | /* Reserved for high performance files, treat as normal file */ | 169 | /* Reserved for high performance files, treat as normal file */ |
158 | case 0: | 170 | case 0: |
159 | case '0': | 171 | case '0': |
160 | #ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY | 172 | #if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY |
161 | if (last_char_is(file_header->name, '/')) { | 173 | if (last_char_is(file_header->name, '/')) { |
162 | file_header->mode |= S_IFDIR; | 174 | file_header->mode |= S_IFDIR; |
163 | } else | 175 | } else |
@@ -179,17 +191,19 @@ char get_header_tar(archive_handle_t *archive_handle) | |||
179 | case '6': | 191 | case '6': |
180 | file_header->mode |= S_IFIFO; | 192 | file_header->mode |= S_IFIFO; |
181 | break; | 193 | break; |
182 | #ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS | 194 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS |
183 | case 'L': | 195 | case 'L': |
196 | /* paranoia: tar with several consecutive longnames */ | ||
197 | free(longname); | ||
184 | longname = xzalloc(file_header->size + 1); | 198 | longname = xzalloc(file_header->size + 1); |
185 | xread(archive_handle->src_fd, longname, file_header->size); | 199 | xread(archive_handle->src_fd, longname, file_header->size); |
186 | archive_handle->offset += file_header->size; | 200 | archive_handle->offset += file_header->size; |
187 | return get_header_tar(archive_handle); | 201 | return get_header_tar(archive_handle); |
188 | case 'K': | 202 | case 'K': |
203 | free(linkname); | ||
189 | linkname = xzalloc(file_header->size + 1); | 204 | linkname = xzalloc(file_header->size + 1); |
190 | xread(archive_handle->src_fd, linkname, file_header->size); | 205 | xread(archive_handle->src_fd, linkname, file_header->size); |
191 | archive_handle->offset += file_header->size; | 206 | archive_handle->offset += file_header->size; |
192 | file_header->name = linkname; | ||
193 | return get_header_tar(archive_handle); | 207 | return get_header_tar(archive_handle); |
194 | case 'D': /* GNU dump dir */ | 208 | case 'D': /* GNU dump dir */ |
195 | case 'M': /* Continuation of multi volume archive */ | 209 | case 'M': /* Continuation of multi volume archive */ |
@@ -205,6 +219,17 @@ char get_header_tar(archive_handle_t *archive_handle) | |||
205 | bb_error_msg("unknown typeflag: 0x%x", tar.typeflag); | 219 | bb_error_msg("unknown typeflag: 0x%x", tar.typeflag); |
206 | } | 220 | } |
207 | 221 | ||
222 | #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS | ||
223 | if (longname) { | ||
224 | file_header->name = longname; | ||
225 | longname = NULL; | ||
226 | } | ||
227 | if (linkname) { | ||
228 | file_header->link_name = linkname; | ||
229 | linkname = NULL; | ||
230 | } | ||
231 | #endif | ||
232 | |||
208 | /* Strip trailing '/' in directories */ | 233 | /* Strip trailing '/' in directories */ |
209 | /* Must be done after mode is set as '/' is used to check if its a directory */ | 234 | /* Must be done after mode is set as '/' is used to check if its a directory */ |
210 | cp = last_char_is(file_header->name, '/'); | 235 | cp = last_char_is(file_header->name, '/'); |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index e6f4e3a48..1dbd7521b 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -74,6 +74,7 @@ char * xstrndup(const char *s, int n) | |||
74 | if (ENABLE_DEBUG && s == NULL) | 74 | if (ENABLE_DEBUG && s == NULL) |
75 | bb_error_msg_and_die("xstrndup bug"); | 75 | bb_error_msg_and_die("xstrndup bug"); |
76 | 76 | ||
77 | /* TODO: think about xstrndup("abc", 10000)!!! */ | ||
77 | t = xmalloc(++n); | 78 | t = xmalloc(++n); |
78 | 79 | ||
79 | return safe_strncpy(t,s,n); | 80 | return safe_strncpy(t,s,n); |