Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/archival/unzip.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/archival/unzip.c
r1765 r2725 8 8 * All options and features should work in this version. 9 9 * 10 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 11 */ 12 12 … … 17 17 18 18 /* TODO 19 * Endian issues20 19 * Zip64 + other methods 21 * Improve handling of zip format, ie.22 * - deferred CRC, comp. & uncomp. lengths (zip header flags bit 3)23 * - unix file permissions, etc.24 * - central directory25 20 */ 26 21 27 22 #include "libbb.h" 28 #include "unarchive.h" 29 30 #define ZIP_FILEHEADER_MAGIC SWAP_LE32(0x04034b50) 31 #define ZIP_CDS_MAGIC SWAP_LE32(0x02014b50) 32 #define ZIP_CDS_END_MAGIC SWAP_LE32(0x06054b50) 33 #define ZIP_DD_MAGIC SWAP_LE32(0x08074b50) 23 #include "archive.h" 24 25 enum { 26 #if BB_BIG_ENDIAN 27 ZIP_FILEHEADER_MAGIC = 0x504b0304, 28 ZIP_CDF_MAGIC = 0x504b0102, /* central directory's file header */ 29 ZIP_CDE_MAGIC = 0x504b0506, /* "end of central directory" record */ 30 ZIP_DD_MAGIC = 0x504b0708, 31 #else 32 ZIP_FILEHEADER_MAGIC = 0x04034b50, 33 ZIP_CDF_MAGIC = 0x02014b50, 34 ZIP_CDE_MAGIC = 0x06054b50, 35 ZIP_DD_MAGIC = 0x08074b50, 36 #endif 37 }; 38 39 #define ZIP_HEADER_LEN 26 34 40 35 41 typedef union { 36 u nsigned char raw[26];42 uint8_t raw[ZIP_HEADER_LEN]; 37 43 struct { 38 unsigned short version; /* 0-1 */ 39 unsigned short flags; /* 2-3 */ 40 unsigned short method; /* 4-5 */ 41 unsigned short modtime; /* 6-7 */ 42 unsigned short moddate; /* 8-9 */ 43 unsigned int crc32 ATTRIBUTE_PACKED; /* 10-13 */ 44 unsigned int cmpsize ATTRIBUTE_PACKED; /* 14-17 */ 45 unsigned int ucmpsize ATTRIBUTE_PACKED; /* 18-21 */ 46 unsigned short filename_len; /* 22-23 */ 47 unsigned short extra_len; /* 24-25 */ 48 } formatted ATTRIBUTE_PACKED; 49 } zip_header_t; 50 51 static void unzip_skip(int fd, off_t skip) 44 uint16_t version; /* 0-1 */ 45 uint16_t zip_flags; /* 2-3 */ 46 uint16_t method; /* 4-5 */ 47 uint16_t modtime; /* 6-7 */ 48 uint16_t moddate; /* 8-9 */ 49 uint32_t crc32 PACKED; /* 10-13 */ 50 uint32_t cmpsize PACKED; /* 14-17 */ 51 uint32_t ucmpsize PACKED; /* 18-21 */ 52 uint16_t filename_len; /* 22-23 */ 53 uint16_t extra_len; /* 24-25 */ 54 } formatted PACKED; 55 } zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ 56 57 /* Check the offset of the last element, not the length. This leniency 58 * allows for poor packing, whereby the overall struct may be too long, 59 * even though the elements are all in the right place. 60 */ 61 struct BUG_zip_header_must_be_26_bytes { 62 char BUG_zip_header_must_be_26_bytes[ 63 offsetof(zip_header_t, formatted.extra_len) + 2 64 == ZIP_HEADER_LEN ? 1 : -1]; 65 }; 66 67 #define FIX_ENDIANNESS_ZIP(zip_header) do { \ 68 (zip_header).formatted.version = SWAP_LE16((zip_header).formatted.version ); \ 69 (zip_header).formatted.method = SWAP_LE16((zip_header).formatted.method ); \ 70 (zip_header).formatted.modtime = SWAP_LE16((zip_header).formatted.modtime ); \ 71 (zip_header).formatted.moddate = SWAP_LE16((zip_header).formatted.moddate ); \ 72 (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \ 73 (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \ 74 (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \ 75 (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \ 76 (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \ 77 } while (0) 78 79 #define CDF_HEADER_LEN 42 80 81 typedef union { 82 uint8_t raw[CDF_HEADER_LEN]; 83 struct { 84 /* uint32_t signature; 50 4b 01 02 */ 85 uint16_t version_made_by; /* 0-1 */ 86 uint16_t version_needed; /* 2-3 */ 87 uint16_t cdf_flags; /* 4-5 */ 88 uint16_t method; /* 6-7 */ 89 uint16_t mtime; /* 8-9 */ 90 uint16_t mdate; /* 10-11 */ 91 uint32_t crc32; /* 12-15 */ 92 uint32_t cmpsize; /* 16-19 */ 93 uint32_t ucmpsize; /* 20-23 */ 94 uint16_t file_name_length; /* 24-25 */ 95 uint16_t extra_field_length; /* 26-27 */ 96 uint16_t file_comment_length; /* 28-29 */ 97 uint16_t disk_number_start; /* 30-31 */ 98 uint16_t internal_file_attributes; /* 32-33 */ 99 uint32_t external_file_attributes PACKED; /* 34-37 */ 100 uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ 101 } formatted PACKED; 102 } cdf_header_t; 103 104 struct BUG_cdf_header_must_be_42_bytes { 105 char BUG_cdf_header_must_be_42_bytes[ 106 offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4 107 == CDF_HEADER_LEN ? 1 : -1]; 108 }; 109 110 #define FIX_ENDIANNESS_CDF(cdf_header) do { \ 111 (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \ 112 (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \ 113 (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \ 114 (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \ 115 (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \ 116 (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \ 117 IF_DESKTOP( \ 118 (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \ 119 (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \ 120 ) \ 121 } while (0) 122 123 #define CDE_HEADER_LEN 16 124 125 typedef union { 126 uint8_t raw[CDE_HEADER_LEN]; 127 struct { 128 /* uint32_t signature; 50 4b 05 06 */ 129 uint16_t this_disk_no; 130 uint16_t disk_with_cdf_no; 131 uint16_t cdf_entries_on_this_disk; 132 uint16_t cdf_entries_total; 133 uint32_t cdf_size; 134 uint32_t cdf_offset; 135 /* uint16_t file_comment_length; */ 136 /* .ZIP file comment (variable size) */ 137 } formatted PACKED; 138 } cde_header_t; 139 140 struct BUG_cde_header_must_be_16_bytes { 141 char BUG_cde_header_must_be_16_bytes[ 142 sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1]; 143 }; 144 145 #define FIX_ENDIANNESS_CDE(cde_header) do { \ 146 (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \ 147 } while (0) 148 149 enum { zip_fd = 3 }; 150 151 152 #if ENABLE_DESKTOP 153 154 #define PEEK_FROM_END 16384 155 156 /* NB: does not preserve file position! */ 157 static uint32_t find_cdf_offset(void) 52 158 { 53 if (lseek(fd, skip, SEEK_CUR) == (off_t)-1) { 54 if (errno != ESPIPE) 55 bb_error_msg_and_die("seek failure"); 56 bb_copyfd_exact_size(fd, -1, skip); 57 } 159 cde_header_t cde_header; 160 unsigned char *p; 161 off_t end; 162 unsigned char *buf = xzalloc(PEEK_FROM_END); 163 164 end = xlseek(zip_fd, 0, SEEK_END); 165 end -= PEEK_FROM_END; 166 if (end < 0) 167 end = 0; 168 xlseek(zip_fd, end, SEEK_SET); 169 full_read(zip_fd, buf, PEEK_FROM_END); 170 171 p = buf; 172 while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { 173 if (*p != 'P') { 174 p++; 175 continue; 176 } 177 if (*++p != 'K') 178 continue; 179 if (*++p != 5) 180 continue; 181 if (*++p != 6) 182 continue; 183 /* we found CDE! */ 184 memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN); 185 FIX_ENDIANNESS_CDE(cde_header); 186 free(buf); 187 return cde_header.formatted.cdf_offset; 188 } 189 //free(buf); 190 bb_error_msg_and_die("can't find file table"); 191 }; 192 193 static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) 194 { 195 off_t org; 196 197 org = xlseek(zip_fd, 0, SEEK_CUR); 198 199 if (!cdf_offset) 200 cdf_offset = find_cdf_offset(); 201 202 xlseek(zip_fd, cdf_offset + 4, SEEK_SET); 203 xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); 204 FIX_ENDIANNESS_CDF(*cdf_ptr); 205 cdf_offset += 4 + CDF_HEADER_LEN 206 + cdf_ptr->formatted.file_name_length 207 + cdf_ptr->formatted.extra_field_length 208 + cdf_ptr->formatted.file_comment_length; 209 210 xlseek(zip_fd, org, SEEK_SET); 211 return cdf_offset; 212 }; 213 #endif 214 215 static void unzip_skip(off_t skip) 216 { 217 if (lseek(zip_fd, skip, SEEK_CUR) == (off_t)-1) 218 bb_copyfd_exact_size(zip_fd, -1, skip); 58 219 } 59 220 60 static void unzip_create_leading_dirs(c har *fn)221 static void unzip_create_leading_dirs(const char *fn) 61 222 { 62 223 /* Create all leading directories */ … … 68 229 } 69 230 70 static int unzip_extract(zip_header_t *zip_header, int src_fd, int dst_fd)231 static void unzip_extract(zip_header_t *zip_header, int dst_fd) 71 232 { 72 233 if (zip_header->formatted.method == 0) { … … 74 235 off_t size = zip_header->formatted.ucmpsize; 75 236 if (size) 76 bb_copyfd_exact_size( src_fd, dst_fd, size);237 bb_copyfd_exact_size(zip_fd, dst_fd, size); 77 238 } else { 78 239 /* Method 8 - inflate */ 79 240 inflate_unzip_result res; 80 /* err = */ inflate_unzip(&res, zip_header->formatted.cmpsize, src_fd, dst_fd);81 // we should check for -1 error return 241 if (inflate_unzip(&res, zip_header->formatted.cmpsize, zip_fd, dst_fd) < 0) 242 bb_error_msg_and_die("inflate error"); 82 243 /* Validate decompression - crc */ 83 244 if (zip_header->formatted.crc32 != (res.crc ^ 0xffffffffL)) { 84 bb_error_msg("invalid compressed data--%s error", "crc"); 85 return 1; 245 bb_error_msg_and_die("crc error"); 86 246 } 87 247 /* Validate decompression - size */ 88 248 if (zip_header->formatted.ucmpsize != res.bytes_out) { 89 bb_error_msg("invalid compressed data--%s error", "length");90 return 1;91 }92 }93 return 0;249 /* Don't die. Who knows, maybe len calculation 250 * was botched somewhere. After all, crc matched! */ 251 bb_error_msg("bad length"); 252 } 253 } 94 254 } 95 255 96 int unzip_main(int argc, char **argv) ;256 int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 97 257 int unzip_main(int argc, char **argv) 98 258 { 259 enum { O_PROMPT, O_NEVER, O_ALWAYS }; 260 99 261 zip_header_t zip_header; 100 enum {v_silent, v_normal, v_list} verbosity = v_normal; 101 enum {o_prompt, o_never, o_always} overwrite = o_prompt; 102 unsigned int total_size = 0; 103 unsigned int total_entries = 0; 104 int src_fd = -1, dst_fd = -1; 105 char *src_fn = NULL, *dst_fn = NULL; 262 smallint quiet = 0; 263 IF_NOT_DESKTOP(const) smallint verbose = 0; 264 smallint listing = 0; 265 smallint overwrite = O_PROMPT; 266 #if ENABLE_DESKTOP 267 uint32_t cdf_offset; 268 #endif 269 unsigned long total_usize; 270 unsigned long total_size; 271 unsigned total_entries; 272 int dst_fd = -1; 273 char *src_fn = NULL; 274 char *dst_fn = NULL; 106 275 llist_t *zaccept = NULL; 107 276 llist_t *zreject = NULL; 108 277 char *base_dir = NULL; 109 int failed, i, opt, opt_range = 0, list_header_done = 0; 110 char key_buf[512]; 278 int i, opt; 279 int opt_range = 0; 280 char key_buf[80]; 111 281 struct stat stat_buf; 112 282 113 while ((opt = getopt(argc, argv, "-d:lnopqx")) != -1) { 283 /* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP: 284 * 285 * # /usr/bin/unzip -qq -v decompress_unlzma.i.zip 286 * 204372 Defl:N 35278 83% 09-06-09 14:23 0d056252 decompress_unlzma.i 287 * # /usr/bin/unzip -q -v decompress_unlzma.i.zip 288 * Length Method Size Ratio Date Time CRC-32 Name 289 * -------- ------ ------- ----- ---- ---- ------ ---- 290 * 204372 Defl:N 35278 83% 09-06-09 14:23 0d056252 decompress_unlzma.i 291 * -------- ------- --- ------- 292 * 204372 35278 83% 1 file 293 * # /usr/bin/unzip -v decompress_unlzma.i.zip 294 * Archive: decompress_unlzma.i.zip 295 * Length Method Size Ratio Date Time CRC-32 Name 296 * -------- ------ ------- ----- ---- ---- ------ ---- 297 * 204372 Defl:N 35278 83% 09-06-09 14:23 0d056252 decompress_unlzma.i 298 * -------- ------- --- ------- 299 * 204372 35278 83% 1 file 300 * # unzip -v decompress_unlzma.i.zip 301 * Archive: decompress_unlzma.i.zip 302 * Length Date Time Name 303 * -------- ---- ---- ---- 304 * 204372 09-06-09 14:23 decompress_unlzma.i 305 * -------- ------- 306 * 204372 1 files 307 * # /usr/bin/unzip -l -qq decompress_unlzma.i.zip 308 * 204372 09-06-09 14:23 decompress_unlzma.i 309 * # /usr/bin/unzip -l -q decompress_unlzma.i.zip 310 * Length Date Time Name 311 * -------- ---- ---- ---- 312 * 204372 09-06-09 14:23 decompress_unlzma.i 313 * -------- ------- 314 * 204372 1 file 315 * # /usr/bin/unzip -l decompress_unlzma.i.zip 316 * Archive: decompress_unlzma.i.zip 317 * Length Date Time Name 318 * -------- ---- ---- ---- 319 * 204372 09-06-09 14:23 decompress_unlzma.i 320 * -------- ------- 321 * 204372 1 file 322 */ 323 324 /* '-' makes getopt return 1 for non-options */ 325 while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { 114 326 switch (opt_range) { 115 327 case 0: /* Options */ 116 328 switch (opt) { 117 329 case 'l': /* List */ 118 verbosity = v_list;330 listing = 1; 119 331 break; 120 332 121 333 case 'n': /* Never overwrite existing files */ 122 overwrite = o_never;334 overwrite = O_NEVER; 123 335 break; 124 336 125 337 case 'o': /* Always overwrite existing files */ 126 overwrite = o_always;338 overwrite = O_ALWAYS; 127 339 break; 128 340 … … 131 343 132 344 case 'q': /* Be quiet */ 133 verbosity = (verbosity == v_normal) ? v_silent : verbosity; 134 break; 135 136 case 1 : /* The zip file */ 137 src_fn = xmalloc(strlen(optarg)+4); 345 quiet++; 346 break; 347 348 case 'v': /* Verbose list */ 349 IF_DESKTOP(verbose++;) 350 listing = 1; 351 break; 352 353 case 1: /* The zip file */ 354 /* +5: space for ".zip" and NUL */ 355 src_fn = xmalloc(strlen(optarg) + 5); 138 356 strcpy(src_fn, optarg); 139 357 opt_range++; … … 142 360 default: 143 361 bb_show_usage(); 144 145 362 } 146 363 break; … … 149 366 if (opt == 1) { 150 367 llist_add_to(&zaccept, optarg); 151 152 } else if (opt == 'd') { 368 break; 369 } 370 if (opt == 'd') { 153 371 base_dir = optarg; 154 372 opt_range += 2; 155 156 } else if (opt == 'x') { 373 break; 374 } 375 if (opt == 'x') { 157 376 opt_range++; 158 159 } else { 160 bb_show_usage(); 161 } 162 break; 377 break; 378 } 379 bb_show_usage(); 163 380 164 381 case 2 : /* Exclude files */ 165 382 if (opt == 1) { 166 383 llist_add_to(&zreject, optarg); 167 168 } else if (opt == 'd') { /* Extract to base directory */ 384 break; 385 } 386 if (opt == 'd') { /* Extract to base directory */ 169 387 base_dir = optarg; 170 388 opt_range++; 171 172 } else { 173 bb_show_usage(); 174 } 175 break; 389 break; 390 } 391 /* fall through */ 176 392 177 393 default: … … 186 402 /* Open input file */ 187 403 if (LONE_DASH(src_fn)) { 188 src_fd = STDIN_FILENO;404 xdup2(STDIN_FILENO, zip_fd); 189 405 /* Cannot use prompt mode since zip data is arriving on STDIN */ 190 overwrite = (overwrite == o_prompt) ? o_never : overwrite; 406 if (overwrite == O_PROMPT) 407 overwrite = O_NEVER; 191 408 } else { 192 static const char *const extn[] = {"", ".zip", ".ZIP"};409 static const char extn[][5] = {"", ".zip", ".ZIP"}; 193 410 int orig_src_fn_len = strlen(src_fn); 411 int src_fd = -1; 412 194 413 for (i = 0; (i < 3) && (src_fd == -1); i++) { 195 414 strcpy(src_fn + orig_src_fn_len, extn[i]); … … 198 417 if (src_fd == -1) { 199 418 src_fn[orig_src_fn_len] = '\0'; 200 bb_error_msg_and_die("cannot open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); 201 } 419 bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); 420 } 421 xmove_fd(src_fd, zip_fd); 202 422 } 203 423 … … 206 426 xchdir(base_dir); 207 427 208 if (verbosity != v_silent) 209 printf("Archive: %s\n", src_fn); 210 211 failed = 0; 212 428 if (quiet <= 1) { /* not -qq */ 429 if (quiet == 0) 430 printf("Archive: %s\n", src_fn); 431 if (listing) { 432 puts(verbose ? 433 " Length Method Size Ratio Date Time CRC-32 Name\n" 434 "-------- ------ ------- ----- ---- ---- ------ ----" 435 : 436 " Length Date Time Name\n" 437 " -------- ---- ---- ----" 438 ); 439 } 440 } 441 442 /* Example of an archive with one 0-byte long file named 'z' 443 * created by Zip 2.31 on Unix: 444 * 0000 [50 4b]03 04 0a 00 00 00 00 00 42 1a b8 3c 00 00 |PK........B..<..| 445 * sig........ vneed flags compr mtime mdate crc32> 446 * 0010 00 00 00 00 00 00 00 00 00 00 01 00 15 00 7a 55 |..............zU| 447 * >..... csize...... usize...... fnlen exlen fn ex> 448 * 0020 54 09 00 03 cc d3 f9 4b cc d3 f9 4b 55 78 04 00 |T......K...KUx..| 449 * >tra_field...................................... 450 * 0030 00 00 00 00[50 4b]01 02 17 03 0a 00 00 00 00 00 |....PK..........| 451 * ........... sig........ vmade vneed flags compr 452 * 0040 42 1a b8 3c 00 00 00 00 00 00 00 00 00 00 00 00 |B..<............| 453 * mtime mdate crc32...... csize...... usize...... 454 * 0050 01 00 0d 00 00 00 00 00 00 00 00 00 a4 81 00 00 |................| 455 * fnlen exlen clen. dnum. iattr eattr...... relofs> (eattr = rw-r--r--) 456 * 0060 00 00 7a 55 54 05 00 03 cc d3 f9 4b 55 78 00 00 |..zUT......KUx..| 457 * >..... fn extra_field........................... 458 * 0070 [50 4b]05 06 00 00 00 00 01 00 01 00 3c 00 00 00 |PK..........<...| 459 * 0080 34 00 00 00 00 00 |4.....| 460 */ 461 total_usize = 0; 462 total_size = 0; 463 total_entries = 0; 464 #if ENABLE_DESKTOP 465 cdf_offset = 0; 466 #endif 213 467 while (1) { 214 unsigned int magic; 468 uint32_t magic; 469 mode_t dir_mode = 0777; 470 #if ENABLE_DESKTOP 471 mode_t file_mode = 0666; 472 #endif 215 473 216 474 /* Check magic number */ 217 xread(src_fd, &magic, 4); 218 if (magic == ZIP_CDS_MAGIC) { 475 xread(zip_fd, &magic, 4); 476 /* Central directory? It's at the end, so exit */ 477 if (magic == ZIP_CDF_MAGIC) 219 478 break; 220 } else if (magic != ZIP_FILEHEADER_MAGIC) { 221 bb_error_msg_and_die("invalid zip magic %08X", magic); 222 } 479 #if ENABLE_DESKTOP 480 /* Data descriptor? It was a streaming file, go on */ 481 if (magic == ZIP_DD_MAGIC) { 482 /* skip over duplicate crc32, cmpsize and ucmpsize */ 483 unzip_skip(3 * 4); 484 continue; 485 } 486 #endif 487 if (magic != ZIP_FILEHEADER_MAGIC) 488 bb_error_msg_and_die("invalid zip magic %08X", (int)magic); 223 489 224 490 /* Read the file header */ 225 xread(src_fd, zip_header.raw, 26); 226 zip_header.formatted.version = SWAP_LE32(zip_header.formatted.version); 227 zip_header.formatted.flags = SWAP_LE32(zip_header.formatted.flags); 228 zip_header.formatted.method = SWAP_LE32(zip_header.formatted.method); 229 zip_header.formatted.modtime = SWAP_LE32(zip_header.formatted.modtime); 230 zip_header.formatted.moddate = SWAP_LE32(zip_header.formatted.moddate); 231 zip_header.formatted.crc32 = SWAP_LE32(zip_header.formatted.crc32); 232 zip_header.formatted.cmpsize = SWAP_LE32(zip_header.formatted.cmpsize); 233 zip_header.formatted.ucmpsize = SWAP_LE32(zip_header.formatted.ucmpsize); 234 zip_header.formatted.filename_len = SWAP_LE32(zip_header.formatted.filename_len); 235 zip_header.formatted.extra_len = SWAP_LE32(zip_header.formatted.extra_len); 491 xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); 492 FIX_ENDIANNESS_ZIP(zip_header); 236 493 if ((zip_header.formatted.method != 0) && (zip_header.formatted.method != 8)) { 237 bb_error_msg_and_die("unsupported compression method %d", zip_header.formatted.method); 238 } 494 bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method); 495 } 496 #if !ENABLE_DESKTOP 497 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) { 498 bb_error_msg_and_die("zip flags 1 and 8 are not supported"); 499 } 500 #else 501 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) { 502 /* 0x0001 - encrypted */ 503 bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); 504 } 505 506 { 507 cdf_header_t cdf_header; 508 cdf_offset = read_next_cdf(cdf_offset, &cdf_header); 509 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { 510 /* 0x0008 - streaming. [u]cmpsize can be reliably gotten 511 * only from Central Directory. See unzip_doc.txt */ 512 zip_header.formatted.crc32 = cdf_header.formatted.crc32; 513 zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; 514 zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; 515 } 516 if ((cdf_header.formatted.version_made_by >> 8) == 3) { 517 /* this archive is created on Unix */ 518 dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); 519 } 520 } 521 #endif 239 522 240 523 /* Read filename */ 241 524 free(dst_fn); 242 525 dst_fn = xzalloc(zip_header.formatted.filename_len + 1); 243 xread( src_fd, dst_fn, zip_header.formatted.filename_len);526 xread(zip_fd, dst_fn, zip_header.formatted.filename_len); 244 527 245 528 /* Skip extra header bytes */ 246 unzip_skip(src_fd, zip_header.formatted.extra_len); 247 248 if ((verbosity == v_list) && !list_header_done){ 249 puts(" Length Date Time Name\n" 250 " -------- ---- ---- ----"); 251 list_header_done = 1; 252 } 529 unzip_skip(zip_header.formatted.extra_len); 253 530 254 531 /* Filter zip entries */ 255 if (find_list_entry(zreject, dst_fn) || 256 (zaccept && !find_list_entry(zaccept, dst_fn))) { /* Skip entry */ 532 if (find_list_entry(zreject, dst_fn) 533 || (zaccept && !find_list_entry(zaccept, dst_fn)) 534 ) { /* Skip entry */ 257 535 i = 'n'; 258 536 259 537 } else { /* Extract entry */ 260 total_size += zip_header.formatted.ucmpsize; 261 262 if (verbosity == v_list) { /* List entry */ 263 unsigned int dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16); 264 printf("%9u %02u-%02u-%02u %02u:%02u %s\n", 265 zip_header.formatted.ucmpsize, 266 (dostime & 0x01e00000) >> 21, 267 (dostime & 0x001f0000) >> 16, 268 (((dostime & 0xfe000000) >> 25) + 1980) % 100, 269 (dostime & 0x0000f800) >> 11, 270 (dostime & 0x000007e0) >> 5, 271 dst_fn); 272 total_entries++; 538 if (listing) { /* List entry */ 539 unsigned dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16); 540 if (!verbose) { 541 // " Length Date Time Name\n" 542 // " -------- ---- ---- ----" 543 printf( "%9u %02u-%02u-%02u %02u:%02u %s\n", 544 (unsigned)zip_header.formatted.ucmpsize, 545 (dostime & 0x01e00000) >> 21, 546 (dostime & 0x001f0000) >> 16, 547 (((dostime & 0xfe000000) >> 25) + 1980) % 100, 548 (dostime & 0x0000f800) >> 11, 549 (dostime & 0x000007e0) >> 5, 550 dst_fn); 551 total_usize += zip_header.formatted.ucmpsize; 552 } else { 553 unsigned long percents = zip_header.formatted.ucmpsize - zip_header.formatted.cmpsize; 554 percents = percents * 100; 555 if (zip_header.formatted.ucmpsize) 556 percents /= zip_header.formatted.ucmpsize; 557 // " Length Method Size Ratio Date Time CRC-32 Name\n" 558 // "-------- ------ ------- ----- ---- ---- ------ ----" 559 printf( "%8u Defl:N" "%9u%4u%% %02u-%02u-%02u %02u:%02u %08x %s\n", 560 (unsigned)zip_header.formatted.ucmpsize, 561 (unsigned)zip_header.formatted.cmpsize, 562 (unsigned)percents, 563 (dostime & 0x01e00000) >> 21, 564 (dostime & 0x001f0000) >> 16, 565 (((dostime & 0xfe000000) >> 25) + 1980) % 100, 566 (dostime & 0x0000f800) >> 11, 567 (dostime & 0x000007e0) >> 5, 568 zip_header.formatted.crc32, 569 dst_fn); 570 total_usize += zip_header.formatted.ucmpsize; 571 total_size += zip_header.formatted.cmpsize; 572 } 273 573 i = 'n'; 274 574 } else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */ … … 277 577 if (stat(dst_fn, &stat_buf) == -1) { 278 578 if (errno != ENOENT) { 279 bb_perror_msg_and_die("can not stat '%s'",dst_fn);579 bb_perror_msg_and_die("can't stat '%s'", dst_fn); 280 580 } 281 if ( verbosity == v_normal) {581 if (!quiet) { 282 582 printf(" creating: %s\n", dst_fn); 283 583 } 284 584 unzip_create_leading_dirs(dst_fn); 285 if (bb_make_directory(dst_fn, 0777, 0)) {585 if (bb_make_directory(dst_fn, dir_mode, 0)) { 286 586 bb_error_msg_and_die("exiting"); 287 587 } … … 294 594 295 595 } else { /* Extract file */ 296 _check_file:596 check_file: 297 597 if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */ 298 598 if (errno != ENOENT) { 299 bb_perror_msg_and_die("can not stat '%s'",dst_fn);599 bb_perror_msg_and_die("can't stat '%s'", dst_fn); 300 600 } 301 601 i = 'y'; 302 602 } else { /* File already exists */ 303 if (overwrite == o_never) {603 if (overwrite == O_NEVER) { 304 604 i = 'n'; 305 605 } else if (S_ISREG(stat_buf.st_mode)) { /* File is regular file */ 306 if (overwrite == o_always) {606 if (overwrite == O_ALWAYS) { 307 607 i = 'y'; 308 608 } else { 309 609 printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); 310 if (!fgets(key_buf, 512, stdin)) {311 bb_perror_msg_and_die("can not read input");610 if (!fgets(key_buf, sizeof(key_buf), stdin)) { 611 bb_perror_msg_and_die("can't read input"); 312 612 } 313 613 i = key_buf[0]; 314 614 } 315 615 } else { /* File is not regular file */ 316 bb_error_msg_and_die("'%s' exists but is not regular file", dst_fn);616 bb_error_msg_and_die("'%s' exists but is not regular file", dst_fn); 317 617 } 318 618 } … … 322 622 switch (i) { 323 623 case 'A': 324 overwrite = o_always;624 overwrite = O_ALWAYS; 325 625 case 'y': /* Open file and fall into unzip */ 326 626 unzip_create_leading_dirs(dst_fn); 627 #if ENABLE_DESKTOP 628 dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); 629 #else 327 630 dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); 631 #endif 328 632 case -1: /* Unzip */ 329 if ( verbosity == v_normal) {633 if (!quiet) { 330 634 printf(" inflating: %s\n", dst_fn); 331 635 } 332 if (unzip_extract(&zip_header, src_fd, dst_fd)) { 333 failed = 1; 334 } 636 unzip_extract(&zip_header, dst_fd); 335 637 if (dst_fd != STDOUT_FILENO) { 336 638 /* closing STDOUT is potentially bad for future business */ … … 340 642 341 643 case 'N': 342 overwrite = o_never;644 overwrite = O_NEVER; 343 645 case 'n': 344 646 /* Skip entry data */ 345 unzip_skip( src_fd,zip_header.formatted.cmpsize);647 unzip_skip(zip_header.formatted.cmpsize); 346 648 break; 347 649 … … 349 651 /* Prompt for new name */ 350 652 printf("new name: "); 351 if (!fgets(key_buf, 512, stdin)) {352 bb_perror_msg_and_die("can not read input");653 if (!fgets(key_buf, sizeof(key_buf), stdin)) { 654 bb_perror_msg_and_die("can't read input"); 353 655 } 354 656 free(dst_fn); 355 657 dst_fn = xstrdup(key_buf); 356 658 chomp(dst_fn); 357 goto _check_file;659 goto check_file; 358 660 359 661 default: 360 printf("error: invalid response [%c]\n",(char)i); 361 goto _check_file; 362 } 363 364 /* Data descriptor section */ 365 if (zip_header.formatted.flags & 4) { 366 /* skip over duplicate crc, compressed size and uncompressed size */ 367 unzip_skip(src_fd, 12); 368 } 369 } 370 371 if (verbosity == v_list) { 372 printf(" -------- -------\n" 373 "%9d %d files\n", total_size, total_entries); 374 } 375 376 return failed; 662 printf("error: invalid response [%c]\n", (char)i); 663 goto check_file; 664 } 665 666 total_entries++; 667 } 668 669 if (listing && quiet <= 1) { 670 if (!verbose) { 671 // " Length Date Time Name\n" 672 // " -------- ---- ---- ----" 673 printf( " -------- -------\n" 674 "%9lu" " %u files\n", 675 total_usize, total_entries); 676 } else { 677 unsigned long percents = total_usize - total_size; 678 percents = percents * 100; 679 if (total_usize) 680 percents /= total_usize; 681 // " Length Method Size Ratio Date Time CRC-32 Name\n" 682 // "-------- ------ ------- ----- ---- ---- ------ ----" 683 printf( "-------- ------- --- -------\n" 684 "%8lu" "%17lu%4u%% %u files\n", 685 total_usize, total_size, (unsigned)percents, 686 total_entries); 687 } 688 } 689 690 return 0; 377 691 }
Note:
See TracChangeset
for help on using the changeset viewer.