From: Tradukado <tra...@es...> - 2008-05-14 23:18:24
|
I tried many programs, in Windows and Linux, to no avail. The problem was that Backuppc (actuallly the perl zip module) created the zip file on the fly, with the normal 32bit headers, without knowing that it would be bigger than 2G. Whenever a program tried to get the "central directory", at the end of the zip file, it would actually land in the middle of the file. There were other problems too but, anyway, what I did was code a small program that "walks" all entries and dumps them. I created the directory structure first. Good thing that the files were not compressed. I'm not particulary proud of the coding but it works, so I'm leaving it here. It might help somebody else en in the future. Thanks to everybody for the tips. Eduardo. #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <limits.h> #define CPBUFSIZE 16384 main() { unsigned long i; long c; unsigned long descr,efl,fnl,t,t1,t2,t3,t4; unsigned long total,csize,usize; long flags; long long donde; char name[2000]; unsigned int s[4]; FILE *arch,*osa; unsigned char buf[CPBUFSIZE + 1]; int chunk; donde = 0; arch = fopen64("broken.zip","r"); while ((c=fgetc(arch)) != EOF) { s[0] = c; s[1] = fgetc(arch); s[2] = fgetc(arch); s[3] = fgetc(arch); if (s[0] != 0x50) { printf("Missing signature! %02x %02x %02x %02x\n", s[0],s[1],s[2],s[3]); exit(1); } else if (s[1] == 0x4b & s[2] == 0x01 && s[3] == 0x02) { printf("Central directory found, stopping\n"); exit(0); } for (i = 0;i < 2;i++) fgetc(arch); t1 = fgetc(arch); t2 = fgetc(arch); flags = (t1 + (t2 << 8)); descr = flags & 0x08; for (i = 0;i < 10;i++) fgetc(arch); t1 = fgetc(arch); t2 = fgetc(arch); t3 = fgetc(arch); t4 = fgetc(arch); csize = t1 + (t2 << 8) + (t3 << 16) + (t4 << 24); t1 = fgetc(arch); t2 = fgetc(arch); t3 = fgetc(arch); t4 = fgetc(arch); usize = t1 + (t2 << 8) + (t3 << 16) + (t4 << 24); t1 = fgetc(arch); t2 = fgetc(arch); fnl = t1 + (t2 << 8); t1 = fgetc(arch); t2 = fgetc(arch); efl = t1 + (t2 << 8); for (i = 0;i < fnl;i++) name[i] = fgetc(arch); name[i] = 0; printf("%12llx (%12llu) |%s|[flags=%02lX efl=%ld csize=%ld usize=%ld fnl=%ld]\n",donde,donde,name,flags,efl,csize,usize,fnl); fflush(stdout); for (i = 0;i < efl;i++) fgetc(arch); if (csize > 0) { osa = fopen(name,"w+b"); total = csize; while (total > 0) { chunk = (total > CPBUFSIZE) ? CPBUFSIZE : total; fread(buf,chunk,1,arch); fwrite(buf,chunk,1,osa); total -= chunk; } fclose(osa); } donde += csize + fnl + efl + 30; if (descr) { for (i = 0;i < 16;i++) fgetc(arch); donde += 16; } } } |