aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--archival/Config.src11
-rw-r--r--archival/ar.c23
-rw-r--r--archival/bbunzip.c8
-rw-r--r--archival/cpio.c13
-rw-r--r--archival/dpkg.c29
-rw-r--r--archival/libarchive/Kbuild.src2
-rw-r--r--archival/libarchive/data_extract_all.c8
-rw-r--r--archival/libarchive/decompress_gunzip.c6
-rw-r--r--archival/libarchive/get_header_tar.c5
-rw-r--r--archival/libarchive/open_transformer.c33
-rw-r--r--archival/libarchive/unpack_ar_archive.c8
-rw-r--r--archival/libarchive/unsafe_prefix.c6
-rw-r--r--archival/libarchive/unsafe_symlink_target.c8
-rw-r--r--archival/rpm.c25
-rw-r--r--archival/tar.c30
-rw-r--r--archival/unzip.c5
16 files changed, 192 insertions, 28 deletions
diff --git a/archival/Config.src b/archival/Config.src
index 6f4f30c43..cbcd7217c 100644
--- a/archival/Config.src
+++ b/archival/Config.src
@@ -35,4 +35,15 @@ config FEATURE_LZMA_FAST
35 This option reduces decompression time by about 25% at the cost of 35 This option reduces decompression time by about 25% at the cost of
36 a 1K bigger binary. 36 a 1K bigger binary.
37 37
38config FEATURE_PATH_TRAVERSAL_PROTECTION
39 bool "Prevent extraction of filenames with /../ path component"
40 default n
41 help
42 busybox tar and unzip remove "PREFIX/../" (if it exists)
43 from extracted names.
44 This option enables this behavior for all other unpacking applets,
45 such as cpio, ar, rpm.
46 GNU cpio 2.15 has NO such sanity check.
47# try other archivers and document their behavior?
48
38endmenu 49endmenu
diff --git a/archival/ar.c b/archival/ar.c
index 320cbae72..16bb33227 100644
--- a/archival/ar.c
+++ b/archival/ar.c
@@ -30,12 +30,12 @@
30//config:config FEATURE_AR_LONG_FILENAMES 30//config:config FEATURE_AR_LONG_FILENAMES
31//config: bool "Support long filenames (not needed for debs)" 31//config: bool "Support long filenames (not needed for debs)"
32//config: default y 32//config: default y
33//config: depends on AR 33//config: depends on AR || MAKE || PDPMAKE
34//config: help 34//config: help
35//config: By default the ar format can only store the first 15 characters 35//config: By default the ar format can only store the first 15 characters
36//config: of the filename, this option removes that limitation. 36//config: of the filename, this option removes that limitation.
37//config: It supports the GNU ar long filename method which moves multiple long 37//config: It supports the GNU ar long filename method which moves multiple long
38//config: filenames into a the data section of a new ar entry. 38//config: filenames into the data section of a new ar entry.
39//config: 39//config:
40//config:config FEATURE_AR_CREATE 40//config:config FEATURE_AR_CREATE
41//config: bool "Support archive creation" 41//config: bool "Support archive creation"
@@ -153,6 +153,9 @@ static int write_ar_archive(archive_handle_t *handle)
153{ 153{
154 struct stat st; 154 struct stat st;
155 archive_handle_t *out_handle; 155 archive_handle_t *out_handle;
156#if ENABLE_PLATFORM_MINGW32
157 char *temp_fn = NULL;
158#endif
156 159
157 xfstat(handle->src_fd, &st, handle->ar__name); 160 xfstat(handle->src_fd, &st, handle->ar__name);
158 161
@@ -161,8 +164,14 @@ static int write_ar_archive(archive_handle_t *handle)
161 */ 164 */
162 if (st.st_size != 0) { 165 if (st.st_size != 0) {
163 out_handle = init_handle(); 166 out_handle = init_handle();
167#if !ENABLE_PLATFORM_MINGW32
164 xunlink(handle->ar__name); 168 xunlink(handle->ar__name);
165 out_handle->src_fd = xopen(handle->ar__name, O_WRONLY | O_CREAT | O_TRUNC); 169 out_handle->src_fd = xopen(handle->ar__name, O_WRONLY | O_CREAT | O_TRUNC);
170#else
171 /* can't unlink open file, create temporary output file */
172 temp_fn = xasprintf("%sXXXXXX", handle->ar__name);
173 out_handle->src_fd = xmkstemp(temp_fn);
174#endif
166 out_handle->accept = handle->accept; 175 out_handle->accept = handle->accept;
167 } else { 176 } else {
168 out_handle = handle; 177 out_handle = handle;
@@ -184,12 +193,20 @@ static int write_ar_archive(archive_handle_t *handle)
184 continue; 193 continue;
185 194
186 /* optional, since we exit right after we return */ 195 /* optional, since we exit right after we return */
187 if (ENABLE_FEATURE_CLEAN_UP) { 196 if (ENABLE_FEATURE_CLEAN_UP || ENABLE_PLATFORM_MINGW32) {
188 close(handle->src_fd); 197 close(handle->src_fd);
189 if (out_handle->src_fd != handle->src_fd) 198 if (out_handle->src_fd != handle->src_fd)
190 close(out_handle->src_fd); 199 close(out_handle->src_fd);
191 } 200 }
192 201
202#if ENABLE_PLATFORM_MINGW32
203 if (temp_fn != NULL) {
204 xrename(temp_fn, handle->ar__name);
205 if (ENABLE_FEATURE_CLEAN_UP)
206 free(temp_fn);
207 }
208#endif
209
193 return EXIT_SUCCESS; 210 return EXIT_SUCCESS;
194} 211}
195#endif /* FEATURE_AR_CREATE */ 212#endif /* FEATURE_AR_CREATE */
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index b7944a62a..1f1f28b61 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -71,8 +71,8 @@ int FAST_FUNC bbunpack(char **argv,
71 goto err; 71 goto err;
72 } else { 72 } else {
73 /* "clever zcat" with FILE */ 73 /* "clever zcat" with FILE */
74 /* fail_if_not_compressed because zcat refuses uncompressed input */ 74 /* die_if_not_compressed because zcat refuses uncompressed input */
75 int fd = open_zipped(filename, /*fail_if_not_compressed:*/ 1); 75 int fd = open_zipped(filename, /*die_if_not_compressed:*/ 1);
76 if (fd < 0) 76 if (fd < 0)
77 goto err_name; 77 goto err_name;
78 xmove_fd(fd, STDIN_FILENO); 78 xmove_fd(fd, STDIN_FILENO);
@@ -80,7 +80,7 @@ int FAST_FUNC bbunpack(char **argv,
80 } else 80 } else
81 if (option_mask32 & BBUNPK_SEAMLESS_MAGIC) { 81 if (option_mask32 & BBUNPK_SEAMLESS_MAGIC) {
82 /* "clever zcat" on stdin */ 82 /* "clever zcat" on stdin */
83 if (setup_unzip_on_fd(STDIN_FILENO, /*fail_if_not_compressed*/ 1)) 83 if (setup_unzip_on_fd(STDIN_FILENO, /*die_if_not_compressed*/ 1))
84 goto err; 84 goto err;
85 } 85 }
86 86
@@ -178,6 +178,8 @@ int FAST_FUNC bbunpack(char **argv,
178 if (option_mask32 & BBUNPK_OPT_KEEP) /* ... unless -k */ 178 if (option_mask32 & BBUNPK_OPT_KEEP) /* ... unless -k */
179 del = NULL; 179 del = NULL;
180 } 180 }
181 if (ENABLE_PLATFORM_MINGW32)
182 xclose(STDIN_FILENO);
181 if (del) 183 if (del)
182 xunlink(del); 184 xunlink(del);
183 free_name: 185 free_name:
diff --git a/archival/cpio.c b/archival/cpio.c
index f0d990048..38d826a3c 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -49,7 +49,7 @@
49//config:config FEATURE_CPIO_RENUMBER_INODES 49//config:config FEATURE_CPIO_RENUMBER_INODES
50//config: bool "Support --renumber-inodes like GNU cpio" 50//config: bool "Support --renumber-inodes like GNU cpio"
51//config: default y 51//config: default y
52//config: depends on FEATURE_CPIO_O && LONG_OPTS 52//config: depends on FEATURE_CPIO_O && LONG_OPTS && (PLATFORM_POSIX || FEATURE_EXTRA_FILE_DATA)
53//config: help 53//config: help
54//config: Optionally renumber inodes when creating archives. 54//config: Optionally renumber inodes when creating archives.
55 55
@@ -275,6 +275,7 @@ static NOINLINE int cpio_o(void)
275 if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode))) 275 if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode)))
276 st.st_size = 0; /* paranoia */ 276 st.st_size = 0; /* paranoia */
277 277
278#if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_EXTRA_FILE_DATA
278 /* Store hardlinks for later processing, dont output them */ 279 /* Store hardlinks for later processing, dont output them */
279 if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) { 280 if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) {
280 struct name_s *n; 281 struct name_s *n;
@@ -310,6 +311,7 @@ static NOINLINE int cpio_o(void)
310 free(line); 311 free(line);
311 continue; 312 continue;
312 } 313 }
314#endif
313#if ENABLE_FEATURE_CPIO_RENUMBER_INODES 315#if ENABLE_FEATURE_CPIO_RENUMBER_INODES
314 else if (option_mask32 & OPT_RENUMBER_INODES) { 316 else if (option_mask32 & OPT_RENUMBER_INODES) {
315 st.st_ino = ++G.next_inode; 317 st.st_ino = ++G.next_inode;
@@ -345,10 +347,18 @@ static NOINLINE int cpio_o(void)
345 } 347 }
346 } 348 }
347 349
350#if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_EXTRA_FILE_DATA
348#if ENABLE_FEATURE_CPIO_IGNORE_DEVNO 351#if ENABLE_FEATURE_CPIO_IGNORE_DEVNO
349 if (option_mask32 & OPT_IGNORE_DEVNO) 352 if (option_mask32 & OPT_IGNORE_DEVNO)
350 st.st_dev = st.st_rdev = 0; 353 st.st_dev = st.st_rdev = 0;
351#endif 354#endif
355#endif
356
357 if (sizeof(st.st_size) > 4
358 && st.st_size > (off_t)0xffffffff
359 ) {
360 bb_error_msg_and_die("error: file '%s' is larger than 4GB", name);
361 }
352 362
353 bytes += printf("070701" 363 bytes += printf("070701"
354 "%08X%08X%08X%08X%08X%08X%08X" 364 "%08X%08X%08X%08X%08X%08X%08X"
@@ -421,6 +431,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
421#endif 431#endif
422#endif 432#endif
423 "owner\0" Required_argument "R" 433 "owner\0" Required_argument "R"
434 "file\0" Required_argument "F"
424 "verbose\0" No_argument "v" 435 "verbose\0" No_argument "v"
425 "null\0" No_argument "0" 436 "null\0" No_argument "0"
426 "quiet\0" No_argument "\xff" 437 "quiet\0" No_argument "\xff"
diff --git a/archival/dpkg.c b/archival/dpkg.c
index 8031956e9..a6a8333a8 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -149,6 +149,11 @@ enum edge_type_e {
149 EDGE_RECOMMENDS = 13, 149 EDGE_RECOMMENDS = 13,
150 EDGE_ENHANCES = 15 150 EDGE_ENHANCES = 15
151}; 151};
152#if ENABLE_PLATFORM_MINGW32
153#undef VER_EQUAL
154#undef VER_LESS
155#undef VER_LESS_EQUAL
156#endif
152enum operator_e { 157enum operator_e {
153 VER_NULL = 0, 158 VER_NULL = 0,
154 VER_EQUAL = 1, 159 VER_EQUAL = 1,
@@ -1770,6 +1775,10 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv)
1770 int state_status; 1775 int state_status;
1771 int status_num; 1776 int status_num;
1772 int i; 1777 int i;
1778#if ENABLE_PLATFORM_MINGW32
1779 char **ptr, *path;
1780 int fd;
1781#endif
1773#if ENABLE_LONG_OPTS 1782#if ENABLE_LONG_OPTS
1774 static const char dpkg_longopts[] ALIGN1 = 1783 static const char dpkg_longopts[] ALIGN1 =
1775// FIXME: we use -C non-compatibly, should be: 1784// FIXME: we use -C non-compatibly, should be:
@@ -1814,6 +1823,26 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv)
1814 bb_show_usage(); 1823 bb_show_usage();
1815 } 1824 }
1816 1825
1826#if ENABLE_PLATFORM_MINGW32
1827 if (opt & OPT_install) {
1828 /* add system drive prefix to filenames, if necessary */
1829 for (ptr = argv; *ptr; ++ptr) {
1830 *ptr = xabsolute_path(*ptr);
1831 }
1832 }
1833
1834 chdir_system_drive();
1835
1836 /* initialise data store */
1837 path = xstrdup("/var/lib/dpkg/info");
1838 bb_make_directory(path, -1, FILEUTILS_RECUR);
1839 free(path);
1840
1841 fd = open("/var/lib/dpkg/status", O_RDWR|O_CREAT, 0666);
1842 if (fd >= 0)
1843 xclose(fd);
1844#endif
1845
1817/* puts("(Reading database ... xxxxx files and directories installed.)"); */ 1846/* puts("(Reading database ... xxxxx files and directories installed.)"); */
1818 index_status_file("/var/lib/dpkg/status"); 1847 index_status_file("/var/lib/dpkg/status");
1819 1848
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index d2f284b08..1b1dabbf5 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -47,6 +47,8 @@ lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
47 47
48lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o 48lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
49lib-$(CONFIG_CPIO) += get_header_cpio.o 49lib-$(CONFIG_CPIO) += get_header_cpio.o
50lib-$(CONFIG_MAKE) += get_header_ar.o unpack_ar_archive.o
51lib-$(CONFIG_PDPMAKE) += get_header_ar.o unpack_ar_archive.o
50lib-$(CONFIG_TAR) += get_header_tar.o unsafe_prefix.o 52lib-$(CONFIG_TAR) += get_header_tar.o unsafe_prefix.o
51lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o 53lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o
52lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o 54lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index 049c2c156..8a69711c1 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -65,6 +65,14 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
65 } while (--n != 0); 65 } while (--n != 0);
66 } 66 }
67#endif 67#endif
68#if ENABLE_FEATURE_PATH_TRAVERSAL_PROTECTION
69 /* Strip leading "/" and up to last "/../" path component */
70 dst_name = (char *)strip_unsafe_prefix(dst_name);
71#endif
72// ^^^ This may be a problem if some applets do need to extract absolute names.
73// (Probably will need to invent ARCHIVE_ALLOW_UNSAFE_NAME flag).
74// You might think that rpm needs it, but in my tests rpm's internal cpio
75// archive has names like "./usr/bin/FOO", not "/usr/bin/FOO".
68 76
69 if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { 77 if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
70 char *slash = strrchr(dst_name, '/'); 78 char *slash = strrchr(dst_name, '/');
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c
index d051ecb81..d2f7a9309 100644
--- a/archival/libarchive/decompress_gunzip.c
+++ b/archival/libarchive/decompress_gunzip.c
@@ -1137,6 +1137,9 @@ static uint32_t buffer_read_le_u32(STATE_PARAM_ONLY)
1137 return res; 1137 return res;
1138} 1138}
1139 1139
1140#if ENABLE_PLATFORM_MINGW32 && __GNUC__
1141#pragma pack(2)
1142#endif
1140static int check_header_gzip(STATE_PARAM transformer_state_t *xstate) 1143static int check_header_gzip(STATE_PARAM transformer_state_t *xstate)
1141{ 1144{
1142 union { 1145 union {
@@ -1208,6 +1211,9 @@ static int check_header_gzip(STATE_PARAM transformer_state_t *xstate)
1208 } 1211 }
1209 return 1; 1212 return 1;
1210} 1213}
1214#if ENABLE_PLATFORM_MINGW32 && __GNUC__
1215#pragma pack()
1216#endif
1211 1217
1212IF_DESKTOP(long long) int FAST_FUNC 1218IF_DESKTOP(long long) int FAST_FUNC
1213unpack_gz_stream(transformer_state_t *xstate) 1219unpack_gz_stream(transformer_state_t *xstate)
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index cc6f3f0ad..5fd5a7980 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -239,8 +239,13 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
239 /* Check header has valid magic, "ustar" is for the proper tar, 239 /* Check header has valid magic, "ustar" is for the proper tar,
240 * five NULs are for the old tar format */ 240 * five NULs are for the old tar format */
241 if (!is_prefixed_with(tar.magic, "ustar") 241 if (!is_prefixed_with(tar.magic, "ustar")
242#if !ENABLE_PLATFORM_MINGW32
242 && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY 243 && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
243 || memcmp(tar.magic, "\0\0\0\0", 5) != 0) 244 || memcmp(tar.magic, "\0\0\0\0", 5) != 0)
245#else
246 && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
247 || memcmp(tar.magic, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) != 0)
248#endif
244 ) { 249 ) {
245#if ENABLE_FEATURE_TAR_AUTODETECT 250#if ENABLE_FEATURE_TAR_AUTODETECT
246 autodetect: 251 autodetect:
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c
index 44715ef25..a949c4509 100644
--- a/archival/libarchive/open_transformer.c
+++ b/archival/libarchive/open_transformer.c
@@ -64,6 +64,7 @@ ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *bu
64 return nwrote; 64 return nwrote;
65} 65}
66 66
67#if !ENABLE_PLATFORM_MINGW32
67void check_errors_in_children(int signo) 68void check_errors_in_children(int signo)
68{ 69{
69 int status; 70 int status;
@@ -150,6 +151,12 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
150 close(fd_pipe.wr); /* don't want to write to the child */ 151 close(fd_pipe.wr); /* don't want to write to the child */
151 xmove_fd(fd_pipe.rd, fd); 152 xmove_fd(fd_pipe.rd, fd);
152} 153}
154#else /* ENABLE_PLATFORM_MINGW */
155void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
156{
157 mingw_fork_compressor(fd, transform_prog, "r");
158}
159#endif
153 160
154 161
155#if SEAMLESS_COMPRESSION 162#if SEAMLESS_COMPRESSION
@@ -157,7 +164,7 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
157/* Used by e.g. rpm which gives us a fd without filename, 164/* Used by e.g. rpm which gives us a fd without filename,
158 * thus we can't guess the format from filename's extension. 165 * thus we can't guess the format from filename's extension.
159 */ 166 */
160static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed) 167static transformer_state_t *setup_transformer_on_fd(int fd, int die_if_not_compressed)
161{ 168{
162 transformer_state_t *xstate; 169 transformer_state_t *xstate;
163 170
@@ -204,7 +211,7 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
204 } 211 }
205 212
206 /* No known magic seen */ 213 /* No known magic seen */
207 if (fail_if_not_compressed) 214 if (die_if_not_compressed)
208 bb_simple_error_msg_and_die("no gzip" 215 bb_simple_error_msg_and_die("no gzip"
209 IF_FEATURE_SEAMLESS_BZ2("/bzip2") 216 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
210 IF_FEATURE_SEAMLESS_XZ("/xz") 217 IF_FEATURE_SEAMLESS_XZ("/xz")
@@ -240,13 +247,15 @@ static void fork_transformer_and_free(transformer_state_t *xstate)
240/* Used by e.g. rpm which gives us a fd without filename, 247/* Used by e.g. rpm which gives us a fd without filename,
241 * thus we can't guess the format from filename's extension. 248 * thus we can't guess the format from filename's extension.
242 */ 249 */
243int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed) 250int FAST_FUNC setup_unzip_on_fd(int fd, int die_if_not_compressed)
244{ 251{
245 transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); 252 transformer_state_t *xstate = setup_transformer_on_fd(fd, die_if_not_compressed);
246 253
247 if (!xstate->xformer) { 254 if (!xstate->xformer) {
255 /* Not compressed */
256 int retval = xstate->signature_skipped; /* never zero */
248 free(xstate); 257 free(xstate);
249 return 1; 258 return retval;
250 } 259 }
251 260
252 fork_transformer_and_free(xstate); 261 fork_transformer_and_free(xstate);
@@ -264,7 +273,7 @@ void FAST_FUNC setup_lzma_on_fd(int fd)
264} 273}
265#endif 274#endif
266 275
267static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed) 276static transformer_state_t *open_transformer(const char *fname, int die_if_not_compressed)
268{ 277{
269 transformer_state_t *xstate; 278 transformer_state_t *xstate;
270 int fd; 279 int fd;
@@ -284,18 +293,18 @@ static transformer_state_t *open_transformer(const char *fname, int fail_if_not_
284 } 293 }
285 } 294 }
286 295
287 xstate = setup_transformer_on_fd(fd, fail_if_not_compressed); 296 xstate = setup_transformer_on_fd(fd, die_if_not_compressed);
288 297
289 return xstate; 298 return xstate;
290} 299}
291 300
292int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed) 301int FAST_FUNC open_zipped(const char *fname, int die_if_not_compressed)
293{ 302{
294 int fd; 303 int fd;
295 transformer_state_t *xstate; 304 transformer_state_t *xstate;
296 305
297 xstate = open_transformer(fname, fail_if_not_compressed); 306 xstate = open_transformer(fname, die_if_not_compressed);
298 if (!xstate) 307 if (!xstate) /* open error */
299 return -1; 308 return -1;
300 309
301 fd = xstate->src_fd; 310 fd = xstate->src_fd;
@@ -326,7 +335,7 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_
326 transformer_state_t *xstate; 335 transformer_state_t *xstate;
327 char *image; 336 char *image;
328 337
329 xstate = open_transformer(fname, /*fail_if_not_compressed:*/ 0); 338 xstate = open_transformer(fname, /*die_if_not_compressed:*/ 0);
330 if (!xstate) /* file open error */ 339 if (!xstate) /* file open error */
331 return NULL; 340 return NULL;
332 341
@@ -371,7 +380,7 @@ void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_
371 int fd; 380 int fd;
372 char *image; 381 char *image;
373 382
374 fd = open_zipped(fname, /*fail_if_not_compressed:*/ 0); 383 fd = open_zipped(fname, /*die_if_not_compressed:*/ 0);
375 if (fd < 0) 384 if (fd < 0)
376 return NULL; 385 return NULL;
377 386
diff --git a/archival/libarchive/unpack_ar_archive.c b/archival/libarchive/unpack_ar_archive.c
index 125d424c9..923a0b2ab 100644
--- a/archival/libarchive/unpack_ar_archive.c
+++ b/archival/libarchive/unpack_ar_archive.c
@@ -16,6 +16,10 @@ void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive)
16 } 16 }
17 ar_archive->offset += AR_MAGIC_LEN; 17 ar_archive->offset += AR_MAGIC_LEN;
18 18
19 while (get_header_ar(ar_archive) == EXIT_SUCCESS) 19 while (get_header_ar(ar_archive) == EXIT_SUCCESS) {
20 continue; 20#if ENABLE_MAKE
21 free(ar_archive->file_header->name);
22 ar_archive->file_header->name = NULL;
23#endif
24 }
21} 25}
diff --git a/archival/libarchive/unsafe_prefix.c b/archival/libarchive/unsafe_prefix.c
index 33e487bf9..667081195 100644
--- a/archival/libarchive/unsafe_prefix.c
+++ b/archival/libarchive/unsafe_prefix.c
@@ -14,7 +14,11 @@ const char* FAST_FUNC strip_unsafe_prefix(const char *str)
14 cp++; 14 cp++;
15 continue; 15 continue;
16 } 16 }
17 if (is_prefixed_with(cp, "/../"+1)) { 17 /* We are called lots of times.
18 * is_prefixed_with(cp, "../") is slower than open-coding it,
19 * with minimal code growth (~few bytes).
20 */
21 if (cp[0] == '.' && cp[1] == '.' && cp[2] == '/') {
18 cp += 3; 22 cp += 3;
19 continue; 23 continue;
20 } 24 }
diff --git a/archival/libarchive/unsafe_symlink_target.c b/archival/libarchive/unsafe_symlink_target.c
index f8dc8033d..d9100f30f 100644
--- a/archival/libarchive/unsafe_symlink_target.c
+++ b/archival/libarchive/unsafe_symlink_target.c
@@ -10,18 +10,26 @@ void FAST_FUNC create_or_remember_link(llist_t **link_placeholders,
10 const char *linkname, 10 const char *linkname,
11 int hard_link) 11 int hard_link)
12{ 12{
13#if ENABLE_PLATFORM_MINGW32
14 /* defer reporting error if symlink(2) fails on Windows */
15 if (hard_link || target[0] == '/' || strstr(target, "..") ||
16 symlink(target, linkname) != 0) {
17#else
13 if (hard_link || target[0] == '/' || strstr(target, "..")) { 18 if (hard_link || target[0] == '/' || strstr(target, "..")) {
19#endif
14 llist_add_to_end(link_placeholders, 20 llist_add_to_end(link_placeholders,
15 xasprintf("%c%s%c%s", hard_link, linkname, '\0', target) 21 xasprintf("%c%s%c%s", hard_link, linkname, '\0', target)
16 ); 22 );
17 return; 23 return;
18 } 24 }
25#if !ENABLE_PLATFORM_MINGW32
19 if (symlink(target, linkname) != 0) { 26 if (symlink(target, linkname) != 0) {
20 /* shared message */ 27 /* shared message */
21 bb_perror_msg_and_die("can't create %slink '%s' to '%s'", 28 bb_perror_msg_and_die("can't create %slink '%s' to '%s'",
22 "sym", linkname, target 29 "sym", linkname, target
23 ); 30 );
24 } 31 }
32#endif
25} 33}
26 34
27void FAST_FUNC create_links_from_list(llist_t *list) 35void FAST_FUNC create_links_from_list(llist_t *list)
diff --git a/archival/rpm.c b/archival/rpm.c
index af8db99a6..c2f0550ff 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -142,6 +142,7 @@ static int rpm_gettags(const char *filename)
142 } 142 }
143 G.mytags = tags; 143 G.mytags = tags;
144 144
145#if !ENABLE_PLATFORM_MINGW32
145 /* Map the store */ 146 /* Map the store */
146 storepos = (storepos + G_pagesize) & -(int)G_pagesize; 147 storepos = (storepos + G_pagesize) & -(int)G_pagesize;
147 /* remember size for munmap */ 148 /* remember size for munmap */
@@ -150,6 +151,14 @@ static int rpm_gettags(const char *filename)
150 G.map = mmap_read(fd, storepos); 151 G.map = mmap_read(fd, storepos);
151 if (G.map == MAP_FAILED) 152 if (G.map == MAP_FAILED)
152 bb_perror_msg_and_die("mmap '%s'", filename); 153 bb_perror_msg_and_die("mmap '%s'", filename);
154#else
155# undef munmap
156# define munmap(p, l) free(p)
157 /* Allocate memory for the store */
158 G.map = xmalloc(storepos);
159 xlseek(fd, 0, SEEK_SET);
160 full_read(fd, G.map, storepos);
161#endif
153 162
154 return fd; 163 return fd;
155} 164}
@@ -240,6 +249,7 @@ static void fileaction_dobackup(char *filename, int fileref)
240 } 249 }
241} 250}
242 251
252#if !ENABLE_PLATFORM_MINGW32
243static void fileaction_setowngrp(char *filename, int fileref) 253static void fileaction_setowngrp(char *filename, int fileref)
244{ 254{
245 /* real rpm warns: "user foo does not exist - using <you>" */ 255 /* real rpm warns: "user foo does not exist - using <you>" */
@@ -249,6 +259,7 @@ static void fileaction_setowngrp(char *filename, int fileref)
249 int gid = gr ? gr->gr_gid : getgid(); 259 int gid = gr ? gr->gr_gid : getgid();
250 chown(filename, uid, gid); 260 chown(filename, uid, gid);
251} 261}
262#endif
252 263
253static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref)) 264static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref))
254{ 265{
@@ -296,6 +307,9 @@ static void extract_cpio(int fd, const char *source_rpm)
296 307
297 if (source_rpm != NULL) { 308 if (source_rpm != NULL) {
298 /* Binary rpm (it was built from some SRPM), install to root */ 309 /* Binary rpm (it was built from some SRPM), install to root */
310#if ENABLE_PLATFORM_MINGW32
311 if (chdir_system_drive())
312#endif
299 xchdir("/"); 313 xchdir("/");
300 } /* else: SRPM, install to current dir */ 314 } /* else: SRPM, install to current dir */
301 315
@@ -316,7 +330,7 @@ static void extract_cpio(int fd, const char *source_rpm)
316 archive_handle->src_fd = fd; 330 archive_handle->src_fd = fd;
317 /*archive_handle->offset = 0; - init_handle() did it */ 331 /*archive_handle->offset = 0; - init_handle() did it */
318 332
319 setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_compressed:*/ 1); 333 setup_unzip_on_fd(archive_handle->src_fd, /*die_if_not_compressed:*/ 1);
320 while (get_header_cpio(archive_handle) == EXIT_SUCCESS) 334 while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
321 continue; 335 continue;
322} 336}
@@ -410,8 +424,10 @@ int rpm_main(int argc, char **argv)
410 loop_through_files(TAG_BASENAMES, fileaction_dobackup); 424 loop_through_files(TAG_BASENAMES, fileaction_dobackup);
411 /* Extact the archive */ 425 /* Extact the archive */
412 extract_cpio(rpm_fd, source_rpm); 426 extract_cpio(rpm_fd, source_rpm);
427#if !ENABLE_PLATFORM_MINGW32
413 /* Set the correct file uid/gid's */ 428 /* Set the correct file uid/gid's */
414 loop_through_files(TAG_BASENAMES, fileaction_setowngrp); 429 loop_through_files(TAG_BASENAMES, fileaction_setowngrp);
430#endif
415 } 431 }
416 else 432 else
417 if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) { 433 if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) {
@@ -533,6 +549,7 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
533 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */ 549 // /* We need to know whether child (gzip/bzip/etc) exits abnormally */
534 // signal(SIGCHLD, check_errors_in_children); 550 // signal(SIGCHLD, check_errors_in_children);
535 551
552 str = NULL;
536 if (ENABLE_FEATURE_SEAMLESS_LZMA 553 if (ENABLE_FEATURE_SEAMLESS_LZMA
537 && (str = rpm_getstr0(TAG_PAYLOADCOMPRESSOR)) != NULL 554 && (str = rpm_getstr0(TAG_PAYLOADCOMPRESSOR)) != NULL
538 && strcmp(str, "lzma") == 0 555 && strcmp(str, "lzma") == 0
@@ -541,7 +558,11 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
541 // set up decompressor without detection 558 // set up decompressor without detection
542 setup_lzma_on_fd(rpm_fd); 559 setup_lzma_on_fd(rpm_fd);
543 } else { 560 } else {
544 setup_unzip_on_fd(rpm_fd, /*fail_if_not_compressed:*/ 1); 561 int signature_bytes = setup_unzip_on_fd(rpm_fd, /*die_if_not_compressed:*/ 0);
562 if (signature_bytes != 0) {
563 xlseek(rpm_fd, - signature_bytes, SEEK_CUR);
564 bb_error_msg("warning, unknown compression '%s'", str);
565 }
545 } 566 }
546 567
547 if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0) 568 if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0)
diff --git a/archival/tar.c b/archival/tar.c
index d6ca6c1e0..fd20d6ce7 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -119,6 +119,9 @@
119#include "libbb.h" 119#include "libbb.h"
120#include "common_bufsiz.h" 120#include "common_bufsiz.h"
121#include "bb_archive.h" 121#include "bb_archive.h"
122#if ENABLE_PLATFORM_MINGW32
123# include "BB_VER.h"
124#endif
122/* FIXME: Stop using this non-standard feature */ 125/* FIXME: Stop using this non-standard feature */
123#ifndef FNM_LEADING_DIR 126#ifndef FNM_LEADING_DIR
124# define FNM_LEADING_DIR 0 127# define FNM_LEADING_DIR 0
@@ -161,11 +164,13 @@ typedef struct TarBallInfo {
161# endif 164# endif
162 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */ 165 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
163 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */ 166 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
167#if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_EXTRA_FILE_DATA
164//TODO: save only st_dev + st_ino 168//TODO: save only st_dev + st_ino
165 struct stat tarFileStatBuf; /* Stat info for the tarball, letting 169 struct stat tarFileStatBuf; /* Stat info for the tarball, letting
166 * us know the inode and device that the 170 * us know the inode and device that the
167 * tarball lives, so we can avoid trying 171 * tarball lives, so we can avoid trying
168 * to include the tarball into itself */ 172 * to include the tarball into itself */
173#endif
169} TarBallInfo; 174} TarBallInfo;
170 175
171/* A nice enum with all the possible tar file content types */ 176/* A nice enum with all the possible tar file content types */
@@ -506,15 +511,21 @@ static int FAST_FUNC writeFileToTarball(struct recursive_state *state,
506 } 511 }
507 } 512 }
508 513
514#if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_EXTRA_FILE_DATA
509 /* It is a bad idea to store the archive we are in the process of creating, 515 /* It is a bad idea to store the archive we are in the process of creating,
510 * so check the device and inode to be sure that this particular file isn't 516 * so check the device and inode to be sure that this particular file isn't
511 * the new tarball */ 517 * the new tarball */
512 if (tbInfo->tarFileStatBuf.st_dev == statbuf->st_dev 518 if (tbInfo->tarFileStatBuf.st_dev == statbuf->st_dev
513 && tbInfo->tarFileStatBuf.st_ino == statbuf->st_ino 519 && tbInfo->tarFileStatBuf.st_ino == statbuf->st_ino
520# if ENABLE_FEATURE_EXTRA_FILE_DATA
521 /* ignore invalid inode numbers */
522 && statbuf->st_ino != 0
523# endif
514 ) { 524 ) {
515 bb_error_msg("%s: file is the archive; skipping", fileName); 525 bb_error_msg("%s: file is the archive; skipping", fileName);
516 return TRUE; 526 return TRUE;
517 } 527 }
528#endif
518 529
519# if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS 530# if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS
520 if (strlen(header_name) >= NAME_SIZE) { 531 if (strlen(header_name) >= NAME_SIZE) {
@@ -568,7 +579,7 @@ static int FAST_FUNC writeFileToTarball(struct recursive_state *state,
568 return TRUE; 579 return TRUE;
569} 580}
570 581
571# if SEAMLESS_COMPRESSION 582# if SEAMLESS_COMPRESSION && !ENABLE_PLATFORM_MINGW32
572/* Don't inline: vfork scares gcc and pessimizes code */ 583/* Don't inline: vfork scares gcc and pessimizes code */
573static void NOINLINE vfork_compressor(int tar_fd, const char *gzip) 584static void NOINLINE vfork_compressor(int tar_fd, const char *gzip)
574{ 585{
@@ -645,6 +656,10 @@ static void NOINLINE vfork_compressor(int tar_fd, const char *gzip)
645} 656}
646# endif /* SEAMLESS_COMPRESSION */ 657# endif /* SEAMLESS_COMPRESSION */
647 658
659# if ENABLE_PLATFORM_MINGW32
660# define vfork_compressor(f, g) mingw_fork_compressor((f), (g), "w")
661# endif
662
648 663
649# if !SEAMLESS_COMPRESSION 664# if !SEAMLESS_COMPRESSION
650/* Do not pass gzip flag to writeTarFile() */ 665/* Do not pass gzip flag to writeTarFile() */
@@ -659,16 +674,21 @@ static NOINLINE int writeTarFile(
659 const char *gzip) 674 const char *gzip)
660{ 675{
661 int errorFlag = FALSE; 676 int errorFlag = FALSE;
677# if SEAMLESS_COMPRESSION && ENABLE_PLATFORM_MINGW32
678 pid_t pid = 0;
679# endif
662 680
663 /*tbInfo->hlInfoHead = NULL; - already is */ 681 /*tbInfo->hlInfoHead = NULL; - already is */
664 682
683# if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_EXTRA_FILE_DATA
665 /* Store the stat info for the tarball's file, so 684 /* Store the stat info for the tarball's file, so
666 * can avoid including the tarball into itself.... */ 685 * can avoid including the tarball into itself.... */
667 xfstat(tbInfo->tarFd, &tbInfo->tarFileStatBuf, "can't stat tar file"); 686 xfstat(tbInfo->tarFd, &tbInfo->tarFileStatBuf, "can't stat tar file");
687# endif
668 688
669# if SEAMLESS_COMPRESSION 689# if SEAMLESS_COMPRESSION
670 if (gzip) 690 if (gzip)
671 vfork_compressor(tbInfo->tarFd, gzip); 691 IF_PLATFORM_MINGW32(pid = )vfork_compressor(tbInfo->tarFd, gzip);
672# endif 692# endif
673 693
674 /* Read the directory/files and iterate over them one at a time */ 694 /* Read the directory/files and iterate over them one at a time */
@@ -702,7 +722,11 @@ static NOINLINE int writeTarFile(
702# if SEAMLESS_COMPRESSION 722# if SEAMLESS_COMPRESSION
703 if (gzip) { 723 if (gzip) {
704 int status; 724 int status;
725# if !ENABLE_PLATFORM_MINGW32
705 if (safe_waitpid(-1, &status, 0) == -1) 726 if (safe_waitpid(-1, &status, 0) == -1)
727# else
728 if (safe_waitpid(pid, &status, 0) == -1)
729# endif
706 bb_simple_perror_msg("waitpid"); 730 bb_simple_perror_msg("waitpid");
707 else if (!WIFEXITED(status) || WEXITSTATUS(status)) 731 else if (!WIFEXITED(status) || WEXITSTATUS(status))
708 /* gzip was killed or has exited with nonzero! */ 732 /* gzip was killed or has exited with nonzero! */
@@ -1164,7 +1188,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1164 * on e.g. tarball with 1st file named "BZh5". 1188 * on e.g. tarball with 1st file named "BZh5".
1165 */ 1189 */
1166 ) { 1190 ) {
1167 tar_handle->src_fd = open_zipped(tar_filename, /*fail_if_not_compressed:*/ 0); 1191 tar_handle->src_fd = open_zipped(tar_filename, /*die_if_not_compressed:*/ 0);
1168 if (tar_handle->src_fd < 0) 1192 if (tar_handle->src_fd < 0)
1169 bb_perror_msg_and_die("can't open '%s'", tar_filename); 1193 bb_perror_msg_and_die("can't open '%s'", tar_filename);
1170 } else { 1194 } else {
diff --git a/archival/unzip.c b/archival/unzip.c
index 71a302915..7b945c250 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -72,6 +72,9 @@
72 72
73#include "libbb.h" 73#include "libbb.h"
74#include "bb_archive.h" 74#include "bb_archive.h"
75#if ENABLE_PLATFORM_MINGW32 && __GNUC__
76#pragma pack(2)
77#endif
75 78
76#if 0 79#if 0
77# define dbg(...) bb_error_msg(__VA_ARGS__) 80# define dbg(...) bb_error_msg(__VA_ARGS__)
@@ -634,7 +637,7 @@ int unzip_main(int argc, char **argv)
634 } 637 }
635 } 638 }
636 639
637#ifndef __GLIBC__ 640#if !defined(__GLIBC__) && !ENABLE_PLATFORM_MINGW32
638 /* 641 /*
639 * This code is needed for non-GNU getopt 642 * This code is needed for non-GNU getopt
640 * which doesn't understand "-" in option string. 643 * which doesn't understand "-" in option string.