aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archival/libunarchive/get_header_ar.c2
-rw-r--r--archival/libunarchive/get_header_tar.c65
-rw-r--r--libbb/xfuncs.c1
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
18static char *longname = NULL; 18static char *longname;
19static char *linkname = NULL; 19static char *linkname;
20#else
21enum {
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);