1 /* 2 Copyright (c) 1990-2002 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 2000-Apr-09 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 #endif 141 142 143 /*************/ 144 /* Globals */ 145 /*************/ 146 147 typedef struct Globals { 148 #ifdef DLL 149 zvoid *callerglobs; /* pointer to structure of pass-through global vars */ 150 #endif 151 152 /* command options of general use */ 153 UzpOpts UzO; /* command options of general use */ 154 155 #ifndef FUNZIP 156 /* command options specific to the high level command line interface */ 157 #ifdef MORE 158 int M_flag; /* -M: built-in "more" function */ 159 #endif 160 161 /* internal flags and general globals */ 162 #ifdef MORE 163 int height; /* check for SIGWINCH, etc., eventually... */ 164 int lines; /* count of lines displayed on current screen */ 165 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP)) 166 int width; 167 int chars; /* count of screen characters in current line */ 168 # endif 169 #endif /* MORE */ 170 #if (defined(IZ_CHECK_TZ) && defined(USE_EF_UT_TIME)) 171 int tz_is_valid; /* indicates that timezone info can be used */ 172 #endif 173 int noargs; /* did true command line have *any* arguments? */ 174 unsigned filespecs; /* number of real file specifications to be matched */ 175 unsigned xfilespecs; /* number of excluded filespecs to be matched */ 176 int process_all_files; 177 int overwrite_mode; /* 0 - query, 1 - always, 2 - never */ 178 int create_dirs; /* used by main(), mapname(), checkdir() */ 179 int extract_flag; 180 int newzip; /* reset in extract.c; used in crypt.c */ 181 LONGINT real_ecrec_offset; 182 LONGINT expect_ecrec_offset; 183 long csize; /* used by decompr. (NEXTBYTE): must be signed */ 184 long used_csize; /* used by extract_or_test_member(), explode() */ 185 186 #ifdef DLL 187 int fValidate; /* true if only validating an archive */ 188 int filenotfound; 189 int redirect_data; /* redirect data to memory buffer */ 190 int redirect_text; /* redirect text output to buffer */ 191 # ifndef NO_SLIDE_REDIR 192 int redirect_slide; /* redirect decompression area to mem buffer */ 193 # if (defined(USE_DEFLATE64) && defined(INT_16BIT)) 194 ulg _wsize; /* size of sliding window exceeds "unsigned" range */ 195 # else 196 unsigned _wsize; /* sliding window size can be hold in unsigned */ 197 # endif 198 # endif 199 ulg redirect_size; /* size of redirected output buffer */ 200 uch *redirect_buffer; /* pointer to head of allocated buffer */ 201 uch *redirect_pointer; /* pointer past end of written data */ 202 # ifndef NO_SLIDE_REDIR 203 uch *redirect_sldptr; /* head of decompression slide buffer */ 204 # endif 205 # ifdef OS2DLL 206 cbList(processExternally); /* call-back list */ 207 # endif 208 #endif /* DLL */ 209 210 char **pfnames; 211 char **pxnames; 212 char sig[4]; 213 char answerbuf[10]; 214 min_info info[DIR_BLKSIZ]; 215 min_info *pInfo; 216 #endif /* !FUNZIP */ 217 union work area; /* see unzpriv.h for definition of work */ 218 219 #ifndef FUNZIP 220 # if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) 221 ZCONST ulg near *crc_32_tab; 222 # else 223 ZCONST ulg Far *crc_32_tab; 224 # endif 225 #endif 226 ulg crc32val; /* CRC shift reg. (was static in funzip) */ 227 228 #ifdef FUNZIP 229 FILE *in; /* file descriptor of compressed stream */ 230 #endif 231 uch *inbuf; /* input buffer (any size is OK) */ 232 uch *inptr; /* pointer into input buffer */ 233 int incnt; 234 235 #ifndef FUNZIP 236 ulg bitbuf; 237 int bits_left; /* unreduce and unshrink only */ 238 int zipeof; 239 char *argv0; /* used for NT and EXE_EXTENSION */ 240 char *wildzipfn; 241 char *zipfn; /* GRR: WINDLL: must nuke any malloc'd zipfn... */ 242 #ifdef USE_STRM_INPUT 243 FILE *zipfd; /* zipfile file descriptor */ 244 #else 245 int zipfd; /* zipfile file handle */ 246 #endif 247 LONGINT ziplen; 248 LONGINT cur_zipfile_bufstart; /* extract_or_test, readbuf, ReadByte */ 249 LONGINT extra_bytes; /* used in unzip.c, misc.c */ 250 uch *extra_field; /* Unix, VMS, Mac, OS/2, Acorn, ... */ 251 uch *hold; 252 253 local_file_hdr lrec; /* used in unzip.c, extract.c */ 254 cdir_file_hdr crec; /* used in unzip.c, extract.c, misc.c */ 255 ecdir_rec ecrec; /* used in unzip.c, extract.c */ 256 struct stat statbuf; /* used by main, mapname, check_for_newer */ 257 258 int mem_mode; 259 uch *outbufptr; /* extract.c static */ 260 ulg outsize; /* extract.c static */ 261 int reported_backslash; /* extract.c static */ 262 int disk_full; 263 int newfile; 264 265 int didCRlast; /* fileio static */ 266 ulg numlines; /* fileio static: number of lines printed */ 267 int sol; /* fileio static: at start of line */ 268 int no_ecrec; /* process static */ 269 #ifdef SYMLINKS 270 int symlnk; 271 #endif 272 #ifdef NOVELL_BUG_FAILSAFE 273 int dne; /* true if stat() says file doesn't exist */ 274 #endif 275 276 FILE *outfile; 277 uch *outbuf; 278 uch *realbuf; 279 280 #ifndef VMS /* if SMALL_MEM, outbuf2 is initialized in */ 281 uch *outbuf2; /* process_zipfiles() (never changes); */ 282 #endif /* else malloc'd ONLY if unshrink and -a */ 283 #endif /* !FUNZIP */ 284 uch *outptr; 285 ulg outcnt; /* number of chars stored in outbuf */ 286 #ifndef FUNZIP 287 char filename[FILNAMSIZ]; /* also used by NT for temporary SFX path */ 288 289 #ifdef CMS_MVS 290 char *tempfn; /* temp file used; erase on close */ 291 #endif 292 293 char *key; /* crypt static: decryption password or NULL */ 294 int nopwd; /* crypt static */ 295 #endif /* !FUNZIP */ 296 ulg keys[3]; /* crypt static: keys defining pseudo-random sequence */ 297 298 #if (!defined(DOS_FLX_H68_NLM_OS2_W32) && !defined(AMIGA) && !defined(RISCOS)) 299 #if (!defined(MACOS) && !defined(ATARI) && !defined(VMS)) 300 int echofd; /* ttyio static: file descriptor whose echo is off */ 301 #endif /* !(MACOS || ATARI || VMS) */ 302 #endif /* !(DOS_FLX_H68_NLM_OS2_W32 || AMIGA || RISCOS) */ 303 304 unsigned hufts; /* track memory usage */ 305 306 #ifdef USE_ZLIB 307 int inflInit; /* inflate static: zlib inflate() initialized */ 308 z_stream dstrm; /* inflate global: decompression stream */ 309 #else 310 struct huft *fixed_tl; /* inflate static */ 311 struct huft *fixed_td; /* inflate static */ 312 int fixed_bl, fixed_bd; /* inflate static */ 313 #ifdef USE_DEFLATE64 314 struct huft *fixed_tl64; /* inflate static */ 315 struct huft *fixed_td64; /* inflate static */ 316 int fixed_bl64, fixed_bd64; /* inflate static */ 317 struct huft *fixed_tl32; /* inflate static */ 318 struct huft *fixed_td32; /* inflate static */ 319 int fixed_bl32, fixed_bd32; /* inflate static */ 320 ZCONST ush *cplens; /* inflate static */ 321 ZCONST uch *cplext; /* inflate static */ 322 ZCONST uch *cpdext; /* inflate static */ 323 #endif 324 unsigned wp; /* inflate static: current position in slide */ 325 ulg bb; /* inflate static: bit buffer */ 326 unsigned bk; /* inflate static: bits in bit buffer */ 327 #endif /* ?USE_ZLIB */ 328 329 #ifndef FUNZIP 330 #ifdef SMALL_MEM 331 char rgchBigBuffer[512]; 332 char rgchSmallBuffer[96]; 333 char rgchSmallBuffer2[160]; /* boosted to 160 for local3[] in unzip.c */ 334 #endif 335 336 MsgFn *message; 337 InputFn *input; 338 PauseFn *mpause; 339 PasswdFn *decr_passwd; 340 StatCBFn *statreportcb; 341 #ifdef WINDLL 342 LPUSERFUNCTIONS lpUserFunctions; 343 #endif 344 345 int incnt_leftover; /* so improved NEXTBYTE does not waste input */ 346 uch *inptr_leftover; 347 348 #ifdef VMS_TEXT_CONV 349 unsigned VMS_line_length; /* so native VMS variable-length text files */ 350 int VMS_line_state; /* are readable on other platforms */ 351 int VMS_line_pad; 352 #endif 353 354 #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN)) 355 char autorun_command[FILNAMSIZ]; 356 #endif 357 #endif /* !FUNZIP */ 358 359 #ifdef SYSTEM_SPECIFIC_GLOBALS 360 SYSTEM_SPECIFIC_GLOBALS 361 #endif 362 363 } Uz_Globs; /* end of struct Globals */ 364 365 366 /***************************************************************************/ 367 368 369 #ifdef FUNZIP 370 # if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) 371 extern ZCONST ulg near crc_32_tab[256]; 372 # else 373 extern ZCONST ulg Far *crc_32_tab; 374 # endif 375 # define CRC_32_TAB crc_32_tab 376 #else 377 # define CRC_32_TAB G.crc_32_tab 378 #endif 379 380 381 Uz_Globs *globalsCtor OF((void)); 382 383 /* pseudo constant sigs; they are initialized at runtime so unzip executable 384 * won't look like a zipfile 385 */ 386 extern char local_hdr_sig[4]; 387 extern char central_hdr_sig[4]; 388 extern char end_central_sig[4]; 389 /* extern char extd_local_sig[4]; NOT USED YET */ 390 391 #ifdef REENTRANT 392 # define G (*(Uz_Globs *)pG) 393 # define __G pG 394 # define __G__ pG, 395 # define __GPRO Uz_Globs *pG 396 # define __GPRO__ Uz_Globs *pG, 397 # define __GDEF Uz_Globs *pG; 398 # ifdef USETHREADID 399 extern int lastScan; 400 void deregisterGlobalPointer OF((__GPRO)); 401 Uz_Globs *getGlobalPointer OF((void)); 402 # define GETGLOBALS() Uz_Globs *pG = getGlobalPointer() 403 # define DESTROYGLOBALS() do {free_G_buffers(pG); \ 404 deregisterGlobalPointer(pG);} while (0) 405 # else 406 extern Uz_Globs *GG; 407 # define GETGLOBALS() Uz_Globs *pG = GG 408 # define DESTROYGLOBALS() do {free_G_buffers(pG); free(pG);} while (0) 409 # endif /* ?USETHREADID */ 410 # define CONSTRUCTGLOBALS() Uz_Globs *pG = globalsCtor() 411 #else /* !REENTRANT */ 412 extern Uz_Globs G; 413 # define __G 414 # define __G__ 415 # define __GPRO void 416 # define __GPRO__ 417 # define __GDEF 418 # define GETGLOBALS() 419 # define CONSTRUCTGLOBALS() globalsCtor() 420 # define DESTROYGLOBALS() 421 #endif /* ?REENTRANT */ 422 423 #define uO G.UzO 424 425 #endif /* __globals_h */ 426