diff --git a/cmsmvs/vmmvs.c b/cmsmvs/vmmvs.c index 8416ce8..13d410d 100644 --- a/cmsmvs/vmmvs.c +++ b/cmsmvs/vmmvs.c @@ -35,17 +35,23 @@ /* Function vmmvs_open_infile() */ /********************************/ -FILE *vmmvs_open_infile(__G) +FILE *vmmvs_open_infile(__G fn) __GDEF + char *fn; { FILE *fzip; - G.tempfn = NULL; - fzip = fopen(G.zipfn, FOPR); + fzip = fopen(.fn, FOPR); +#ifdef CMS_MVS_INFILE_TMP -#if 0 /* Let's try it without the convert for a while -- RG Hartwig */ + /* 2015-03-17 SMS. + * If ever re-enabled, this code will need changes to accommodate the + * additional archive segment file(s) (variable file name). + */ + + G.tempfn = NULL; if ((fzip = fopen(G.zipfn,"rb,recfm=fb")) == NULL) { size_t cnt; @@ -82,7 +88,7 @@ FILE *vmmvs_open_infile(__G) G.ziplen = ftell(fzip); } -#endif +#endif /* def CMS_MVS_INFILE_TMP */ return fzip; } @@ -177,15 +183,21 @@ void close_outfile(__G) /* Function close_infile() */ /***************************/ -void close_infile(__G) +void close_infile(__G__ pfd) __GDEF + zipfd_t *pfd; { - fclose(G.zipfd); + int sts; + sts = fclose( *pfd); + *pfd = NULL; - /* If we're working from a temp file, erase it now */ - if (G.tempfn) - remove(G.tempfn); +#ifdef CMS_MVS_INFILE_TMP + /* If we're working from a temp file, erase it now */ + if (G.tempfn) + remove(G.tempfn); +#endif /* def CMS_MVS_INFILE_TMP */ + return sts; } /* end function close_infile() */ diff --git a/consts.h b/consts.h index 5dfc0a0..dee57b1 100644 --- a/consts.h +++ b/consts.h @@ -33,7 +33,7 @@ ZCONST char Far VersionDate[] = UZ_VERSION_DATE; /* now defined in unzvers.h */ ZCONST char Far CentSigMsg[] = "error: expected central file header signature not found (file #%lu).\n"; ZCONST char Far SeekMsg[] = - "error [%s]: attempt to seek before beginning of zipfile\n%s"; + "error [%s]: attempt to seek before beginning of zipfile (%d)\n%s"; ZCONST char Far FilenameNotMatched[] = "caution: filename not matched: %s\n"; ZCONST char Far ExclFilenameNotMatched[] = "caution: excluded filename not matched: %s\n"; diff --git a/extract.c b/extract.c index 7134bfe..e41803f 100644 --- a/extract.c +++ b/extract.c @@ -19,6 +19,7 @@ find_compr_idx() extract_or_test_entrylist() extract_or_test_member() + close_segment() TestExtraField() test_compr_eb() memextract() @@ -323,8 +324,20 @@ static ZCONST char Far BadExtraFieldCRC[] = "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n"; +/*******************************/ +/* Function close_segment(). */ +/*******************************/ +static void close_segment(__G) + __GDEF +{ + if (G.zipfn_sgmnt != NULL) + { + izu_free(G.zipfn_sgmnt); + G.zipfn_sgmnt = NULL; + } + CLOSE_INFILE( &G.zipfd_sgmnt); - +} /* close_segment(). */ /**************************************/ /* Function extract_or_test_files() */ @@ -351,6 +364,8 @@ int extract_or_test_files(__G) /* return PK-type error code */ unsigned num_dirs=0; direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL; #endif + zuvl_t sgmnt_nr; + zipfd_t zipfd; /* * First, two general initializations are applied. These have been moved @@ -578,6 +593,12 @@ int extract_or_test_files(__G) /* return PK-type error code */ cd_inptr = G.inptr; cd_incnt = G.incnt; + /* Save the file descr/pointer and segment number, which are subject + * to change when the archive is segmented. + */ + zipfd = G.zipfd; + sgmnt_nr = G.sgmnt_nr; + /*----------------------------------------------------------------------- Second loop: process files in current block, extracting or testing each one. @@ -606,7 +627,8 @@ int extract_or_test_files(__G) /* return PK-type error code */ * Jump back to where we were in the central directory, then go and do * the next batch of files. */ - + G.zipfd = zipfd; + G.sgmnt_nr = sgmnt_nr; #ifdef USE_STRM_INPUT zfseeko(G.zipfd, cd_bufstart, SEEK_SET); G.cur_zipfile_bufstart = zftello(G.zipfd); @@ -1060,8 +1082,51 @@ static int extract_or_test_entrylist(__G__ numchunk, * (either haven't yet read far enough, or (maybe) skipping back- * ward), skip to the target position and reset readbuf(). */ + if(G.ecrec.number_this_disk > 0) + { + /* Open file (when it is segmented) even if it is a duplicate + * of the same fd, due to possible unwanted changes of G.zipfd + * and G.sgmnt_nr which were saved in extract_or_test_files(). + */ + if (!fd_is_valid(G.zipfd_sgmnt) || G.sgmnt_nr != G.pInfo->diskstart) + { + if (fd_is_valid(G.zipfd_sgmnt)) + close_segment( __G); /* We need a different file. */ + + set_zipfn_sgmnt_name( __G__ G.pInfo->diskstart); + if (open_infile( __G__ OIF_SEGMENT)) + { + /* TODO: ask for place/path of zipfile, see wild*!, ... */ + /* Create new function for this all? */ + izu_free(G.zipfn_sgmnt); + G.zipfn_sgmnt = NULL; + error = PK_NOZIP; + return error; + } + else + { + /* TODO: that's not best solution but for + * testing/alpha version is good enough now. */ + G.zipfd = G.zipfd_sgmnt; + G.sgmnt_nr = G.pInfo->diskstart; + } + /* When we change file, we must refill buffer always! + * (Same method as in seek_zipf().) + */ + G.cur_zipfile_bufstart = -1; + } + /* TODO: check better too -- Is G.extra_bytes important in + * segmented? Otherwise bigger harakiri is here + * needed (here = whole request block below) + */ + request = G.pInfo->offset; + } + else + { + request = G.pInfo->offset + G.extra_bytes; + } + /* seek_zipf(__G__ pInfo->offset); */ - request = G.pInfo->offset + G.extra_bytes; inbuf_offset = request % INBUFSIZ; bufstart = request - inbuf_offset; diff --git a/fileio.c b/fileio.c index 2a61a30..8bbe1b9 100644 --- a/fileio.c +++ b/fileio.c @@ -147,6 +147,10 @@ static int disk_error OF((__GPRO)); static ZCONST char Far CannotOpenZipfile[] = "error: cannot open zipfile [ %s ]\n %s\n"; +static ZCONST char Far NoSuchSegment[] = + "Bad archive segment value (%d > %d)"; + + #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) #if (!defined(TANDEM)) #if (defined(ATH_BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32)) @@ -215,51 +219,234 @@ static ZCONST char Far ExtraFieldCorrupt[] = /******************************/ -/* Function open_input_file() */ +/* Function open_infile() */ /******************************/ -int open_input_file(__G) /* return 1 if open failed */ +int open_infile(__G__ which) /* return 1 if open failed */ __GDEF + int which; /* 0: Primary archive; 1: Segment archive. */ + { - /* - * open the zipfile for reading and in BINARY mode to prevent cr/lf - * translation, which would corrupt the bitstreams - */ + + /* Open an archive (zipfile) for reading and in BINARY mode to + * prevent CR/LF translation, which would corrupt the data. + * Return 0: success; 1: failure. + */ + + char *fn; + zipfd_t *pfd; + + if (which == OIF_PRIMARY) + { + fn = G.zipfn; /* Primary archive file name (".zip"). */ + pfd = &G.zipfd; /* Primary archive file descr/pointer. */ + } + else + { + fn = G.zipfn_sgmnt; /* Segment archive file name (".zXX"). */ + pfd = &G.zipfd_sgmnt; /* Segment archive file descr/pointer. */ + } #ifdef VMS - G.zipfd = open(G.zipfn, O_RDONLY, 0, OPNZIP_RMS_ARGS); + *pfd = open( fn, O_RDONLY, 0, OPNZIP_RMS_ARGS); #else /* !VMS */ #ifdef MACOS - G.zipfd = open(G.zipfn, 0); + *pfd = open(fn, 0); #else /* !MACOS */ #ifdef CMS_MVS - G.zipfd = vmmvs_open_infile(__G); + *pfd = vmmvs_open_infile(__G__ fn, pfd); #else /* !CMS_MVS */ #ifdef USE_STRM_INPUT - G.zipfd = fopen(G.zipfn, FOPR); + *pfd = fopen(fn, FOPR); #else /* !USE_STRM_INPUT */ - G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY); + *pfd = open(fn, O_RDONLY | O_BINARY); #endif /* ?USE_STRM_INPUT */ #endif /* ?CMS_MVS */ #endif /* ?MACOS */ #endif /* ?VMS */ -#ifdef USE_STRM_INPUT - if (G.zipfd == NULL) -#else - /* if (G.zipfd < 0) */ /* no good for Windows CE port */ - if (G.zipfd == -1) -#endif + if (!fd_is_valid( *pfd)) { Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile), - G.zipfn, strerror(errno))); + fn, strerror(errno))); return 1; } return 0; } /* end function open_input_file() */ +/***************************/ +/* Function close_infile() */ +/***************************/ +int close_infile( __G__ pfd) + __GDEF + zipfd_t *pfd; +{ + int sts = 0; + + if (fd_is_valid( *pfd)) + { +#ifdef USE_STRM_INPUT + sts = fclose( *pfd); +#else /* def USE_STRM_INPUT */ + sts = close( *pfd); +#endif /* def USE_STRM_INPUT [else] */ + *pfd = ZIPFD_INVALID; + } + return sts; +} /* close_infile() */ + +/***********************************/ +/* Function set_zipfn_sgmnt_name() */ +/***********************************/ +int set_zipfn_sgmnt_name( __G__ sgmnt_nr) + __GDEF + zuvl_t sgmnt_nr; +{ + char *suffix; + int sufx_len; + +/* sizeof( ".z65535") == 8 should be safe. */ +#define SGMNT_NAME_BOOST 8 + + if (sgmnt_nr > G.ecrec.number_this_disk) + { + /* Segment number greater than (max?) central-dir disk number. */ + Info(slide, 1, ((char *)slide, LoadFarString(NoSuchSegment), + sgmnt_nr, G.ecrec.number_this_disk)); + return 1; + } + + if (G.zipfn_sgmnt == NULL) + { + G.zipfn_sgmnt_size = strlen(G.zipfn)+ SGMNT_NAME_BOOST; + if ((G.zipfn_sgmnt = izu_malloc(G.zipfn_sgmnt_size)) == NULL) + { + G.zipfn_sgmnt_size = -1; + return 1; + } + } + else + { + if (G.zipfn_sgmnt_size < (int)strlen(G.zipfn)+ SGMNT_NAME_BOOST) + { + G.zipfn_sgmnt_size = strlen(G.zipfn)+ SGMNT_NAME_BOOST; + izu_free(G.zipfn_sgmnt); + if ((G.zipfn_sgmnt = izu_malloc(G.zipfn_sgmnt_size)) == NULL) + { + G.zipfn_sgmnt_size = -1; + return 1; + } + } + } + + + if (sgmnt_nr == G.ecrec.number_this_disk) + { + zfstrcpy(G.zipfn_sgmnt, G.zipfn); + return 0; /* Last segment. Name already ".zip." */ + } + +#ifdef VMS + + /* A VMS archive file spec may include a version number (";nnn"), + * confusing any simple scheme (like the one below). $PARSE can + * easily replace one file type with another (and null out the version + * number), so use it, instead. + */ + vms_sgmnt_name( G.zipfn_sgmnt, G.zipfn, (sgmnt_nr+ 1)); + +#else /* def VMS */ + + zfstrcpy(G.zipfn_sgmnt, G.zipfn); + /* Expect to find ".zXX" at the end of the segment file name. */ + sufx_len = IZ_MAX( 0, ((int)strlen(G.zipfn_sgmnt)- 4)); + suffix = G.zipfn_sgmnt+ sufx_len; + + /* try find filename extension and set right position for add number */ + if (zfstrcmp(suffix, ZSUFX) == 0) + { + suffix += 2; /* Point to digits after ".z". */ +# ifdef ZSUFX2 + } + else if (zfstrcmp(suffix, ZSUFX2) == 0) /* Check alternate suffix. */ + { + suffix[1] = 'z'; /* Should be always lowercase??? */ + suffix += 2; /* Point to digits after ".z". */ +# endif + } + else + { + zfstrcpy( (suffix+ sufx_len), ZSUFX); + suffix += sufx_len+ 2; + } + /* Insert the next segment number into the file name (G.zipfn_sgmnt). */ + sprintf(suffix, "%02d", (sgmnt_nr+ 1)); + +#endif /* def VMS [else] */ + + return 0; +} /* set_zipfn_sgmnt_name(). */ + +/********************************/ +/* Function open_infile_sgmnt() */ +/********************************/ +int open_infile_sgmnt(__G__ movement) + __GDEF + int movement; +{ + zipfd_t zipfd; + zipfd_t zipfd_sgmnt; + + if (movement == 0) /* Nothing to do. */ + return 0; + + zipfd = G.zipfd; + zipfd_sgmnt = G.zipfd_sgmnt; + + /* Set the new segment file name. */ + if (set_zipfn_sgmnt_name( __G__ G.sgmnt_nr+ movement)) + return 1; + + if (open_infile( __G__ OIF_SEGMENT)) + { + /* TODO: ask for input and try it again */ + /* error, load back old zipfn (it shouldn't be frequently) */ + if (fd_is_valid(zipfd_sgmnt)) + { + set_zipfn_sgmnt_name( __G__ G.sgmnt_nr); + } + else + { + /* Loading of central directory record probably??? */ + izu_free(G.zipfn_sgmnt); + G.zipfn_sgmnt = NULL; + } + + G.zipfd_sgmnt = zipfd_sgmnt; + return 1; + } + + G.sgmnt_nr += movement; + + /* close old file - yes, that's nasty solution */ + /* Switch I/O to the new segment. */ + G.zipfd = G.zipfd_sgmnt; + G.zipfd_sgmnt = zipfd; /* Old G.zipfd. */ + CLOSE_INFILE( &G.zipfd_sgmnt); + if (fd_is_valid(zipfd_sgmnt)) /* Old G.zipfd_sgmnt. */ + { + G.zipfd_sgmnt = G.zipfd; + } + else + { + izu_free(G.zipfn_sgmnt); /* We must clean it now. */ + G.zipfn_sgmnt = NULL; + } + + return 0; +} /* open_infile_sgmnt() */ #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) @@ -581,11 +768,26 @@ unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */ unsigned n; n = size; - while (size) { - if (G.incnt <= 0) { + while (size) + { + if (G.incnt <= 0) + { if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) - return (n-size); - else if (G.incnt < 0) { + { + /* read() got no data. If the srchive is segmented, then + * try again with the next segment file. + */ + if (G.ecrec.number_this_disk > 0) + { + if ((open_infile_sgmnt( __G__ 1) != 0) || + (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) + return (n-size); /* Return short retry size. */ + } else + return (n-size); /* Return short size. */ + } + + if (G.incnt < 0) + { /* another hack, but no real harm copying same thing twice */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), /* CANNOT use slide */ @@ -620,16 +822,33 @@ int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */ { if (G.mem_mode) return EOF; - if (G.csize <= 0) { + if (G.csize <= 0) + { G.csize--; /* for tests done after exploding */ G.incnt = 0; return EOF; } - if (G.incnt <= 0) { - if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) { - return EOF; - } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */ - /* another hack, but no real harm copying same thing twice */ + if (G.incnt <= 0) + { + if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) + { + /* read() got no data. If the srchive is segmented, then + * try again with the next segment file. + */ + /* if(fd_is_valid(G.zipfd_sgmnt)) { */ + if (G.ecrec.number_this_disk > 0) + { + if ((open_infile_sgmnt( __G__ 1) != 0) || + (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) + return EOF; + } else + return EOF; + } + + if (G.incnt < 0) + { /* "fail" (abort, retry, ...) returns this. + * another hack, but no real harm copying same thing twice. + */ (*G.message)((zvoid *)&G, (uch *)LoadFarString(ReadError), (ulg)strlen(LoadFarString(ReadError)), 0x401); @@ -724,55 +943,142 @@ int seek_zipf(__G__ abs_offset) * "proper offset" (i.e., if there were no extra bytes prepended); * cur_zipfile_bufstart contains the corrected offset. * - * Since seek_zipf() is never used during decompression, it is safe to - * use the slide[] buffer for the error message. + * Because seek_zipf() is never used during decompression, it is safe + * to use the slide[] buffer for the error message. * * returns PK error codes: * PK_BADERR if effective offset in zipfile is negative * PK_EOF if seeking past end of zipfile * PK_OK when seek was successful */ - zoff_t request = abs_offset + G.extra_bytes; - zoff_t inbuf_offset = request % INBUFSIZ; - zoff_t bufstart = request - inbuf_offset; - if (request < 0) { + zoff_t request; + zoff_t inbuf_offset; + zoff_t bufstart; + + request = abs_offset + G.extra_bytes; + +#if 0 /* Pre-segment-support. */ + if (request < 0) + { + Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg), + 2, G.zipfn, LoadFarString(ReportMsg))); + return PK_BADERR; + } +#endif /* 0 */ /* Pre-segment-support. */ + + while (request < 0) + { + if (G.sgmnt_size == 0) + { + if ((G.sgmnt_nr == 0) || open_infile_sgmnt( __G__ -1)) + { Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg), - G.zipfn, LoadFarString(ReportMsg))); - return(PK_BADERR); - } else if (bufstart != G.cur_zipfile_bufstart) { - Trace((stderr, - "fpos_zip: abs_offset = %s, G.extra_bytes = %s\n", - FmZofft(abs_offset, NULL, NULL), - FmZofft(G.extra_bytes, NULL, NULL))); + 3, G.zipfn, LoadFarString(ReportMsg))); + return PK_BADERR; + } + /* Get the new segment size, and calculate the new offset. + * This is where G.sgmnt_size gets a real (non-zero) value. + */ #ifdef USE_STRM_INPUT - zfseeko(G.zipfd, bufstart, SEEK_SET); - G.cur_zipfile_bufstart = zftello(G.zipfd); + zfseeko(G.zipfd, 0, SEEK_END); + G.sgmnt_size = zftello(G.zipfd); #else /* !USE_STRM_INPUT */ - G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET); -#endif /* ?USE_STRM_INPUT */ - Trace((stderr, - " request = %s, (abs+extra) = %s, inbuf_offset = %s\n", - FmZofft(request, NULL, NULL), - FmZofft((abs_offset+G.extra_bytes), NULL, NULL), - FmZofft(inbuf_offset, NULL, NULL))); - Trace((stderr, " bufstart = %s, cur_zipfile_bufstart = %s\n", - FmZofft(bufstart, NULL, NULL), - FmZofft(G.cur_zipfile_bufstart, NULL, NULL))); - if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) - return(PK_EOF); - G.incnt -= (int)inbuf_offset; - G.inptr = G.inbuf + (int)inbuf_offset; - } else { - G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset; - G.inptr = G.inbuf + (int)inbuf_offset; + G.sgmnt_size = zlseek(G.zipfd, 0, SEEK_END); +#endif /* USE_STRM_INPUT */ + request += G.sgmnt_size; } - return(PK_OK); -} /* end function seek_zipf() */ - + else + { + /* SMSd. Can we trust that all segments have the same size? */ + /* We know segment size(s?), so we can calculate against + * abs_offset and sgmnt_nr, and open the segment file which we + * actually need. + */ + unsigned int tmp_disk = G.ecrec.number_this_disk; + + while (request < 0) + { + tmp_disk--; + request += G.sgmnt_size; + } + /* for same as actual disk (movement == 0) return 0 */ + if (open_infile_sgmnt( __G__ (tmp_disk- G.sgmnt_nr))) + { + Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg), + 4, G.zipfn, LoadFarString(ReportMsg))); + return PK_BADERR; + } + } + /* In both cases we need to refill buffer, so set + * G.cur_zipfile_bufstart negative (so that bufstart != + * G.cur_zipfile_bufstart, below). + */ + G.cur_zipfile_bufstart = -1; + } + inbuf_offset = request % INBUFSIZ; + bufstart = request - inbuf_offset; + if (bufstart != G.cur_zipfile_bufstart) + { + Trace((stderr, + "fpos_zip: abs_offset = %s, G.extra_bytes = %s\n", + FmZofft(abs_offset, NULL, NULL), + FmZofft(G.extra_bytes, NULL, NULL))); +#ifdef USE_STRM_INPUT + zfseeko(G.zipfd, bufstart, SEEK_SET); + G.cur_zipfile_bufstart = zftello(G.zipfd); +#else /* def USE_STRM_INPUT */ + G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET); +#endif /* def USE_STRM_INPUT [else] */ + + Trace((stderr, + " request = %s, (abs+extra) = %s, inbuf_offset = %s\n", + FmZofft(request, NULL, NULL), + FmZofft((abs_offset+G.extra_bytes), NULL, NULL), + FmZofft(inbuf_offset, NULL, NULL))); + Trace((stderr, " bufstart = %s, cur_zipfile_bufstart = %s\n", + FmZofft(bufstart, NULL, NULL), + FmZofft(G.cur_zipfile_bufstart, NULL, NULL))); + + if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) < INBUFSIZ) + { + /* If we're not at the end of file, then we need move to the + * next segment file. + * TODO: Check if EOF, instead? + */ + if (G.ecrec.number_this_disk != G.sgmnt_nr) + { + int tmp; + + if (open_infile_sgmnt( __G__ 1)) + return PK_EOF; /*TODO: Add some new return code? */ + + /* append rest of data to buffer - it's important when we are only + * few bytes before EOF and want read CDR! Now it's more safe. + * Only some disk error could be wrong for us in that case. + */ + tmp = read(G.zipfd, (char *)(G.inbuf+ G.incnt), (INBUFSIZ- G.incnt)); + if (tmp <= 0) + return PK_EOF; + + G.incnt += tmp; + } + else if (G.incnt <= 0) + return PK_EOF; + } + G.incnt -= (int)inbuf_offset; + G.inptr = G.inbuf + (int)inbuf_offset; + } + else + { + G.incnt += (int)(G.inptr- G.inbuf) - (int)inbuf_offset; + G.inptr = G.inbuf + (int)inbuf_offset; + } + return(PK_OK); +} /* end function seek_zipf() */ #ifndef VMS /* for VMS use code in vms.c */ diff --git a/globals.c b/globals.c index fa8cca5..9cac035 100644 --- a/globals.c +++ b/globals.c @@ -198,6 +198,9 @@ Uz_Globs *globalsCtor() G.mpause = UzpMorePause; #endif G.decr_passwd = UzpPassword; + G.zipfn_sgmnt = NULL; /* Archive segment name */ + G.zipfn_sgmnt_size = 0; /* Archive segment size */ + G.zipfd_sgmnt = ZIPFD_INVALID; /* Archive segment file descr/pntr */ #endif /* !FUNZIP */ #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) diff --git a/globals.h b/globals.h index 11b7215..0a84432 100644 --- a/globals.h +++ b/globals.h @@ -243,12 +243,13 @@ typedef struct Globals { int zipeof; char *argv0; /* used for NT and EXE_EXTENSION */ char *wildzipfn; - char *zipfn; /* GRR: WINDLL: must nuke any malloc'd zipfn... */ -#ifdef USE_STRM_INPUT - FILE *zipfd; /* zipfile file descriptor */ -#else - int zipfd; /* zipfile file handle */ -#endif + char *zipfn; /* zipfile path/name */ + char *zipfn_sgmnt; /* zipfile segment path/name */ + int zipfn_sgmnt_size; /* zipfile segment path/name size */ + zuvl_t sgmnt_nr; /* zipfile segment number */ + zoff_t sgmnt_size; /* zipfile segment size */ + zipfd_t zipfd; /* zipfile primary file descr/pointer */ + zipfd_t zipfd_sgmnt; /* zipfile segment file descr/pointer */ zoff_t ziplen; zoff_t cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */ zoff_t extra_bytes; /* used in unzip.c, misc.c */ @@ -306,7 +307,8 @@ typedef struct Globals { char *unipath_filename; /* UTF-8 path */ #endif /* UNICODE_SUPPORT */ -#ifdef CMS_MVS +# ifdef CMS_MVS_INFILE_TMP + /* 2015-03-17 SMS. See note in zos/vmmvs.c. */ char *tempfn; /* temp file used; erase on close */ #endif diff --git a/process.c b/process.c index 0d57ab4..76652a9 100644 --- a/process.c +++ b/process.c @@ -726,8 +726,10 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ return PK_ERR; #endif - if (open_input_file(__G)) /* this should never happen, given */ - return PK_NOZIP; /* the stat() test above, but... */ + if (open_infile(__G__ OIF_PRIMARY)) + { /* This should never fail, given the stat() test above, but... */ + return PK_NOZIP; + } #ifdef DO_SAFECHECK_2GB /* Need more care: Do not trust the size returned by stat() but @@ -740,7 +742,7 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ printf( " We need a better error message for: 64-bit file, 32-bit program.\n"); */ - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); return IZ_ERRBF; } #endif /* DO_SAFECHECK_2GB */ @@ -755,6 +757,7 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ G.cur_zipfile_bufstart = 0; G.inptr = G.inbuf; + G.sgmnt_size = 0; /* Init before ECREC for each archive in the list. */ #if ((!defined(WINDLL) && !defined(SFX)) || !defined(NO_ZIPINFO)) # if (!defined(WINDLL) && !defined(SFX)) @@ -785,7 +788,7 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ MIN(G.ziplen, 66000L))) > PK_WARN ) { - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); #ifdef SFX ++lastchance; /* avoid picky compiler warnings */ @@ -804,7 +807,7 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ } if ((uO.zflag > 0) && !uO.zipinfo_mode) { /* unzip: zflag = comment ONLY */ - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); return error_in_archive; } @@ -892,10 +895,13 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ else Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty), G.zipfn)); - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN; } + /* Set the segment number (needed for segmented archives). */ + G.sgmnt_nr = G.ecrec.number_this_disk; + /*----------------------------------------------------------------------- Compensate for missing or extra bytes, and seek to where the start of central directory should be. If header not found, uncompensate @@ -905,12 +911,12 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); if (error == PK_BADERR) { - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); return PK_BADERR; } #ifdef OLD_SEEK_TEST if (error != PK_OK || readbuf(__G__ G.sig, 4) == 0) { - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); return PK_ERR; /* file may be locked, or possibly disk error(?) */ } if (memcmp(G.sig, central_hdr_sig, 4)) @@ -932,7 +938,7 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirStartNotFound), G.zipfn, LoadFarStringSmall(ReportMsg))); - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); return (error != PK_OK ? error : PK_BADERR); } #ifndef SFX @@ -950,7 +956,7 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ error = seek_zipf(__G__ G.ecrec.offset_start_central_directory); if (error != PK_OK) { - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); return error; } @@ -996,7 +1002,7 @@ static int do_seekable(__G__ lastchance) /* return PK-type error code */ } /* end if (!too_weird_to_continue) */ #endif - CLOSE_INFILE(); + CLOSE_INFILE( &G.zipfd); #ifdef TIMESTAMP if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0L)) { diff --git a/unix/Makefile b/unix/Makefile index ab32270..783f261 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -47,7 +47,7 @@ LD = $(CC)# must match, else "unresolved symbol: ___main" is possible) AS = as LOC = $(D_USE_BZ2) $(LOCAL_UNZIP) AF = $(LOC) -CFLAGS = -O +CFLAGS = -O0 CF_NOOPT = -I. -I$(IZ_BZIP2) -DUNIX $(LOC) CF = $(CFLAGS) $(CF_NOOPT) LFLAGS1 = @@ -594,12 +594,12 @@ generic_shlib: unix_make @echo\ 'which is UnZip linked with the DLL). This target is an example only.' @echo "" - $(MAKE) objsdll CC=gcc CFLAGS="-O3 -Wall -fPIC -DDLL" + $(MAKE) objsdll CC=gcc CFLAGS="-O0 -Wall -fPIC -DDLL" gcc -shared -Wl,-soname,libunzip.so.0 -o libunzip.so.0.4 $(OBJSDLL) $(RM) libunzip.so.0 libunzip.so $(LN) -s libunzip.so.0.4 libunzip.so.0 $(LN) -s libunzip.so.0 libunzip.so - gcc -c -O unzipstb.c + gcc -c -O0 unzipstb.c gcc -o unzip_shlib unzipstb.o -L. -lunzip #---------------------------------------------------------------------------- @@ -694,7 +694,7 @@ _v7: $(MAKE) unzips CF="$(CF) -DNO_DIR -DNO_MKDIR -DNO_STRNICMP -DNO_UID_GID -DNO_FCHMOD -DNO_LCHOWN -DNO_LCHMOD -DCBREAK=2" 7300_gcc: unix_make - $(MAKE) unzips CC=gcc LD=gcc LF2="" CFLAGS="-O2" \ + $(MAKE) unzips CC=gcc LD=gcc LF2="" CFLAGS="-O0" \ LOC="-DNO_DIR -DNO_MKDIR -DNO_STDLIB_H -DNO_STRNICMP -DNO_UID_GID -DNO_FCHMOD -DNO_LCHOWN -DNO_LCHMOD -DCBREAK=2 $(LOC)" $(STRIP) $(UNZIPS) @@ -717,13 +717,13 @@ apollo: unix_make bsdi: unix_make @echo 'NOTE: use bsdi_noasm target for non-Intel BSD/OS compiles.' $(MAKE) unzips CC=gcc2 LD=shlicc2 AS=gcc2\ - CFLAGS="-O3 -Wall -DASM_CRC -DBSD" CRCA_O=crc_gcc$O + CFLAGS="-O0 -Wall -DASM_CRC -DBSD" CRCA_O=crc_gcc$O # BSDI BSD/OS bsdi_noasm: unix_make # @echo 'NOTE: use bsd target for non-Intel BSD/OS compiles.' $(MAKE) unzips CC=gcc2 LD=shlicc2 AS=gcc2\ - CFLAGS="-O3 -Wall -DBSD" + CFLAGS="-O0 -Wall -DBSD" # Coherent 3.x/4.x, Mark Williams C. ``For Coherent's CC, it needs either # -T0 or -T150000 (or bigger) added to the CFLAGS, otherwise the compiler @@ -747,7 +747,7 @@ cyber_sgi: unix_make # Info-ZIP recommends using "win32/Makefile.gcc" instead. cygwin: unix_make $(MAKE) unzips CC=gcc LD=gcc AS=gcc\ - CFLAGS="-O3 -DASM_CRC -DNO_LCHOWN -DNO_LCHMOD"\ + CFLAGS="-O0 -DASM_CRC -DNO_LCHOWN -DNO_LCHMOD"\ AF="-Di386 $(AF)" CRCA_O=crc_gcc$O\ E=".exe" CP="cp" LN="ln -s" @@ -764,7 +764,7 @@ dnix: unix_make freebsd: unix_make @echo 'NOTE: use bsd target for non-Intel FreeBSD compiles (if any).' $(MAKE) unzips CC=gcc LD=gcc AS=gcc\ - CFLAGS="-O3 -Wall -DASM_CRC -DBSD"\ + CFLAGS="-O0 -Wall -DASM_CRC -DBSD"\ AF="-Di386 $(AF)" CRCA_O=crc_gcc$O # Generic BSDish Unix gcc. ``The -O3 only works with later versions of gcc; @@ -775,7 +775,7 @@ freebsd: unix_make # with "echo" instead). # gcc: unix_make - $(MAKE) unzips CC=gcc LD=gcc CFLAGS="-O3" LF2="" + $(MAKE) unzips CC=gcc LD=gcc CFLAGS="-O0" LF2="" $(STRIP) $(UNZIPS) # Heurikon HK68 (68010), UniPlus+ System V 5.0, Green Hills C-68000 @@ -787,13 +787,13 @@ hk68: unix_make # ISC Unix on 386 platform isc: unix_make $(MAKE) unzips LF2="-lc_s $(LF2)" CRCA_O=crc_sysv$O \ - CFLAGS="-O" LOC="-DASM_CRC -DSYSV -DNO_UID_GID -DNEED_PTEM -DNO_LCHOWN -DNO_LCHMOD $(LOC)" \ + CFLAGS="-O0" LOC="-DASM_CRC -DSYSV -DNO_UID_GID -DNEED_PTEM -DNO_LCHOWN -DNO_LCHMOD $(LOC)" \ AF="-DNO_UNDERLINE -Djecxz=jcxz -DALIGNMENT='.align 16' $(AF)" isc_gcc: unix_make $(MAKE) unzips AS=gcc CC=gcc LD=gcc CRCA_O=crc_gcc$O \ LF="-shlib $(LF)" SL="-shlib $(SL)" FL="-shlib $(FL)" LF2="" \ - CFLAGS="-O3" LOC="-DSYSV -DASM_CRC -DNO_UID_GID -DNEED_PTEM -DNO_LCHOWN -DNO_LCHMOD $(LOC)" \ + CFLAGS="-O0" LOC="-DSYSV -DASM_CRC -DNO_UID_GID -DNEED_PTEM -DNO_LCHOWN -DNO_LCHMOD $(LOC)" \ AF="-DNO_UNDERLINE -Djecxz=jcxz -DALIGNMENT='.align 16' $(AF)" $(STRIP) $(UNZIPS) @@ -809,7 +809,7 @@ isi: unix_make linux: unix_make @echo 'NOTE: use linux_noasm target for non-Intel Linux compiles.' $(MAKE) unzips CC=gcc LD=gcc AS=gcc\ - CFLAGS="-O3 -Wall -DASM_CRC"\ + CFLAGS="-O0 -Wall -DASM_CRC"\ AF="-Di386 $(AF)" CRCA_O=crc_gcc$O # GRR: this echo is pointless; if user gets this far, no difference to install # @echo 'Be sure to use the install_asm target rather than the install target' @@ -819,19 +819,19 @@ linux_asm: linux # Linux (Posix, approximately SysV): virtually any version since before 0.96, # for any platform. Change "-O" to "-O3" or whatever, as desired... linux_noasm: unix_make - $(MAKE) unzips CC=gcc LD=gcc CFLAGS="-O -Wall" + $(MAKE) unzips CC=gcc LD=gcc CFLAGS="-O0 -Wall" # Linux with lcc compiler: __inline__ (stat.h) not recognized, and must edit # /usr/include/gnu/types.h to get rid of "long long" if __LCC__ defined. -O3 # (or -O2 or -O) is ignored. [GRR 960828: test target only] # linux_lcc: unix_make - $(MAKE) unzips CC=lcc LD=lcc CFLAGS="-O3 -Wall -D__inline__= " + $(MAKE) unzips CC=lcc LD=lcc CFLAGS="-O0 -Wall -D__inline__= " # Linux host with go32 (djgpp) cross-compiler (go32crs.tgz) for 32-bit DOS. linux_dos: unix_make $(MAKE) unzips CC=go32gcc LD=go32gcc M=msdos OSDEP_H="msdos/doscfg.h" \ - CFLAGS="-O2 -Wall" + CFLAGS="-O0 -Wall" # go32-strip unzip # Due to limitations of the cross-compiling package, this has to be # done manually: @@ -845,25 +845,25 @@ linux_dos: unix_make # library). # linux_shlib: unix_make - $(MAKE) objsdll CC=gcc CFLAGS="-O3 -Wall -fPIC"\ + $(MAKE) objsdll CC=gcc CFLAGS="-O0 -Wall -fPIC"\ LOC="-DDLL -DASM_CRC $(LOC)"\ AS=gcc AF="-fPIC -Di386 $(AF)" CRCA_O=crc_gcc$O gcc -shared -Wl,-soname,libunzip.so.0 -o libunzip.so.0.4 $(OBJSDLL)\ crc_gcc.pic.o ln -sf libunzip.so.0.4 libunzip.so.0 ln -sf libunzip.so.0 libunzip.so - gcc -c -O unzipstb.c + gcc -c -O0 unzipstb.c gcc -o unzip_shlib unzipstb.o -L. -lunzip # Linux ELF shared library, as above, but using inflate() from zlib (libz.so) # instead of the original UnZip version. (libz was libgz prior to 0.94) linux_shlibz: unix_make $(MAKE) objsdll CC=gcc AS=gcc AF="-fPIC -Di386 $(AF)" CRCA_O=crc_gcc$O\ - CFLAGS="-O3 -Wall -fPIC" LOC="-DDLL -DUSE_ZLIB -DASM_CRC $(LOC)" + CFLAGS="-O0 -Wall -fPIC" LOC="-DDLL -DUSE_ZLIB -DASM_CRC $(LOC)" gcc -shared -Wl,-soname,libunzip.so.0 -o libunzip.so.0.4 $(OBJSDLL)\ crc_gcc.pic.o ln -sf libunzip.so.0.4 libunzip.so.0 - gcc -c -O unzipstb.c + gcc -c -O0 unzipstb.c gcc -o unzip unzipstb.o -L. -lunzip -lz # LynxOS-x86 2.3.0 and newer, a real-time BSD-like OS; uses gcc. @@ -872,12 +872,12 @@ lynx: unix_make # Macintosh MacOS X (Unix-compatible enviroment), using standard compiler macosx: unix_make - $(MAKE) unzips CFLAGS="-O3 -Wall -DBSD" LF2="" + $(MAKE) unzips CFLAGS="-O0 -Wall -DBSD" LF2="" $(STRIP) $(UNZIPS) # Macintosh MacOS X (Unix-compatible enviroment), using gcc macosx_gcc: unix_make - $(MAKE) unzips CC=gcc CFLAGS="-O3 -Wall -DBSD" LF2="" + $(MAKE) unzips CC=gcc CFLAGS="-O0 -Wall -DBSD" LF2="" $(STRIP) $(UNZIPS) # Minix 1.5 PC for the 386. Invoke as is to use default cc, or as "make @@ -914,12 +914,12 @@ next2x: unix_make # NeXT 3.x: as above, plus better optimization. next3x: unix_make - $(MAKE) unzips CFLAGS="-O2" LF2="-object -s" + $(MAKE) unzips CFLAGS="-O0" LF2="-object -s" # NeXT 3.1+: make the executable fat (multi-architecture binary [MAB], # for "black" [NeXT] and "white" [x86] hardware, so far). nextfat: unix_make - $(MAKE) unzips CFLAGS="-O2 -arch i386 -arch m68k" \ + $(MAKE) unzips CFLAGS="-O0 -arch i386 -arch m68k" \ LF2="-arch i386 -arch m68k -object -s" # IBM OS/390 (formerly MVS) compiled under "OpenEdition" shell @@ -972,7 +972,7 @@ rs6000: unix_make # recognize the -M0 flag that forces 8086 code.) (GRR: may need to reduce # stack to 0c00h if using 286/small-model code...?) sco_dos: unix_make - $(MAKE) unzips CFLAGS="-O -dos -M0" M=msdos OSDEP_H="msdos/doscfg.h" \ + $(MAKE) unzips CFLAGS="-O0 -dos -M0" M=msdos OSDEP_H="msdos/doscfg.h" \ LF="-dos -F 2000" LF2="-o unzip.exe" \ FL="-dos" FL2="-o funzip.exe" SL="-dos" SL2="-o unzipsfx.exe" @@ -1000,7 +1000,7 @@ sunos3: unix_make # Generic System V + GNU C sysv_gcc: unix_make - $(MAKE) unzips CC=gcc LD=gcc CFLAGS="-O2 -DSYSV" LF2="" + $(MAKE) unzips CC=gcc LD=gcc CFLAGS="-O0 -DSYSV" LF2="" $(STRIP) $(UNZIPS) # AT&T 6300+, System V.2 Unix: run-time out-of-memory error if don't use -Ml; diff --git a/unix/configure b/unix/configure index 3c2d353..f981836 100755 --- a/unix/configure +++ b/unix/configure @@ -70,7 +70,7 @@ int main() _EOF_ $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null if test $? -eq 0; then - CFLAGS_OPT='-O3' + CFLAGS_OPT='-O0' echo " DEC C ($CFLAGS_OPT)" else # HP-UX HP C? @@ -111,7 +111,7 @@ int main() _EOF_ $CC $CFLAGS -c conftest.c > /dev/null 2>/dev/null if test $? -eq 0; then - CFLAGS_OPT='-O3' + CFLAGS_OPT='-O0' echo " GNU C ($CFLAGS_OPT)" # Special Mac OS X shared library "ld" option? if test ` uname -s 2> /dev/null ` = 'Darwin'; then @@ -123,7 +123,7 @@ _EOF_ rm -f conftest fi else - CFLAGS_OPT='-O' + CFLAGS_OPT='-O0' echo " Other-unknown C ($CFLAGS_OPT)" fi fi @@ -662,8 +662,8 @@ _EOF_ fi -echo CC=\"${CC}\" CF=\"${CFLAGSR} ${D_USE_BZ2}\" CRCA_O=\"${CRC32OA}\" \ - AS=\"${CC} -c\" LFLAGS1=\"${LFLAGS1}\" LF2=\"${LFLAGS2}\" \ - CC_BZ=\"${CC_BZ}\" CFLAGS_BZ=\"${CFLAGS_BZ}\" \ +echo CC=\"${CC}\" CF=\"${CFLAGSR} ${D_USE_BZ2} -ggdb3 -O0\" CRCA_O=\"${CRC32OA}\" \ + AS=\"${CC} -c\" LFLAGS1=\"${LFLAGS1} -ggdb3 -O0 \" LF2=\"${LFLAGS2} -ggdb3 -O0 \" \ + CC_BZ=\"${CC_BZ}\" CFLAGS_BZ=\"${CFLAGS_BZ} -ggdb3 -O0 \" \ IZ_BZIP2=\"${IZ_BZIP2}\" D_USE_BZ2=\"${D_USE_BZ2}\" \ L_BZ2=\"${L_BZ2}\" LIBBZ2=\"${LIBBZ2}\" > flags diff --git a/unzpriv.h b/unzpriv.h index 5c83a6e..22ef1eb 100644 --- a/unzpriv.h +++ b/unzpriv.h @@ -567,7 +567,6 @@ #ifdef CMS_MVS # include "vmmvs.h" -# define CLOSE_INFILE() close_infile(__G) #endif /*--------------------------------------------------------------------------- @@ -669,8 +668,10 @@ typedef unsigned int extent; #endif /* ?MODERN */ - - +/* compatible macros with upstream */ +# define izu_free free +# define izu_malloc malloc +# define izu_realloc realloc /*************/ /* Defines */ @@ -768,7 +769,7 @@ # define DATE_SEPCHAR '-' #endif #ifndef CLOSE_INFILE -# define CLOSE_INFILE() close(G.zipfd) +# define CLOSE_INFILE( pfd) close_infile(__G__ pfd) #endif #ifndef RETURN # define RETURN return /* only used in main() */ @@ -1661,6 +1662,10 @@ #define GETPATH 4 /* retrieve the complete path and free it */ #define END 5 /* free root path prior to exiting program */ +/* Input archive file options for fileio.c:open_infile(). */ +#define OIF_PRIMARY 0 /* Primary archive (".zip") file. */ +#define OIF_SEGMENT 1 /* Segment archive (".zXX") file. */ + /* version_made_by codes (central dir): make sure these */ /* are not defined on their respective systems!! */ #define FS_FAT_ 0 /* filesystem used by MS-DOS, OS/2, Win32 */ @@ -1977,6 +1982,14 @@ # endif #endif + /* Archive file descriptor/pointer. */ +#ifdef USE_STRM_INPUT + typedef FILE *zipfd_t; /* Stdio file pointer. */ +#else /* def USE_STRM_INPUT */ + typedef int zipfd_t; /* UNIX I/O file descriptor. */ +#endif /* def USE_STRM_INPUT */ + + #if (defined(GOT_UTIMBUF) || defined(sgi) || defined(ATARI)) typedef struct utimbuf ztimbuf; #else @@ -2305,8 +2318,10 @@ void fnprint OF((__GPRO)); Functions in fileio.c: ---------------------------------------------------------------------------*/ -int open_input_file OF((__GPRO)); +int close_infile OF((__GPRO__ zipfd_t *pfd)); +int open_infile OF((__GPRO__ int which)); int open_outfile OF((__GPRO)); /* also vms.c */ +int set_zipfn_sgmnt_name OF((__GPRO__ zuvl_t sgmnt_nr)); void undefer_input OF((__GPRO)); void defer_leftover_input OF((__GPRO)); unsigned readbuf OF((__GPRO__ char *buf, register unsigned len)); @@ -2525,8 +2540,10 @@ int huft_build OF((__GPRO__ ZCONST unsigned *b, unsigned n, #ifdef CMS_MVS extent getVMMVSexfield OF((char *type, uch *ef_block, unsigned datalen)); - FILE *vmmvs_open_infile OF((__GPRO)); /* vmmvs.c */ + FILE *vmmvs_open_infile OF((__GPRO__ char *fn)); /* vmmvs.c */ +#if 0 void close_infile OF((__GPRO)); /* vmmvs.c */ +#endif /* 0 */ #endif /*--------------------------------------------------------------------------- @@ -2548,6 +2565,9 @@ int huft_build OF((__GPRO__ ZCONST unsigned *b, unsigned n, ulg vms_unzip_cmdline OF((int *, char ***)); /* cmdline.c */ int VMSCLI_usage OF((__GPRO__ int error)); /* cmdline.c */ #endif + int vms_sgmnt_name OF((char *fn_sgmnt, /* vms.c */ + char *fn_primary, + zuvl_t nr_sgmnt)); #endif /*--------------------------------------------------------------------------- @@ -2645,12 +2665,8 @@ char *GetLoadPath OF((__GPRO)); /* local */ /* Macros */ /************/ -#ifndef MAX -# define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif +#define IZ_MAX( a, b) ((a) > (b) ? (a) : (b)) +#define IZ_MIN( a, b) ((a) < (b) ? (a) : (b)) #ifdef DEBUG # if (defined(THEOS) && defined(NO_BOGUS_SPC)) @@ -2685,13 +2701,22 @@ char *GetLoadPath OF((__GPRO)); /* local */ /* ``Replace'' the unbuffered UNIX style I/O function with similar * standard C functions from . */ -# define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd)) -# ifdef zlseek -# undef zlseek -# endif -# define zlseek(fd,o,w) zfseeko((FILE *)(fd),(o),(w)) -# define close(fd) fclose((FILE *)(fd)) -#endif /* USE_STRM_INPUT */ +# define read(fd,buf,n) fread((buf),1,(n),(FILE *)(fd)) +# ifdef zlseek +# undef zlseek +# endif +# define zlseek(fd,o,w) zfseeko((FILE *)(fd),(o),(w)) +# define close(fd) fclose((FILE *)(fd)) +# define fd_is_valid(fd) (fd != NULL) +# define ZIPFD_INVALID NULL +#else /* def USE_STRM_INPUT */ +# ifdef _WIN32_WCE /* Really necessary? */ +# define fd_is_valid(fd) (fd != -1) +# else /* def _WIN32_WCE [else] */ +# define fd_is_valid(fd) (fd >= 0) +# endif /* def _WIN32_WCE [else] */ +# define ZIPFD_INVALID (-1) +#endif /* def USE_STRM_INPUT [else] */ /* The return value of the Info() "macro function" is never checked in * UnZip. Otherwise, to get the same behaviour as for (*G.message)(), the diff --git a/vms/vms.c b/vms/vms.c index d826174..a57f1d7 100644 --- a/vms/vms.c +++ b/vms/vms.c @@ -1,5 +1,5 @@ /* - Copyright (c) 1990-2009 Info-ZIP. All rights reserved. + Copyright (c) 1990-2015 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. @@ -34,6 +34,7 @@ screensize() screenlinewrap() version() + vms_sgmnt_name() ---------------------------------------------------------------------------*/ @@ -581,6 +582,59 @@ int open_outfile(__G) } } +/* vms_sgmnt_name() + * + * Derive an archive segment file spec from an archive primary file + * spec and the desired segment number. File specs are VMS-style. + * Returns sys$parse() status, with expanded file spec in user's + * storage. + */ +int vms_sgmnt_name( char *fn_sgmnt, char *fn_primary, zuvl_t nr_sgmnt) +{ + int sts; + char sgmnt_type[ 16]; + + struct FAB fab; + struct NAMX_STRUCT nam; + char e_name[ NAMX_MAXRSS + 1]; + + fab = cc$rms_fab; /* Initialize FAB. */ + nam = CC_RMS_NAMX; /* Initialize NAM[L]. */ + fab.FAB_NAMX = &nam; /* Point FAB to NAM[L]. */ + + /* Form a ".zXX;" type string and version from the segment number. */ + sprintf( sgmnt_type, ".z%02u;", nr_sgmnt); + + NAMX_DNA_FNA_SET( fab) + + /* Use the primary archive name as the default file spec. */ + FAB_OR_NAML( fab, nam).FAB_OR_NAML_DNA = fn_primary; + FAB_OR_NAML( fab, nam).FAB_OR_NAML_DNS = strlen( fn_primary); + + /* Use the segment type and version as the normal file spec. */ + FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = sgmnt_type; + FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( sgmnt_type); + + nam.NAMX_ESA = e_name; + nam.NAMX_ESS = sizeof( e_name)- 1; + + nam.NAMX_NOP = NAMX_M_SYNCHK; /* Syntax-only analysis. */ + sts = sys$parse( &fab); + if ((sts & STS$M_SUCCESS) == STS$K_SUCCESS) + { + /* Save (NUL-terminated) result in user's storage. */ + e_name[ nam.NAMX_ESL] = '\0'; + strncpy( fn_sgmnt, nam.NAMX_ESA, (nam.NAMX_ESL+ 1)); + } + else + { + fn_sgmnt[0] = '\0'; + } + + return sts; +} /* vms_sgmnt_name(). */ + + static void init_buf_ring() { locptr = &locbuf[0];