ArchiveEntryNode *next_zip_entry(void) { unsigned long magic; unsigned short flen, elen, hdrsiz; URL url; long compsize, origsize; char buff[BUFSIZ]; ArchiveEntryNode *entry; int method; unsigned short flags; int macbin_check; url = arc_handler.url; macbin_check = (arc_handler.counter == 0); retry_read: if(url_read(url, buff, 4) != 4) return NULL; hdrsiz = 4; magic = get_long(buff); if(magic == EXTLOCSIG) { /* ignored */ if(url_read(url, buff, 20) != 20) return NULL; magic = get_long(buff + 16); hdrsiz += 20; } else if(macbin_check && buff[0] == '0') { macbin_check = 0; url_skip(url, 128-4); if(arc_handler.isfile) arc_handler.pos += 128; goto retry_read; } if(magic != LOCSIG) return NULL; /* Version needed to extract */ url_skip(url, 2); hdrsiz += 2; /* General purpose bit flag */ if(url_read(url, buff, 2) != 2) return NULL; flags = get_short(buff); hdrsiz += 2; /* Compression method */ if(url_read(url, buff, 2) != 2) return NULL; method = get_short(buff); hdrsiz += 2; switch(method) { case 0: /* The file is stored (no compression) */ method = ARCHIVEC_STORED; break; case 1: /* The file is Shrunk */ method = ARCHIVEC_SHRUNKED; break; case 2: /* The file is Reduced with compression factor 1 */ method = ARCHIVEC_REDUCED1; break; case 3: /* The file is Reduced with compression factor 2 */ method = ARCHIVEC_REDUCED2; break; case 4: /* The file is Reduced with compression factor 3 */ method = ARCHIVEC_REDUCED3; break; case 5: /* The file is Reduced with compression factor 4 */ method = ARCHIVEC_REDUCED4; break; case 6: /* The file is Imploded */ if(flags & 4) { if(flags & 2) method = ARCHIVEC_IMPLODED_LIT8; else method = ARCHIVEC_IMPLODED_LIT4; } else if(flags & 2) method = ARCHIVEC_IMPLODED_NOLIT8; else method = ARCHIVEC_IMPLODED_NOLIT4; break; case 7: /* Reserved for Tokenizing compression algorithm */ method = -1; break; case 8: /* The file is Deflated */ method = ARCHIVEC_DEFLATED; break; default: return NULL; } /* Last mod file time */ url_skip(url, 2); hdrsiz += 2; /* Last mod file date */ url_skip(url, 2); hdrsiz += 2; /* CRC-32 */ url_skip(url, 4); hdrsiz += 4; /* Compressed size */ if(url_read(url, buff, 4) != 4) return NULL; hdrsiz += 4; compsize = (long)get_long(buff); /* Uncompressed size */ if(url_read(url, buff, 4) != 4) return NULL; hdrsiz += 4; origsize = (long)get_long(buff); /* Filename length */ if(url_read(url, buff, 2) != 2) return NULL; hdrsiz += 2; flen = get_short(buff); if(flen >= sizeof(buff)-1) return NULL; /* Extra field length */ if(url_read(url, buff, 2) != 2) return NULL; hdrsiz += 2; elen = get_short(buff); /* filename */ if(url_read(url, buff, flen) != flen) return NULL; hdrsiz += flen; buff[flen] = '\0'; if(compsize == 0 && flen > 0 && (buff[flen - 1] == '/' || buff[flen - 1] == '\\')) { url_skip(url, elen); hdrsiz += elen; if(arc_handler.isfile) arc_handler.pos += hdrsiz; goto retry_read; } entry = new_entry_node(buff, flen); if(entry == NULL) return NULL; entry->comptype = method; entry->origsize = origsize; entry->compsize = compsize; /* Extra field */ url_skip(url, elen); hdrsiz += elen; if(arc_handler.isfile) { arc_handler.pos += hdrsiz; entry->start = arc_handler.pos; entry->cache = NULL; url_skip(url, compsize); arc_handler.pos += compsize; } else { long n; entry->start = 0; entry->cache = url_dump(url, compsize, &n); if(n != compsize) { free_entry_node(entry); return NULL; } } return entry; }
ArchiveEntryNode *next_tar_entry(void) { char hdr[TARHDRSIZ]; long size, sizeb; ArchiveEntryNode *entry; URL url; int flen; int macbin_check; url = arc_handler.url; macbin_check = (arc_handler.counter == 0); retry_read: if(!macbin_check) { if(url_read(url, hdr, TARHDRSIZ) != TARHDRSIZ) return NULL; } else { int c = url_getc(url); if(c == 0) { url_skip(url, 127); if(arc_handler.isfile) arc_handler.pos += 128; if(url_read(url, hdr, TARHDRSIZ) != TARHDRSIZ) return NULL; } else { hdr[0] = c; if(url_read(url, hdr+1, TARHDRSIZ-1) != TARHDRSIZ-1) return NULL; } } macbin_check = 0; if(hdr[0] == '\0') return NULL; if(!tar_checksum(hdr)) return NULL; size = octal_value(hdr + 124, 12); flen = strlen(hdr); if(size == 0 && flen > 0 && hdr[flen - 1] == '/') { if(arc_handler.isfile) arc_handler.pos += TARHDRSIZ; goto retry_read; } entry = new_entry_node(hdr, flen); if(entry == NULL) return NULL; sizeb = (((size) + (TARBLKSIZ-1)) & ~(TARBLKSIZ-1)); if((arc_handler.isfile) || (size > MAX_SAFE_MALLOC_SIZE)) { arc_handler.pos += TARHDRSIZ; entry->comptype = ARCHIVEC_STORED; entry->compsize = entry->origsize = size; entry->start = arc_handler.pos; url_skip(url, sizeb); arc_handler.pos += sizeb; } else { void *data; long n; data = url_dump(url, size, &n); if(size != n) { if(data != NULL) free(data); free_entry_node(entry); return NULL; } entry->cache = arc_compress(data, size, ARC_DEFLATE_LEVEL, &entry->compsize); free(data); entry->comptype = ARCHIVEC_DEFLATED; entry->origsize = size; entry->start = 0; url_skip(url, sizeb - size); } return entry; }