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