Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/archival/unzip.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/archival/unzip.c
r821 r1770 25 25 */ 26 26 27 #include <fcntl.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <unistd.h> 31 #include <errno.h> 27 #include "libbb.h" 32 28 #include "unarchive.h" 33 #include "busybox.h" 34 35 #if BB_BIG_ENDIAN 36 static inline unsigned short 37 __swap16(unsigned short x) { 38 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8); 39 } 40 41 static inline uint32_t 42 __swap32(uint32_t x) { 43 return (((x & 0xFF) << 24) | 44 ((x & 0xFF00) << 8) | 45 ((x & 0xFF0000) >> 8) | 46 ((x & 0xFF000000) >> 24)); 47 } 48 #else /* it's little-endian */ 49 # define __swap16(x) (x) 50 # define __swap32(x) (x) 51 #endif /* BB_BIG_ENDIAN */ 52 53 #define ZIP_FILEHEADER_MAGIC __swap32(0x04034b50) 54 #define ZIP_CDS_MAGIC __swap32(0x02014b50) 55 #define ZIP_CDS_END_MAGIC __swap32(0x06054b50) 56 #define ZIP_DD_MAGIC __swap32(0x08074b50) 57 58 extern unsigned int gunzip_crc; 59 extern unsigned int gunzip_bytes_out; 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) 60 34 61 35 typedef union { … … 72 46 unsigned short filename_len; /* 22-23 */ 73 47 unsigned short extra_len; /* 24-25 */ 74 } format ed ATTRIBUTE_PACKED;48 } formatted ATTRIBUTE_PACKED; 75 49 } zip_header_t; 76 50 … … 78 52 { 79 53 if (lseek(fd, skip, SEEK_CUR) == (off_t)-1) { 80 if ((errno != ESPIPE) || (bb_copyfd_size(fd, -1, skip) != skip)) { 81 bb_error_msg_and_die("Seek failure"); 82 } 83 } 84 } 85 86 static void unzip_read(int fd, void *buf, size_t count) 87 { 88 if (bb_xread(fd, buf, count) != count) { 89 bb_error_msg_and_die(bb_msg_read_error); 54 if (errno != ESPIPE) 55 bb_error_msg_and_die("seek failure"); 56 bb_copyfd_exact_size(fd, -1, skip); 90 57 } 91 58 } … … 94 61 { 95 62 /* Create all leading directories */ 96 char *name = bb_xstrdup(fn);63 char *name = xstrdup(fn); 97 64 if (bb_make_directory(dirname(name), 0777, FILEUTILS_RECUR)) { 98 bb_error_msg_and_die(" Exiting"); /* bb_make_directory is noisy */65 bb_error_msg_and_die("exiting"); /* bb_make_directory is noisy */ 99 66 } 100 67 free(name); … … 103 70 static int unzip_extract(zip_header_t *zip_header, int src_fd, int dst_fd) 104 71 { 105 if (zip_header->format ed.method == 0) {72 if (zip_header->formatted.method == 0) { 106 73 /* Method 0 - stored (not compressed) */ 107 int size = zip_header->formated.ucmpsize; 108 if (size && (bb_copyfd_size(src_fd, dst_fd, size) != size)) { 109 bb_error_msg_and_die("Cannot complete extraction"); 110 } 111 74 off_t size = zip_header->formatted.ucmpsize; 75 if (size) 76 bb_copyfd_exact_size(src_fd, dst_fd, size); 112 77 } else { 113 78 /* Method 8 - inflate */ 114 inflate_ init(zip_header->formated.cmpsize);115 inflate_unzip(src_fd, dst_fd);116 inflate_cleanup(); 79 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 117 82 /* Validate decompression - crc */ 118 if (zip_header->format ed.crc32 != (gunzip_crc ^ 0xffffffffL)) {119 bb_error_msg(" Invalid compressed data--crc error");83 if (zip_header->formatted.crc32 != (res.crc ^ 0xffffffffL)) { 84 bb_error_msg("invalid compressed data--%s error", "crc"); 120 85 return 1; 121 86 } 122 87 /* Validate decompression - size */ 123 if (zip_header->format ed.ucmpsize != gunzip_bytes_out) {124 bb_error_msg(" Invalid compressed data--length error");88 if (zip_header->formatted.ucmpsize != res.bytes_out) { 89 bb_error_msg("invalid compressed data--%s error", "length"); 125 90 return 1; 126 91 } … … 129 94 } 130 95 96 int unzip_main(int argc, char **argv); 131 97 int unzip_main(int argc, char **argv) 132 98 { … … 145 111 struct stat stat_buf; 146 112 147 while ((opt = getopt(argc, argv, "-d:lnopqx")) != -1) {148 switch (opt_range) {113 while ((opt = getopt(argc, argv, "-d:lnopqx")) != -1) { 114 switch (opt_range) { 149 115 case 0: /* Options */ 150 switch (opt) {116 switch (opt) { 151 117 case 'l': /* List */ 152 118 verbosity = v_list; … … 169 135 170 136 case 1 : /* The zip file */ 171 src_fn = bb_xstrndup(optarg, strlen(optarg)+4); 137 src_fn = xmalloc(strlen(optarg)+4); 138 strcpy(src_fn, optarg); 172 139 opt_range++; 173 140 break; … … 218 185 219 186 /* Open input file */ 220 if ( strcmp("-", src_fn) == 0) {187 if (LONE_DASH(src_fn)) { 221 188 src_fd = STDIN_FILENO; 222 189 /* Cannot use prompt mode since zip data is arriving on STDIN */ 223 190 overwrite = (overwrite == o_prompt) ? o_never : overwrite; 224 225 191 } else { 226 192 static const char *const extn[] = {"", ".zip", ".ZIP"}; 227 193 int orig_src_fn_len = strlen(src_fn); 228 for (i = 0; (i < 3) && (src_fd == -1); i++) {194 for (i = 0; (i < 3) && (src_fd == -1); i++) { 229 195 strcpy(src_fn + orig_src_fn_len, extn[i]); 230 196 src_fd = open(src_fn, O_RDONLY); 231 197 } 232 198 if (src_fd == -1) { 233 src_fn[orig_src_fn_len] = 0;234 bb_error_msg_and_die(" Cannot open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn);199 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); 235 201 } 236 202 } … … 238 204 /* Change dir if necessary */ 239 205 if (base_dir) 240 bb_xchdir(base_dir);206 xchdir(base_dir); 241 207 242 208 if (verbosity != v_silent) … … 249 215 250 216 /* Check magic number */ 251 unzip_read(src_fd, &magic, 4);217 xread(src_fd, &magic, 4); 252 218 if (magic == ZIP_CDS_MAGIC) { 253 219 break; 254 220 } else if (magic != ZIP_FILEHEADER_MAGIC) { 255 bb_error_msg_and_die(" Invalid zip magic %08X", magic);221 bb_error_msg_and_die("invalid zip magic %08X", magic); 256 222 } 257 223 258 224 /* Read the file header */ 259 unzip_read(src_fd, zip_header.raw, 26); 260 #if BB_BIG_ENDIAN 261 zip_header.formated.version = __swap16(zip_header.formated.version); 262 zip_header.formated.flags = __swap16(zip_header.formated.flags); 263 zip_header.formated.method = __swap16(zip_header.formated.method); 264 zip_header.formated.modtime = __swap16(zip_header.formated.modtime); 265 zip_header.formated.moddate = __swap16(zip_header.formated.moddate); 266 zip_header.formated.crc32 = __swap32(zip_header.formated.crc32); 267 zip_header.formated.cmpsize = __swap32(zip_header.formated.cmpsize); 268 zip_header.formated.ucmpsize = __swap32(zip_header.formated.ucmpsize); 269 zip_header.formated.filename_len = __swap16(zip_header.formated.filename_len); 270 zip_header.formated.extra_len = __swap16(zip_header.formated.extra_len); 271 #endif /* BB_BIG_ENDIAN */ 272 if ((zip_header.formated.method != 0) && (zip_header.formated.method != 8)) { 273 bb_error_msg_and_die("Unsupported compression method %d", zip_header.formated.method); 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); 236 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); 274 238 } 275 239 276 240 /* Read filename */ 277 241 free(dst_fn); 278 dst_fn = xzalloc(zip_header.format ed.filename_len + 1);279 unzip_read(src_fd, dst_fn, zip_header.formated.filename_len);242 dst_fn = xzalloc(zip_header.formatted.filename_len + 1); 243 xread(src_fd, dst_fn, zip_header.formatted.filename_len); 280 244 281 245 /* Skip extra header bytes */ 282 unzip_skip(src_fd, zip_header.format ed.extra_len);246 unzip_skip(src_fd, zip_header.formatted.extra_len); 283 247 284 248 if ((verbosity == v_list) && !list_header_done){ 285 p rintf(" Length Date Time Name\n"286 " -------- ---- ---- ----\n");249 puts(" Length Date Time Name\n" 250 " -------- ---- ---- ----"); 287 251 list_header_done = 1; 288 252 } … … 294 258 295 259 } else { /* Extract entry */ 296 total_size += zip_header.format ed.ucmpsize;260 total_size += zip_header.formatted.ucmpsize; 297 261 298 262 if (verbosity == v_list) { /* List entry */ 299 unsigned int dostime = zip_header.format ed.modtime | (zip_header.formated.moddate << 16);263 unsigned int dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16); 300 264 printf("%9u %02u-%02u-%02u %02u:%02u %s\n", 301 zip_header.format ed.ucmpsize,265 zip_header.formatted.ucmpsize, 302 266 (dostime & 0x01e00000) >> 21, 303 267 (dostime & 0x001f0000) >> 16, … … 308 272 total_entries++; 309 273 i = 'n'; 310 311 274 } else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */ 312 275 i = -1; 313 314 276 } else if (last_char_is(dst_fn, '/')) { /* Extract directory */ 315 277 if (stat(dst_fn, &stat_buf) == -1) { 316 278 if (errno != ENOENT) { 317 bb_perror_msg_and_die(" Cannot stat '%s'",dst_fn);279 bb_perror_msg_and_die("cannot stat '%s'",dst_fn); 318 280 } 319 281 if (verbosity == v_normal) { … … 322 284 unzip_create_leading_dirs(dst_fn); 323 285 if (bb_make_directory(dst_fn, 0777, 0)) { 324 bb_error_msg_and_die(" Exiting");286 bb_error_msg_and_die("exiting"); 325 287 } 326 288 } else { … … 332 294 333 295 } else { /* Extract file */ 334 296 _check_file: 335 297 if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */ 336 298 if (errno != ENOENT) { 337 bb_perror_msg_and_die(" Cannot stat '%s'",dst_fn);299 bb_perror_msg_and_die("cannot stat '%s'",dst_fn); 338 300 } 339 301 i = 'y'; 340 341 302 } else { /* File already exists */ 342 303 if (overwrite == o_never) { 343 304 i = 'n'; 344 345 305 } else if (S_ISREG(stat_buf.st_mode)) { /* File is regular file */ 346 306 if (overwrite == o_always) { … … 349 309 printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); 350 310 if (!fgets(key_buf, 512, stdin)) { 351 bb_perror_msg_and_die(" Cannot read input");311 bb_perror_msg_and_die("cannot read input"); 352 312 } 353 313 i = key_buf[0]; 354 314 } 355 356 315 } else { /* File is not regular file */ 357 316 bb_error_msg_and_die("'%s' exists but is not regular file",dst_fn); … … 366 325 case 'y': /* Open file and fall into unzip */ 367 326 unzip_create_leading_dirs(dst_fn); 368 dst_fd = bb_xopen(dst_fn, O_WRONLY | O_CREAT);327 dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); 369 328 case -1: /* Unzip */ 370 329 if (verbosity == v_normal) { … … 372 331 } 373 332 if (unzip_extract(&zip_header, src_fd, dst_fd)) { 374 333 failed = 1; 375 334 } 376 335 if (dst_fd != STDOUT_FILENO) { … … 384 343 case 'n': 385 344 /* Skip entry data */ 386 unzip_skip(src_fd, zip_header.format ed.cmpsize);345 unzip_skip(src_fd, zip_header.formatted.cmpsize); 387 346 break; 388 347 … … 391 350 printf("new name: "); 392 351 if (!fgets(key_buf, 512, stdin)) { 393 bb_perror_msg_and_die(" Cannot read input");352 bb_perror_msg_and_die("cannot read input"); 394 353 } 395 354 free(dst_fn); 396 dst_fn = bb_xstrdup(key_buf);355 dst_fn = xstrdup(key_buf); 397 356 chomp(dst_fn); 398 357 goto _check_file; … … 404 363 405 364 /* Data descriptor section */ 406 if (zip_header.format ed.flags & 4) {365 if (zip_header.formatted.flags & 4) { 407 366 /* skip over duplicate crc, compressed size and uncompressed size */ 408 367 unzip_skip(src_fd, 12);
Note:
See TracChangeset
for help on using the changeset viewer.