Rev 6725 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 1 | /* |
2 | Copyright (c) 1990-2009 Info-ZIP. All rights reserved. |
||
3 | |||
4 | See the accompanying file LICENSE, version 2009-Jan-02 or later |
||
5 | (the contents of which are also included in unzip.h) for terms of use. |
||
6 | If, for some reason, all these files are missing, the Info-ZIP license |
||
7 | also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html |
||
8 | */ |
||
9 | /*--------------------------------------------------------------------------- |
||
10 | |||
11 | fileio.c |
||
12 | |||
13 | This file contains routines for doing direct but relatively generic input/ |
||
14 | output, file-related sorts of things, plus some miscellaneous stuff. Most |
||
15 | of the stuff has to do with opening, closing, reading and/or writing files. |
||
16 | |||
17 | Contains: open_input_file() |
||
18 | open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM) |
||
19 | undefer_input() |
||
20 | defer_leftover_input() |
||
21 | readbuf() |
||
22 | readbyte() |
||
23 | fillinbuf() |
||
24 | seek_zipf() |
||
25 | flush() (non-VMS) |
||
26 | is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only) |
||
27 | disk_error() (non-VMS) |
||
28 | UzpMessagePrnt() |
||
29 | UzpMessageNull() (DLL only) |
||
30 | UzpInput() |
||
31 | UzpMorePause() |
||
32 | UzpPassword() (non-WINDLL) |
||
33 | handler() |
||
34 | dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS) |
||
35 | check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS) |
||
36 | do_string() |
||
37 | makeword() |
||
38 | makelong() |
||
39 | makeint64() |
||
40 | fzofft() |
||
41 | str2iso() (CRYPT && NEED_STR2ISO, only) |
||
42 | str2oem() (CRYPT && NEED_STR2OEM, only) |
||
43 | memset() (ZMEM only) |
||
44 | memcpy() (ZMEM only) |
||
45 | zstrnicmp() (NO_STRNICMP only) |
||
46 | zstat() (REGULUS only) |
||
47 | plastchar() (_MBCS only) |
||
48 | uzmbclen() (_MBCS && NEED_UZMBCLEN, only) |
||
49 | uzmbschr() (_MBCS && NEED_UZMBSCHR, only) |
||
50 | uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only) |
||
51 | fLoadFarString() (SMALL_MEM only) |
||
52 | fLoadFarStringSmall() (SMALL_MEM only) |
||
53 | fLoadFarStringSmall2() (SMALL_MEM only) |
||
54 | zfstrcpy() (SMALL_MEM only) |
||
55 | zfstrcmp() (SMALL_MEM && !(SFX || FUNZIP) only) |
||
56 | |||
57 | ---------------------------------------------------------------------------*/ |
||
58 | |||
59 | |||
60 | #define __FILEIO_C /* identifies this source module */ |
||
61 | #define UNZIP_INTERNAL |
||
62 | #include "unzip.h" |
||
63 | #ifdef WINDLL |
||
64 | # ifdef POCKET_UNZIP |
||
65 | # include "wince/intrface.h" |
||
66 | # else |
||
67 | # include "windll/windll.h" |
||
68 | # endif |
||
69 | # include |
||
70 | #endif |
||
71 | #include "crc32.h" |
||
72 | #include "crypt.h" |
||
73 | #include "ttyio.h" |
||
74 | |||
75 | /* setup of codepage conversion for decryption passwords */ |
||
76 | #if CRYPT |
||
77 | # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY)) |
||
78 | # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */ |
||
79 | # endif |
||
80 | # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY)) |
||
81 | # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */ |
||
82 | # endif |
||
83 | #endif |
||
84 | #include "ebcdic.h" /* definition/initialization of ebcdic[] */ |
||
85 | |||
86 | |||
87 | /* |
||
88 | Note: Under Windows, the maximum size of the buffer that can be used |
||
89 | with any of the *printf calls is 16,384, so win_fprintf was used to |
||
90 | feed the fprintf clone no more than 16K chunks at a time. This should |
||
91 | be valid for anything up to 64K (and probably beyond, assuming your |
||
92 | buffers are that big). |
||
93 | */ |
||
94 | #ifdef WINDLL |
||
95 | # define WriteError(buf,len,strm) \ |
||
96 | (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len)) |
||
97 | #else /* !WINDLL */ |
||
98 | # ifdef USE_FWRITE |
||
99 | # define WriteError(buf,len,strm) \ |
||
100 | ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len)) |
||
101 | # else |
||
102 | # define WriteError(buf,len,strm) \ |
||
103 | ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len)) |
||
104 | # endif |
||
105 | #endif /* ?WINDLL */ |
||
106 | |||
107 | /* |
||
108 | 2005-09-16 SMS. |
||
109 | On VMS, when output is redirected to a file, as in a command like |
||
110 | "PIPE UNZIP -v > X.OUT", the output file is created with VFC record |
||
111 | format, and multiple calls to write() or fwrite() will produce multiple |
||
112 | records, even when there's no newline terminator in the buffer. |
||
113 | The result is unsightly output with spurious newlines. Using fprintf() |
||
114 | instead of write() here, and disabling a fflush(stdout) in UzpMessagePrnt() |
||
115 | below, together seem to solve the problem. |
||
116 | |||
117 | According to the C RTL manual, "The write and decc$record_write |
||
118 | functions always generate at least one record." Also, "[T]he fwrite |
||
119 | function always generates at least |
||
120 | "fwrite(buf, len, 1, strm)" is much better ("1" record) than |
||
121 | "fwrite(buf, 1, len, strm)" ("len" (1-character) records, _really_ |
||
122 | ugly), but neither is better than write(). Similarly, "The fflush |
||
123 | function always generates a record if there is unwritten data in the |
||
124 | buffer." Apparently fprintf() buffers the stuff somewhere, and puts |
||
125 | out a record (only) when it sees a newline. |
||
126 | */ |
||
127 | #ifdef VMS |
||
128 | # define WriteTxtErr(buf,len,strm) \ |
||
129 | ((extent)fprintf(strm, "%.*s", len, buf) != (extent)(len)) |
||
130 | #else |
||
131 | # define WriteTxtErr(buf,len,strm) WriteError(buf,len,strm) |
||
132 | #endif |
||
133 | |||
134 | #if (defined(USE_DEFLATE64) && defined(__16BIT__)) |
||
135 | static int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink)); |
||
136 | #endif |
||
137 | #ifdef VMS_TEXT_CONV |
||
138 | static int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len)); |
||
139 | #endif |
||
140 | static int disk_error OF((__GPRO)); |
||
141 | |||
142 | |||
143 | /****************************/ |
||
144 | /* Strings used in fileio.c */ |
||
145 | /****************************/ |
||
146 | |||
147 | static ZCONST char Far CannotOpenZipfile[] = |
||
148 | "error: cannot open zipfile [ %s ]\n %s\n"; |
||
149 | |||
150 | #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) |
||
151 | #if (!defined(TANDEM)) |
||
152 | #if (defined(ATH_BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32)) |
||
153 | static ZCONST char Far CannotDeleteOldFile[] = |
||
154 | "error: cannot delete old %s\n %s\n"; |
||
155 | #ifdef UNIXBACKUP |
||
156 | static ZCONST char Far CannotRenameOldFile[] = |
||
157 | "error: cannot rename old %s\n %s\n"; |
||
158 | static ZCONST char Far BackupSuffix[] = "~"; |
||
159 | #endif |
||
160 | #endif /* ATH_BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */ |
||
161 | #ifdef NOVELL_BUG_FAILSAFE |
||
162 | static ZCONST char Far NovellBug[] = |
||
163 | "error: %s: stat() says does not exist, but fopen() found anyway\n"; |
||
164 | #endif |
||
165 | static ZCONST char Far CannotCreateFile[] = |
||
166 | "error: cannot create %s\n %s\n"; |
||
167 | #endif /* !TANDEM */ |
||
168 | #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ |
||
169 | |||
170 | static ZCONST char Far ReadError[] = "error: zipfile read error\n"; |
||
171 | static ZCONST char Far FilenameTooLongTrunc[] = |
||
172 | "warning: filename too long--truncating.\n"; |
||
173 | #ifdef UNICODE_SUPPORT |
||
174 | static ZCONST char Far UFilenameTooLongTrunc[] = |
||
175 | "warning: Converted unicode filename too long--truncating.\n"; |
||
176 | #endif |
||
177 | static ZCONST char Far ExtraFieldTooLong[] = |
||
178 | "warning: extra field too long (%d). Ignoring...\n"; |
||
179 | |||
180 | #ifdef WINDLL |
||
181 | static ZCONST char Far DiskFullQuery[] = |
||
182 | "%s: write error (disk full?).\n"; |
||
183 | #else |
||
184 | static ZCONST char Far DiskFullQuery[] = |
||
185 | "%s: write error (disk full?). Continue? (y/n/^C) "; |
||
186 | static ZCONST char Far ZipfileCorrupt[] = |
||
187 | "error: zipfile probably corrupt (%s)\n"; |
||
188 | # ifdef SYMLINKS |
||
189 | static ZCONST char Far FileIsSymLink[] = |
||
190 | "%s exists and is a symbolic link%s.\n"; |
||
191 | # endif |
||
192 | # ifdef MORE |
||
193 | static ZCONST char Far MorePrompt[] = "--More--(%lu)"; |
||
194 | # endif |
||
195 | static ZCONST char Far QuitPrompt[] = |
||
196 | "--- Press `Q' to quit, or any other key to continue ---"; |
||
197 | static ZCONST char Far HidePrompt[] = /* "\r \r"; */ |
||
198 | "\r \r"; |
||
199 | # if CRYPT |
||
200 | # ifdef MACOS |
||
201 | /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */ |
||
202 | static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: "; |
||
203 | # else |
||
204 | static ZCONST char Far PasswPrompt[] = "[%s] %s password: "; |
||
205 | # endif |
||
206 | static ZCONST char Far PasswPrompt2[] = "Enter password: "; |
||
207 | static ZCONST char Far PasswRetry[] = "password incorrect--reenter: "; |
||
208 | # endif /* CRYPT */ |
||
209 | #endif /* !WINDLL */ |
||
210 | |||
211 | |||
212 | |||
213 | |||
214 | |||
215 | /******************************/ |
||
216 | /* Function open_input_file() */ |
||
217 | /******************************/ |
||
218 | |||
219 | int open_input_file(__G) /* return 1 if open failed */ |
||
220 | __GDEF |
||
221 | { |
||
222 | /* |
||
223 | * open the zipfile for reading and in BINARY mode to prevent cr/lf |
||
224 | * translation, which would corrupt the bitstreams |
||
225 | */ |
||
226 | |||
227 | #ifdef VMS |
||
228 | G.zipfd = open(G.zipfn, O_RDONLY, 0, OPNZIP_RMS_ARGS); |
||
229 | #else /* !VMS */ |
||
230 | #ifdef MACOS |
||
231 | G.zipfd = open(G.zipfn, 0); |
||
232 | #else /* !MACOS */ |
||
233 | #ifdef CMS_MVS |
||
234 | G.zipfd = vmmvs_open_infile(__G); |
||
235 | #else /* !CMS_MVS */ |
||
236 | #ifdef USE_STRM_INPUT |
||
237 | G.zipfd = fopen(G.zipfn, FOPR); |
||
238 | #else /* !USE_STRM_INPUT */ |
||
239 | G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY); |
||
240 | #endif /* ?USE_STRM_INPUT */ |
||
241 | #endif /* ?CMS_MVS */ |
||
242 | #endif /* ?MACOS */ |
||
243 | #endif /* ?VMS */ |
||
244 | |||
245 | #ifdef USE_STRM_INPUT |
||
246 | if (G.zipfd == NULL) |
||
247 | #else |
||
248 | /* if (G.zipfd < 0) */ /* no good for Windows CE port */ |
||
249 | if (G.zipfd == -1) |
||
250 | #endif |
||
251 | { |
||
252 | Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile), |
||
253 | G.zipfn, strerror(errno))); |
||
254 | return 1; |
||
255 | } |
||
256 | return 0; |
||
257 | |||
258 | } /* end function open_input_file() */ |
||
259 | |||
260 | |||
261 | |||
262 | |||
263 | #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS)) |
||
264 | #if (!defined(TANDEM)) |
||
265 | |||
266 | /***************************/ |
||
267 | /* Function open_outfile() */ |
||
268 | /***************************/ |
||
269 | |||
270 | int open_outfile(__G) /* return 1 if fail */ |
||
271 | __GDEF |
||
272 | { |
||
273 | #ifdef DLL |
||
274 | if (G.redirect_data) |
||
275 | return (redirect_outfile(__G) == FALSE); |
||
276 | #endif |
||
277 | #ifdef QDOS |
||
278 | QFilename(__G__ G.filename); |
||
279 | #endif |
||
280 | #if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_THS_UNX)) |
||
281 | #ifdef BORLAND_STAT_BUG |
||
282 | /* Borland 5.0's stat() barfs if the filename has no extension and the |
||
283 | * file doesn't exist. */ |
||
284 | if (access(G.filename, 0) == -1) { |
||
285 | FILE *tmp = fopen(G.filename, "wb+"); |
||
286 | |||
287 | /* file doesn't exist, so create a dummy file to keep stat() from |
||
288 | * failing (will be over-written anyway) */ |
||
289 | fputc('0', tmp); /* just to have something in the file */ |
||
290 | fclose(tmp); |
||
291 | } |
||
292 | #endif /* BORLAND_STAT_BUG */ |
||
293 | #ifdef SYMLINKS |
||
294 | if (SSTAT(G.filename, &G.statbuf) == 0 || |
||
295 | lstat(G.filename, &G.statbuf) == 0) |
||
296 | #else |
||
297 | if (SSTAT(G.filename, &G.statbuf) == 0) |
||
298 | #endif /* ?SYMLINKS */ |
||
299 | { |
||
300 | Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n", |
||
301 | FnFilter1(G.filename))); |
||
302 | #ifdef UNIXBACKUP |
||
303 | if (uO.B_flag) { /* do backup */ |
||
304 | char *tname; |
||
305 | z_stat tmpstat; |
||
306 | int blen, flen, tlen; |
||
307 | |||
308 | blen = strlen(BackupSuffix); |
||
309 | flen = strlen(G.filename); |
||
310 | tlen = flen + blen + 6; /* includes space for 5 digits */ |
||
311 | if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */ |
||
312 | tname = (char *)malloc(FILNAMSIZ); |
||
313 | if (tname == NULL) |
||
314 | return 1; /* in case we run out of space */ |
||
315 | tlen = FILNAMSIZ - 1 - blen; |
||
316 | strcpy(tname, G.filename); /* make backup name */ |
||
317 | tname[tlen] = '\0'; |
||
318 | if (flen > tlen) flen = tlen; |
||
319 | tlen = FILNAMSIZ; |
||
320 | } else { |
||
321 | tname = (char *)malloc(tlen); |
||
322 | if (tname == NULL) |
||
323 | return 1; /* in case we run out of space */ |
||
324 | strcpy(tname, G.filename); /* make backup name */ |
||
325 | } |
||
326 | strcpy(tname+flen, BackupSuffix); |
||
327 | |||
328 | if (IS_OVERWRT_ALL) { |
||
329 | /* If there is a previous backup file, delete it, |
||
330 | * otherwise the following rename operation may fail. |
||
331 | */ |
||
332 | if (SSTAT(tname, &tmpstat) == 0) |
||
333 | unlink(tname); |
||
334 | } else { |
||
335 | /* Check if backupname exists, and, if it's true, try |
||
336 | * appending numbers of up to 5 digits (or the maximum |
||
337 | * "unsigned int" number on 16-bit systems) to the |
||
338 | * BackupSuffix, until an unused name is found. |
||
339 | */ |
||
340 | unsigned maxtail, i; |
||
341 | char *numtail = tname + flen + blen; |
||
342 | |||
343 | /* take account of the "unsigned" limit on 16-bit systems: */ |
||
344 | maxtail = ( ((~0) >= 99999L) ? 99999 : (~0) ); |
||
345 | switch (tlen - flen - blen - 1) { |
||
346 | case 4: maxtail = 9999; break; |
||
347 | case 3: maxtail = 999; break; |
||
348 | case 2: maxtail = 99; break; |
||
349 | case 1: maxtail = 9; break; |
||
350 | case 0: maxtail = 0; break; |
||
351 | } |
||
352 | /* while filename exists */ |
||
353 | for (i = 0; (i < maxtail) && (SSTAT(tname, &tmpstat) == 0);) |
||
354 | sprintf(numtail,"%u", ++i); |
||
355 | } |
||
356 | |||
357 | if (rename(G.filename, tname) != 0) { /* move file */ |
||
358 | Info(slide, 0x401, ((char *)slide, |
||
359 | LoadFarString(CannotRenameOldFile), |
||
360 | FnFilter1(G.filename), strerror(errno))); |
||
361 | free(tname); |
||
362 | return 1; |
||
363 | } |
||
364 | Trace((stderr, "open_outfile: %s now renamed into %s\n", |
||
365 | FnFilter1(G.filename), FnFilter2(tname))); |
||
366 | free(tname); |
||
367 | } else |
||
368 | #endif /* UNIXBACKUP */ |
||
369 | { |
||
370 | #ifdef DOS_FLX_OS2_W32 |
||
371 | if (!(G.statbuf.st_mode & S_IWRITE)) { |
||
372 | Trace((stderr, |
||
373 | "open_outfile: existing file %s is read-only\n", |
||
374 | FnFilter1(G.filename))); |
||
375 | chmod(G.filename, S_IREAD | S_IWRITE); |
||
376 | Trace((stderr, "open_outfile: %s now writable\n", |
||
377 | FnFilter1(G.filename))); |
||
378 | } |
||
379 | #endif /* DOS_FLX_OS2_W32 */ |
||
380 | #ifdef NLM |
||
381 | /* Give the file read/write permission (non-POSIX shortcut) */ |
||
382 | chmod(G.filename, 0); |
||
383 | #endif /* NLM */ |
||
384 | if (unlink(G.filename) != 0) { |
||
385 | Info(slide, 0x401, ((char *)slide, |
||
386 | LoadFarString(CannotDeleteOldFile), |
||
387 | FnFilter1(G.filename), strerror(errno))); |
||
388 | return 1; |
||
389 | } |
||
390 | Trace((stderr, "open_outfile: %s now deleted\n", |
||
391 | FnFilter1(G.filename))); |
||
392 | } |
||
393 | } |
||
394 | #endif /* DOS_FLX_NLM_OS2_W32 || ATH_BEO_THS_UNX */ |
||
395 | #ifdef RISCOS |
||
396 | if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) { |
||
397 | Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), |
||
398 | FnFilter1(G.filename), strerror(errno))); |
||
399 | return 1; |
||
400 | } |
||
401 | #endif /* RISCOS */ |
||
402 | #ifdef TOPS20 |
||
403 | char *tfilnam; |
||
404 | |||
405 | if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL) |
||
406 | return 1; |
||
407 | strcpy(tfilnam, G.filename); |
||
408 | upper(tfilnam); |
||
409 | enquote(tfilnam); |
||
410 | if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) { |
||
411 | Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), |
||
412 | tfilnam, strerror(errno))); |
||
413 | free(tfilnam); |
||
414 | return 1; |
||
415 | } |
||
416 | free(tfilnam); |
||
417 | #else /* !TOPS20 */ |
||
418 | #ifdef MTS |
||
419 | if (uO.aflag) |
||
420 | G.outfile = zfopen(G.filename, FOPWT); |
||
421 | else |
||
422 | G.outfile = zfopen(G.filename, FOPW); |
||
423 | if (G.outfile == (FILE *)NULL) { |
||
424 | Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile), |
||
425 | FnFilter1(G.filename), strerror(errno))); |
||
426 | return 1; |
||
427 | } |
||
428 | #else /* !MTS */ |
||
429 | #ifdef DEBUG |
||
430 | Info(slide, 1, ((char *)slide, |
||
431 | "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename))); |
||
432 | if ((G.outfile = zfopen(G.filename, FOPR)) == (FILE *)NULL) |
||
433 | Info(slide, 1, ((char *)slide, |
||
434 | "open_outfile: fopen(%s) for reading failed: does not exist\n", |
||
435 | FnFilter1(G.filename))); |
||
436 | else { |
||
437 | Info(slide, 1, ((char *)slide, |
||
438 | "open_outfile: fopen(%s) for reading succeeded: file exists\n", |
||
439 | FnFilter1(G.filename))); |
||
440 | fclose(G.outfile); |
||
441 | } |
||
442 | #endif /* DEBUG */ |
||
443 | #ifdef NOVELL_BUG_FAILSAFE |
||
444 | if (G.dne && ((G.outfile = zfopen(G.filename, FOPR)) != (FILE *)NULL)) { |
||
445 | Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug), |
||
446 | FnFilter1(G.filename))); |
||
447 | fclose(G.outfile); |
||
448 | return 1; /* with "./" fix in checkdir(), should never reach here */ |
||
449 | } |
||
450 | #endif /* NOVELL_BUG_FAILSAFE */ |
||
451 | Trace((stderr, "open_outfile: doing fopen(%s) for writing\n", |
||
452 | FnFilter1(G.filename))); |
||
453 | { |
||
454 | #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM) |
||
455 | mode_t umask_sav = umask(0077); |
||
456 | #endif |
||
457 | #if defined(SYMLINKS) || defined(QLZIP) |
||
458 | /* These features require the ability to re-read extracted data from |
||
459 | the output files. Output files are created with Read&Write access. |
||
460 | */ |
||
461 | G.outfile = zfopen(G.filename, FOPWR); |
||
462 | #else |
||
463 | G.outfile = zfopen(G.filename, FOPW); |
||
464 | #endif |
||
465 | #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM) |
||
466 | umask(umask_sav); |
||
467 | #endif |
||
468 | } |
||
469 | if (G.outfile == (FILE *)NULL) { |
||
470 | Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile), |
||
471 | FnFilter1(G.filename), strerror(errno))); |
||
472 | return 1; |
||
473 | } |
||
474 | Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n", |
||
475 | FnFilter1(G.filename))); |
||
476 | #endif /* !MTS */ |
||
477 | #endif /* !TOPS20 */ |
||
478 | |||
479 | #ifdef USE_FWRITE |
||
480 | #ifdef DOS_NLM_OS2_W32 |
||
481 | /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */ |
||
482 | setbuf(G.outfile, (char *)NULL); /* make output unbuffered */ |
||
483 | #else /* !DOS_NLM_OS2_W32 */ |
||
484 | #ifndef RISCOS |
||
485 | #ifdef _IOFBF /* make output fully buffered (works just about like write()) */ |
||
486 | setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE); |
||
487 | #else |
||
488 | setbuf(G.outfile, (char *)slide); |
||
489 | #endif |
||
490 | #endif /* !RISCOS */ |
||
491 | #endif /* ?DOS_NLM_OS2_W32 */ |
||
492 | #endif /* USE_FWRITE */ |
||
493 | #ifdef OS2_W32 |
||
494 | /* preallocate the final file size to prevent file fragmentation */ |
||
495 | SetFileSize(G.outfile, G.lrec.ucsize); |
||
496 | #endif |
||
497 | return 0; |
||
498 | |||
499 | } /* end function open_outfile() */ |
||
500 | |||
501 | #endif /* !TANDEM */ |
||
502 | #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */ |
||
503 | |||
504 | |||
505 | |||
506 | |||
507 | |||
508 | /* |
||
509 | * These functions allow NEXTBYTE to function without needing two bounds |
||
510 | * checks. Call defer_leftover_input() if you ever have filled G.inbuf |
||
511 | * by some means other than readbyte(), and you then want to start using |
||
512 | * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call |
||
513 | * undefer_input(). For example, extract_or_test_member brackets its |
||
514 | * central section that does the decompression with these two functions. |
||
515 | * If you need to check the number of bytes remaining in the current |
||
516 | * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize. |
||
517 | */ |
||
518 | |||
519 | /****************************/ |
||
520 | /* function undefer_input() */ |
||
521 | /****************************/ |
||
522 | |||
523 | void undefer_input(__G) |
||
524 | __GDEF |
||
525 | { |
||
526 | if (G.incnt > 0) |
||
527 | G.csize += G.incnt; |
||
528 | if (G.incnt_leftover > 0) { |
||
529 | /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int: |
||
530 | * This condition was checked when G.incnt_leftover was set > 0 in |
||
531 | * defer_leftover_input(), and it is NOT allowed to touch G.csize |
||
532 | * before calling undefer_input() when (G.incnt_leftover > 0) |
||
533 | * (single exception: see read_byte()'s "G.csize <= 0" handling) !! |
||
534 | */ |
||
535 | G.incnt = G.incnt_leftover + (int)G.csize; |
||
536 | G.inptr = G.inptr_leftover - (int)G.csize; |
||
537 | G.incnt_leftover = 0; |
||
538 | } else if (G.incnt < 0) |
||
539 | G.incnt = 0; |
||
540 | } /* end function undefer_input() */ |
||
541 | |||
542 | |||
543 | |||
544 | |||
545 | |||
546 | /***********************************/ |
||
547 | /* function defer_leftover_input() */ |
||
548 | /***********************************/ |
||
549 | |||
550 | void defer_leftover_input(__G) |
||
551 | __GDEF |
||
552 | { |
||
553 | if ((zoff_t)G.incnt > G.csize) { |
||
554 | /* (G.csize < MAXINT), we can safely cast it to int !! */ |
||
555 | if (G.csize < 0L) |
||
556 | G.csize = 0L; |
||
557 | G.inptr_leftover = G.inptr + (int)G.csize; |
||
558 | G.incnt_leftover = G.incnt - (int)G.csize; |
||
559 | G.incnt = (int)G.csize; |
||
560 | } else |
||
561 | G.incnt_leftover = 0; |
||
562 | G.csize -= G.incnt; |
||
563 | } /* end function defer_leftover_input() */ |
||
564 | |||
565 | |||
566 | |||
567 | |||
568 | |||
569 | /**********************/ |
||
570 | /* Function readbuf() */ |
||
571 | /**********************/ |
||
572 | |||
573 | unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */ |
||
574 | __GDEF |
||
575 | char *buf; |
||
576 | register unsigned size; |
||
577 | { |
||
578 | register unsigned count; |
||
579 | unsigned n; |
||
580 | |||
581 | n = size; |
||
582 | while (size) { |
||
583 | if (G.incnt <= 0) { |
||
584 | if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) |
||
585 | return (n-size); |
||
586 | else if (G.incnt < 0) { |
||
587 | /* another hack, but no real harm copying same thing twice */ |
||
588 | (*G.message)((zvoid *)&G, |
||
589 | (uch *)LoadFarString(ReadError), /* CANNOT use slide */ |
||
590 | (ulg)strlen(LoadFarString(ReadError)), 0x401); |
||
591 | return 0; /* discarding some data; better than lock-up */ |
||
592 | } |
||
593 | /* buffer ALWAYS starts on a block boundary: */ |
||
594 | G.cur_zipfile_bufstart += INBUFSIZ; |
||
595 | G.inptr = G.inbuf; |
||
596 | } |
||
597 | count = MIN(size, (unsigned)G.incnt); |
||
598 | memcpy(buf, G.inptr, count); |
||
599 | buf += count; |
||
600 | G.inptr += count; |
||
601 | G.incnt -= count; |
||
602 | size -= count; |
||
603 | } |
||
604 | return n; |
||
605 | |||
606 | } /* end function readbuf() */ |
||
607 | |||
608 | |||
609 | |||
610 | |||
611 | |||
612 | /***********************/ |
||
613 | /* Function readbyte() */ |
||
614 | /***********************/ |
||
615 | |||
616 | int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */ |
||
617 | __GDEF |
||
618 | { |
||
619 | if (G.mem_mode) |
||
620 | return EOF; |
||
621 | if (G.csize <= 0) { |
||
622 | G.csize--; /* for tests done after exploding */ |
||
623 | G.incnt = 0; |
||
624 | return EOF; |
||
625 | } |
||
626 | if (G.incnt <= 0) { |
||
627 | if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) { |
||
628 | return EOF; |
||
629 | } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */ |
||
630 | /* another hack, but no real harm copying same thing twice */ |
||
631 | (*G.message)((zvoid *)&G, |
||
632 | (uch *)LoadFarString(ReadError), |
||
633 | (ulg)strlen(LoadFarString(ReadError)), 0x401); |
||
634 | echon(); |
||
635 | #ifdef WINDLL |
||
636 | longjmp(dll_error_return, 1); |
||
637 | #else |
||
638 | DESTROYGLOBALS(); |
||
639 | EXIT(PK_BADERR); /* totally bailing; better than lock-up */ |
||
640 | #endif |
||
641 | } |
||
642 | G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */ |
||
643 | G.inptr = G.inbuf; |
||
644 | defer_leftover_input(__G); /* decrements G.csize */ |
||
645 | } |
||
646 | |||
647 | #if CRYPT |
||
648 | if (G.pInfo->encrypted) { |
||
649 | uch *p; |
||
650 | int n; |
||
651 | |||
652 | /* This was previously set to decrypt one byte beyond G.csize, when |
||
653 | * incnt reached that far. GRR said, "but it's required: why?" This |
||
654 | * was a bug in fillinbuf() -- was it also a bug here? |
||
655 | */ |
||
656 | for (n = G.incnt, p = G.inptr; n--; p++) |
||
657 | zdecode(*p); |
||
658 | } |
||
659 | #endif /* CRYPT */ |
||
660 | |||
661 | --G.incnt; |
||
662 | return *G.inptr++; |
||
663 | |||
664 | } /* end function readbyte() */ |
||
665 | |||
666 | |||
667 | |||
668 | |||
669 | |||
670 | #if defined(USE_ZLIB) || defined(USE_BZIP2) |
||
671 | |||
672 | /************************/ |
||
673 | /* Function fillinbuf() */ |
||
674 | /************************/ |
||
675 | |||
676 | int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */ |
||
677 | __GDEF |
||
678 | { |
||
679 | if (G.mem_mode || |
||
680 | (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) |
||
681 | return 0; |
||
682 | G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */ |
||
683 | G.inptr = G.inbuf; |
||
684 | defer_leftover_input(__G); /* decrements G.csize */ |
||
685 | |||
686 | #if CRYPT |
||
687 | if (G.pInfo->encrypted) { |
||
688 | uch *p; |
||
689 | int n; |
||
690 | |||
691 | for (n = G.incnt, p = G.inptr; n--; p++) |
||
692 | zdecode(*p); |
||
693 | } |
||
694 | #endif /* CRYPT */ |
||
695 | |||
696 | return G.incnt; |
||
697 | |||
698 | } /* end function fillinbuf() */ |
||
699 | |||
700 | #endif /* USE_ZLIB || USE_BZIP2 */ |
||
701 | |||
702 | |||
703 | |||
704 | |||
705 | |||
706 | /************************/ |
||
707 | /* Function seek_zipf() */ |
||
708 | /************************/ |
||
709 | |||
710 | int seek_zipf(__G__ abs_offset) |
||
711 | __GDEF |
||
712 | zoff_t abs_offset; |
||
713 | { |
||
714 | /* |
||
715 | * Seek to the block boundary of the block which includes abs_offset, |
||
716 | * then read block into input buffer and set pointers appropriately. |
||
717 | * If block is already in the buffer, just set the pointers. This function |
||
718 | * is used by do_seekable (process.c), extract_or_test_entrylist (extract.c) |
||
719 | * and do_string (fileio.c). Also, a slightly modified version is embedded |
||
720 | * within extract_or_test_entrylist (extract.c). readbyte() and readbuf() |
||
721 | * (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the |
||
722 | * "proper offset" (i.e., if there were no extra bytes prepended); |
||
723 | * cur_zipfile_bufstart contains the corrected offset. |
||
724 | * |
||
725 | * Since seek_zipf() is never used during decompression, it is safe to |
||
726 | * use the slide[] buffer for the error message. |
||
727 | * |
||
728 | * returns PK error codes: |
||
729 | * PK_BADERR if effective offset in zipfile is negative |
||
730 | * PK_EOF if seeking past end of zipfile |
||
731 | * PK_OK when seek was successful |
||
732 | */ |
||
733 | zoff_t request = abs_offset + G.extra_bytes; |
||
734 | zoff_t inbuf_offset = request % INBUFSIZ; |
||
735 | zoff_t bufstart = request - inbuf_offset; |
||
736 | |||
737 | if (request < 0) { |
||
738 | Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg), |
||
739 | G.zipfn, LoadFarString(ReportMsg))); |
||
740 | return(PK_BADERR); |
||
741 | } else if (bufstart != G.cur_zipfile_bufstart) { |
||
742 | Trace((stderr, |
||
743 | "fpos_zip: abs_offset = %s, G.extra_bytes = %s\n", |
||
744 | FmZofft(abs_offset, NULL, NULL), |
||
745 | FmZofft(G.extra_bytes, NULL, NULL))); |
||
746 | #ifdef USE_STRM_INPUT |
||
747 | zfseeko(G.zipfd, bufstart, SEEK_SET); |
||
748 | G.cur_zipfile_bufstart = zftello(G.zipfd); |
||
749 | #else /* !USE_STRM_INPUT */ |
||
750 | G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET); |
||
751 | #endif /* ?USE_STRM_INPUT */ |
||
752 | Trace((stderr, |
||
753 | " request = %s, (abs+extra) = %s, inbuf_offset = %s\n", |
||
754 | FmZofft(request, NULL, NULL), |
||
755 | FmZofft((abs_offset+G.extra_bytes), NULL, NULL), |
||
756 | FmZofft(inbuf_offset, NULL, NULL))); |
||
757 | Trace((stderr, " bufstart = %s, cur_zipfile_bufstart = %s\n", |
||
758 | FmZofft(bufstart, NULL, NULL), |
||
759 | FmZofft(G.cur_zipfile_bufstart, NULL, NULL))); |
||
760 | if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) |
||
761 | return(PK_EOF); |
||
762 | G.incnt -= (int)inbuf_offset; |
||
763 | G.inptr = G.inbuf + (int)inbuf_offset; |
||
764 | } else { |
||
765 | G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset; |
||
766 | G.inptr = G.inbuf + (int)inbuf_offset; |
||
767 | } |
||
768 | return(PK_OK); |
||
769 | } /* end function seek_zipf() */ |
||
770 | |||
771 | |||
772 | |||
773 | |||
774 | |||
775 | #ifndef VMS /* for VMS use code in vms.c */ |
||
776 | |||
777 | /********************/ |
||
778 | /* Function flush() */ /* returns PK error codes: */ |
||
779 | /********************/ /* if tflag => always 0; PK_DISK if write error */ |
||
780 | |||
781 | int flush(__G__ rawbuf, size, unshrink) |
||
782 | __GDEF |
||
783 | uch *rawbuf; |
||
784 | ulg size; |
||
785 | int unshrink; |
||
786 | #if (defined(USE_DEFLATE64) && defined(__16BIT__)) |
||
787 | { |
||
788 | int ret; |
||
789 | |||
790 | /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions |
||
791 | * cannot handle writes of 64k blocks at once. For these systems, the |
||
792 | * blocks to flush are split into pieces of 32k or less. |
||
793 | */ |
||
794 | while (size > 0x8000L) { |
||
795 | ret = partflush(__G__ rawbuf, 0x8000L, unshrink); |
||
796 | if (ret != PK_OK) |
||
797 | return ret; |
||
798 | size -= 0x8000L; |
||
799 | rawbuf += (extent)0x8000; |
||
800 | } |
||
801 | return partflush(__G__ rawbuf, size, unshrink); |
||
802 | } /* end function flush() */ |
||
803 | |||
804 | |||
805 | /************************/ |
||
806 | /* Function partflush() */ /* returns PK error codes: */ |
||
807 | /************************/ /* if tflag => always 0; PK_DISK if write error */ |
||
808 | |||
809 | static int partflush(__G__ rawbuf, size, unshrink) |
||
810 | __GDEF |
||
811 | uch *rawbuf; /* cannot be ZCONST, gets passed to (*G.message)() */ |
||
812 | ulg size; |
||
813 | int unshrink; |
||
814 | #endif /* USE_DEFLATE64 && __16BIT__ */ |
||
815 | { |
||
816 | register uch *p; |
||
817 | register uch *q; |
||
818 | uch *transbuf; |
||
819 | #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) |
||
820 | ulg transbufsiz; |
||
821 | #endif |
||
822 | /* static int didCRlast = FALSE; moved to globals.h */ |
||
823 | |||
824 | |||
825 | /*--------------------------------------------------------------------------- |
||
826 | Compute the CRC first; if testing or if disk is full, that's it. |
||
827 | ---------------------------------------------------------------------------*/ |
||
828 | |||
829 | G.crc32val = crc32(G.crc32val, rawbuf, (extent)size); |
||
830 | |||
831 | #ifdef DLL |
||
832 | if ((G.statreportcb != NULL) && |
||
833 | (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL)) |
||
834 | return IZ_CTRLC; /* cancel operation by user request */ |
||
835 | #endif |
||
836 | |||
837 | if (uO.tflag || size == 0L) /* testing or nothing to write: all done */ |
||
838 | return PK_OK; |
||
839 | |||
840 | if (G.disk_full) |
||
841 | return PK_DISK; /* disk already full: ignore rest of file */ |
||
842 | |||
843 | /*--------------------------------------------------------------------------- |
||
844 | Write the bytes rawbuf[0..size-1] to the output device, first converting |
||
845 | end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT |
||
846 | defined, outbuf is assumed to be at least as large as rawbuf and is not |
||
847 | necessarily checked for overflow. |
||
848 | ---------------------------------------------------------------------------*/ |
||
849 | |||
850 | if (!G.pInfo->textmode) { /* write raw binary data */ |
||
851 | /* GRR: note that for standard MS-DOS compilers, size argument to |
||
852 | * fwrite() can never be more than 65534, so WriteError macro will |
||
853 | * have to be rewritten if size can ever be that large. For now, |
||
854 | * never more than 32K. Also note that write() returns an int, which |
||
855 | * doesn't necessarily limit size to 32767 bytes if write() is used |
||
856 | * on 16-bit systems but does make it more of a pain; however, because |
||
857 | * at least MSC 5.1 has a lousy implementation of fwrite() (as does |
||
858 | * DEC Ultrix cc), write() is used anyway. |
||
859 | */ |
||
860 | #ifdef DLL |
||
861 | if (G.redirect_data) { |
||
862 | #ifdef NO_SLIDE_REDIR |
||
863 | if (writeToMemory(__G__ rawbuf, (extent)size)) return PK_ERR; |
||
864 | #else |
||
865 | writeToMemory(__G__ rawbuf, (extent)size); |
||
866 | #endif |
||
867 | } else |
||
868 | #endif |
||
869 | if (!uO.cflag && WriteError(rawbuf, size, G.outfile)) |
||
870 | return disk_error(__G); |
||
871 | else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0)) |
||
872 | return PK_OK; |
||
873 | } else { /* textmode: aflag is true */ |
||
874 | if (unshrink) { |
||
875 | /* rawbuf = outbuf */ |
||
876 | transbuf = G.outbuf2; |
||
877 | #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) |
||
878 | transbufsiz = TRANSBUFSIZ; |
||
879 | #endif |
||
880 | } else { |
||
881 | /* rawbuf = slide */ |
||
882 | transbuf = G.outbuf; |
||
883 | #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV)) |
||
884 | transbufsiz = OUTBUFSIZ; |
||
885 | Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", |
||
886 | (unsigned)OUTBUFSIZ)); |
||
887 | #endif |
||
888 | } |
||
889 | if (G.newfile) { |
||
890 | #ifdef VMS_TEXT_CONV |
||
891 | if (G.pInfo->hostnum == VMS_ && G.extra_field && |
||
892 | is_vms_varlen_txt(__G__ G.extra_field, |
||
893 | G.lrec.extra_field_length)) |
||
894 | G.VMS_line_state = 0; /* 0: ready to read line length */ |
||
895 | else |
||
896 | G.VMS_line_state = -1; /* -1: don't treat as VMS text */ |
||
897 | #endif |
||
898 | G.didCRlast = FALSE; /* no previous buffers written */ |
||
899 | G.newfile = FALSE; |
||
900 | } |
||
901 | |||
902 | #ifdef VMS_TEXT_CONV |
||
903 | if (G.VMS_line_state >= 0) |
||
904 | { |
||
905 | p = rawbuf; |
||
906 | q = transbuf; |
||
907 | while ((extent)(p-rawbuf) < (extent)size) { |
||
908 | switch (G.VMS_line_state) { |
||
909 | |||
910 | /* 0: ready to read line length */ |
||
911 | case 0: |
||
912 | G.VMS_line_length = 0; |
||
913 | if ((extent)(p-rawbuf) == (extent)size-1) { |
||
914 | /* last char */ |
||
915 | G.VMS_line_length = (unsigned)(*p++); |
||
916 | G.VMS_line_state = 1; |
||
917 | } else { |
||
918 | G.VMS_line_length = makeword(p); |
||
919 | p += 2; |
||
920 | G.VMS_line_state = 2; |
||
921 | } |
||
922 | G.VMS_line_pad = |
||
923 | ((G.VMS_line_length & 1) != 0); /* odd */ |
||
924 | break; |
||
925 | |||
926 | /* 1: read one byte of length, need second */ |
||
927 | case 1: |
||
928 | G.VMS_line_length += ((unsigned)(*p++) << 8); |
||
929 | G.VMS_line_state = 2; |
||
930 | break; |
||
931 | |||
932 | /* 2: ready to read VMS_line_length chars */ |
||
933 | case 2: |
||
934 | { |
||
935 | extent remaining = (extent)size+(rawbuf-p); |
||
936 | extent outroom; |
||
937 | |||
938 | if (G.VMS_line_length < remaining) { |
||
939 | remaining = G.VMS_line_length; |
||
940 | G.VMS_line_state = 3; |
||
941 | } |
||
942 | |||
943 | outroom = transbuf+(extent)transbufsiz-q; |
||
944 | if (remaining >= outroom) { |
||
945 | remaining -= outroom; |
||
946 | for (;outroom > 0; p++, outroom--) |
||
947 | *q++ = native(*p); |
||
948 | #ifdef DLL |
||
949 | if (G.redirect_data) { |
||
950 | if (writeToMemory(__G__ transbuf, |
||
951 | (extent)(q-transbuf))) return PK_ERR; |
||
952 | } else |
||
953 | #endif |
||
954 | if (!uO.cflag && WriteError(transbuf, |
||
955 | (extent)(q-transbuf), G.outfile)) |
||
956 | return disk_error(__G); |
||
957 | else if (uO.cflag && (*G.message)((zvoid *)&G, |
||
958 | transbuf, (ulg)(q-transbuf), 0)) |
||
959 | return PK_OK; |
||
960 | q = transbuf; |
||
961 | /* fall through to normal case */ |
||
962 | } |
||
963 | G.VMS_line_length -= remaining; |
||
964 | for (;remaining > 0; p++, remaining--) |
||
965 | *q++ = native(*p); |
||
966 | } |
||
967 | break; |
||
968 | |||
969 | /* 3: ready to PutNativeEOL */ |
||
970 | case 3: |
||
971 | if (q > transbuf+(extent)transbufsiz-lenEOL) { |
||
972 | #ifdef DLL |
||
973 | if (G.redirect_data) { |
||
974 | if (writeToMemory(__G__ transbuf, |
||
975 | (extent)(q-transbuf))) return PK_ERR; |
||
976 | } else |
||
977 | #endif |
||
978 | if (!uO.cflag && |
||
979 | WriteError(transbuf, (extent)(q-transbuf), |
||
980 | G.outfile)) |
||
981 | return disk_error(__G); |
||
982 | else if (uO.cflag && (*G.message)((zvoid *)&G, |
||
983 | transbuf, (ulg)(q-transbuf), 0)) |
||
984 | return PK_OK; |
||
985 | q = transbuf; |
||
986 | } |
||
987 | PutNativeEOL |
||
988 | G.VMS_line_state = G.VMS_line_pad ? 4 : 0; |
||
989 | break; |
||
990 | |||
991 | /* 4: ready to read pad byte */ |
||
992 | case 4: |
||
993 | ++p; |
||
994 | G.VMS_line_state = 0; |
||
995 | break; |
||
996 | } |
||
997 | } /* end while */ |
||
998 | |||
999 | } else |
||
1000 | #endif /* VMS_TEXT_CONV */ |
||
1001 | |||
1002 | /*----------------------------------------------------------------------- |
||
1003 | Algorithm: CR/LF => native; lone CR => native; lone LF => native. |
||
1004 | This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e., |
||
1005 | stream-oriented files, not record-oriented). |
||
1006 | -----------------------------------------------------------------------*/ |
||
1007 | |||
1008 | /* else not VMS text */ { |
||
1009 | p = rawbuf; |
||
1010 | if (*p == LF && G.didCRlast) |
||
1011 | ++p; |
||
1012 | G.didCRlast = FALSE; |
||
1013 | for (q = transbuf; (extent)(p-rawbuf) < (extent)size; ++p) { |
||
1014 | if (*p == CR) { /* lone CR or CR/LF: treat as EOL */ |
||
1015 | PutNativeEOL |
||
1016 | if ((extent)(p-rawbuf) == (extent)size-1) |
||
1017 | /* last char in buffer */ |
||
1018 | G.didCRlast = TRUE; |
||
1019 | else if (p[1] == LF) /* get rid of accompanying LF */ |
||
1020 | ++p; |
||
1021 | } else if (*p == LF) /* lone LF */ |
||
1022 | PutNativeEOL |
||
1023 | else |
||
1024 | #ifndef DOS_FLX_OS2_W32 |
||
1025 | if (*p != CTRLZ) /* lose all ^Z's */ |
||
1026 | #endif |
||
1027 | *q++ = native(*p); |
||
1028 | |||
1029 | #if (defined(SMALL_MEM) || defined(MED_MEM)) |
||
1030 | # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */ |
||
1031 | if (!unshrink) |
||
1032 | # endif |
||
1033 | /* check for danger of buffer overflow and flush */ |
||
1034 | if (q > transbuf+(extent)transbufsiz-lenEOL) { |
||
1035 | Trace((stderr, |
||
1036 | "p - rawbuf = %u q-transbuf = %u size = %lu\n", |
||
1037 | (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); |
||
1038 | if (!uO.cflag && WriteError(transbuf, |
||
1039 | (extent)(q-transbuf), G.outfile)) |
||
1040 | return disk_error(__G); |
||
1041 | else if (uO.cflag && (*G.message)((zvoid *)&G, |
||
1042 | transbuf, (ulg)(q-transbuf), 0)) |
||
1043 | return PK_OK; |
||
1044 | q = transbuf; |
||
1045 | continue; |
||
1046 | } |
||
1047 | #endif /* SMALL_MEM || MED_MEM */ |
||
1048 | } |
||
1049 | } |
||
1050 | |||
1051 | /*----------------------------------------------------------------------- |
||
1052 | Done translating: write whatever we've got to file (or screen). |
||
1053 | -----------------------------------------------------------------------*/ |
||
1054 | |||
1055 | Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n", |
||
1056 | (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size)); |
||
1057 | if (q > transbuf) { |
||
1058 | #ifdef DLL |
||
1059 | if (G.redirect_data) { |
||
1060 | if (writeToMemory(__G__ transbuf, (extent)(q-transbuf))) |
||
1061 | return PK_ERR; |
||
1062 | } else |
||
1063 | #endif |
||
1064 | if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf), |
||
1065 | G.outfile)) |
||
1066 | return disk_error(__G); |
||
1067 | else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf, |
||
1068 | (ulg)(q-transbuf), 0)) |
||
1069 | return PK_OK; |
||
1070 | } |
||
1071 | } |
||
1072 | |||
1073 | return PK_OK; |
||
1074 | |||
1075 | } /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */ |
||
1076 | |||
1077 | |||
1078 | |||
1079 | |||
1080 | |||
1081 | #ifdef VMS_TEXT_CONV |
||
1082 | |||
1083 | /********************************/ |
||
1084 | /* Function is_vms_varlen_txt() */ |
||
1085 | /********************************/ |
||
1086 | |||
1087 | static int is_vms_varlen_txt(__G__ ef_buf, ef_len) |
||
1088 | __GDEF |
||
1089 | uch *ef_buf; /* buffer containing extra field */ |
||
1090 | unsigned ef_len; /* total length of extra field */ |
||
1091 | { |
||
1092 | unsigned eb_id; |
||
1093 | unsigned eb_len; |
||
1094 | uch *eb_data; |
||
1095 | unsigned eb_datlen; |
||
1096 | #define VMSREC_C_UNDEF 0 |
||
1097 | #define VMSREC_C_VAR 2 |
||
1098 | uch vms_rectype = VMSREC_C_UNDEF; |
||
1099 | /* uch vms_fileorg = 0; */ /* currently, fileorg is not used... */ |
||
1100 | |||
1101 | #define VMSPK_ITEMID 0 |
||
1102 | #define VMSPK_ITEMLEN 2 |
||
1103 | #define VMSPK_ITEMHEADSZ 4 |
||
1104 | |||
1105 | #define VMSATR_C_RECATTR 4 |
||
1106 | #define VMS_FABSIG 0x42414656 /* "VFAB" */ |
||
1107 | /* offsets of interesting fields in VMS fabdef structure */ |
||
1108 | #define VMSFAB_B_RFM 31 /* record format byte */ |
||
1109 | #define VMSFAB_B_ORG 29 /* file organization byte */ |
||
1110 | |||
1111 | if (ef_len == 0 || ef_buf == NULL) |
||
1112 | return FALSE; |
||
1113 | |||
1114 | while (ef_len >= EB_HEADSIZE) { |
||
1115 | eb_id = makeword(EB_ID + ef_buf); |
||
1116 | eb_len = makeword(EB_LEN + ef_buf); |
||
1117 | |||
1118 | if (eb_len > (ef_len - EB_HEADSIZE)) { |
||
1119 | /* discovered some extra field inconsistency! */ |
||
1120 | Trace((stderr, |
||
1121 | "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len, |
||
1122 | ef_len - EB_HEADSIZE)); |
||
1123 | break; |
||
1124 | } |
||
1125 | |||
1126 | switch (eb_id) { |
||
1127 | case EF_PKVMS: |
||
1128 | /* The PKVMS e.f. raw data part consists of: |
||
1129 | * a) 4 bytes CRC checksum |
||
1130 | * b) list of uncompressed variable-length data items |
||
1131 | * Each data item is introduced by a fixed header |
||
1132 | * - 2 bytes data type ID |
||
1133 | * - 2 bytes |
||
1134 | * - |
||
1135 | */ |
||
1136 | |||
1137 | /* get pointer to start of data and its total length */ |
||
1138 | eb_data = ef_buf+(EB_HEADSIZE+4); |
||
1139 | eb_datlen = eb_len-4; |
||
1140 | |||
1141 | /* test the CRC checksum */ |
||
1142 | if (makelong(ef_buf+EB_HEADSIZE) != |
||
1143 | crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen)) |
||
1144 | { |
||
1145 | Info(slide, 1, ((char *)slide, |
||
1146 | "[Warning: CRC error, discarding PKWARE extra field]\n")); |
||
1147 | /* skip over the data analysis code */ |
||
1148 | break; |
||
1149 | } |
||
1150 | |||
1151 | /* scan through the attribute data items */ |
||
1152 | while (eb_datlen > 4) |
||
1153 | { |
||
1154 | unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]); |
||
1155 | |||
1156 | /* check the item type word */ |
||
1157 | switch (makeword(&eb_data[VMSPK_ITEMID])) { |
||
1158 | case VMSATR_C_RECATTR: |
||
1159 | /* we have found the (currently only) interesting |
||
1160 | * data item */ |
||
1161 | if (fldsize >= 1) { |
||
1162 | vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15; |
||
1163 | /* vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; */ |
||
1164 | } |
||
1165 | break; |
||
1166 | default: |
||
1167 | break; |
||
1168 | } |
||
1169 | /* skip to next data item */ |
||
1170 | eb_datlen -= fldsize + VMSPK_ITEMHEADSZ; |
||
1171 | eb_data += fldsize + VMSPK_ITEMHEADSZ; |
||
1172 | } |
||
1173 | break; |
||
1174 | |||
1175 | case EF_IZVMS: |
||
1176 | if (makelong(ef_buf+EB_HEADSIZE) == VMS_FABSIG) { |
||
1177 | if ((eb_data = extract_izvms_block(__G__ |
||
1178 | ef_buf+EB_HEADSIZE, eb_len, |
||
1179 | &eb_datlen, NULL, 0)) |
||
1180 | != NULL) |
||
1181 | { |
||
1182 | if (eb_datlen >= VMSFAB_B_RFM+1) { |
||
1183 | vms_rectype = eb_data[VMSFAB_B_RFM] & 15; |
||
1184 | /* vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4; */ |
||
1185 | } |
||
1186 | free(eb_data); |
||
1187 | } |
||
1188 | } |
||
1189 | break; |
||
1190 | |||
1191 | default: |
||
1192 | break; |
||
1193 | } |
||
1194 | |||
1195 | /* Skip this extra field block */ |
||
1196 | ef_buf += (eb_len + EB_HEADSIZE); |
||
1197 | ef_len -= (eb_len + EB_HEADSIZE); |
||
1198 | } |
||
1199 | |||
1200 | return (vms_rectype == VMSREC_C_VAR); |
||
1201 | |||
1202 | } /* end function is_vms_varlen_txtfile() */ |
||
1203 | |||
1204 | #endif /* VMS_TEXT_CONV */ |
||
1205 | |||
1206 | |||
1207 | |||
1208 | |||
1209 | /*************************/ |
||
1210 | /* Function disk_error() */ |
||
1211 | /*************************/ |
||
1212 | |||
1213 | static int disk_error(__G) |
||
1214 | __GDEF |
||
1215 | { |
||
1216 | /* OK to use slide[] here because this file is finished regardless */ |
||
6775 | siemargl | 1217 | Info(slide, 0x4a1 & 0xFE, ((char *)slide, LoadFarString(DiskFullQuery), |
6725 | siemargl | 1218 | FnFilter1(G.filename))); |
1219 | |||
1220 | #ifndef WINDLL |
||
1221 | fgets(G.answerbuf, sizeof(G.answerbuf), stdin); |
||
1222 | if (*G.answerbuf == 'y') /* stop writing to this file */ |
||
1223 | G.disk_full = 1; /* (outfile bad?), but new OK */ |
||
1224 | else |
||
1225 | #endif |
||
1226 | G.disk_full = 2; /* no: exit program */ |
||
1227 | |||
1228 | return PK_DISK; |
||
1229 | |||
1230 | } /* end function disk_error() */ |
||
1231 | |||
1232 | #endif /* !VMS */ |
||
1233 | |||
1234 | |||
1235 | |||
1236 | |||
1237 | |||
1238 | /*****************************/ |
||
1239 | /* Function UzpMessagePrnt() */ |
||
1240 | /*****************************/ |
||
1241 | |||
1242 | int UZ_EXP UzpMessagePrnt(pG, buf, size, flag) |
||
1243 | zvoid *pG; /* globals struct: always passed */ |
||
1244 | uch *buf; /* preformatted string to be printed */ |
||
1245 | ulg size; /* length of string (may include nulls) */ |
||
1246 | int flag; /* flag bits */ |
||
1247 | { |
||
1248 | /* IMPORTANT NOTE: |
||
1249 | * The name of the first parameter of UzpMessagePrnt(), which passes |
||
1250 | * the "Uz_Globs" address, >>> MUST <<< be identical to the string |
||
1251 | * expansion of the __G__ macro in the REENTRANT case (see globals.h). |
||
1252 | * This name identity is mandatory for the LoadFarString() macro |
||
1253 | * (in the SMALL_MEM case) !!! |
||
1254 | */ |
||
1255 | int error; |
||
1256 | uch *q=buf, *endbuf=buf+(unsigned)size; |
||
1257 | #ifdef MORE |
||
1258 | uch *p=buf; |
||
1259 | #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) |
||
1260 | int islinefeed = FALSE; |
||
1261 | #endif |
||
1262 | #endif |
||
1263 | FILE *outfp; |
||
1264 | |||
1265 | |||
1266 | /*--------------------------------------------------------------------------- |
||
1267 | These tests are here to allow fine-tuning of UnZip's output messages, |
||
1268 | but none of them will do anything without setting the appropriate bit |
||
1269 | in the flag argument of every Info() statement which is to be turned |
||
1270 | *off*. That is, all messages are currently turned on for all ports. |
||
1271 | To turn off *all* messages, use the UzpMessageNull() function instead |
||
1272 | of this one. |
||
1273 | ---------------------------------------------------------------------------*/ |
||
1274 | |||
1275 | #if (defined(OS2) && defined(DLL)) |
||
1276 | if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */ |
||
1277 | return 0; |
||
1278 | #endif |
||
1279 | #ifdef WINDLL |
||
1280 | if (MSG_NO_WDLL(flag)) |
||
1281 | return 0; |
||
1282 | #endif |
||
1283 | #ifdef WINDLL |
||
1284 | if (MSG_NO_WGUI(flag)) |
||
1285 | return 0; |
||
1286 | #endif |
||
1287 | /* |
||
1288 | #ifdef ACORN_GUI |
||
1289 | if (MSG_NO_AGUI(flag)) |
||
1290 | return 0; |
||
1291 | #endif |
||
1292 | */ |
||
1293 | #ifdef DLL /* don't display message if data is redirected */ |
||
1294 | if (((Uz_Globs *)pG)->redirect_data && |
||
1295 | !((Uz_Globs *)pG)->redirect_text) |
||
1296 | return 0; |
||
1297 | #endif |
||
1298 | |||
1299 | if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag) |
||
1300 | outfp = (FILE *)stderr; |
||
1301 | else |
||
1302 | outfp = (FILE *)stdout; |
||
1303 | |||
1304 | #ifdef QUERY_TRNEWLN |
||
1305 | /* some systems require termination of query prompts with '\n' to force |
||
1306 | * immediate display */ |
||
1307 | if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */ |
||
1308 | *endbuf++ = '\n'; /* with room for one more char at end of buf */ |
||
1309 | ++size; /* (safe assumption: only used for four */ |
||
1310 | } /* short queries in extract.c and fileio.c) */ |
||
1311 | #endif |
||
1312 | |||
1313 | if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */ |
||
1314 | if ((!size && !((Uz_Globs *)pG)->sol) || |
||
1315 | (size && (endbuf[-1] != '\n'))) |
||
1316 | { |
||
1317 | *endbuf++ = '\n'; |
||
1318 | ++size; |
||
1319 | } |
||
1320 | } |
||
1321 | |||
1322 | #ifdef MORE |
||
1323 | # ifdef SCREENSIZE |
||
1324 | /* room for --More-- and one line of overlap: */ |
||
1325 | # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) |
||
1326 | SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width); |
||
1327 | # else |
||
1328 | SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL); |
||
1329 | # endif |
||
1330 | ((Uz_Globs *)pG)->height -= 2; |
||
1331 | # else |
||
1332 | /* room for --More-- and one line of overlap: */ |
||
1333 | ((Uz_Globs *)pG)->height = SCREENLINES - 2; |
||
1334 | # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) |
||
1335 | ((Uz_Globs *)pG)->width = SCREENWIDTH; |
||
1336 | # endif |
||
1337 | # endif |
||
1338 | #endif /* MORE */ |
||
1339 | |||
1340 | if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) { |
||
1341 | /* not at start of line: want newline */ |
||
1342 | #ifdef OS2DLL |
||
1343 | if (!((Uz_Globs *)pG)->redirect_text) { |
||
1344 | #endif |
||
1345 | putc('\n', outfp); |
||
1346 | fflush(outfp); |
||
1347 | #ifdef MORE |
||
1348 | if (((Uz_Globs *)pG)->M_flag) |
||
1349 | { |
||
1350 | #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) |
||
1351 | ((Uz_Globs *)pG)->chars = 0; |
||
1352 | #endif |
||
1353 | ++((Uz_Globs *)pG)->numlines; |
||
1354 | ++((Uz_Globs *)pG)->lines; |
||
1355 | if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) |
||
1356 | (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, |
||
1357 | LoadFarString(MorePrompt), 1); |
||
1358 | } |
||
1359 | #endif /* MORE */ |
||
1360 | if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && |
||
1361 | !isatty(1) && isatty(2)) |
||
1362 | { |
||
1363 | /* error output from testing redirected: also send to stderr */ |
||
1364 | putc('\n', stderr); |
||
1365 | fflush(stderr); |
||
1366 | } |
||
1367 | #ifdef OS2DLL |
||
1368 | } else |
||
1369 | REDIRECTC('\n'); |
||
1370 | #endif |
||
1371 | ((Uz_Globs *)pG)->sol = TRUE; |
||
1372 | } |
||
1373 | |||
1374 | /* put zipfile name, filename and/or error/warning keywords here */ |
||
1375 | |||
1376 | #ifdef MORE |
||
1377 | if (((Uz_Globs *)pG)->M_flag |
||
1378 | #ifdef OS2DLL |
||
1379 | && !((Uz_Globs *)pG)->redirect_text |
||
1380 | #endif |
||
1381 | ) |
||
1382 | { |
||
1383 | while (p < endbuf) { |
||
1384 | if (*p == '\n') { |
||
1385 | #if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) |
||
1386 | islinefeed = TRUE; |
||
1387 | } else if (SCREENLWRAP) { |
||
1388 | if (*p == '\r') { |
||
1389 | ((Uz_Globs *)pG)->chars = 0; |
||
1390 | } else { |
||
1391 | # ifdef TABSIZE |
||
1392 | if (*p == '\t') |
||
1393 | ((Uz_Globs *)pG)->chars += |
||
1394 | (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE)); |
||
1395 | else |
||
1396 | # endif |
||
1397 | ++((Uz_Globs *)pG)->chars; |
||
1398 | |||
1399 | if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width) |
||
1400 | islinefeed = TRUE; |
||
1401 | } |
||
1402 | } |
||
1403 | if (islinefeed) { |
||
1404 | islinefeed = FALSE; |
||
1405 | ((Uz_Globs *)pG)->chars = 0; |
||
1406 | #endif /* (SCREENWIDTH && SCREEN_LWRAP) */ |
||
1407 | ++((Uz_Globs *)pG)->numlines; |
||
1408 | ++((Uz_Globs *)pG)->lines; |
||
1409 | if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height) |
||
1410 | { |
||
1411 | if ((error = WriteTxtErr(q, p-q+1, outfp)) != 0) |
||
1412 | return error; |
||
1413 | fflush(outfp); |
||
1414 | ((Uz_Globs *)pG)->sol = TRUE; |
||
1415 | q = p + 1; |
||
1416 | (*((Uz_Globs *)pG)->mpause)((zvoid *)pG, |
||
1417 | LoadFarString(MorePrompt), 1); |
||
1418 | } |
||
1419 | } |
||
1420 | INCSTR(p); |
||
1421 | } /* end while */ |
||
1422 | size = (ulg)(p - q); /* remaining text */ |
||
1423 | } |
||
1424 | #endif /* MORE */ |
||
1425 | |||
1426 | if (size) { |
||
1427 | #ifdef OS2DLL |
||
1428 | if (!((Uz_Globs *)pG)->redirect_text) { |
||
1429 | #endif |
||
1430 | if ((error = WriteTxtErr(q, size, outfp)) != 0) |
||
1431 | return error; |
||
1432 | #ifndef VMS /* 2005-09-16 SMS. See note at "WriteTxtErr()", above. */ |
||
1433 | fflush(outfp); |
||
1434 | #endif |
||
1435 | if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag && |
||
1436 | !isatty(1) && isatty(2)) |
||
1437 | { |
||
1438 | /* error output from testing redirected: also send to stderr */ |
||
1439 | if ((error = WriteTxtErr(q, size, stderr)) != 0) |
||
1440 | return error; |
||
1441 | fflush(stderr); |
||
1442 | } |
||
1443 | #ifdef OS2DLL |
||
1444 | } else { /* GRR: this is ugly: hide with macro */ |
||
1445 | if ((error = REDIRECTPRINT(q, size)) != 0) |
||
1446 | return error; |
||
1447 | } |
||
1448 | #endif /* OS2DLL */ |
||
1449 | ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n'); |
||
1450 | } |
||
1451 | return 0; |
||
1452 | |||
1453 | } /* end function UzpMessagePrnt() */ |
||
1454 | |||
1455 | |||
1456 | |||
1457 | |||
1458 | |||
1459 | #ifdef DLL |
||
1460 | |||
1461 | /*****************************/ |
||
1462 | /* Function UzpMessageNull() */ /* convenience routine for no output at all */ |
||
1463 | /*****************************/ |
||
1464 | |||
1465 | int UZ_EXP UzpMessageNull(pG, buf, size, flag) |
||
1466 | zvoid *pG; /* globals struct: always passed */ |
||
1467 | uch *buf; /* preformatted string to be printed */ |
||
1468 | ulg size; /* length of string (may include nulls) */ |
||
1469 | int flag; /* flag bits */ |
||
1470 | { |
||
1471 | return 0; |
||
1472 | |||
1473 | } /* end function UzpMessageNull() */ |
||
1474 | |||
1475 | #endif /* DLL */ |
||
1476 | |||
1477 | |||
1478 | |||
1479 | |||
1480 | |||
1481 | /***********************/ |
||
1482 | /* Function UzpInput() */ /* GRR: this is a placeholder for now */ |
||
1483 | /***********************/ |
||
1484 | |||
1485 | int UZ_EXP UzpInput(pG, buf, size, flag) |
||
1486 | zvoid *pG; /* globals struct: always passed */ |
||
1487 | uch *buf; /* preformatted string to be printed */ |
||
1488 | int *size; /* (address of) size of buf and of returned string */ |
||
1489 | int flag; /* flag bits (bit 0: no echo) */ |
||
1490 | { |
||
1491 | /* tell picky compilers to shut up about "unused variable" warnings */ |
||
1492 | pG = pG; buf = buf; flag = flag; |
||
1493 | |||
1494 | *size = 0; |
||
1495 | return 0; |
||
1496 | |||
1497 | } /* end function UzpInput() */ |
||
1498 | |||
1499 | |||
1500 | |||
1501 | |||
1502 | |||
1503 | #if (!defined(WINDLL) && !defined(MACOS)) |
||
1504 | |||
1505 | /***************************/ |
||
1506 | /* Function UzpMorePause() */ |
||
1507 | /***************************/ |
||
1508 | |||
1509 | void UZ_EXP UzpMorePause(pG, prompt, flag) |
||
1510 | zvoid *pG; /* globals struct: always passed */ |
||
1511 | ZCONST char *prompt; /* "--More--" prompt */ |
||
1512 | int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */ |
||
1513 | { |
||
1514 | uch c; |
||
1515 | |||
1516 | /*--------------------------------------------------------------------------- |
||
1517 | Print a prompt and wait for the user to press a key, then erase prompt |
||
1518 | if possible. |
||
1519 | ---------------------------------------------------------------------------*/ |
||
1520 | |||
1521 | if (!((Uz_Globs *)pG)->sol) |
||
1522 | fprintf(stderr, "\n"); |
||
1523 | /* numlines may or may not be used: */ |
||
1524 | fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines); |
||
1525 | fflush(stderr); |
||
1526 | if (flag & 1) { |
||
1527 | do { |
||
1528 | c = (uch)FGETCH(0); |
||
1529 | } while ( |
||
1530 | #ifdef THEOS |
||
1531 | c != 17 && /* standard QUIT key */ |
||
1532 | #endif |
||
1533 | c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q'); |
||
1534 | } else |
||
1535 | c = (uch)FGETCH(0); |
||
1536 | |||
1537 | /* newline was not echoed, so cover up prompt line */ |
||
1538 | fprintf(stderr, LoadFarString(HidePrompt)); |
||
1539 | fflush(stderr); |
||
1540 | |||
1541 | if ( |
||
1542 | #ifdef THEOS |
||
1543 | (c == 17) || /* standard QUIT key */ |
||
1544 | #endif |
||
1545 | (ToLower(c) == 'q')) { |
||
1546 | DESTROYGLOBALS(); |
||
1547 | EXIT(PK_COOL); |
||
1548 | } |
||
1549 | |||
1550 | ((Uz_Globs *)pG)->sol = TRUE; |
||
1551 | |||
1552 | #ifdef MORE |
||
1553 | /* space for another screen, enter for another line. */ |
||
1554 | if ((flag & 1) && c == ' ') |
||
1555 | ((Uz_Globs *)pG)->lines = 0; |
||
1556 | #endif /* MORE */ |
||
1557 | |||
1558 | } /* end function UzpMorePause() */ |
||
1559 | |||
1560 | #endif /* !WINDLL && !MACOS */ |
||
1561 | |||
1562 | |||
1563 | |||
1564 | |||
1565 | #ifndef WINDLL |
||
1566 | |||
1567 | /**************************/ |
||
1568 | /* Function UzpPassword() */ |
||
1569 | /**************************/ |
||
1570 | |||
1571 | int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn) |
||
1572 | zvoid *pG; /* pointer to UnZip's internal global vars */ |
||
1573 | int *rcnt; /* retry counter */ |
||
1574 | char *pwbuf; /* buffer for password */ |
||
1575 | int size; /* size of password buffer */ |
||
1576 | ZCONST char *zfn; /* name of zip archive */ |
||
1577 | ZCONST char *efn; /* name of archive entry being processed */ |
||
1578 | { |
||
1579 | #if CRYPT |
||
1580 | int r = IZ_PW_ENTERED; |
||
1581 | char *m; |
||
1582 | char *prompt; |
||
1583 | |||
1584 | #ifndef REENTRANT |
||
1585 | /* tell picky compilers to shut up about "unused variable" warnings */ |
||
1586 | pG = pG; |
||
1587 | #endif |
||
1588 | |||
1589 | if (*rcnt == 0) { /* First call for current entry */ |
||
1590 | *rcnt = 2; |
||
1591 | if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) { |
||
1592 | sprintf(prompt, LoadFarString(PasswPrompt), |
||
1593 | FnFilter1(zfn), FnFilter2(efn)); |
||
1594 | m = prompt; |
||
1595 | } else |
||
1596 | m = (char *)LoadFarString(PasswPrompt2); |
||
1597 | } else { /* Retry call, previous password was wrong */ |
||
1598 | (*rcnt)--; |
||
1599 | prompt = NULL; |
||
1600 | m = (char *)LoadFarString(PasswRetry); |
||
1601 | } |
||
1602 | |||
1603 | m = getp(__G__ m, pwbuf, size); |
||
1604 | if (prompt != (char *)NULL) { |
||
1605 | free(prompt); |
||
1606 | } |
||
1607 | if (m == (char *)NULL) { |
||
1608 | r = IZ_PW_ERROR; |
||
1609 | } |
||
1610 | else if (*pwbuf == '\0') { |
||
1611 | r = IZ_PW_CANCELALL; |
||
1612 | } |
||
1613 | return r; |
||
1614 | |||
1615 | #else /* !CRYPT */ |
||
1616 | /* tell picky compilers to shut up about "unused variable" warnings */ |
||
1617 | pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn; |
||
1618 | |||
1619 | return IZ_PW_ERROR; /* internal error; function should never get called */ |
||
1620 | #endif /* ?CRYPT */ |
||
1621 | |||
1622 | } /* end function UzpPassword() */ |
||
1623 | |||
1624 | |||
1625 | |||
1626 | |||
1627 | |||
1628 | /**********************/ |
||
1629 | /* Function handler() */ |
||
1630 | /**********************/ |
||
1631 | |||
1632 | void handler(signal) /* upon interrupt, turn on echo and exit cleanly */ |
||
1633 | int signal; |
||
1634 | { |
||
1635 | GETGLOBALS(); |
||
1636 | |||
1637 | #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */ |
||
1638 | (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */ |
||
1639 | #endif /* slide[] should be safe) */ |
||
1640 | |||
1641 | echon(); |
||
1642 | |||
1643 | #ifdef SIGBUS |
||
1644 | if (signal == SIGBUS) { |
||
1645 | Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), |
||
1646 | "bus error")); |
||
1647 | DESTROYGLOBALS(); |
||
1648 | EXIT(PK_BADERR); |
||
1649 | } |
||
1650 | #endif /* SIGBUS */ |
||
1651 | |||
1652 | #ifdef SIGILL |
||
1653 | if (signal == SIGILL) { |
||
1654 | Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), |
||
1655 | "illegal instruction")); |
||
1656 | DESTROYGLOBALS(); |
||
1657 | EXIT(PK_BADERR); |
||
1658 | } |
||
1659 | #endif /* SIGILL */ |
||
1660 | |||
1661 | #ifdef SIGSEGV |
||
1662 | if (signal == SIGSEGV) { |
||
1663 | Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt), |
||
1664 | "segmentation violation")); |
||
1665 | DESTROYGLOBALS(); |
||
1666 | EXIT(PK_BADERR); |
||
1667 | } |
||
1668 | #endif /* SIGSEGV */ |
||
1669 | |||
1670 | /* probably ctrl-C */ |
||
1671 | DESTROYGLOBALS(); |
||
1672 | #if defined(AMIGA) && defined(__SASC) |
||
1673 | _abort(); |
||
1674 | #endif |
||
1675 | EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */ |
||
1676 | } |
||
1677 | |||
1678 | #endif /* !WINDLL */ |
||
1679 | |||
1680 | |||
1681 | |||
1682 | |||
1683 | #if (!defined(VMS) && !defined(CMS_MVS)) |
||
1684 | #if (!defined(OS2) || defined(TIMESTAMP)) |
||
1685 | |||
1686 | #if (!defined(HAVE_MKTIME) || defined(WIN32)) |
||
1687 | /* also used in amiga/filedate.c and win32/win32.c */ |
||
1688 | ZCONST ush ydays[] = |
||
1689 | { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; |
||
1690 | #endif |
||
1691 | |||
1692 | /*******************************/ |
||
1693 | /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */ |
||
1694 | /*******************************/ |
||
1695 | |||
1696 | time_t dos_to_unix_time(dosdatetime) |
||
1697 | ulg dosdatetime; |
||
1698 | { |
||
1699 | time_t m_time; |
||
1700 | |||
1701 | #ifdef HAVE_MKTIME |
||
1702 | |||
1703 | ZCONST time_t now = time(NULL); |
||
1704 | struct tm *tm; |
||
1705 | # define YRBASE 1900 |
||
1706 | |||
1707 | tm = localtime(&now); |
||
1708 | tm->tm_isdst = -1; /* let mktime determine if DST is in effect */ |
||
1709 | |||
1710 | /* dissect date */ |
||
1711 | tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); |
||
1712 | tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1; |
||
1713 | tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f); |
||
1714 | |||
1715 | /* dissect time */ |
||
1716 | tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f; |
||
1717 | tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f; |
||
1718 | tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e; |
||
1719 | |||
1720 | m_time = mktime(tm); |
||
1721 | NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ |
||
1722 | TTrace((stderr, " final m_time = %lu\n", (ulg)m_time)); |
||
1723 | |||
1724 | #else /* !HAVE_MKTIME */ |
||
1725 | |||
1726 | int yr, mo, dy, hh, mm, ss; |
||
1727 | #ifdef TOPS20 |
||
1728 | # define YRBASE 1900 |
||
1729 | struct tmx *tmx; |
||
1730 | char temp[20]; |
||
1731 | #else /* !TOPS20 */ |
||
1732 | # define YRBASE 1970 |
||
1733 | int leap; |
||
1734 | unsigned days; |
||
1735 | struct tm *tm; |
||
1736 | #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) |
||
1737 | #ifdef WIN32 |
||
1738 | TIME_ZONE_INFORMATION tzinfo; |
||
1739 | DWORD res; |
||
1740 | #else /* ! WIN32 */ |
||
1741 | #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */ |
||
1742 | #if (defined(BSD) || defined(MTS) || defined(__GO32__)) |
||
1743 | struct timeb tbp; |
||
1744 | #else /* !(BSD || MTS || __GO32__) */ |
||
1745 | #ifdef DECLARE_TIMEZONE |
||
1746 | extern time_t timezone; |
||
1747 | #endif |
||
1748 | #endif /* ?(BSD || MTS || __GO32__) */ |
||
1749 | #endif /* !BSD4_4 */ |
||
1750 | #endif /* ?WIN32 */ |
||
1751 | #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ |
||
1752 | #endif /* ?TOPS20 */ |
||
1753 | |||
1754 | |||
1755 | /* dissect date */ |
||
1756 | yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE); |
||
1757 | mo = ((int)(dosdatetime >> 21) & 0x0f) - 1; |
||
1758 | dy = ((int)(dosdatetime >> 16) & 0x1f) - 1; |
||
1759 | |||
1760 | /* dissect time */ |
||
1761 | hh = (int)((unsigned)dosdatetime >> 11) & 0x1f; |
||
1762 | mm = (int)((unsigned)dosdatetime >> 5) & 0x3f; |
||
1763 | ss = (int)((unsigned)dosdatetime & 0x1f) * 2; |
||
1764 | |||
1765 | #ifdef TOPS20 |
||
1766 | tmx = (struct tmx *)malloc(sizeof(struct tmx)); |
||
1767 | sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss); |
||
1768 | time_parse(temp, tmx, (char *)0); |
||
1769 | m_time = time_make(tmx); |
||
1770 | free(tmx); |
||
1771 | |||
1772 | #else /* !TOPS20 */ |
||
1773 | |||
1774 | /*--------------------------------------------------------------------------- |
||
1775 | Calculate the number of seconds since the epoch, usually 1 January 1970. |
||
1776 | ---------------------------------------------------------------------------*/ |
||
1777 | |||
1778 | /* leap = # of leap yrs from YRBASE up to but not including current year */ |
||
1779 | leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */ |
||
1780 | |||
1781 | /* calculate days from BASE to this year and add expired days this year */ |
||
1782 | days = (yr * 365) + (leap - 492) + ydays[mo]; |
||
1783 | |||
1784 | /* if year is a leap year and month is after February, add another day */ |
||
1785 | if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100)) |
||
1786 | ++days; /* OK through 2199 */ |
||
1787 | |||
1788 | /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */ |
||
1789 | m_time = (time_t)((unsigned long)(days + dy) * 86400L + |
||
1790 | (unsigned long)hh * 3600L + |
||
1791 | (unsigned long)(mm * 60 + ss)); |
||
1792 | /* - 1; MS-DOS times always rounded up to nearest even second */ |
||
1793 | TTrace((stderr, "dos_to_unix_time:\n")); |
||
1794 | TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time)); |
||
1795 | |||
1796 | /*--------------------------------------------------------------------------- |
||
1797 | Adjust for local standard timezone offset. |
||
1798 | ---------------------------------------------------------------------------*/ |
||
1799 | |||
1800 | #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM)) |
||
1801 | #ifdef WIN32 |
||
1802 | /* account for timezone differences */ |
||
1803 | res = GetTimeZoneInformation(&tzinfo); |
||
1804 | if (res != TIME_ZONE_ID_INVALID) |
||
1805 | { |
||
1806 | m_time += 60*(tzinfo.Bias); |
||
1807 | #else /* !WIN32 */ |
||
1808 | #if (defined(BSD) || defined(MTS) || defined(__GO32__)) |
||
1809 | #ifdef BSD4_4 |
||
1810 | if ( (dosdatetime >= DOSTIME_2038_01_18) && |
||
1811 | (m_time < (time_t)0x70000000L) ) |
||
1812 | m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ |
||
1813 | if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ |
||
1814 | m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ |
||
1815 | if ((tm = localtime(&m_time)) != (struct tm *)NULL) |
||
1816 | m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */ |
||
1817 | #else /* !(BSD4_4 */ |
||
1818 | ftime(&tbp); /* get `timezone' */ |
||
1819 | m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */ |
||
1820 | #endif /* ?(BSD4_4 || __EMX__) */ |
||
1821 | #else /* !(BSD || MTS || __GO32__) */ |
||
1822 | /* tzset was already called at start of process_zipfiles() */ |
||
1823 | /* tzset(); */ /* set `timezone' variable */ |
||
1824 | #if !defined(__BEOS__) && !defined(KOS32) /* BeOS DR8 has no timezones... */ |
||
1825 | m_time += timezone; /* seconds WEST of GMT: add */ |
||
1826 | #endif |
||
1827 | #endif /* ?(BSD || MTS || __GO32__) */ |
||
1828 | #endif /* ?WIN32 */ |
||
1829 | TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time)); |
||
1830 | |||
1831 | /*--------------------------------------------------------------------------- |
||
1832 | Adjust for local daylight savings (summer) time. |
||
1833 | ---------------------------------------------------------------------------*/ |
||
1834 | |||
1835 | #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */ |
||
1836 | if ( (dosdatetime >= DOSTIME_2038_01_18) && |
||
1837 | (m_time < (time_t)0x70000000L) ) |
||
1838 | m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ |
||
1839 | if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ |
||
1840 | m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ |
||
1841 | TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */ |
||
1842 | if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst) |
||
1843 | #ifdef WIN32 |
||
1844 | m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */ |
||
1845 | else |
||
1846 | m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */ |
||
1847 | #else |
||
1848 | m_time -= 60L * 60L; /* adjust for daylight savings time */ |
||
1849 | #endif |
||
1850 | NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */ |
||
1851 | TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time)); |
||
1852 | #endif /* !BSD4_4 */ |
||
1853 | #ifdef WIN32 |
||
1854 | } |
||
1855 | #endif |
||
1856 | #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */ |
||
1857 | #endif /* ?TOPS20 */ |
||
1858 | |||
1859 | #endif /* ?HAVE_MKTIME */ |
||
1860 | |||
1861 | if ( (dosdatetime >= DOSTIME_2038_01_18) && |
||
1862 | (m_time < (time_t)0x70000000L) ) |
||
1863 | m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */ |
||
1864 | if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */ |
||
1865 | m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */ |
||
1866 | |||
1867 | return m_time; |
||
1868 | |||
1869 | } /* end function dos_to_unix_time() */ |
||
1870 | |||
1871 | #endif /* !OS2 || TIMESTAMP */ |
||
1872 | #endif /* !VMS && !CMS_MVS */ |
||
1873 | |||
1874 | |||
1875 | |||
1876 | #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS)) |
||
1877 | |||
1878 | /******************************/ |
||
1879 | /* Function check_for_newer() */ /* used for overwriting/freshening/updating */ |
||
1880 | /******************************/ |
||
1881 | |||
1882 | int check_for_newer(__G__ filename) /* return 1 if existing file is newer */ |
||
1883 | __GDEF /* or equal; 0 if older; -1 if doesn't */ |
||
1884 | char *filename; /* exist yet */ |
||
1885 | { |
||
1886 | time_t existing, archive; |
||
1887 | #ifdef USE_EF_UT_TIME |
||
1888 | iztimes z_utime; |
||
1889 | #endif |
||
1890 | #ifdef AOS_VS |
||
1891 | long dyy, dmm, ddd, dhh, dmin, dss; |
||
1892 | |||
1893 | |||
1894 | dyy = (lrec.last_mod_dos_datetime >> 25) + 1980; |
||
1895 | dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f; |
||
1896 | ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f; |
||
1897 | dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f; |
||
1898 | dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f; |
||
1899 | dss = (lrec.last_mod_dos_datetime & 0x1f) * 2; |
||
1900 | |||
1901 | /* under AOS/VS, file times can only be set at creation time, |
||
1902 | * with the info in a special DG format. Make sure we can create |
||
1903 | * it here - we delete it later & re-create it, whether or not |
||
1904 | * it exists now. |
||
1905 | */ |
||
1906 | if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) | |
||
1907 | (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1)) |
||
1908 | return DOES_NOT_EXIST; |
||
1909 | #endif /* AOS_VS */ |
||
1910 | |||
1911 | Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename))); |
||
1912 | if (SSTAT(filename, &G.statbuf)) { |
||
1913 | Trace((stderr, |
||
1914 | "check_for_newer: stat(%s) returns %d: file does not exist\n", |
||
1915 | FnFilter1(filename), SSTAT(filename, &G.statbuf))); |
||
1916 | #ifdef SYMLINKS |
||
1917 | Trace((stderr, "check_for_newer: doing lstat(%s)\n", |
||
1918 | FnFilter1(filename))); |
||
1919 | /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ |
||
1920 | if (lstat(filename, &G.statbuf) == 0) { |
||
1921 | Trace((stderr, |
||
1922 | "check_for_newer: lstat(%s) returns 0: symlink does exist\n", |
||
1923 | FnFilter1(filename))); |
||
1924 | if (QCOND2 && !IS_OVERWRT_ALL) |
||
1925 | Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), |
||
1926 | FnFilter1(filename), " with no real file")); |
||
1927 | return EXISTS_AND_OLDER; /* symlink dates are meaningless */ |
||
1928 | } |
||
1929 | #endif /* SYMLINKS */ |
||
1930 | return DOES_NOT_EXIST; |
||
1931 | } |
||
1932 | Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n", |
||
1933 | FnFilter1(filename))); |
||
1934 | |||
1935 | #ifdef SYMLINKS |
||
1936 | /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */ |
||
1937 | if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) { |
||
1938 | Trace((stderr, "check_for_newer: %s is a symbolic link\n", |
||
1939 | FnFilter1(filename))); |
||
1940 | if (QCOND2 && !IS_OVERWRT_ALL) |
||
1941 | Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink), |
||
1942 | FnFilter1(filename), "")); |
||
1943 | return EXISTS_AND_OLDER; /* symlink dates are meaningless */ |
||
1944 | } |
||
1945 | #endif /* SYMLINKS */ |
||
1946 | |||
1947 | NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */ |
||
1948 | |||
1949 | #ifdef USE_EF_UT_TIME |
||
1950 | /* The `Unix extra field mtime' should be used for comparison with the |
||
1951 | * time stamp of the existing file >>>ONLY<<< when the EF info is also |
||
1952 | * used to set the modification time of the extracted file. |
||
1953 | */ |
||
1954 | if (G.extra_field && |
||
1955 | #ifdef IZ_CHECK_TZ |
||
1956 | G.tz_is_valid && |
||
1957 | #endif |
||
1958 | (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, |
||
1959 | G.lrec.last_mod_dos_datetime, &z_utime, NULL) |
||
1960 | & EB_UT_FL_MTIME)) |
||
1961 | { |
||
1962 | TTrace((stderr, "check_for_newer: using Unix extra field mtime\n")); |
||
1963 | existing = G.statbuf.st_mtime; |
||
1964 | archive = z_utime.mtime; |
||
1965 | } else { |
||
1966 | /* round up existing filetime to nearest 2 seconds for comparison, |
||
1967 | * but saturate in case of arithmetic overflow |
||
1968 | */ |
||
1969 | existing = ((G.statbuf.st_mtime & 1) && |
||
1970 | (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? |
||
1971 | G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; |
||
1972 | archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); |
||
1973 | } |
||
1974 | #else /* !USE_EF_UT_TIME */ |
||
1975 | /* round up existing filetime to nearest 2 seconds for comparison, |
||
1976 | * but saturate in case of arithmetic overflow |
||
1977 | */ |
||
1978 | existing = ((G.statbuf.st_mtime & 1) && |
||
1979 | (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ? |
||
1980 | G.statbuf.st_mtime + 1 : G.statbuf.st_mtime; |
||
1981 | archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime); |
||
1982 | #endif /* ?USE_EF_UT_TIME */ |
||
1983 | |||
1984 | TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n", |
||
1985 | (ulg)existing, (ulg)archive, (long)(existing-archive))); |
||
1986 | |||
1987 | return (existing >= archive); |
||
1988 | |||
1989 | } /* end function check_for_newer() */ |
||
1990 | |||
1991 | #endif /* !VMS && !OS2 && !CMS_MVS */ |
||
1992 | |||
1993 | |||
1994 | |||
1995 | |||
1996 | |||
1997 | /************************/ |
||
1998 | /* Function do_string() */ |
||
1999 | /************************/ |
||
2000 | |||
2001 | int do_string(__G__ length, option) /* return PK-type error code */ |
||
2002 | __GDEF |
||
2003 | unsigned int length; /* without prototype, ush converted to this */ |
||
2004 | int option; |
||
2005 | { |
||
2006 | unsigned comment_bytes_left; |
||
2007 | unsigned int block_len; |
||
2008 | int error=PK_OK; |
||
2009 | #ifdef AMIGA |
||
2010 | char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */ |
||
2011 | #endif |
||
2012 | |||
2013 | |||
2014 | /*--------------------------------------------------------------------------- |
||
2015 | This function processes arbitrary-length (well, usually) strings. Four |
||
2016 | major options are allowed: SKIP, wherein the string is skipped (pretty |
||
2017 | logical, eh?); DISPLAY, wherein the string is printed to standard output |
||
2018 | after undergoing any necessary or unnecessary character conversions; |
||
2019 | DS_FN, wherein the string is put into the filename[] array after under- |
||
2020 | going appropriate conversions (including case-conversion, if that is |
||
2021 | indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD, |
||
2022 | wherein the `string' is assumed to be an extra field and is copied to |
||
2023 | the (freshly malloced) buffer G.extra_field. The third option should |
||
2024 | be OK since filename is dimensioned at 1025, but we check anyway. |
||
2025 | |||
2026 | The string, by the way, is assumed to start at the current file-pointer |
||
2027 | position; its length is given by 'length'. So start off by checking the |
||
2028 | length of the string: if zero, we're already done. |
||
2029 | ---------------------------------------------------------------------------*/ |
||
2030 | |||
2031 | if (!length) |
||
2032 | return PK_COOL; |
||
2033 | |||
2034 | switch (option) { |
||
2035 | |||
2036 | #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) |
||
2037 | /* |
||
2038 | * Special case: See if the comment begins with an autorun command line. |
||
2039 | * Save that and display (or skip) the remainder. |
||
2040 | */ |
||
2041 | |||
2042 | case CHECK_AUTORUN: |
||
2043 | case CHECK_AUTORUN_Q: |
||
2044 | comment_bytes_left = length; |
||
2045 | if (length >= 10) |
||
2046 | { |
||
2047 | block_len = readbuf(__G__ (char *)G.outbuf, 10); |
||
2048 | if (block_len == 0) |
||
2049 | return PK_EOF; |
||
2050 | comment_bytes_left -= block_len; |
||
2051 | G.outbuf[block_len] = '\0'; |
||
2052 | if (!strcmp((char *)G.outbuf, "$AUTORUN$>")) { |
||
2053 | char *eol; |
||
2054 | length -= 10; |
||
2055 | block_len = readbuf(__G__ G.autorun_command, |
||
2056 | MIN(length, sizeof(G.autorun_command)-1)); |
||
2057 | if (block_len == 0) |
||
2058 | return PK_EOF; |
||
2059 | comment_bytes_left -= block_len; |
||
2060 | G.autorun_command[block_len] = '\0'; |
||
2061 | A_TO_N(G.autorun_command); |
||
2062 | eol = strchr(G.autorun_command, '\n'); |
||
2063 | if (!eol) |
||
2064 | eol = G.autorun_command + strlen(G.autorun_command) - 1; |
||
2065 | length -= eol + 1 - G.autorun_command; |
||
2066 | while (eol >= G.autorun_command && isspace(*eol)) |
||
2067 | *eol-- = '\0'; |
||
2068 | #if (defined(WIN32) && !defined(_WIN32_WCE)) |
||
2069 | /* Win9x console always uses OEM character coding, and |
||
2070 | WinNT console is set to OEM charset by default, too */ |
||
2071 | INTERN_TO_OEM(G.autorun_command, G.autorun_command); |
||
2072 | #endif /* (WIN32 && !_WIN32_WCE) */ |
||
2073 | } |
||
2074 | } |
||
2075 | if (option == CHECK_AUTORUN_Q) /* don't display the remainder */ |
||
2076 | length = 0; |
||
2077 | /* seek to beginning of remaining part of comment -- rewind if */ |
||
2078 | /* displaying entire comment, or skip to end if discarding it */ |
||
2079 | seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + |
||
2080 | (G.inptr - G.inbuf) + comment_bytes_left - length); |
||
2081 | if (!length) |
||
2082 | break; |
||
2083 | /* FALL THROUGH... */ |
||
2084 | #endif /* SFX && CHEAP_SFX_AUTORUN */ |
||
2085 | |||
2086 | /* |
||
2087 | * First normal case: print string on standard output. First set loop |
||
2088 | * variables, then loop through the comment in chunks of OUTBUFSIZ bytes, |
||
2089 | * converting formats and printing as we go. The second half of the |
||
2090 | * loop conditional was added because the file might be truncated, in |
||
2091 | * which case comment_bytes_left will remain at some non-zero value for |
||
2092 | * all time. outbuf and slide are used as scratch buffers because they |
||
2093 | * are available (we should be either before or in between any file pro- |
||
2094 | * cessing). |
||
2095 | */ |
||
2096 | |||
2097 | case DISPLAY: |
||
2098 | case DISPL_8: |
||
2099 | comment_bytes_left = length; |
||
2100 | block_len = OUTBUFSIZ; /* for the while statement, first time */ |
||
2101 | while (comment_bytes_left > 0 && block_len > 0) { |
||
2102 | register uch *p = G.outbuf; |
||
2103 | register uch *q = G.outbuf; |
||
2104 | |||
2105 | if ((block_len = readbuf(__G__ (char *)G.outbuf, |
||
2106 | MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0) |
||
2107 | return PK_EOF; |
||
2108 | comment_bytes_left -= block_len; |
||
2109 | |||
2110 | /* this is why we allocated an extra byte for outbuf: terminate |
||
2111 | * with zero (ASCIIZ) */ |
||
2112 | G.outbuf[block_len] = '\0'; |
||
2113 | |||
2114 | /* remove all ASCII carriage returns from comment before printing |
||
2115 | * (since used before A_TO_N(), check for CR instead of '\r') |
||
2116 | */ |
||
2117 | while (*p) { |
||
2118 | while (*p == CR) |
||
2119 | ++p; |
||
2120 | *q++ = *p++; |
||
2121 | } |
||
2122 | /* could check whether (p - outbuf) == block_len here */ |
||
2123 | *q = '\0'; |
||
2124 | |||
2125 | if (option == DISPL_8) { |
||
2126 | /* translate the text coded in the entry's host-dependent |
||
2127 | "extended ASCII" charset into the compiler's (system's) |
||
2128 | internal text code page */ |
||
2129 | Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum, |
||
2130 | G.pInfo->hostver, G.pInfo->HasUxAtt, |
||
2131 | FALSE); |
||
2132 | #ifdef WINDLL |
||
2133 | /* translate to ANSI (RTL internal codepage may be OEM) */ |
||
2134 | INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf); |
||
2135 | #else /* !WINDLL */ |
||
2136 | #if (defined(WIN32) && !defined(_WIN32_WCE)) |
||
2137 | /* Win9x console always uses OEM character coding, and |
||
2138 | WinNT console is set to OEM charset by default, too */ |
||
2139 | INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf); |
||
2140 | #endif /* (WIN32 && !_WIN32_WCE) */ |
||
2141 | #endif /* ?WINDLL */ |
||
2142 | } else { |
||
2143 | A_TO_N(G.outbuf); /* translate string to native */ |
||
2144 | } |
||
2145 | |||
2146 | #ifdef WINDLL |
||
2147 | /* ran out of local mem -- had to cheat */ |
||
2148 | win_fprintf((zvoid *)&G, stdout, (extent)(q-G.outbuf), |
||
2149 | (char *)G.outbuf); |
||
2150 | win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n"); |
||
2151 | #else /* !WINDLL */ |
||
2152 | #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */ |
||
2153 | (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0); |
||
2154 | #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */ |
||
2155 | p = G.outbuf - 1; |
||
2156 | q = slide; |
||
2157 | while (*++p) { |
||
2158 | int pause = FALSE; |
||
2159 | |||
2160 | if (*p == 0x1B) { /* ASCII escape char */ |
||
2161 | *q++ = '^'; |
||
2162 | *q++ = '['; |
||
2163 | } else if (*p == 0x13) { /* ASCII ^S (pause) */ |
||
2164 | pause = TRUE; |
||
2165 | if (p[1] == LF) /* ASCII LF */ |
||
2166 | *q++ = *++p; |
||
2167 | else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */ |
||
2168 | *q++ = *++p; |
||
2169 | *q++ = *++p; |
||
2170 | } |
||
2171 | } else |
||
2172 | *q++ = *p; |
||
2173 | if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */ |
||
2174 | (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); |
||
2175 | q = slide; |
||
2176 | if (pause && G.extract_flag) /* don't pause for list/test */ |
||
2177 | (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0); |
||
2178 | } |
||
2179 | } |
||
2180 | (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0); |
||
2181 | #endif /* ?NOANSIFILT */ |
||
2182 | #endif /* ?WINDLL */ |
||
2183 | } |
||
2184 | /* add '\n' if not at start of line */ |
||
2185 | (*G.message)((zvoid *)&G, slide, 0L, 0x40); |
||
2186 | break; |
||
2187 | |||
2188 | /* |
||
2189 | * Second case: read string into filename[] array. The filename should |
||
2190 | * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check, |
||
2191 | * just to be sure. |
||
2192 | */ |
||
2193 | |||
2194 | case DS_FN: |
||
2195 | case DS_FN_L: |
||
2196 | #ifdef UNICODE_SUPPORT |
||
2197 | /* get the whole filename as need it for Unicode checksum */ |
||
2198 | if (G.fnfull_bufsize <= length) { |
||
2199 | extent fnbufsiz = FILNAMSIZ; |
||
2200 | |||
2201 | if (fnbufsiz <= length) |
||
2202 | fnbufsiz = length + 1; |
||
2203 | if (G.filename_full) |
||
2204 | free(G.filename_full); |
||
2205 | G.filename_full = malloc(fnbufsiz); |
||
2206 | if (G.filename_full == NULL) |
||
2207 | return PK_MEM; |
||
2208 | G.fnfull_bufsize = fnbufsiz; |
||
2209 | } |
||
2210 | if (readbuf(__G__ G.filename_full, length) == 0) |
||
2211 | return PK_EOF; |
||
2212 | G.filename_full[length] = '\0'; /* terminate w/zero: ASCIIZ */ |
||
2213 | |||
2214 | /* if needed, chop off end so standard filename is a valid length */ |
||
2215 | if (length >= FILNAMSIZ) { |
||
2216 | Info(slide, 0x401, ((char *)slide, |
||
2217 | LoadFarString(FilenameTooLongTrunc))); |
||
2218 | error = PK_WARN; |
||
2219 | length = FILNAMSIZ - 1; |
||
2220 | } |
||
2221 | /* no excess size */ |
||
2222 | block_len = 0; |
||
2223 | strncpy(G.filename, G.filename_full, length); |
||
2224 | G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ |
||
2225 | #else /* !UNICODE_SUPPORT */ |
||
2226 | if (length >= FILNAMSIZ) { |
||
2227 | Info(slide, 0x401, ((char *)slide, |
||
2228 | LoadFarString(FilenameTooLongTrunc))); |
||
2229 | error = PK_WARN; |
||
2230 | /* remember excess length in block_len */ |
||
2231 | block_len = length - (FILNAMSIZ - 1); |
||
2232 | length = FILNAMSIZ - 1; |
||
2233 | } else |
||
2234 | /* no excess size */ |
||
2235 | block_len = 0; |
||
2236 | if (readbuf(__G__ G.filename, length) == 0) |
||
2237 | return PK_EOF; |
||
2238 | G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ |
||
2239 | #endif /* ?UNICODE_SUPPORT */ |
||
2240 | |||
2241 | /* translate the Zip entry filename coded in host-dependent "extended |
||
2242 | ASCII" into the compiler's (system's) internal text code page */ |
||
2243 | Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver, |
||
2244 | G.pInfo->HasUxAtt, (option == DS_FN_L)); |
||
2245 | |||
2246 | if (G.pInfo->lcflag) /* replace with lowercase filename */ |
||
2247 | STRLOWER(G.filename, G.filename); |
||
2248 | |||
2249 | if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') { |
||
2250 | char *p = G.filename+8; |
||
2251 | while (*p++) |
||
2252 | p[-1] = *p; /* disk label, and 8th char is dot: remove dot */ |
||
2253 | } |
||
2254 | |||
2255 | if (!block_len) /* no overflow, we're done here */ |
||
2256 | break; |
||
2257 | |||
2258 | /* |
||
2259 | * We truncated the filename, so print what's left and then fall |
||
2260 | * through to the SKIP routine. |
||
2261 | */ |
||
2262 | Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename))); |
||
2263 | length = block_len; /* SKIP the excess bytes... */ |
||
2264 | /* FALL THROUGH... */ |
||
2265 | |||
2266 | /* |
||
2267 | * Third case: skip string, adjusting readbuf's internal variables |
||
2268 | * as necessary (and possibly skipping to and reading a new block of |
||
2269 | * data). |
||
2270 | */ |
||
2271 | |||
2272 | case SKIP: |
||
2273 | /* cur_zipfile_bufstart already takes account of extra_bytes, so don't |
||
2274 | * correct for it twice: */ |
||
2275 | seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + |
||
2276 | (G.inptr-G.inbuf) + length); |
||
2277 | break; |
||
2278 | |||
2279 | /* |
||
2280 | * Fourth case: assume we're at the start of an "extra field"; malloc |
||
2281 | * storage for it and read data into the allocated space. |
||
2282 | */ |
||
2283 | |||
2284 | case EXTRA_FIELD: |
||
2285 | if (G.extra_field != (uch *)NULL) |
||
2286 | free(G.extra_field); |
||
2287 | if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) { |
||
2288 | Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), |
||
2289 | length)); |
||
2290 | /* cur_zipfile_bufstart already takes account of extra_bytes, |
||
2291 | * so don't correct for it twice: */ |
||
2292 | seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes + |
||
2293 | (G.inptr-G.inbuf) + length); |
||
2294 | } else { |
||
2295 | if (readbuf(__G__ (char *)G.extra_field, length) == 0) |
||
2296 | return PK_EOF; |
||
2297 | /* Looks like here is where extra fields are read */ |
||
2298 | getZip64Data(__G__ G.extra_field, length); |
||
2299 | #ifdef UNICODE_SUPPORT |
||
2300 | G.unipath_filename = NULL; |
||
2301 | if (G.UzO.U_flag < 2) { |
||
2302 | /* check if GPB11 (General Purpuse Bit 11) is set indicating |
||
2303 | the standard path and comment are UTF-8 */ |
||
2304 | if (G.pInfo->GPFIsUTF8) { |
||
2305 | /* if GPB11 set then filename_full is untruncated UTF-8 */ |
||
2306 | G.unipath_filename = G.filename_full; |
||
2307 | } else { |
||
2308 | /* Get the Unicode fields if exist */ |
||
2309 | getUnicodeData(__G__ G.extra_field, length); |
||
2310 | if (G.unipath_filename && strlen(G.unipath_filename) == 0) { |
||
2311 | /* the standard filename field is UTF-8 */ |
||
2312 | free(G.unipath_filename); |
||
2313 | G.unipath_filename = G.filename_full; |
||
2314 | } |
||
2315 | } |
||
2316 | if (G.unipath_filename) { |
||
2317 | # ifdef UTF8_MAYBE_NATIVE |
||
2318 | if (G.native_is_utf8 |
||
2319 | # ifdef UNICODE_WCHAR |
||
2320 | && (!G.unicode_escape_all) |
||
2321 | # endif |
||
2322 | ) { |
||
2323 | strncpy(G.filename, G.unipath_filename, FILNAMSIZ - 1); |
||
2324 | /* make sure filename is short enough */ |
||
2325 | if (strlen(G.unipath_filename) >= FILNAMSIZ) { |
||
2326 | G.filename[FILNAMSIZ - 1] = '\0'; |
||
2327 | Info(slide, 0x401, ((char *)slide, |
||
2328 | LoadFarString(UFilenameTooLongTrunc))); |
||
2329 | error = PK_WARN; |
||
2330 | } |
||
2331 | } |
||
2332 | # ifdef UNICODE_WCHAR |
||
2333 | else |
||
2334 | # endif |
||
2335 | # endif /* UTF8_MAYBE_NATIVE */ |
||
2336 | # ifdef UNICODE_WCHAR |
||
2337 | { |
||
2338 | char *fn; |
||
2339 | |||
2340 | /* convert UTF-8 to local character set */ |
||
2341 | fn = utf8_to_local_string(G.unipath_filename, |
||
2342 | G.unicode_escape_all); |
||
2343 | /* make sure filename is short enough */ |
||
2344 | if (strlen(fn) >= FILNAMSIZ) { |
||
2345 | fn[FILNAMSIZ - 1] = '\0'; |
||
2346 | Info(slide, 0x401, ((char *)slide, |
||
2347 | LoadFarString(UFilenameTooLongTrunc))); |
||
2348 | error = PK_WARN; |
||
2349 | } |
||
2350 | /* replace filename with converted UTF-8 */ |
||
2351 | strcpy(G.filename, fn); |
||
2352 | free(fn); |
||
2353 | } |
||
2354 | # endif /* UNICODE_WCHAR */ |
||
2355 | if (G.unipath_filename != G.filename_full) |
||
2356 | free(G.unipath_filename); |
||
2357 | G.unipath_filename = NULL; |
||
2358 | } |
||
2359 | } |
||
2360 | #endif /* UNICODE_SUPPORT */ |
||
2361 | } |
||
2362 | break; |
||
2363 | |||
2364 | #ifdef AMIGA |
||
2365 | /* |
||
2366 | * Fifth case, for the Amiga only: take the comment that would ordinarily |
||
2367 | * be skipped over, and turn it into a 79 character string that will be |
||
2368 | * attached to the file as a "filenote" after it is extracted. |
||
2369 | */ |
||
2370 | |||
2371 | case FILENOTE: |
||
2372 | if ((block_len = readbuf(__G__ tmp_fnote, (unsigned) |
||
2373 | MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0) |
||
2374 | return PK_EOF; |
||
2375 | if ((length -= block_len) > 0) /* treat remainder as in case SKIP: */ |
||
2376 | seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes |
||
2377 | + (G.inptr - G.inbuf) + length); |
||
2378 | /* convert multi-line text into single line with no ctl-chars: */ |
||
2379 | tmp_fnote[block_len] = '\0'; |
||
2380 | while ((short int) --block_len >= 0) |
||
2381 | if ((unsigned) tmp_fnote[block_len] < ' ') |
||
2382 | if (tmp_fnote[block_len+1] == ' ') /* no excess */ |
||
2383 | strcpy(tmp_fnote+block_len, tmp_fnote+block_len+1); |
||
2384 | else |
||
2385 | tmp_fnote[block_len] = ' '; |
||
2386 | tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0'; |
||
2387 | if (G.filenotes[G.filenote_slot]) |
||
2388 | free(G.filenotes[G.filenote_slot]); /* should not happen */ |
||
2389 | G.filenotes[G.filenote_slot] = NULL; |
||
2390 | if (tmp_fnote[0]) { |
||
2391 | if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1))) |
||
2392 | return PK_MEM; |
||
2393 | strcpy(G.filenotes[G.filenote_slot], tmp_fnote); |
||
2394 | } |
||
2395 | break; |
||
2396 | #endif /* AMIGA */ |
||
2397 | |||
2398 | } /* end switch (option) */ |
||
2399 | |||
2400 | return error; |
||
2401 | |||
2402 | } /* end function do_string() */ |
||
2403 | |||
2404 | |||
2405 | |||
2406 | |||
2407 | |||
2408 | /***********************/ |
||
2409 | /* Function makeword() */ |
||
2410 | /***********************/ |
||
2411 | |||
2412 | ush makeword(b) |
||
2413 | ZCONST uch *b; |
||
2414 | { |
||
2415 | /* |
||
2416 | * Convert Intel style 'short' integer to non-Intel non-16-bit |
||
2417 | * host format. This routine also takes care of byte-ordering. |
||
2418 | */ |
||
2419 | return (ush)((b[1] << 8) | b[0]); |
||
2420 | } |
||
2421 | |||
2422 | |||
2423 | |||
2424 | |||
2425 | |||
2426 | /***********************/ |
||
2427 | /* Function makelong() */ |
||
2428 | /***********************/ |
||
2429 | |||
2430 | ulg makelong(sig) |
||
2431 | ZCONST uch *sig; |
||
2432 | { |
||
2433 | /* |
||
2434 | * Convert intel style 'long' variable to non-Intel non-16-bit |
||
2435 | * host format. This routine also takes care of byte-ordering. |
||
2436 | */ |
||
2437 | return (((ulg)sig[3]) << 24) |
||
2438 | + (((ulg)sig[2]) << 16) |
||
2439 | + (ulg)((((unsigned)sig[1]) << 8) |
||
2440 | + ((unsigned)sig[0])); |
||
2441 | } |
||
2442 | |||
2443 | |||
2444 | |||
2445 | |||
2446 | |||
2447 | /************************/ |
||
2448 | /* Function makeint64() */ |
||
2449 | /************************/ |
||
2450 | |||
2451 | zusz_t makeint64(sig) |
||
2452 | ZCONST uch *sig; |
||
2453 | { |
||
2454 | #ifdef LARGE_FILE_SUPPORT |
||
2455 | /* |
||
2456 | * Convert intel style 'int64' variable to non-Intel non-16-bit |
||
2457 | * host format. This routine also takes care of byte-ordering. |
||
2458 | */ |
||
2459 | return (((zusz_t)sig[7]) << 56) |
||
2460 | + (((zusz_t)sig[6]) << 48) |
||
2461 | + (((zusz_t)sig[4]) << 32) |
||
2462 | + (zusz_t)((((ulg)sig[3]) << 24) |
||
2463 | + (((ulg)sig[2]) << 16) |
||
2464 | + (((unsigned)sig[1]) << 8) |
||
2465 | + (sig[0])); |
||
2466 | |||
2467 | #else /* !LARGE_FILE_SUPPORT */ |
||
2468 | |||
2469 | if ((sig[7] | sig[6] | sig[5] | sig[4]) != 0) |
||
2470 | return (zusz_t)0xffffffffL; |
||
2471 | else |
||
2472 | return (zusz_t)((((ulg)sig[3]) << 24) |
||
2473 | + (((ulg)sig[2]) << 16) |
||
2474 | + (((unsigned)sig[1]) << 8) |
||
2475 | + (sig[0])); |
||
2476 | |||
2477 | #endif /* ?LARGE_FILE_SUPPORT */ |
||
2478 | } |
||
2479 | |||
2480 | |||
2481 | |||
2482 | |||
2483 | |||
2484 | /*********************/ |
||
2485 | /* Function fzofft() */ |
||
2486 | /*********************/ |
||
2487 | |||
2488 | /* Format a zoff_t value in a cylindrical buffer set. */ |
||
2489 | char *fzofft(__G__ val, pre, post) |
||
2490 | __GDEF |
||
2491 | zoff_t val; |
||
2492 | ZCONST char *pre; |
||
2493 | ZCONST char *post; |
||
2494 | { |
||
2495 | /* Storage cylinder. (now in globals.h) */ |
||
2496 | /*static char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];*/ |
||
2497 | /*static int fzofft_index = 0;*/ |
||
2498 | |||
2499 | /* Temporary format string storage. */ |
||
2500 | char fmt[16]; |
||
2501 | |||
2502 | /* Assemble the format string. */ |
||
2503 | fmt[0] = '%'; |
||
2504 | fmt[1] = '\0'; /* Start after initial "%". */ |
||
2505 | if (pre == FZOFFT_HEX_WID) /* Special hex width. */ |
||
2506 | { |
||
2507 | strcat(fmt, FZOFFT_HEX_WID_VALUE); |
||
2508 | } |
||
2509 | else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex ".width". */ |
||
2510 | { |
||
2511 | strcat(fmt, "."); |
||
2512 | strcat(fmt, FZOFFT_HEX_WID_VALUE); |
||
2513 | } |
||
2514 | else if (pre != NULL) /* Caller's prefix (width). */ |
||
2515 | { |
||
2516 | strcat(fmt, pre); |
||
2517 | } |
||
2518 | |||
2519 | strcat(fmt, FZOFFT_FMT); /* Long or long-long or whatever. */ |
||
2520 | |||
2521 | if (post == NULL) |
||
2522 | strcat(fmt, "d"); /* Default radix = decimal. */ |
||
2523 | else |
||
2524 | strcat(fmt, post); /* Caller's radix. */ |
||
2525 | |||
2526 | /* Advance the cylinder. */ |
||
2527 | G.fzofft_index = (G.fzofft_index + 1) % FZOFFT_NUM; |
||
2528 | |||
2529 | /* Write into the current chamber. */ |
||
2530 | sprintf(G.fzofft_buf[G.fzofft_index], fmt, val); |
||
2531 | |||
2532 | /* Return a pointer to this chamber. */ |
||
2533 | return G.fzofft_buf[G.fzofft_index]; |
||
2534 | } |
||
2535 | |||
2536 | |||
2537 | |||
2538 | |||
2539 | #if CRYPT |
||
2540 | |||
2541 | #ifdef NEED_STR2ISO |
||
2542 | /**********************/ |
||
2543 | /* Function str2iso() */ |
||
2544 | /**********************/ |
||
2545 | |||
2546 | char *str2iso(dst, src) |
||
2547 | char *dst; /* destination buffer */ |
||
2548 | register ZCONST char *src; /* source string */ |
||
2549 | { |
||
2550 | #ifdef INTERN_TO_ISO |
||
2551 | INTERN_TO_ISO(src, dst); |
||
2552 | #else |
||
2553 | register uch c; |
||
2554 | register char *dstp = dst; |
||
2555 | |||
2556 | do { |
||
2557 | c = (uch)foreign(*src++); |
||
2558 | *dstp++ = (char)ASCII2ISO(c); |
||
2559 | } while (c != '\0'); |
||
2560 | #endif |
||
2561 | |||
2562 | return dst; |
||
2563 | } |
||
2564 | #endif /* NEED_STR2ISO */ |
||
2565 | |||
2566 | |||
2567 | #ifdef NEED_STR2OEM |
||
2568 | /**********************/ |
||
2569 | /* Function str2oem() */ |
||
2570 | /**********************/ |
||
2571 | |||
2572 | char *str2oem(dst, src) |
||
2573 | char *dst; /* destination buffer */ |
||
2574 | register ZCONST char *src; /* source string */ |
||
2575 | { |
||
2576 | #ifdef INTERN_TO_OEM |
||
2577 | INTERN_TO_OEM(src, dst); |
||
2578 | #else |
||
2579 | register uch c; |
||
2580 | register char *dstp = dst; |
||
2581 | |||
2582 | do { |
||
2583 | c = (uch)foreign(*src++); |
||
2584 | *dstp++ = (char)ASCII2OEM(c); |
||
2585 | } while (c != '\0'); |
||
2586 | #endif |
||
2587 | |||
2588 | return dst; |
||
2589 | } |
||
2590 | #endif /* NEED_STR2OEM */ |
||
2591 | |||
2592 | #endif /* CRYPT */ |
||
2593 | |||
2594 | |||
2595 | #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */ |
||
2596 | /* bzero/bcmp/bcopy */ |
||
2597 | /* (no known systems as of 960211) */ |
||
2598 | |||
2599 | /*********************/ |
||
2600 | /* Function memset() */ |
||
2601 | /*********************/ |
||
2602 | |||
2603 | zvoid *memset(buf, init, len) |
||
2604 | register zvoid *buf; /* buffer location */ |
||
2605 | register int init; /* initializer character */ |
||
2606 | register unsigned int len; /* length of the buffer */ |
||
2607 | { |
||
2608 | zvoid *start; |
||
2609 | |||
2610 | start = buf; |
||
2611 | while (len--) |
||
2612 | *((char *)buf++) = (char)init; |
||
2613 | return start; |
||
2614 | } |
||
2615 | |||
2616 | |||
2617 | |||
2618 | /*********************/ |
||
2619 | /* Function memcmp() */ |
||
2620 | /*********************/ |
||
2621 | |||
2622 | int memcmp(b1, b2, len) |
||
2623 | register ZCONST zvoid *b1; |
||
2624 | register ZCONST zvoid *b2; |
||
2625 | register unsigned int len; |
||
2626 | { |
||
2627 | register int c; |
||
2628 | |||
2629 | if (len > 0) do { |
||
2630 | if ((c = (int)(*((ZCONST unsigned char *)b1)++) - |
||
2631 | (int)(*((ZCONST unsigned char *)b2)++)) != 0) |
||
2632 | return c; |
||
2633 | } while (--len > 0) |
||
2634 | return 0; |
||
2635 | } |
||
2636 | |||
2637 | |||
2638 | |||
2639 | /*********************/ |
||
2640 | /* Function memcpy() */ |
||
2641 | /*********************/ |
||
2642 | |||
2643 | zvoid *memcpy(dst, src, len) |
||
2644 | register zvoid *dst; |
||
2645 | register ZCONST zvoid *src; |
||
2646 | register unsigned int len; |
||
2647 | { |
||
2648 | zvoid *start; |
||
2649 | |||
2650 | start = dst; |
||
2651 | while (len-- > 0) |
||
2652 | *((char *)dst)++ = *((ZCONST char *)src)++; |
||
2653 | return start; |
||
2654 | } |
||
2655 | |||
2656 | #endif /* ZMEM */ |
||
2657 | |||
2658 | |||
2659 | |||
2660 | |||
2661 | #ifdef NO_STRNICMP |
||
2662 | |||
2663 | /************************/ |
||
2664 | /* Function zstrnicmp() */ |
||
2665 | /************************/ |
||
2666 | |||
2667 | int zstrnicmp(s1, s2, n) |
||
2668 | register ZCONST char *s1, *s2; |
||
2669 | register unsigned n; |
||
2670 | { |
||
2671 | for (; n > 0; --n, ++s1, ++s2) { |
||
2672 | |||
2673 | if (ToLower(*s1) != ToLower(*s2)) |
||
2674 | /* test includes early termination of one string */ |
||
2675 | return ((uch)ToLower(*s1) < (uch)ToLower(*s2))? -1 : 1; |
||
2676 | |||
2677 | if (*s1 == '\0') /* both strings terminate early */ |
||
2678 | return 0; |
||
2679 | } |
||
2680 | return 0; |
||
2681 | } |
||
2682 | |||
2683 | #endif /* NO_STRNICMP */ |
||
2684 | |||
2685 | |||
2686 | |||
2687 | |||
2688 | #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */ |
||
2689 | # undef stat |
||
2690 | |||
2691 | /********************/ |
||
2692 | /* Function zstat() */ |
||
2693 | /********************/ |
||
2694 | |||
2695 | int zstat(p, s) |
||
2696 | ZCONST char *p; |
||
2697 | struct stat *s; |
||
2698 | { |
||
2699 | return (stat((char *)p,s) >= 0? 0 : (-1)); |
||
2700 | } |
||
2701 | |||
2702 | #endif /* REGULUS */ |
||
2703 | |||
2704 | |||
2705 | |||
2706 | |||
2707 | #ifdef _MBCS |
||
2708 | |||
2709 | /* DBCS support for Info-ZIP's zip (mainly for japanese (-: ) |
||
2710 | * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp) |
||
2711 | * This code is public domain! Date: 1998/12/20 |
||
2712 | */ |
||
2713 | |||
2714 | /************************/ |
||
2715 | /* Function plastchar() */ |
||
2716 | /************************/ |
||
2717 | |||
2718 | char *plastchar(ptr, len) |
||
2719 | ZCONST char *ptr; |
||
2720 | extent len; |
||
2721 | { |
||
2722 | unsigned clen; |
||
2723 | ZCONST char *oldptr = ptr; |
||
2724 | while(*ptr != '\0' && len > 0){ |
||
2725 | oldptr = ptr; |
||
2726 | clen = CLEN(ptr); |
||
2727 | ptr += clen; |
||
2728 | len -= clen; |
||
2729 | } |
||
2730 | return (char *)oldptr; |
||
2731 | } |
||
2732 | |||
2733 | |||
2734 | #ifdef NEED_UZMBCLEN |
||
2735 | /***********************/ |
||
2736 | /* Function uzmbclen() */ |
||
2737 | /***********************/ |
||
2738 | |||
2739 | extent uzmbclen(ptr) |
||
2740 | ZCONST unsigned char *ptr; |
||
2741 | { |
||
2742 | int mbl; |
||
2743 | |||
2744 | mbl = mblen((ZCONST char *)ptr, MB_CUR_MAX); |
||
2745 | /* For use in code scanning through MBCS strings, we need a strictly |
||
2746 | positive "MB char bytes count". For our scanning purpose, it is not |
||
2747 | not relevant whether the MB character is valid or not. And, the NUL |
||
2748 | char '\0' has a byte count of 1, but mblen() returns 0. So, we make |
||
2749 | sure that the uzmbclen() return value is not less than 1. |
||
2750 | */ |
||
2751 | return (extent)(mbl > 0 ? mbl : 1); |
||
2752 | } |
||
2753 | #endif /* NEED_UZMBCLEN */ |
||
2754 | |||
2755 | |||
2756 | #ifdef NEED_UZMBSCHR |
||
2757 | /***********************/ |
||
2758 | /* Function uzmbschr() */ |
||
2759 | /***********************/ |
||
2760 | |||
2761 | unsigned char *uzmbschr(str, c) |
||
2762 | ZCONST unsigned char *str; |
||
2763 | unsigned int c; |
||
2764 | { |
||
2765 | while(*str != '\0'){ |
||
2766 | if (*str == c) {return (unsigned char *)str;} |
||
2767 | INCSTR(str); |
||
2768 | } |
||
2769 | return NULL; |
||
2770 | } |
||
2771 | #endif /* NEED_UZMBSCHR */ |
||
2772 | |||
2773 | |||
2774 | #ifdef NEED_UZMBSRCHR |
||
2775 | /************************/ |
||
2776 | /* Function uzmbsrchr() */ |
||
2777 | /************************/ |
||
2778 | |||
2779 | unsigned char *uzmbsrchr(str, c) |
||
2780 | ZCONST unsigned char *str; |
||
2781 | unsigned int c; |
||
2782 | { |
||
2783 | unsigned char *match = NULL; |
||
2784 | while(*str != '\0'){ |
||
2785 | if (*str == c) {match = (unsigned char *)str;} |
||
2786 | INCSTR(str); |
||
2787 | } |
||
2788 | return match; |
||
2789 | } |
||
2790 | #endif /* NEED_UZMBSRCHR */ |
||
2791 | #endif /* _MBCS */ |
||
2792 | |||
2793 | |||
2794 | |||
2795 | |||
2796 | |||
2797 | #ifdef SMALL_MEM |
||
2798 | |||
2799 | /*******************************/ |
||
2800 | /* Function fLoadFarString() */ /* (and friends...) */ |
||
2801 | /*******************************/ |
||
2802 | |||
2803 | char *fLoadFarString(__GPRO__ const char Far *sz) |
||
2804 | { |
||
2805 | (void)zfstrcpy(G.rgchBigBuffer, sz); |
||
2806 | return G.rgchBigBuffer; |
||
2807 | } |
||
2808 | |||
2809 | char *fLoadFarStringSmall(__GPRO__ const char Far *sz) |
||
2810 | { |
||
2811 | (void)zfstrcpy(G.rgchSmallBuffer, sz); |
||
2812 | return G.rgchSmallBuffer; |
||
2813 | } |
||
2814 | |||
2815 | char *fLoadFarStringSmall2(__GPRO__ const char Far *sz) |
||
2816 | { |
||
2817 | (void)zfstrcpy(G.rgchSmallBuffer2, sz); |
||
2818 | return G.rgchSmallBuffer2; |
||
2819 | } |
||
2820 | |||
2821 | |||
2822 | |||
2823 | |||
2824 | #if (!defined(_MSC_VER) || (_MSC_VER < 600)) |
||
2825 | /*************************/ |
||
2826 | /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */ |
||
2827 | /*************************/ |
||
2828 | |||
2829 | char Far * Far zfstrcpy(char Far *s1, const char Far *s2) |
||
2830 | { |
||
2831 | char Far *p = s1; |
||
2832 | |||
2833 | while ((*s1++ = *s2++) != '\0'); |
||
2834 | return p; |
||
2835 | } |
||
2836 | |||
2837 | #if (!(defined(SFX) || defined(FUNZIP))) |
||
2838 | /*************************/ |
||
2839 | /* Function zfstrcmp() */ /* portable clone of _fstrcmp() */ |
||
2840 | /*************************/ |
||
2841 | |||
2842 | int Far zfstrcmp(const char Far *s1, const char Far *s2) |
||
2843 | { |
||
2844 | int ret; |
||
2845 | |||
2846 | while ((ret = (int)(uch)*s1 - (int)(uch)*s2) == 0 |
||
2847 | && *s2 != '\0') { |
||
2848 | ++s2; ++s1; |
||
2849 | } |
||
2850 | return ret; |
||
2851 | } |
||
2852 | #endif /* !(SFX || FUNZIP) */ |
||
2853 | #endif /* !_MSC_VER || (_MSC_VER < 600) */ |
||
2854 | |||
2855 | #endif /* SMALL_MEM */>>>><>><>><>><>><>><>><>><>><>><>><>><>><>>>=>=>><><<>><>>>>>>>><>>><><<>>>><>>=>>=>>=>=>>=>>>>=>>>> |