Details | 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 | globals.h |
||
12 | |||
13 | There is usually no need to include this file since unzip.h includes it. |
||
14 | |||
15 | This header file is used by all of the UnZip source files. It contains |
||
16 | a struct definition that is used to "house" all of the global variables. |
||
17 | This is done to allow for multithreaded environments (OS/2, NT, Win95, |
||
18 | Unix) to call UnZip through an API without a semaphore. REENTRANT should |
||
19 | be defined for all platforms that require this. |
||
20 | |||
21 | GLOBAL CONSTRUCTOR AND DESTRUCTOR (API WRITERS READ THIS!!!) |
||
22 | ------------------------------------------------------------ |
||
23 | |||
24 | No, it's not C++, but it's as close as we can get with K&R. |
||
25 | |||
26 | The main() of each process that uses these globals must include the |
||
27 | CONSTRUCTGLOBALS; statement. This will malloc enough memory for the |
||
28 | structure and initialize any variables that require it. This must |
||
29 | also be done by any API function that jumps into the middle of the |
||
30 | code. |
||
31 | |||
32 | The DESTROYGLOBALS(); statement should be inserted before EVERY "EXIT(n)". |
||
33 | Naturally, it also needs to be put before any API returns as well. |
||
34 | In fact, it's much more important in API functions since the process |
||
35 | will NOT end, and therefore the memory WON'T automatically be freed |
||
36 | by the operating system. |
||
37 | |||
38 | USING VARIABLES FROM THE STRUCTURE |
||
39 | ---------------------------------- |
||
40 | |||
41 | All global variables must now be prefixed with `G.' which is either a |
||
42 | global struct (in which case it should be the only global variable) or |
||
43 | a macro for the value of a local pointer variable that is passed from |
||
44 | function to function. Yes, this is a pain. But it's the only way to |
||
45 | allow full reentrancy. |
||
46 | |||
47 | ADDING VARIABLES TO THE STRUCTURE |
||
48 | --------------------------------- |
||
49 | |||
50 | If you make the inclusion of any variables conditional, be sure to only |
||
51 | check macros that are GUARANTEED to be included in every module. |
||
52 | For instance, newzip and pwdarg are needed only if CRYPT is TRUE, |
||
53 | but this is defined after unzip.h has been read. If you are not careful, |
||
54 | some modules will expect your variable to be part of this struct while |
||
55 | others won't. This will cause BIG problems. (Inexplicable crashes at |
||
56 | strange times, car fires, etc.) When in doubt, always include it! |
||
57 | |||
58 | Note also that UnZipSFX needs a few variables that UnZip doesn't. However, |
||
59 | it also includes some object files from UnZip. If we were to conditionally |
||
60 | include the extra variables that UnZipSFX needs, the object files from |
||
61 | UnZip would not mesh with the UnZipSFX object files. Result: we just |
||
62 | include the UnZipSFX variables every time. (It's only an extra 4 bytes |
||
63 | so who cares!) |
||
64 | |||
65 | ADDING FUNCTIONS |
||
66 | ---------------- |
||
67 | |||
68 | To support this new global struct, all functions must now conditionally |
||
69 | pass the globals pointer (pG) to each other. This is supported by 5 macros: |
||
70 | __GPRO, __GPRO__, __G, __G__ and __GDEF. A function that needs no other |
||
71 | parameters would look like this: |
||
72 | |||
73 | int extract_or_test_files(__G) |
||
74 | __GDEF |
||
75 | { |
||
76 | ... stuff ... |
||
77 | } |
||
78 | |||
79 | A function with other parameters would look like: |
||
80 | |||
81 | int memextract(__G__ tgt, tgtsize, src, srcsize) |
||
82 | __GDEF |
||
83 | uch *tgt, *src; |
||
84 | ulg tgtsize, srcsize; |
||
85 | { |
||
86 | ... stuff ... |
||
87 | } |
||
88 | |||
89 | In the Function Prototypes section of unzpriv.h, you should use __GPRO and |
||
90 | __GPRO__ instead: |
||
91 | |||
92 | int uz_opts OF((__GPRO__ int *pargc, char ***pargv)); |
||
93 | int process_zipfiles OF((__GPRO)); |
||
94 | |||
95 | Note that there is NO comma after __G__ or __GPRO__ and no semi-colon after |
||
96 | __GDEF. I wish there was another way but I don't think there is. |
||
97 | |||
98 | |||
99 | TESTING THE CODE |
||
100 | ----------------- |
||
101 | |||
102 | Whether your platform requires reentrancy or not, you should always try |
||
103 | building with REENTRANT defined if any functions have been added. It is |
||
104 | pretty easy to forget a __G__ or a __GDEF and this mistake will only show |
||
105 | up if REENTRANT is defined. All platforms should run with REENTRANT |
||
106 | defined. Platforms that can't take advantage of it will just be paying |
||
107 | a performance penalty needlessly. |
||
108 | |||
109 | SIGNAL MADNESS |
||
110 | -------------- |
||
111 | |||
112 | This whole pointer passing scheme falls apart when it comes to SIGNALs. |
||
113 | I handle this situation 2 ways right now. If you define USETHREADID, |
||
114 | UnZip will include a 64-entry table. Each entry can hold a global |
||
115 | pointer and thread ID for one thread. This should allow up to 64 |
||
116 | threads to access UnZip simultaneously. Calling DESTROYGLOBALS() |
||
117 | will free the global struct and zero the table entry. If somebody |
||
118 | forgets to call DESTROYGLOBALS(), this table will eventually fill up |
||
119 | and UnZip will exit with an error message. A good way to test your |
||
120 | code to make sure you didn't forget a DESTROYGLOBALS() is to change |
||
121 | THREADID_ENTRIES to 3 or 4 in globals.c, making the table real small. |
||
122 | Then make a small test program that calls your API a dozen times. |
||
123 | |||
124 | Those platforms that don't have threads still need to be able to compile |
||
125 | with REENTRANT defined to test and see if new code is correctly written |
||
126 | to work either way. For these platforms, I simply keep a global pointer |
||
127 | called GG that points to the Globals structure. Good enough for testing. |
||
128 | |||
129 | I believe that NT has thread level storage. This could probably be used |
||
130 | to store a global pointer for the sake of the signal handler more cleanly |
||
131 | than my table approach. |
||
132 | |||
133 | ---------------------------------------------------------------------------*/ |
||
134 | |||
135 | #ifndef __globals_h |
||
136 | #define __globals_h |
||
137 | |||
138 | #ifdef USE_ZLIB |
||
139 | # include "zlib.h" |
||
140 | # ifdef zlib_version /* This name is used internally in unzip */ |
||
141 | # undef zlib_version /* and must not be defined as a macro. */ |
||
142 | # endif |
||
143 | #endif |
||
144 | |||
145 | #ifdef USE_BZIP2 |
||
146 | # include "bzlib.h" |
||
147 | #endif |
||
148 | |||
149 | |||
150 | /*************/ |
||
151 | /* Globals */ |
||
152 | /*************/ |
||
153 | |||
154 | typedef struct Globals { |
||
155 | #ifdef DLL |
||
156 | zvoid *callerglobs; /* pointer to structure of pass-through global vars */ |
||
157 | #endif |
||
158 | |||
159 | /* command options of general use */ |
||
160 | UzpOpts UzO; /* command options of general use */ |
||
161 | |||
162 | #ifndef FUNZIP |
||
163 | /* command options specific to the high level command line interface */ |
||
164 | #ifdef MORE |
||
165 | int M_flag; /* -M: built-in "more" function */ |
||
166 | #endif |
||
167 | |||
168 | /* internal flags and general globals */ |
||
169 | #ifdef MORE |
||
170 | int height; /* check for SIGWINCH, etc., eventually... */ |
||
171 | int lines; /* count of lines displayed on current screen */ |
||
172 | # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) |
||
173 | int width; |
||
174 | int chars; /* count of screen characters in current line */ |
||
175 | # endif |
||
176 | #endif /* MORE */ |
||
177 | #if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) |
||
178 | int tz_is_valid; /* indicates that timezone info can be used */ |
||
179 | #endif |
||
180 | int noargs; /* did true command line have *any* arguments? */ |
||
181 | unsigned filespecs; /* number of real file specifications to be matched */ |
||
182 | unsigned xfilespecs; /* number of excluded filespecs to be matched */ |
||
183 | int process_all_files; |
||
184 | int overwrite_mode; /* 0 - query, 1 - always, 2 - never */ |
||
185 | int create_dirs; /* used by main(), mapname(), checkdir() */ |
||
186 | int extract_flag; |
||
187 | int newzip; /* reset in extract.c; used in crypt.c */ |
||
188 | zoff_t real_ecrec_offset; |
||
189 | zoff_t expect_ecrec_offset; |
||
190 | zoff_t csize; /* used by decompr. (NEXTBYTE): must be signed */ |
||
191 | zoff_t used_csize; /* used by extract_or_test_member(), explode() */ |
||
192 | |||
193 | #ifdef DLL |
||
194 | int fValidate; /* true if only validating an archive */ |
||
195 | int filenotfound; |
||
196 | int redirect_data; /* redirect data to memory buffer */ |
||
197 | int redirect_text; /* redirect text output to buffer */ |
||
198 | # ifndef NO_SLIDE_REDIR |
||
199 | int redirect_slide; /* redirect decompression area to mem buffer */ |
||
200 | # if (defined(USE_DEFLATE64) && defined(INT_16BIT)) |
||
201 | ulg _wsize; /* size of sliding window exceeds "unsigned" range */ |
||
202 | # else |
||
203 | unsigned _wsize; /* sliding window size can be hold in unsigned */ |
||
204 | # endif |
||
205 | # endif |
||
206 | ulg redirect_size; /* size of redirected output buffer */ |
||
207 | uch *redirect_buffer; /* pointer to head of allocated buffer */ |
||
208 | uch *redirect_pointer; /* pointer past end of written data */ |
||
209 | # ifndef NO_SLIDE_REDIR |
||
210 | uch *redirect_sldptr; /* head of decompression slide buffer */ |
||
211 | # endif |
||
212 | # ifdef OS2DLL |
||
213 | cbList(processExternally); /* call-back list */ |
||
214 | # endif |
||
215 | #endif /* DLL */ |
||
216 | |||
217 | char **pfnames; |
||
218 | char **pxnames; |
||
219 | char sig[4]; |
||
220 | char answerbuf[10]; |
||
221 | min_info info[DIR_BLKSIZ]; |
||
222 | min_info *pInfo; |
||
223 | #endif /* !FUNZIP */ |
||
224 | union work area; /* see unzpriv.h for definition of work */ |
||
225 | |||
226 | #if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) |
||
227 | ZCONST ulg near *crc_32_tab; |
||
228 | #else |
||
229 | ZCONST ulg Far *crc_32_tab; |
||
230 | #endif |
||
231 | ulg crc32val; /* CRC shift reg. (was static in funzip) */ |
||
232 | |||
233 | #ifdef FUNZIP |
||
234 | FILE *in; /* file descriptor of compressed stream */ |
||
235 | #endif |
||
236 | uch *inbuf; /* input buffer (any size is OK) */ |
||
237 | uch *inptr; /* pointer into input buffer */ |
||
238 | int incnt; |
||
239 | |||
240 | #ifndef FUNZIP |
||
241 | ulg bitbuf; |
||
242 | int bits_left; /* unreduce and unshrink only */ |
||
243 | int zipeof; |
||
244 | char *argv0; /* used for NT and EXE_EXTENSION */ |
||
245 | char *wildzipfn; |
||
246 | char *zipfn; /* GRR: WINDLL: must nuke any malloc'd zipfn... */ |
||
247 | #ifdef USE_STRM_INPUT |
||
248 | FILE *zipfd; /* zipfile file descriptor */ |
||
249 | #else |
||
250 | int zipfd; /* zipfile file handle */ |
||
251 | #endif |
||
252 | zoff_t ziplen; |
||
253 | zoff_t cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */ |
||
254 | zoff_t extra_bytes; /* used in unzip.c, misc.c */ |
||
255 | uch *extra_field; /* Unix, VMS, Mac, OS/2, Acorn, ... */ |
||
256 | uch *hold; |
||
257 | |||
258 | local_file_hdr lrec; /* used in unzip.c, extract.c */ |
||
259 | cdir_file_hdr crec; /* used in unzip.c, extract.c, misc.c */ |
||
260 | ecdir_rec ecrec; /* used in unzip.c, extract.c */ |
||
261 | z_stat statbuf; /* used by main, mapname, check_for_newer */ |
||
262 | |||
263 | int mem_mode; |
||
264 | uch *outbufptr; /* extract.c static */ |
||
265 | ulg outsize; /* extract.c static */ |
||
266 | int reported_backslash; /* extract.c static */ |
||
267 | int disk_full; |
||
268 | int newfile; |
||
269 | |||
270 | int didCRlast; /* fileio static */ |
||
271 | ulg numlines; /* fileio static: number of lines printed */ |
||
272 | int sol; /* fileio static: at start of line */ |
||
273 | int no_ecrec; /* process static */ |
||
274 | #ifdef SYMLINKS |
||
275 | int symlnk; |
||
276 | slinkentry *slink_head; /* pointer to head of symlinks list */ |
||
277 | slinkentry *slink_last; /* pointer to last entry in symlinks list */ |
||
278 | #endif |
||
279 | #ifdef NOVELL_BUG_FAILSAFE |
||
280 | int dne; /* true if stat() says file doesn't exist */ |
||
281 | #endif |
||
282 | |||
283 | FILE *outfile; |
||
284 | uch *outbuf; |
||
285 | uch *realbuf; |
||
286 | |||
287 | #ifndef VMS /* if SMALL_MEM, outbuf2 is initialized in */ |
||
288 | uch *outbuf2; /* process_zipfiles() (never changes); */ |
||
289 | #endif /* else malloc'd ONLY if unshrink and -a */ |
||
290 | #endif /* !FUNZIP */ |
||
291 | uch *outptr; |
||
292 | ulg outcnt; /* number of chars stored in outbuf */ |
||
293 | #ifndef FUNZIP |
||
294 | char filename[FILNAMSIZ]; /* also used by NT for temporary SFX path */ |
||
295 | #ifdef UNICODE_SUPPORT |
||
296 | char *filename_full; /* the full path so Unicode checks work */ |
||
297 | extent fnfull_bufsize; /* size of allocated filename buffer */ |
||
298 | int unicode_escape_all; |
||
299 | int unicode_mismatch; |
||
300 | #ifdef UTF8_MAYBE_NATIVE |
||
301 | int native_is_utf8; /* bool, TRUE => native charset == UTF-8 */ |
||
302 | #endif |
||
303 | |||
304 | int unipath_version; /* version of Unicode field */ |
||
305 | ulg unipath_checksum; /* Unicode field checksum */ |
||
306 | char *unipath_filename; /* UTF-8 path */ |
||
307 | #endif /* UNICODE_SUPPORT */ |
||
308 | |||
309 | #ifdef CMS_MVS |
||
310 | char *tempfn; /* temp file used; erase on close */ |
||
311 | #endif |
||
312 | |||
313 | char *key; /* crypt static: decryption password or NULL */ |
||
314 | int nopwd; /* crypt static */ |
||
315 | #endif /* !FUNZIP */ |
||
316 | z_uint4 keys[3]; /* crypt static: keys defining pseudo-random sequence */ |
||
317 | |||
318 | #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) |
||
319 | #if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) |
||
320 | int echofd; /* ttyio static: file descriptor whose echo is off */ |
||
321 | #endif /* !(MACOS || ATARI || VMS) */ |
||
322 | #endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ |
||
323 | |||
324 | unsigned hufts; /* track memory usage */ |
||
325 | |||
326 | #ifdef USE_ZLIB |
||
327 | int inflInit; /* inflate static: zlib inflate() initialized */ |
||
328 | z_stream dstrm; /* inflate global: decompression stream */ |
||
329 | #else |
||
330 | struct huft *fixed_tl; /* inflate static */ |
||
331 | struct huft *fixed_td; /* inflate static */ |
||
332 | unsigned fixed_bl, fixed_bd; /* inflate static */ |
||
333 | #ifdef USE_DEFLATE64 |
||
334 | struct huft *fixed_tl64; /* inflate static */ |
||
335 | struct huft *fixed_td64; /* inflate static */ |
||
336 | unsigned fixed_bl64, fixed_bd64; /* inflate static */ |
||
337 | struct huft *fixed_tl32; /* inflate static */ |
||
338 | struct huft *fixed_td32; /* inflate static */ |
||
339 | unsigned fixed_bl32, fixed_bd32; /* inflate static */ |
||
340 | ZCONST ush *cplens; /* inflate static */ |
||
341 | ZCONST uch *cplext; /* inflate static */ |
||
342 | ZCONST uch *cpdext; /* inflate static */ |
||
343 | #endif |
||
344 | unsigned wp; /* inflate static: current position in slide */ |
||
345 | ulg bb; /* inflate static: bit buffer */ |
||
346 | unsigned bk; /* inflate static: bits count in bit buffer */ |
||
347 | #endif /* ?USE_ZLIB */ |
||
348 | |||
349 | #ifndef FUNZIP |
||
350 | /* cylindric buffer space for formatting zoff_t values (fileio static) */ |
||
351 | char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN]; |
||
352 | int fzofft_index; |
||
353 | |||
354 | #ifdef SMALL_MEM |
||
355 | char rgchBigBuffer[512]; |
||
356 | char rgchSmallBuffer[96]; |
||
357 | char rgchSmallBuffer2[160]; /* boosted to 160 for local3[] in unzip.c */ |
||
358 | #endif |
||
359 | |||
360 | MsgFn *message; |
||
361 | InputFn *input; |
||
362 | PauseFn *mpause; |
||
363 | PasswdFn *decr_passwd; |
||
364 | StatCBFn *statreportcb; |
||
365 | #ifdef WINDLL |
||
366 | LPUSERFUNCTIONS lpUserFunctions; |
||
367 | #endif |
||
368 | |||
369 | int incnt_leftover; /* so improved NEXTBYTE does not waste input */ |
||
370 | uch *inptr_leftover; |
||
371 | |||
372 | #ifdef VMS_TEXT_CONV |
||
373 | unsigned VMS_line_length; /* so native VMS variable-length text files */ |
||
374 | int VMS_line_state; /* are readable on other platforms */ |
||
375 | int VMS_line_pad; |
||
376 | #endif |
||
377 | |||
378 | #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) |
||
379 | char autorun_command[FILNAMSIZ]; |
||
380 | #endif |
||
381 | #endif /* !FUNZIP */ |
||
382 | |||
383 | #ifdef SYSTEM_SPECIFIC_GLOBALS |
||
384 | SYSTEM_SPECIFIC_GLOBALS |
||
385 | #endif |
||
386 | |||
387 | } Uz_Globs; /* end of struct Globals */ |
||
388 | |||
389 | |||
390 | /***************************************************************************/ |
||
391 | |||
392 | |||
393 | #define CRC_32_TAB G.crc_32_tab |
||
394 | |||
395 | |||
396 | Uz_Globs *globalsCtor OF((void)); |
||
397 | |||
398 | /* pseudo constant sigs; they are initialized at runtime so unzip executable |
||
399 | * won't look like a zipfile |
||
400 | */ |
||
401 | extern char local_hdr_sig[4]; |
||
402 | extern char central_hdr_sig[4]; |
||
403 | extern char end_central_sig[4]; |
||
404 | extern char end_central32_sig[4]; |
||
405 | extern char end_central64_sig[4]; |
||
406 | extern char end_centloc64_sig[4]; |
||
407 | /* extern char extd_local_sig[4]; NOT USED YET */ |
||
408 | |||
409 | #ifdef REENTRANT |
||
410 | # define G (*(Uz_Globs *)pG) |
||
411 | # define __G pG |
||
412 | # define __G__ pG, |
||
413 | # define __GPRO Uz_Globs *pG |
||
414 | # define __GPRO__ Uz_Globs *pG, |
||
415 | # define __GDEF Uz_Globs *pG; |
||
416 | # ifdef USETHREADID |
||
417 | extern int lastScan; |
||
418 | void deregisterGlobalPointer OF((__GPRO)); |
||
419 | Uz_Globs *getGlobalPointer OF((void)); |
||
420 | # define GETGLOBALS() Uz_Globs *pG = getGlobalPointer() |
||
421 | # define DESTROYGLOBALS() do {free_G_buffers(pG); \ |
||
422 | deregisterGlobalPointer(pG);} while (0) |
||
423 | # else |
||
424 | extern Uz_Globs *GG; |
||
425 | # define GETGLOBALS() Uz_Globs *pG = GG |
||
426 | # define DESTROYGLOBALS() do {free_G_buffers(pG); free(pG);} while (0) |
||
427 | # endif /* ?USETHREADID */ |
||
428 | # define CONSTRUCTGLOBALS() Uz_Globs *pG = globalsCtor() |
||
429 | #else /* !REENTRANT */ |
||
430 | extern Uz_Globs G; |
||
431 | # define __G |
||
432 | # define __G__ |
||
433 | # define __GPRO void |
||
434 | # define __GPRO__ |
||
435 | # define __GDEF |
||
436 | # define GETGLOBALS() |
||
437 | # define CONSTRUCTGLOBALS() globalsCtor() |
||
438 | # define DESTROYGLOBALS() |
||
439 | #endif /* ?REENTRANT */ |
||
440 | |||
441 | #define uO G.UzO |
||
442 | |||
443 | #endif /* __globals_h */ |