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
147typedef 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
381Uz_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 */
386extern char local_hdr_sig[4];
387extern char central_hdr_sig[4];
388extern 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