int open_input_file() /* return 1 if open failed */ { /* * open the zipfile for reading and in BINARY mode to prevent cr/lf * translation, which would corrupt the bitstreams */ #if defined(UNIX) || defined(TOPS20) || defined(ATARI_ST) zipfd = open(zipfn, O_RDONLY); #else /* !(UNIX || TOPS20) */ #ifdef VMS zipfd = open(zipfn, O_RDONLY, 0, "ctx=stm"); #else /* !VMS */ #ifdef MACOS zipfd = open(zipfn, 0); #else /* !MACOS */ zipfd = open(zipfn, O_RDONLY | O_BINARY); #endif /* ?MACOS */ #endif /* ?VMS */ #endif /* ?(UNIX || TOPS20) */ if (zipfd < 0) { FPRINTF(stderr, LoadFarString(CantOpenZipfile), zipfn); return 1; } return 0; } /* end function open_input_file() */
Uz_Globs *getGlobalPointer() { int scan=0; ulg tid = GetThreadId(); while (threadIdTable[scan] != tid && scan < THREADID_ENTRIES) scan++; /*--------------------------------------------------------------------------- There are two things we can do if we can't find the entry: ignore it or scream. The most likely reason for it not to be here is the user calling this routine twice. Since this could cause BIG problems if any globals are accessed after the first call, we'd better scream. ---------------------------------------------------------------------------*/ if (scan == THREADID_ENTRIES) { ZCONST char *noEntry = LoadFarString(EntryNotFound); fprintf(stderr, noEntry); /* can't use Info w/o a global pointer */ throw "severe error in zipfile."; //EXIT(PK_ERR); /* programming error while still working */ } return threadPtrTable[scan]; }
int extract_or_test_files() /* return PK-type error code */ { uch *cd_inptr; int cd_incnt, error, error_in_archive=PK_COOL; int i, j, renamed, query, len, filnum=(-1), blknum=0; int *fn_matched=NULL, *xn_matched=NULL; ush members_remaining, num_skipped=0, num_bad_pwd=0; long cd_bufstart, bufstart, inbuf_offset, request; LONGINT old_extra_bytes=0L; static min_info info[DIR_BLKSIZ]; /*--------------------------------------------------------------------------- The basic idea of this function is as follows. Since the central di- rectory lies at the end of the zipfile and the member files lie at the beginning or middle or wherever, it is not very desirable to simply read a central directory entry, jump to the member and extract it, and then jump back to the central directory. In the case of a large zipfile this would lead to a whole lot of disk-grinding, especially if each mem- ber file is small. Instead, we read from the central directory the per- tinent information for a block of files, then go extract/test the whole block. Thus this routine contains two small(er) loops within a very large outer loop: the first of the small ones reads a block of files from the central directory; the second extracts or tests each file; and the outer one loops over blocks. There's some file-pointer positioning stuff in between, but that's about it. Btw, it's because of this jump- ing around that we can afford to be lenient if an error occurs in one of the member files: we should still be able to go find the other members, since we know the offset of each from the beginning of the zipfile. ---------------------------------------------------------------------------*/ pInfo = info; members_remaining = ecrec.total_entries_central_dir; #if (defined(CRYPT) || !defined(NO_ZIPINFO)) newzip = TRUE; #endif /* malloc space for CRC table and generate it */ if ((crc_32_tab = (ulg *)malloc(256*sizeof(ulg))) == (ulg *)NULL) return PK_MEM2; makecrc(); /* malloc space for check on unmatched filespecs (OK if one or both NULL) */ if (filespecs > 0 && (fn_matched=(int *)malloc(filespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < filespecs; ++i) fn_matched[i] = FALSE; if (xfilespecs > 0 && (xn_matched=(int *)malloc(xfilespecs*sizeof(int))) != (int *)NULL) for (i = 0; i < xfilespecs; ++i) xn_matched[i] = FALSE; /*--------------------------------------------------------------------------- Begin main loop over blocks of member files. We know the entire central directory is on this disk: we would not have any of this information un- less the end-of-central-directory record was on this disk, and we would not have gotten to this routine unless this is also the disk on which the central directory starts. In practice, this had better be the ONLY disk in the archive, but maybe someday we'll add multi-disk support. ---------------------------------------------------------------------------*/ while (members_remaining) { j = 0; /* * Loop through files in central directory, storing offsets, file * attributes, case-conversion and text-conversion flags until block * size is reached. */ while (members_remaining && (j < DIR_BLKSIZ)) { --members_remaining; pInfo = &info[j]; if (readbuf(sig, 4) == 0) { error_in_archive = PK_EOF; members_remaining = 0; /* ...so no more left to do */ break; } if (strncmp(sig, central_hdr_sig, 4)) { /* just to make sure */ FPRINTF(stderr, LoadFarString(CentSigMsg), j); /* sig not found */ FPRINTF(stderr, LoadFarString(ReportMsg)); /* check binary transfers */ error_in_archive = PK_BADERR; members_remaining = 0; /* ...so no more left to do */ break; } /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */ if ((error = process_cdir_file_hdr()) != PK_COOL) { error_in_archive = error; /* only PK_EOF defined */ members_remaining = 0; /* ...so no more left to do */ break; } if ((error = do_string(crec.filename_length,FILENAME)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal: no more left to do */ FPRINTF(stderr, LoadFarString(FilNamMsg), filename, "central"); members_remaining = 0; break; } } if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal */ FPRINTF(stderr, LoadFarString(ExtFieldMsg), filename, "central"); members_remaining = 0; break; } } if ((error = do_string(crec.file_comment_length,SKIP)) != PK_COOL) { if (error > error_in_archive) error_in_archive = error; if (error > PK_WARN) { /* fatal */ FPRINTF(stderr, LoadFarString(BadFileCommLength), filename); members_remaining = 0; break; } } if (process_all_files) { if (store_info()) ++j; /* file is OK; info[] stored; continue with next */ else ++num_skipped; } else { int do_this_file = FALSE; char **pfn = pfnames-1; while (*++pfn) if (match(filename, *pfn, C_flag)) { do_this_file = TRUE; /* ^-- ignore case or not? */ if (fn_matched) fn_matched[pfn-pfnames] = TRUE; break; /* found match, so stop looping */ } if (do_this_file) { /* check if this is an excluded file */ char **pxn = pxnames-1; while (*++pxn) if (match(filename, *pxn, C_flag)) { do_this_file = FALSE; /* ^-- ignore case or not? */ if (xn_matched) xn_matched[pxn-pxnames] = TRUE; break; } } if (do_this_file) if (store_info()) ++j; /* file is OK */ else ++num_skipped; /* unsupp. compression or encryption */ } /* end if (process_all_files) */ } /* end while-loop (adding files to current block) */ /* save position in central directory so can come back later */ cd_bufstart = cur_zipfile_bufstart; cd_inptr = inptr; cd_incnt = incnt; /*----------------------------------------------------------------------- Second loop: process files in current block, extracting or testing each one. -----------------------------------------------------------------------*/ for (i = 0; i < j; ++i) { filnum = i + blknum*DIR_BLKSIZ; pInfo = &info[i]; /* if the target position is not within the current input buffer * (either haven't yet read far enough, or (maybe) skipping back- * ward), skip to the target position and reset readbuf(). */ /* LSEEK(pInfo->offset): */ request = pInfo->offset + extra_bytes; inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n", request, inbuf_offset)); Trace((stderr, "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", bufstart, cur_zipfile_bufstart)); if (request < 0) { FPRINTF(stderr, LoadFarStringSmall(SeekMsg), zipfn, LoadFarString(ReportMsg)); error_in_archive = PK_ERR; if (filnum == 0 && extra_bytes != 0L) { FPRINTF(stderr, LoadFarString(AttemptRecompensate)); old_extra_bytes = extra_bytes; extra_bytes = 0L; request = pInfo->offset; /* could also check if this != 0 */ inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n", request, inbuf_offset)); Trace((stderr, "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", bufstart, cur_zipfile_bufstart)); } else { error_in_archive = PK_BADERR; continue; /* this one hosed; try next */ } } /* try again */ if (request < 0) { Trace((stderr, "debug: recompensated request still < 0\n")); FPRINTF(stderr, LoadFarStringSmall(SeekMsg), zipfn, LoadFarString(ReportMsg)); error_in_archive = PK_BADERR; continue; } else if (bufstart != cur_zipfile_bufstart) { Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); cur_zipfile_bufstart = lseek(zipfd,(LONGINT)bufstart,SEEK_SET); if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) <= 0) { FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "lseek", bufstart); error_in_archive = PK_BADERR; continue; /* can still do next file */ } inptr = inbuf + (int)inbuf_offset; incnt -= (int)inbuf_offset; } else { incnt += (inptr-inbuf) - (int)inbuf_offset; inptr = inbuf + (int)inbuf_offset; } /* should be in proper position now, so check for sig */ if (readbuf(sig, 4) == 0) { /* bad offset */ FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "EOF", request); error_in_archive = PK_BADERR; continue; /* but can still try next one */ } if (strncmp(sig, local_hdr_sig, 4)) { FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, LoadFarStringSmall(LocalHdrSig), request); error_in_archive = PK_ERR; if ((filnum == 0 && extra_bytes != 0L) || (extra_bytes == 0L && old_extra_bytes != 0L)) { FPRINTF(stderr, LoadFarString(AttemptRecompensate)); if (extra_bytes) { old_extra_bytes = extra_bytes; extra_bytes = 0L; } else extra_bytes = old_extra_bytes; /* third attempt */ LSEEK(pInfo->offset) if (readbuf(sig, 4) == 0) { /* bad offset */ FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, "EOF", request); error_in_archive = PK_BADERR; continue; /* but can still try next one */ } if (strncmp(sig, local_hdr_sig, 4)) { FPRINTF(stderr, LoadFarString(OffsetMsg), filnum, LoadFarStringSmall(LocalHdrSig), request); error_in_archive = PK_BADERR; continue; } } else continue; /* this one hosed; try next */ }
int open_outfile() /* return 1 if fail */ { #ifdef DOS_NT_OS2 if (stat(filename, &statbuf) == 0 && !(statbuf.st_mode & S_IWRITE)) chmod(filename, S_IREAD | S_IWRITE); #endif #ifdef UNIX if (stat(filename, &statbuf) == 0 && unlink(filename) < 0) { FPRINTF(stderr, LoadFarString(CannotDeleteOldFile), filename); return 1; } #endif #ifdef TOPS20 char *tfilnam; if ((tfilnam = (char *)malloc(2*strlen(filename)+1)) == (char *)NULL) return 1; strcpy(tfilnam, filename); upper(tfilnam); enquote(tfilnam); if ((outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) { FPRINTF(stderr, LoadFarString(CannotCreateFile), tfilnam); free(tfilnam); return 1; } free(tfilnam); #else #ifdef MTS if (aflag) outfile = fopen(filename, FOPWT); else outfile = fopen(filename, FOPW); if (outfile == (FILE *)NULL) { FPRINTF(stderr, LoadFarString(CannotCreateFile), filename); return 1; } #else if ((outfile = fopen(filename, FOPW)) == (FILE *)NULL) { FPRINTF(stderr, LoadFarString(CannotCreateFile), filename); return 1; } #endif #endif #if 0 /* this SUCKS! on Ultrix, it must be writing a byte at a time... */ setbuf(outfile, (char *)NULL); /* make output unbuffered */ #endif #ifdef USE_FWRITE #ifdef DOS_NT_OS2 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */ setbuf(outfile, (char *)NULL); /* make output unbuffered */ #else /* !DOS_NT_OS2 */ #ifdef _IOFBF /* make output fully buffered (works just about like write()) */ setvbuf(outfile, (char *)slide, _IOFBF, WSIZE); #else setbuf(outfile, (char *)slide); #endif #endif /* ?DOS_NT_OS2 */ #endif /* USE_FWRITE */ return 0; } /* end function open_outfile() */