1 /*
2   Copyright (c) 1990-2007 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   macos.c
12 
13   Macintosh-specific routines for use with Info-ZIP's UnZip 5.4 and later.
14 
15   Contains:
16                     do_wild ()
17                     mapattr ()
18                     checkdir ()
19                     version ()
20                     macmkdir ()
21                     macopen ()
22                     maccreat ()
23                     macread ()
24                     macwrite ()
25                     macclose ()
26                     maclseek ()
27                     BuildMacFilename()
28                     SetFinderInfo ()
29                     isMacOSexfield ()
30                     makePPClong ()
31                     makePPCword ()
32                     PrintMacExtraInfo ()
33                     GetExtraFieldData ()
34                     DecodeMac3ExtraField ()
35                     DecodeJLEEextraField ()
36                     PrintTextEncoding ()
37                     MacGlobalsInit ()
38 
39   ---------------------------------------------------------------------------*/
40 
41 
42 /*****************************************************************************/
43 /*  Includes                                                                 */
44 /*****************************************************************************/
45 
46 #define UNZIP_INTERNAL
47 #include "unzip.h"
48 
49 #include <script.h>
50 #include <sound.h>
51 
52 #include "pathname.h"
53 #include "helpers.h"
54 #include "macstuff.h"
55 #include "mactime.h"
56 #include "macbin3.h"
57 
58 /*****************************************************************************/
59 /*  Macros, typedefs                                                         */
60 /*****************************************************************************/
61 
62 /* disable ZipIt support
63 #define SwitchZIPITefSupportOff */
64 
65 #define read_only   file_attr       /* for readability only */
66 #define EB_MAX_OF_VARDATA   1300    /* max possible datasize of extra-field */
67 
68 #ifdef WILD_STOP_AT_DIR
69 #  define WESEP     , (oU.W_flag ? ':' : '\0')
70 #else
71 #  define WESEP
72 #endif
73 
74 
75 /*****************************************************************************/
76 /*  Global Vars                                                              */
77 /*****************************************************************************/
78 
79 /*  Note: sizeof() returns the size of this allusion
80           13 is current length of "XtraStuf.mac:"      */
81 extern const char ResourceMark[13]; /* var is initialized in file pathname.c */
82 
83 Boolean MacUnzip_Noisy;            /* MacUnzip_Noisy is also used by console */
84 
85 MACINFO newExtraField;  /* contains all extra-field data */
86 short MacZipMode;
87 
88 
89 /*****************************************************************************/
90 /*  Module level Vars                                                        */
91 /*****************************************************************************/
92 
93 static const char MacPathEnd = ':';   /* the Macintosh dir separator */
94 
95 static int created_dir;        /* used in mapname(), checkdir() */
96 static int renamed_fullpath;   /* ditto */
97 static FSSpec CurrentFile;
98 
99 static Boolean OpenZipFile = true;
100 static Boolean UseUT_ExtraField     = false;
101 static Boolean IgnoreEF_Macfilename = false;
102 static short fileSystemID;
103 
104 static uch *attrbuff = NULL;
105 static uch *malloced_attrbuff = NULL;
106 
107 const short HFS_fileSystem = 0;
108 
109 /*****************************************************************************/
110 /*  Prototypes                                                               */
111 /*****************************************************************************/
112 
113 extern char *GetUnZipInfoVersions(void);
114 
115 static OSErr SetFinderInfo(__GPRO__ int SetTime, FSSpec *spec, MACINFO *mi);
116 static Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi);
117 static uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len,
118                              short *MacZipMode);
119 static Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode);
120 static void PrintMacExtraInfo(MACINFO *mi);
121 static OSErr SetFileTime(__GPRO);
122 static void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi);
123 static void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi);
124 static void DecodeZPITextraField(ZCONST uch *buff, MACINFO *mi);
125 static char *PrintTextEncoding(short script);
126 static void BuildMacFilename(void);
127 
128 /*****************************************************************************/
129 /*  Constants (strings, etc.)                                                */
130 /*****************************************************************************/
131 
132 static ZCONST char Far CannotCreateFile[] = "error:  cannot create %s\n";
133 
134 static ZCONST char Far OutOfMemEF[] = "Can't allocate memory to uncompress"\
135                                       " file attributes.\n";
136 
137 static ZCONST char Far ErrUncmpEF[] = "Error uncompressing file attributes.\n";
138 
139 static ZCONST char Far No64Time[]   = "Don't support 64 bit Timevalues; get "\
140                                       " a newer version of MacZip \n";
141 
142 static ZCONST char Far NoUniCode[]  = "Don't support Unicoded Filenames; get"\
143                                       " a newer version of MacZip\n";
144 
145 static ZCONST char Far ZitIt_EF[]   = "warning: found ZipIt extra field  "\
146                                       " -> file is probably not "\
147                                       "usable!!\n";
148 
149 static ZCONST char Far CantAllocateWildcard[] =
150     "warning:  cannot allocate wildcard buffers\n";
151 
152 static ZCONST char Far ErrNoTimeSet[] = "error (%d): cannot set the time for"\
153                                         " %s\n";
154 
155 static ZCONST char Far MacBinaryMsg[] = "\n   ... decoding MacBinary ";
156 
157 static ZCONST char Far WarnDirTraversSkip[] =
158   "warning:  skipped \"../\" path component(s) in %s\n";
159 
160 static ZCONST char Far Creating[] = "   creating: %s\n";
161 
162 static ZCONST char Far ConversionFailed[] =
163   "mapname:  conversion of %s failed\n";
164 
165 static ZCONST char Far PathTooLong[] = "checkdir error:  path too long: %s\n";
166 
167 static ZCONST char Far CantCreateDir[] = "checkdir error:  cannot create %s\n\
168                  unable to process %s.\n";
169 
170 static ZCONST char Far DirIsntDirectory[] =
171   "checkdir error:  %s exists but is not directory\n\
172                  unable to process %s.\n";
173 
174 static ZCONST char Far PathTooLongTrunc[] =
175   "checkdir warning:  path too long; truncating\n                   %s\n\
176                 -> %s\n";
177 
178 static ZCONST char Far CantCreateExtractDir[] =
179   "checkdir:  cannot create extraction directory: %s\n";
180 
181 static ZCONST char Far FilenameToLong[] =
182   "Filename is to long; truncated: %s\n";
183 
184 /*****************************************************************************/
185 /*  Functions                                                                */
186 /*****************************************************************************/
187 
188 #ifndef SFX
189 
190 /**********************/
191 /* Function do_wild() */   /* for porting: dir separator; match(ignore_case) */
192 /**********************/
193 
194 char *do_wild(__G__ wildspec)
195     __GDEF
196     ZCONST char *wildspec;  /* only used first time on a given dir */
197 {
198     static DIR *wild_dir = (DIR *)NULL;
199     static ZCONST char *wildname;
200     static char *dirname, matchname[FILNAMSIZ];
201     static int notfirstcall=FALSE, have_dirname;
202     static unsigned long dirnamelen;
203     struct dirent *file;
204 
205     /* Even when we're just returning wildspec, we *always* do so in
206      * matchname[]--calling routine is allowed to append four characters
207      * to the returned string, and wildspec may be a pointer to argv[].
208      */
209     if (!notfirstcall) {    /* first call:  must initialize everything */
210         notfirstcall = TRUE;
211 
212         /* Folder names must always end with a colon */
213         if (uO.exdir[strlen(uO.exdir)-1] != ':') {
214             strcat(uO.exdir, ":");
215         }
216 
217         MacUnzip_Noisy = !uO.qflag;
218 
219         if (MacUnzip_Noisy) printf("%s \n\n", GetUnZipInfoVersions());
220 
221         /* break the wildspec into a directory part and a wildcard filename */
222         if ((wildname = (ZCONST char *)strrchr(wildspec, ':')) ==
223             (ZCONST char *)NULL) {
224             dirname = ":";
225             dirnamelen = 1;
226             have_dirname = FALSE;
227             wildname = wildspec;
228         } else {
229             ++wildname;     /* point at character after ':' */
230             dirnamelen = wildname - wildspec;
231             if ((dirname = (char *)malloc(dirnamelen+1)) == (char *)NULL) {
232                 Info(slide, 0x201, ((char *)slide,
233                   LoadFarString(CantAllocateWildcard)));
234                 strncpy(matchname, wildspec, FILNAMSIZ);
235                 matchname[FILNAMSIZ-1] = '\0';
236                 return matchname;   /* but maybe filespec was not a wildcard */
237             }
238             strncpy(dirname, wildspec, dirnamelen);
239             dirname[dirnamelen] = '\0';   /* terminate for strcpy below */
240             have_dirname = TRUE;
241         }
242 
243         if ((wild_dir = opendir(dirname)) != (DIR *)NULL) {
244             while ((file = readdir(wild_dir)) != (struct dirent *)NULL) {
245                 if (match(file->d_name, wildname, 0 WESEP)) { /* 0=case sens.*/
246                     if (have_dirname) {
247                         strcpy(matchname, dirname);
248                         strcpy(matchname+dirnamelen, file->d_name);
249                     } else
250                         strcpy(matchname, file->d_name);
251                     return matchname;
252                 }
253             }
254             /* if we get to here directory is exhausted, so close it */
255             closedir(wild_dir);
256             wild_dir = (DIR *)NULL;
257         }
258 
259         /* return the raw wildspec in case that works (e.g., directory not
260          * searchable, but filespec was not wild and file is readable) */
261         strncpy(matchname, wildspec, FILNAMSIZ);
262         matchname[FILNAMSIZ-1] = '\0';
263         return matchname;
264     }
265 
266     /* last time through, might have failed opendir but returned raw wildspec */
267     if (wild_dir == (DIR *)NULL) {
268         notfirstcall = FALSE; /* nothing left to try--reset for new wildspec */
269         if (have_dirname)
270             free(dirname);
271         return (char *)NULL;
272     }
273 
274     /* If we've gotten this far, we've read and matched at least one entry
275      * successfully (in a previous call), so dirname has been copied into
276      * matchname already.
277      */
278     while ((file = readdir(wild_dir)) != (struct dirent *)NULL)
279         if (match(file->d_name, wildname, 0 WESEP)) {   /* 0 == case sens. */
280             if (have_dirname) {
281                 /* strcpy(matchname, dirname); */
282                 strcpy(matchname+dirnamelen, file->d_name);
283             } else
284                 strcpy(matchname, file->d_name);
285             return matchname;
286         }
287 
288     closedir(wild_dir);     /* have read at least one entry; nothing left */
289     wild_dir = (DIR *)NULL;
290     notfirstcall = FALSE;   /* reset for new wildspec */
291     if (have_dirname)
292         free(dirname);
293     return (char *)NULL;
294 
295 } /* end function do_wild() */
296 
297 #endif /* !SFX */
298 
299 
300 
301 
302 
303 /***************************/
304 /* Function open_outfile() */
305 /***************************/
306 
open_outfile(__G)307 int open_outfile(__G)         /* return 1 if fail */
308     __GDEF
309 {
310     short outfd, fDataFork = true;
311 
312 #ifdef DLL
313     if (G.redirect_data)
314         return (redirect_outfile(__G) == FALSE);
315 #endif
316     Trace((stderr, "open_outfile:  trying to open (%s) for writing\n",
317       FnFilter1(G.filename)));
318 
319     if (!uO.aflag) {
320          /* unknown type documents */
321          /* all files are considered to be of type 'TEXT' and creator 'hscd' */
322          /* this is the default type for CDROM ISO-9660 without Apple extensions */
323         newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType    =  'TEXT';
324         newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator =  'hscd';
325     } else {
326      /* unknown text-files defaults to 'TEXT' */
327         newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType    =  'TEXT';
328      /* Bare Bones BBEdit */
329         newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator =  'R*ch';
330     }
331 
332     BuildMacFilename();
333 
334     if  (MacZipMode <= TomBrownZipIt2_EF)
335         {
336         fDataFork = true;
337         }
338     else
339         {
340         fDataFork = (newExtraField.flags & EB_M3_FL_DATFRK) ? TRUE : FALSE;
341         }
342 
343 
344     if ((outfd = maccreat(G.filename)) != -1) {
345         outfd = macopen(G.filename, (fDataFork) ? 1 : 2);
346     }
347 
348     if (outfd == -1) {
349         G.outfile = (FILE *)NULL;
350         Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
351           FnFilter1(G.filename)));
352         return 1;
353     }
354     G.outfile = (FILE *)outfd;
355     Trace((stderr, "open_outfile:  successfully opened (%s) for writing\n",
356       FnFilter1(G.filename)));
357 
358     return 0;
359 
360 } /* end function open_outfile() */
361 
362 
363 
364 
365 
366 /**********************/
367 /* Function mapattr() */
368 /**********************/
369 
mapattr(__G)370 int mapattr(__G)
371     __GDEF
372 {
373     /* only care about read-only bit, so just look at MS-DOS side of attrs */
374     G.pInfo->read_only = (unsigned)(G.crec.external_file_attributes & 1);
375     return 0;
376 
377 } /* end function mapattr() */
378 
379 
380 
381 
382 
383 /************************/
384 /*  Function mapname()  */
385 /************************/
386 
387 int mapname(__G__ renamed)
388     __GDEF
389     int renamed;
390 /*
391  * returns:
392  *  MPN_OK          - no problem detected
393  *  MPN_INF_TRUNC   - caution (truncated filename)
394  *  MPN_INF_SKIP    - info "skip entry" (dir doesn't exist)
395  *  MPN_ERR_SKIP    - error -> skip entry
396  *  MPN_ERR_TOOLONG - error -> path is too long
397  *  MPN_NOMEM       - error (memory allocation failed) -> skip entry
398  *  [also MPN_VOL_LABEL, MPN_CREATED_DIR]
399  */
400 {
401     char pathcomp[FILNAMSIZ];      /* path-component buffer */
402     char *pp, *cp=(char *)NULL;    /* character pointers */
403     char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
404     int killed_ddot = FALSE;       /* is set when skipping "../" pathcomp */
405     int error = MPN_OK;
406     register unsigned workch;      /* hold the character being tested */
407 
408 
409 /*---------------------------------------------------------------------------
410     Initialize various pointers and counters and stuff.
411   ---------------------------------------------------------------------------*/
412 
413     if (G.pInfo->vollabel)
414         return MPN_VOL_LABEL;   /* can't set disk volume labels on Macintosh */
415 
416     /* can create path as long as not just freshening, or if user told us */
417     G.create_dirs = (!uO.fflag || renamed);
418 
419     created_dir = FALSE;        /* not yet */
420 
421     /* user gave full pathname:  don't prepend rootpath */
422     renamed_fullpath = (renamed && (*G.filename == '/'));
423 
424     if (checkdir(__G__ (char *)NULL, INIT) == MPN_NOMEM)
425         return MPN_NOMEM;       /* initialize path buffer, unless no memory */
426 
427     *pathcomp = '\0';           /* initialize translation buffer */
428     pp = pathcomp;              /* point to translation buffer */
429 
430     if (uO.jflag)               /* junking directories */
431         cp = (char *)strrchr(G.filename, '/');
432     if (cp == (char *)NULL) {   /* no '/' or not junking dirs */
433         cp = G.filename;        /* point to internal zipfile-member pathname */
434         if (renamed_fullpath)
435             ++cp;               /* skip over leading '/' */
436     } else
437         ++cp;                   /* point to start of last component of path */
438 
439 /*---------------------------------------------------------------------------
440     Begin main loop through characters in filename.
441   ---------------------------------------------------------------------------*/
442 
443     while ((workch = (uch)*cp++) != 0) {
444 
445         switch (workch) {
446             case '/':             /* can assume -j flag not given */
447                 *pp = '\0';
448                 if (strcmp(pathcomp, ".") == 0) {
449                     /* don't bother appending "./" to the path */
450                     *pathcomp = '\0';
451                 } else if (!uO.ddotflag && strcmp(pathcomp, "..") == 0) {
452                     /* "../" dir traversal detected, skip over it */
453                     *pathcomp = '\0';
454                     killed_ddot = TRUE;     /* set "show message" flag */
455                 }
456                 /* when path component is not empty, append it now */
457                 if (*pathcomp != '\0' &&
458                     ((error = checkdir(__G__ pathcomp, APPEND_DIR))
459                      & MPN_MASK) > MPN_INF_TRUNC)
460                     return error;
461                 pp = pathcomp;    /* reset conversion buffer for next piece */
462                 lastsemi = (char *)NULL; /* leave direct. semi-colons alone */
463                 break;
464 
465             case ':':
466                 *pp++ = '/';      /* ':' is a pathseperator for HFS  */
467                 break;
468 
469             case ';':             /* VMS version (or DEC-20 attrib?) */
470                 lastsemi = pp;         /* keep for now; remove VMS ";##" */
471                 *pp++ = (char)workch;  /*  later, if requested */
472                 break;
473 
474             default:
475                 /* allow European characters in filenames: */
476                 if (isprint(workch) || (128 <= workch && workch <= 254))
477                     *pp++ = (char)workch;
478         } /* end switch */
479 
480     } /* end while loop */
481 
482     /* Show warning when stripping insecure "parent dir" path components */
483     if (killed_ddot && QCOND2) {
484         Info(slide, 0, ((char *)slide, LoadFarString(WarnDirTraversSkip),
485           FnFilter1(G.filename)));
486         if (!(error & ~MPN_MASK))
487             error = (error & MPN_MASK) | PK_WARN;
488     }
489 
490 /*---------------------------------------------------------------------------
491     Report if directory was created (and no file to create:  filename ended
492     in '/'), check name to be sure it exists, and combine path and name be-
493     fore exiting.
494   ---------------------------------------------------------------------------*/
495 
496     if (G.filename[strlen(G.filename) - 1] == '/') {
497         checkdir(__G__ G.filename, GETPATH);
498         if (created_dir) {
499             if (QCOND2) {
500                 Info(slide, 0, ((char *)slide, LoadFarString(Creating),
501                   FnFilter1(G.filename)));
502             }
503             /* set dir time (note trailing '/') */
504             return (error & ~MPN_MASK) | MPN_CREATED_DIR;
505         }
506         /* dir existed already; don't look for data to extract */
507         return (error & ~MPN_MASK) | MPN_INF_SKIP;
508     }
509 
510     *pp = '\0';                   /* done with pathcomp:  terminate it */
511 
512     /* if not saving them, remove VMS version numbers (appended ";###") */
513     if (!uO.V_flag && lastsemi) {
514         pp = lastsemi + 1;
515         while (isdigit((uch)(*pp)))
516             ++pp;
517         if (*pp == '\0')          /* only digits between ';' and end:  nuke */
518             *lastsemi = '\0';
519     }
520 
521     if (*pathcomp == '\0') {
522         Info(slide, 1, ((char *)slide, LoadFarString(ConversionFailed),
523           FnFilter1(G.filename)));
524         return (error & ~MPN_MASK) | MPN_ERR_SKIP;
525     }
526 
527     checkdir(__G__ pathcomp, APPEND_NAME);  /* returns 1 if truncated: care? */
528     checkdir(__G__ G.filename, GETPATH);
529 
530     return error;
531 
532 } /* end function mapname() */
533 
534 
535 
536 
537 
538 /***********************/
539 /* Function checkdir() */
540 /***********************/
541 
542 int checkdir(__G__ pathcomp, flag)
543     __GDEF
544     char *pathcomp;
545     int flag;
546 /*
547  * returns:
548  *  MPN_OK          - no problem detected
549  *  MPN_INF_TRUNC   - (on APPEND_NAME) truncated filename
550  *  MPN_INF_SKIP    - path doesn't exist, not allowed to create
551  *  MPN_ERR_SKIP    - path doesn't exist, tried to create and failed; or path
552  *                    exists and is not a directory, but is supposed to be
553  *  MPN_ERR_TOOLONG - path is too long
554  *  MPN_NOMEM       - can't allocate memory for filename buffers
555  */
556 {
557     static int rootlen = 0;   /* length of rootpath */
558     static char *rootpath;    /* user's "extract-to" directory */
559     static char *buildpath;   /* full path (so far) to extracted file */
560     static char *end;         /* pointer to end of buildpath ('\0') */
561 
562 #   define FN_MASK   7
563 #   define FUNCTION  (flag & FN_MASK)
564 
565 
566 /*---------------------------------------------------------------------------
567     APPEND_DIR:  append the path component to the path being built and check
568     for its existence.  If doesn't exist and we are creating directories, do
569     so for this one; else signal success or error as appropriate.
570   ---------------------------------------------------------------------------*/
571 
572     if (FUNCTION == APPEND_DIR) {
573         int too_long = FALSE;
574 #ifdef SHORT_NAMES
575         char *old_end = end;
576 #endif
577 
578         Trace((stderr, "appending dir segment [%s]\n", FnFilter1(pathcomp)));
579         while ((*end = *pathcomp++) != '\0')
580             ++end;
581 #ifdef SHORT_NAMES   /* path components restricted to 14 chars, typically */
582         if ((end-old_end) > NAME_MAX)
583             *(end = old_end + NAME_MAX) = '\0';
584 #endif
585 
586         /* GRR:  could do better check, see if overrunning buffer as we go:
587          * check end-buildpath after each append, set warning variable if
588          * within 20 of FILNAMSIZ; then if var set, do careful check when
589          * appending.  Clear variable when begin new path. */
590 
591         if ((end-buildpath) > NAME_MAX-3)   /* need ':', one-char name, '\0' */
592             too_long = TRUE;                /* check if extracting directory? */
593         if (stat(buildpath, &G.statbuf)) {  /* path doesn't exist */
594             if (!G.create_dirs) { /* told not to create (freshening) */
595                 free(buildpath);
596                 return MPN_INF_SKIP;    /* path doesn't exist: nothing to do */
597             }
598             if (too_long) {
599                 Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),
600                   FnFilter1(buildpath)));
601                 free(buildpath);
602                 /* no room for filenames:  fatal */
603                 return MPN_ERR_TOOLONG;
604             }
605             if (macmkdir(buildpath) == -1) {   /* create the directory */
606                 Info(slide, 1, ((char *)slide, LoadFarString(CantCreateDir),
607                   FnFilter2(buildpath), FnFilter1(G.filename)));
608                 free(buildpath);
609                 /* path didn't exist, tried to create, failed */
610                 return MPN_ERR_SKIP;
611             }
612             created_dir = TRUE;
613         } else if (!S_ISDIR(G.statbuf.st_mode)) {
614             Info(slide, 1, ((char *)slide, LoadFarString(DirIsntDirectory),
615               FnFilter2(buildpath), FnFilter1(G.filename)));
616             free(buildpath);
617             /* path existed but wasn't dir */
618             return MPN_ERR_SKIP;
619         }
620         if (too_long) {
621             Info(slide, 1, ((char *)slide, LoadFarString(PathTooLong),
622               FnFilter1(buildpath)));
623             free(buildpath);
624             /* no room for filenames:  fatal */
625             return MPN_ERR_TOOLONG;
626         }
627         *end++ = ':';
628         *end = '\0';
629         Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath)));
630         return MPN_OK;
631 
632     } /* end if (FUNCTION == APPEND_DIR) */
633 
634 /*---------------------------------------------------------------------------
635     GETPATH:  copy full path to the string pointed at by pathcomp, and free
636     buildpath.
637   ---------------------------------------------------------------------------*/
638 
639     if (FUNCTION == GETPATH) {
640         strcpy(pathcomp, buildpath);
641         Trace((stderr, "getting and freeing path [%s]\n",
642           FnFilter1(pathcomp)));
643         free(buildpath);
644         buildpath = end = (char *)NULL;
645         return MPN_OK;
646     }
647 
648 /*---------------------------------------------------------------------------
649     APPEND_NAME:  assume the path component is the filename; append it and
650     return without checking for existence.
651   ---------------------------------------------------------------------------*/
652 
653     if (FUNCTION == APPEND_NAME) {
654 #ifdef SHORT_NAMES
655         char *old_end = end;
656 #endif
657 
658         Trace((stderr, "appending filename [%s]\n", FnFilter1(pathcomp)));
659         while ((*end = *pathcomp++) != '\0') {
660             ++end;
661 #ifdef SHORT_NAMES  /* truncate name at 14 characters, typically */
662             if ((end-old_end) > NAME_MAX)
663                 *(end = old_end + NAME_MAX) = '\0';
664 #endif
665             if ((end-buildpath) >= NAME_MAX) {
666                 *--end = '\0';
667                 Info(slide, 0x201, ((char *)slide,
668                   LoadFarString(PathTooLongTrunc),
669                   FnFilter1(G.filename), FnFilter2(buildpath)));
670                 return MPN_INF_TRUNC;   /* filename truncated */
671             }
672         }
673         Trace((stderr, "buildpath now = [%s]\n", FnFilter1(buildpath)));
674         /* could check for existence here, prompt for new name... */
675         return MPN_OK;
676     }
677 
678 /*---------------------------------------------------------------------------
679     INIT:  allocate and initialize buffer space for the file currently being
680     extracted.  If file was renamed with an absolute path, don't prepend the
681     extract-to path.
682   ---------------------------------------------------------------------------*/
683 
684     if (FUNCTION == INIT) {
685         Trace((stderr, "initializing buildpath to "));
686         if ((buildpath = (char *)malloc(strlen(G.filename)+rootlen+2))
687             == (char *)NULL)
688             return MPN_NOMEM;
689         if ((rootlen > 0) && !renamed_fullpath) {
690             strcpy(buildpath, rootpath);
691             end = buildpath + rootlen;
692         } else {
693             end = buildpath;
694             if (!renamed_fullpath && !uO.jflag) {
695                 *end++ = ':';           /* indicate relative path */
696             }
697             *end = '\0';
698         }
699         Trace((stderr, "[%s]\n", FnFilter1(buildpath)));
700         return MPN_OK;
701     }
702 
703 /*---------------------------------------------------------------------------
704     ROOT:  if appropriate, store the path in rootpath and create it if
705     necessary; else assume it's a zipfile member and return.  This path
706     segment gets used in extracting all members from every zipfile specified
707     on the command line.
708   ---------------------------------------------------------------------------*/
709 
710 #if (!defined(SFX) || defined(SFX_EXDIR))
711     if (FUNCTION == ROOT) {
712         Trace((stderr, "initializing root path to [%s]\n",
713           FnFilter1pathcomp)));
714         if (pathcomp == (char *)NULL) {
715             rootlen = 0;
716             return MPN_OK;
717         }
718         if (rootlen > 0)        /* rootpath was already set, nothing to do */
719             return MPN_OK;
720         if ((rootlen = strlen(pathcomp)) > 0) {
721             char *tmproot;
722 
723             if ((tmproot = (char *)malloc(rootlen+2)) == (char *)NULL) {
724                 rootlen = 0;
725                 return MPN_NOMEM;
726             }
727             strcpy(tmproot, pathcomp);
728             if (tmproot[rootlen-1] == ':') {
729                 tmproot[--rootlen] = '\0';     /* strip trailing delimiter */
730             }
731             if (rootlen > 0 && (stat(tmproot, &G.statbuf) ||
732                 !S_ISDIR(G.statbuf.st_mode)))
733             {   /* path does not exist */
734                 if (!G.create_dirs /* || iswild(tmproot) */ ) {
735                     free(tmproot);
736                     rootlen = 0;
737                     /* skip (or treat as stored file) */
738                     return MPN_INF_SKIP;
739                 }
740                 /* create the directory (could add loop here scanning tmproot
741                  * to create more than one level, but why really necessary?) */
742                 if (macmkdir(tmproot) == -1) {
743                     Info(slide, 1, ((char *)slide,
744                       LoadFarString(CantCreateExtractDir),
745                       FnFilter1(tmproot)));
746                     free(tmproot);
747                     rootlen = 0;
748                     /* path didn't exist, tried to create, and failed: */
749                     /* file exists, or 2+ subdir levels required */
750                     return MPN_ERR_SKIP;
751                 }
752             }
753             tmproot[rootlen++] = ':';
754             tmproot[rootlen] = '\0';
755             if ((rootpath = (char *)realloc(tmproot, rootlen+1)) == NULL) {
756                 free(tmproot);
757                 rootlen = 0;
758                 return MPN_NOMEM;
759             }
760             Trace((stderr, "rootpath now = [%s]\n", FnFilter1(rootpath)));
761         }
762         return MPN_OK;
763     }
764 #endif /* !SFX || SFX_EXDIR */
765 
766 /*---------------------------------------------------------------------------
767     END:  free rootpath, immediately prior to program exit.
768   ---------------------------------------------------------------------------*/
769 
770     if (FUNCTION == END) {
771         Trace((stderr, "freeing rootpath\n"));
772         if (rootlen > 0) {
773             free(rootpath);
774             rootlen = 0;
775         }
776         return MPN_OK;
777     }
778 
779     return MPN_INVALID; /* should never reach */
780 
781 } /* end function checkdir() */
782 
783 
784 
785 
786 
787 /****************************/
788 /* Function close_outfile() */
789 /****************************/
790 
close_outfile(__G)791 void close_outfile(__G)
792     __GDEF
793 {
794     OSErr err;
795 
796     if (fileno(G.outfile) == 1)
797         return;         /* don't attempt to close or set time on stdout */
798 
799     err = (OSErr)fclose(G.outfile);
800 
801     /* finally set FinderInfo */
802     if  (MacZipMode >= JohnnyLee_EF)
803         {
804         /* skip restoring time stamps on user's request */
805         err = SetFinderInfo(__G__ (uO.D_flag <= 1),
806                             &CurrentFile, &newExtraField);
807         printerr("close_outfile SetFinderInfo ", err, err,
808                  __LINE__, __FILE__, G.filename);
809         }
810     else  /* unknown extra field, set at least file time/dates */
811         {
812         /* skip restoring time stamps on user's request */
813         if (uO.D_flag <= 1)
814             err = SetFileTime(__G);
815         }
816 
817 #ifndef SwitchZIPITefSupportOff
818     if ((MacZipMode == TomBrownZipIt1_EF) ||
819         (MacZipMode == TomBrownZipIt2_EF))
820         {
821         if(FSpIsMacBinary(&CurrentFile))
822             {
823             Info(slide, 0, ((char *)slide, LoadFarString(MacBinaryMsg)));
824                 err = DecodeMacBinaryFile(&CurrentFile);
825                 printerr("close_outfile DecodeMacBinaryFile ", err, err,
826                   __LINE__, __FILE__, G.filename);
827             }
828         }
829 #endif
830 
831         /* set read-only perms if needed */
832     if ((err == noErr) && G.pInfo->read_only)
833         {
834         err = FSpSetFLock(&CurrentFile);
835         printerr("FSpSetFLock",err,err,__LINE__,__FILE__,G.filename);
836         }
837 
838     if (malloced_attrbuff != NULL)
839         {
840         attrbuff = malloced_attrbuff;
841         }
842 
843 } /* end function close_outfile() */
844 
845 
846 
847 
848 /****************************/
849 /* Function SetFileTime() */
850 /****************************/
851 
SetFileTime(__G)852 static OSErr SetFileTime(__G)
853     __GDEF
854 {
855 #ifdef USE_EF_UT_TIME
856     iztimes z_utime;
857     unsigned eb_izux_flg;
858 #endif
859     OSErr err;
860     CInfoPBRec      fpb;
861 
862     fpb.hFileInfo.ioNamePtr    = CurrentFile.name;
863     fpb.hFileInfo.ioVRefNum    = CurrentFile.vRefNum;
864     fpb.hFileInfo.ioDirID      = CurrentFile.parID;
865     fpb.hFileInfo.ioFDirIndex  = 0;
866 
867     err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
868     printerr("PBGetCatInfoSync", err, err, __LINE__, __FILE__, G.filename);
869 
870     if ((MacZipMode == UnKnown_EF) || UseUT_ExtraField ) {
871 
872 #ifdef USE_EF_UT_TIME
873         eb_izux_flg = ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
874                                        G.lrec.last_mod_dos_datetime, &z_utime, NULL);
875 
876         if (G.extra_field && (eb_izux_flg & EB_UT_FL_MTIME))
877             {
878             fpb.hFileInfo.ioFlMdDat = UnixFtime2MacFtime(z_utime.mtime);
879             fpb.hFileInfo.ioFlCrDat = UnixFtime2MacFtime(z_utime.ctime);
880             }
881 
882 #ifdef DEBUG_TIME
883             {
884             struct tm *tp = gmtime(&z_utime.ctime);
885             printf(
886               "SetFileTime:  Unix e.f. creat. time = %d/%2d/%2d  %2d:%2d:%2d -> %lu UTC\n",
887               tp->tm_year, tp->tm_mon+1, tp->tm_mday,
888               tp->tm_hour, tp->tm_min, tp->tm_sec, z_utime.ctime);
889             tp = gmtime(&z_utime.mtime);
890             printf(
891               "SetFileTime:  Unix e.f. modif. time = %d/%2d/%2d  %2d:%2d:%2d -> %lu UTC\n",
892               tp->tm_year, tp->tm_mon+1, tp->tm_mday,
893               tp->tm_hour, tp->tm_min, tp->tm_sec, z_utime.mtime);
894             }
895 #endif /* DEBUG_TIME */
896 
897 
898         else /* no Unix time field found - use dostime  */
899 #endif /* !USE_EF_UT_TIME */
900             {
901             TTrace((stderr, "SetFileTime:  using DOS-Datetime ! \n",
902                     z_utime.mtime));
903             fpb.hFileInfo.ioFlMdDat = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
904             UNIX_TO_MACOS(fpb.hFileInfo.ioFlMdDat);
905             fpb.hFileInfo.ioFlCrDat = fpb.hFileInfo.ioFlMdDat;
906             }
907 
908      /* Restore ioDirID field in pb which was changed by PBGetCatInfoSync */
909         fpb.hFileInfo.ioDirID = CurrentFile.parID;
910 
911         if (err == noErr)
912             {
913             err = PBSetCatInfoSync((CInfoPBPtr)&fpb);
914             printerr("PBSetCatInfoSync",err,err,__LINE__,__FILE__,G.filename);
915             }
916         if (err != noErr)
917             Info(slide, 0x201, ((char *)slide, LoadFarString(ErrNoTimeSet),
918               FnFilter1(G.filename)));
919     }
920 
921 return err;
922 } /* end function SetFileTime() */
923 
924 
925 
926 
927 #ifndef SFX
928 
929 /************************/
930 /*  Function version()  */
931 /************************/
932 
version(__G)933 void version(__G)
934     __GDEF
935 {
936 /*
937 ZCONST char Far CompiledWith[] =
938                "Compiled with %s%s for %s%s%s%s.\n\n"; */
939 
940 char DateTime[50];
941 
942 #ifdef __MWERKS__
943 char CompVer[10];
944 sprintf(CompVer, "%x", __MWERKS__);
945 #endif
946 
947     sprintf(DateTime,"%s  %s",__DATE__, __TIME__);
948 
949     sprintf((char *)slide, LoadFarString(CompiledWith),
950 
951 #ifdef __MWERKS__
952 
953       " Metrowerks CodeWarrior version ",CompVer,
954 #else
955       " ", " ",
956 #endif
957 
958 #ifdef __MC68K__
959       " MC68K Processor",
960 #else
961       " PowerPC Processor",
962 #endif
963 
964 #ifdef __DATE__
965 
966       "\n compile time: ", DateTime, ""
967 #else
968       "", "", ""
969 #endif
970     );
971 
972     (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);
973 
974 } /* end function version() */
975 
976 #endif /* !SFX */
977 
978 
979 
980 
981 
982 /***********************/
983 /* Function macmkdir() */
984 /***********************/
985 
macmkdir(char * path)986 int macmkdir(char *path)
987 {
988     OSErr err = -1;
989     OSErr err_rc;
990     char CompletePath[NAME_MAX], CompletePath2[NAME_MAX];
991     Boolean isDirectory = false;
992     short CurrentFork;
993     unsigned pathlen;
994     long dirID;
995 
996     AssertStr(path, path)
997 
998     GetExtraFieldData(&MacZipMode, &newExtraField);
999 
1000     if (MacZipMode >= JohnnyLee_EF) {
1001         RfDfFilen2Real(CompletePath, G.filename, MacZipMode,
1002                        (newExtraField.flags & EB_M3_FL_NOCHANGE), &CurrentFork);
1003         if (CurrentFork == ResourceFork)
1004             /* don't build a 'XtraStuf.mac:' dir  */
1005             return 0;
1006     }
1007 
1008     if (!IgnoreEF_Macfilename)
1009         {
1010         pathlen = strlen(path);
1011         strcpy(CompletePath, uO.exdir);
1012         strcat(CompletePath, newExtraField.FullPath);
1013         CompletePath[pathlen] = 0x00;
1014         }
1015     else
1016         {
1017         strcpy(CompletePath, path);
1018         }
1019 
1020     GetCompletePath(CompletePath2, CompletePath, &CurrentFile, &err);
1021     printerr("GetCompletePath", (err != -43) && (err != -120) && (err != 0),
1022               err, __LINE__, __FILE__, CompletePath2);
1023 
1024 
1025     err = FSpGetDirectoryID(&CurrentFile, &dirID, &isDirectory);
1026     printerr("macmkdir FSpGetDirectoryID ", (err != -43) && (err != 0),
1027              err, __LINE__, __FILE__, CompletePath2);
1028 
1029     if (err != -43)     /* -43 = file/directory not found  */
1030         return 0;
1031     else {
1032         HParamBlockRec    hpbr;
1033 
1034         hpbr.fileParam.ioCompletion = NULL;
1035         hpbr.fileParam.ioNamePtr    = CurrentFile.name;
1036         hpbr.fileParam.ioVRefNum    = CurrentFile.vRefNum;
1037         hpbr.fileParam.ioDirID      = CurrentFile.parID;
1038         err = PBDirCreateSync(&hpbr);
1039         printerr("macmkdir PBDirCreateSync ", err,
1040                  err, __LINE__, __FILE__, CompletePath2);
1041 
1042         /* finally set FinderInfo */
1043         if  (MacZipMode >= JohnnyLee_EF)
1044             {
1045             err_rc = SetFinderInfo(__G__ (uO.D_flag <= 0),
1046                                    &CurrentFile, &newExtraField);
1047             printerr("macmkdir SetFinderInfo ", err_rc, err_rc,
1048                       __LINE__, __FILE__, CompletePath2);
1049             }
1050     }
1051 
1052     return (int)err;
1053 } /* macmkdir */
1054 
1055 
1056 
1057 
1058 /**********************/
1059 /* Function macopen() */
1060 /**********************/
1061 
macopen(char * sz,short nFlags)1062 short macopen(char *sz, short nFlags)
1063 {
1064     OSErr   err;
1065     char    chPerms = (!nFlags) ? fsRdPerm : fsRdWrPerm;
1066     short   nFRefNum;
1067 
1068     AssertStr(sz, sz)
1069 
1070     /* we only need the filespec of the zipfile;
1071        filespec of the other files (to be extracted) will be
1072        determined by open_outfile() */
1073     if (OpenZipFile)
1074         {
1075         char CompletePath[NAME_MAX];
1076         FSSpec zipfile;
1077         GetCompletePath(CompletePath, sz, &zipfile, &err);
1078         printerr("GetCompletePath", (err != -43) && (err != 0),
1079                   err, __LINE__, __FILE__, sz);
1080         if (CheckMountedVolumes(CompletePath) > 1)
1081             DoWarnUserDupVol(CompletePath);
1082         err = HOpen(zipfile.vRefNum, zipfile.parID, zipfile.name,
1083                     chPerms, &nFRefNum);
1084         printerr("Zipfile HOpen", err, err, __LINE__, __FILE__, sz);
1085         OpenZipFile = false;
1086         }
1087     else   /* open zipfile entries  */
1088         {
1089         if (nFlags > 1)
1090             {
1091             err = HOpenRF(CurrentFile.vRefNum, CurrentFile.parID, CurrentFile.name,
1092                       chPerms, &nFRefNum);
1093             printerr("HOpenRF", (err != -43) && (err != 0) && (err != -54),
1094                  err, __LINE__, __FILE__, sz);
1095             }
1096         else
1097             {
1098             err = HOpen(CurrentFile.vRefNum, CurrentFile.parID, CurrentFile.name,
1099                     chPerms, &nFRefNum);
1100             printerr("HOpen", (err != -43) && (err != 0),
1101                  err, __LINE__, __FILE__, sz);
1102             }
1103         }
1104 
1105     if ( err || (nFRefNum == 1) )
1106         {
1107         printerr("macopen", err, err, __LINE__, __FILE__,
1108                  (char *) CurrentFile.name);
1109         return -1;
1110         }
1111     else
1112         {
1113         if ( nFlags )
1114             SetEOF( nFRefNum, 0 );
1115         return nFRefNum;
1116         }
1117 }
1118 
1119 
1120 
1121 
1122 
1123 /***********************/
1124 /* Function maccreat() */
1125 /***********************/
1126 
maccreat(char * sz)1127 short maccreat(char *sz)
1128 {
1129     OSErr   err;
1130     char scriptTag = newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript;
1131     static char Num = 0;
1132 
1133     sz = sz;
1134 
1135     /* Set fdScript in FXInfo
1136      * The negative script constants (smSystemScript, smCurrentScript,
1137      * and smAllScripts) don't make sense on disk.  So only use scriptTag
1138      * if scriptTag >= smRoman (smRoman is 0).
1139      * fdScript is valid if high bit is set (see IM-6, page 9-38)
1140      */
1141     scriptTag = (scriptTag >= smRoman) ?
1142                 ((char)scriptTag | (char)0x80) : (smRoman);
1143     newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = scriptTag;
1144 
1145     err = FSpCreate(&CurrentFile,
1146                     newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator,
1147                     newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType,
1148                     newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript);
1149 
1150     /* -37 = bad filename; make the filename shorter and try again  */
1151     /* filename must not be longer than 32 chars */
1152     if (err == -37)
1153         {
1154         strcpy((char *)CurrentFile.name,
1155                 MakeFilenameShorter(P2CStr(CurrentFile.name)));
1156         Info(slide, 0x401, ((char *)slide, LoadFarString(FilenameToLong),
1157           FnFilter1((char *)CurrentFile.name)));
1158         C2PStr((char *)CurrentFile.name);
1159         err = FSpCreate(&CurrentFile,
1160                     newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdCreator,
1161                     newExtraField.fpb.hFileInfo.ioFlFndrInfo.fdType,
1162                     newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript);
1163         }
1164 
1165     err = printerr("FSpCreate maccreat ", (err != -48) && (err != 0),
1166                    err, __LINE__, __FILE__, G.filename);
1167 
1168     if (err == noErr)
1169         return noErr;
1170     else
1171         return -1;
1172 }
1173 
1174 
1175 
1176 
1177 
1178 /**********************/
1179 /* Function macread() */
1180 /**********************/
1181 
macread(short nFRefNum,char * pb,unsigned cb)1182 short macread(short nFRefNum, char *pb, unsigned cb)
1183 {
1184     long    lcb = cb;
1185 
1186     (void)FSRead( nFRefNum, &lcb, pb );
1187     return (short)lcb;
1188 }
1189 
1190 
1191 
1192 
1193 /***********************/
1194 /* Function macwrite() */
1195 /***********************/
1196 
macwrite(short nFRefNum,char * pb,unsigned cb)1197 long macwrite(short nFRefNum, char *pb, unsigned cb)
1198 {
1199     long    lcb = cb;
1200     OSErr   err = 0;
1201     FILE    *stream;
1202 
1203     if ( (nFRefNum == 1) || (nFRefNum == 2) )
1204         {
1205         stream = (nFRefNum == 1 ? stdout : stderr);
1206         pb[cb] = '\0';           /* terminate C-string */
1207                                  /* assumes writable buffer (e.g., slide[]) */
1208                                  /* with room for one more char at end of buf */
1209         lcb = fprintf(stream, "%s", pb);
1210         }
1211     else
1212         err = FSWrite( nFRefNum, &lcb, pb );
1213 
1214     if (err != 0)
1215         {
1216         errno = ERANGE;
1217         return -1;
1218         }
1219 
1220     return (long)lcb;
1221 }
1222 
1223 
1224 
1225 
1226 
1227 /***********************/
1228 /* Function macclose() */
1229 /***********************/
1230 
macclose(short nFRefNum)1231 short macclose(short nFRefNum)
1232 {
1233 OSErr err;
1234 
1235 err = FSClose( nFRefNum );
1236 printerr("macclose FSClose ",err,err, __LINE__,__FILE__,G.filename);
1237 
1238 
1239 return err;
1240 }
1241 
1242 
1243 
1244 
1245 
1246 /***********************/
1247 /* Function maclseek() */
1248 /***********************/
1249 
maclseek(short nFRefNum,long lib,short nMode)1250 long maclseek(short nFRefNum, long lib, short nMode)
1251 {
1252     ParamBlockRec   pbr;
1253 
1254     if (nMode == SEEK_SET)
1255         nMode = fsFromStart;
1256     else if (nMode == SEEK_CUR)
1257         nMode = fsFromMark;
1258     else if (nMode == SEEK_END)
1259         nMode = fsFromLEOF;
1260     pbr.ioParam.ioRefNum = nFRefNum;
1261     pbr.ioParam.ioPosMode = nMode;
1262     pbr.ioParam.ioPosOffset = lib;
1263     (void)PBSetFPosSync(&pbr);
1264     return pbr.ioParam.ioPosOffset;
1265 }
1266 
1267 
1268 
BuildMacFilename(void)1269 static void BuildMacFilename(void)
1270 {
1271 char CompletePath[NAME_MAX];
1272 char ArchiveDir[NAME_MAX];
1273 unsigned exdirlen = strlen(uO.exdir);
1274 short CurrentFork;
1275 OSErr err;
1276 
1277 GetExtraFieldData(&MacZipMode, &newExtraField);
1278 
1279 if (MacZipMode >= JohnnyLee_EF)
1280     {
1281     if (IgnoreEF_Macfilename)
1282         {
1283         strcpy(ArchiveDir, &G.filename[exdirlen+1]);
1284         G.filename[exdirlen+1] = '\0';
1285         RfDfFilen2Real(ArchiveDir, ArchiveDir, MacZipMode,
1286                       (newExtraField.flags & EB_M3_FL_DATFRK), &CurrentFork);
1287         strcat(G.filename, ArchiveDir);
1288         }
1289     else
1290         {        /* use the filename of mac extra-field */
1291         G.filename[exdirlen] = '\0';  /* cut resource-path */
1292         strcat(G.filename,newExtraField.FullPath);
1293         }
1294     }
1295 
1296 GetCompletePath(CompletePath, G.filename, &CurrentFile, &err);
1297 printerr("GetCompletePath BuildMacFilename ", (err != -43) && (err != 0),
1298              err, __LINE__, __FILE__, CompletePath);
1299 
1300 err = GetVolFileSystemID(C2PStr(CompletePath), CurrentFile.vRefNum,
1301                          &fileSystemID);
1302 printerr("GetVolFileSystemID BuildMacFilename ", err, err, __LINE__, __FILE__,
1303           CompletePath);
1304 
1305 if (MacZipMode == TomBrownZipIt1_EF)
1306     {
1307     memcpy(CurrentFile.name, newExtraField.filename, newExtraField.filename[0]+1);
1308     CurrentFile.name[0] = CurrentFile.name[0] - 1;
1309     }
1310 
1311 }
1312 
1313 
1314 
1315 
1316 /* The following functions are dealing with the extra-field handling, only. */
1317 
1318 /****************************/
1319 /* Function SetFinderInfo() */
1320 /****************************/
1321 
SetFinderInfo(__GPRO__ int SetTime,FSSpec * spec,MACINFO * mi)1322 static OSErr SetFinderInfo(__GPRO__ int SetTime, FSSpec *spec, MACINFO *mi)
1323 {
1324     OSErr err;
1325     CInfoPBRec      fpb;
1326 
1327     fpb.hFileInfo.ioNamePtr   = (StringPtr) &(spec->name);
1328     fpb.hFileInfo.ioVRefNum   = spec->vRefNum;
1329     fpb.hFileInfo.ioDirID     = spec->parID;
1330     fpb.hFileInfo.ioFDirIndex = 0;
1331 
1332     err = PBGetCatInfoSync(&fpb);
1333     printerr("PBGetCatInfo SetFinderInfo ", err, err,
1334              __LINE__, __FILE__, G.filename);
1335 
1336     if  ((MacZipMode == JohnnyLee_EF) || (MacZipMode == NewZipMode_EF))
1337     {
1338         /* skip restoring time stamps on user's request */
1339         if (SetTime && !UseUT_ExtraField) {
1340             fpb.hFileInfo.ioFlCrDat = mi->fpb.hFileInfo.ioFlCrDat;
1341             fpb.hFileInfo.ioFlMdDat = mi->fpb.hFileInfo.ioFlMdDat;
1342         }
1343 
1344         fpb.hFileInfo.ioFlFndrInfo   = mi->fpb.hFileInfo.ioFlFndrInfo;
1345     }
1346 
1347     if (MacZipMode == NewZipMode_EF)
1348     {
1349         if (uO.E_flag) PrintMacExtraInfo(mi);
1350         fpb.hFileInfo.ioFlXFndrInfo  = mi->fpb.hFileInfo.ioFlXFndrInfo;
1351 
1352         fpb.hFileInfo.ioFVersNum  = mi->fpb.hFileInfo.ioFVersNum;
1353         fpb.hFileInfo.ioACUser    = mi->fpb.hFileInfo.ioACUser;
1354 
1355         /* skip restoring time stamps on user's request */
1356         if (SetTime && !UseUT_ExtraField) {
1357             fpb.hFileInfo.ioFlBkDat = mi->fpb.hFileInfo.ioFlBkDat;
1358 #ifdef USE_EF_UT_TIME
1359             if (!(mi->flags & EB_M3_FL_NOUTC))
1360                 {
1361 #ifdef DEBUG_TIME
1362             {
1363             printf("\nSetFinderInfo:  Mac modif: %lu local -> UTOffset: "\
1364                    "%d before AdjustForTZmoveMac\n",
1365               fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);
1366             }
1367 #endif /* DEBUG_TIME */
1368                 fpb.hFileInfo.ioFlCrDat =
1369                   AdjustForTZmoveMac(fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);
1370                 fpb.hFileInfo.ioFlMdDat =
1371                   AdjustForTZmoveMac(fpb.hFileInfo.ioFlMdDat, mi->Md_UTCoffs);
1372                 fpb.hFileInfo.ioFlBkDat =
1373                   AdjustForTZmoveMac(fpb.hFileInfo.ioFlBkDat, mi->Bk_UTCoffs);
1374 #ifdef DEBUG_TIME
1375             {
1376             printf("SetFinderInfo:  Mac modif: %lu local -> UTOffset: "\
1377                    "%d after AdjustForTZmoveMac\n",
1378               fpb.hFileInfo.ioFlCrDat, mi->Cr_UTCoffs);
1379             }
1380 #endif /* DEBUG_TIME */
1381 
1382                 }
1383 #endif /* USE_EF_UT_TIME */
1384         }
1385 
1386         if ((mi->FinderComment) &&
1387            (fileSystemID == HFS_fileSystem)) {
1388             C2PStr(mi->FinderComment);
1389             err = FSpDTSetComment(spec, (unsigned char *) mi->FinderComment);
1390             printerr("FSpDTSetComment:",err , err,
1391                      __LINE__, __FILE__, mi->FullPath);
1392         }
1393     }
1394 
1395     /* Restore ioDirID field in pb which was changed by PBGetCatInfo */
1396     fpb.hFileInfo.ioDirID = spec->parID;
1397     err = PBSetCatInfoSync(&fpb);
1398 
1399     return err;
1400 } /* SetFinderInfo() */
1401 
1402 
1403 
1404 
1405 /*
1406 ** Scan the extra fields in extra_field, and look for a MacOS EF; return a
1407 ** pointer to that EF, or NULL if it's not there.
1408 */
scanMacOSexfield(uch * ef_ptr,unsigned ef_len,short * MacZipMode)1409 static uch *scanMacOSexfield(uch *ef_ptr, unsigned ef_len,
1410                              short *MacZipMode)
1411 {
1412     while (ef_ptr != NULL && ef_len >= EB_HEADSIZE) {
1413         unsigned eb_id  = makeword(EB_ID  + ef_ptr);
1414         unsigned eb_len = makeword(EB_LEN + ef_ptr);
1415 
1416         if (eb_len > (ef_len - EB_HEADSIZE)) {
1417             Trace((stderr,
1418               "scanMacOSexfield: block length %u > rest ef_size %u\n", eb_len,
1419               ef_len - EB_HEADSIZE));
1420             break;
1421         }
1422 
1423         if (isMacOSexfield(eb_id, eb_len, MacZipMode)) {
1424             return ef_ptr;
1425         }
1426 
1427         ef_ptr += (eb_len + EB_HEADSIZE);
1428         ef_len -= (eb_len + EB_HEADSIZE);
1429     }
1430 
1431     return NULL;
1432 }
1433 
1434 
1435 
1436 
isMacOSexfield(unsigned id,unsigned size,short * MacZipMode)1437 static Boolean isMacOSexfield(unsigned id, unsigned size, short *MacZipMode)
1438 {
1439 size = size;
1440 
1441     switch (id)
1442         {
1443         case EF_ZIPIT:
1444             {           /* we do not (yet) support ZipIt's format completely */
1445             *MacZipMode = TomBrownZipIt1_EF;
1446             IgnoreEF_Macfilename = true;
1447             return true;
1448             }
1449 
1450         case EF_ZIPIT2:
1451             {           /* we do not (yet) support ZipIt's format completely */
1452             *MacZipMode = TomBrownZipIt2_EF;
1453             IgnoreEF_Macfilename = true;
1454             return true;
1455             }
1456 
1457         case EF_MAC3:
1458             {           /* the new maczip format */
1459             *MacZipMode = NewZipMode_EF;
1460             IgnoreEF_Macfilename = false;
1461             return true;
1462             }
1463 
1464         case EF_JLMAC:
1465             {           /* Johnny Lee's old maczip format */
1466             *MacZipMode = JohnnyLee_EF;
1467             IgnoreEF_Macfilename = true;
1468             return true;
1469             }
1470 
1471         default:
1472             {           /* any other format */
1473             *MacZipMode = UnKnown_EF;
1474             IgnoreEF_Macfilename = true;
1475             return false;
1476             }
1477         }
1478 
1479     return false;
1480 }
1481 
1482 
1483 
1484 
1485 /*
1486 ** Return a unsigned long from a four-byte sequence
1487 ** in big endian format
1488 */
1489 
makePPClong(ZCONST uch * sig)1490 ulg makePPClong(ZCONST uch *sig)
1491 {
1492     return (((ulg)sig[0]) << 24)
1493          + (((ulg)sig[1]) << 16)
1494          + (((ulg)sig[2]) << 8)
1495          +  ((ulg)sig[3]);
1496 }
1497 
1498 
1499 
1500 
1501 /*
1502 ** Return a unsigned short from a two-byte sequence
1503 ** in big endian format
1504 */
1505 
makePPCword(ZCONST uch * b)1506 ush makePPCword(ZCONST uch *b)
1507 {
1508     return (ush)((b[0] << 8) | b[1]);
1509 }
1510 
1511 
1512 
1513 
1514 /*
1515 ** Print mac extra-field
1516 **
1517 */
1518 
PrintMacExtraInfo(MACINFO * mi)1519 static void PrintMacExtraInfo(MACINFO *mi)
1520 {
1521 #define MY_FNDRINFO fpb.hFileInfo.ioFlFndrInfo
1522     DateTimeRec  MacTime;
1523     static ZCONST char space[] = "                                    ";
1524     static ZCONST char line[]  = "------------------------------------"\
1525                                  "------------------------------";
1526 
1527     printf("\n\n%s", line);
1528 
1529     printf("\nFullPath      = [%s]", mi->FullPath);
1530     printf("\nFinderComment = [%s]", mi->FinderComment);
1531     printf("\nText Encoding Base (Filename)       \"%s\" \n",
1532         PrintTextEncoding(mi->fpb.hFileInfo.ioFlXFndrInfo.fdScript));
1533 
1534     printf("\nExtraField Flags :                  %s  0x%x  %4d",
1535              sBit2Str(mi->flags), mi->flags, mi->flags);
1536 
1537     printf("\n%sExtra Field is %s", space,
1538            (mi->flags & EB_M3_FL_UNCMPR ?
1539             "Uncompressed" : "Compressed"));
1540     printf("\n%sFile Dates are in %u Bit", space,
1541            (mi->flags & EB_M3_FL_TIME64 ? 64 : 32));
1542     printf("\n%sFile UTC time adjustments are %ssupported", space,
1543            (mi->flags & EB_M3_FL_NOUTC ? "not " : ""));
1544     printf("\n%sFile Name is %schanged", space,
1545            (mi->flags & EB_M3_FL_NOCHANGE ? "not " : ""));
1546     printf("\n%sFile is a %s\n", space,
1547            (mi->flags & EB_M3_FL_DATFRK ?
1548             "Datafork" : "Resourcefork"));
1549 
1550     /* not all type / creator codes are printable */
1551     if (isprint((char)(mi->MY_FNDRINFO.fdType >> 24)) &&
1552         isprint((char)(mi->MY_FNDRINFO.fdType >> 16)) &&
1553         isprint((char)(mi->MY_FNDRINFO.fdType >> 8)) &&
1554         isprint((char)mi->MY_FNDRINFO.fdType))
1555     {
1556         printf("\nFile Type =                         [%c%c%c%c]  0x%lx",
1557             (char)(mi->MY_FNDRINFO.fdType >> 24),
1558             (char)(mi->MY_FNDRINFO.fdType >> 16),
1559             (char)(mi->MY_FNDRINFO.fdType >> 8),
1560             (char)(mi->MY_FNDRINFO.fdType),
1561             mi->MY_FNDRINFO.fdType);
1562     }
1563     else
1564     {
1565         printf("\nFile Type =                                     0x%lx",
1566             mi->MY_FNDRINFO.fdType);
1567     }
1568 
1569     if (isprint((char)(mi->MY_FNDRINFO.fdCreator >> 24)) &&
1570         isprint((char)(mi->MY_FNDRINFO.fdCreator >> 16)) &&
1571         isprint((char)(mi->MY_FNDRINFO.fdCreator >> 8)) &&
1572         isprint((char)mi->MY_FNDRINFO.fdCreator))
1573     {
1574         printf("\nFile Creator =                      [%c%c%c%c]  0x%lx",
1575             (char)(mi->MY_FNDRINFO.fdCreator >> 24),
1576             (char)(mi->MY_FNDRINFO.fdCreator >> 16),
1577             (char)(mi->MY_FNDRINFO.fdCreator >> 8),
1578             (char)(mi->MY_FNDRINFO.fdCreator),
1579             mi->MY_FNDRINFO.fdCreator);
1580     }
1581     else
1582     {
1583         printf("\nFile Creator =                                  0x%lx",
1584             mi->MY_FNDRINFO.fdCreator);
1585     }
1586 
1587     printf("\n\nDates (local time of archiving location):");
1588     SecondsToDate(mi->fpb.hFileInfo.ioFlCrDat, &MacTime);
1589     printf("\n    Created  =                      %4d/%2d/%2d %2d:%2d:%2d  ",
1590            MacTime.year, MacTime.month, MacTime.day,
1591            MacTime.hour, MacTime.minute, MacTime.second);
1592     SecondsToDate(mi->fpb.hFileInfo.ioFlMdDat, &MacTime);
1593     printf("\n    Modified =                      %4d/%2d/%2d %2d:%2d:%2d  ",
1594            MacTime.year, MacTime.month, MacTime.day,
1595            MacTime.hour, MacTime.minute, MacTime.second);
1596     SecondsToDate(mi->fpb.hFileInfo.ioFlBkDat, &MacTime);
1597     printf("\n    Backup   =                      %4d/%2d/%2d %2d:%2d:%2d  ",
1598         MacTime.year, MacTime.month, MacTime.day,
1599         MacTime.hour, MacTime.minute, MacTime.second);
1600 
1601     if (!(mi->flags & EB_M3_FL_NOUTC)) {
1602         printf("\nGMT Offset of Creation time  =      %4ld sec  %2d h",
1603           mi->Cr_UTCoffs, (int)mi->Cr_UTCoffs / (60 * 60));
1604         printf("\nGMT Offset of Modification time  =  %4ld sec  %2d h",
1605           mi->Md_UTCoffs, (int)mi->Md_UTCoffs / (60 * 60));
1606         printf("\nGMT Offset of Backup time  =        %4ld sec  %2d h",
1607           mi->Bk_UTCoffs, (int)mi->Bk_UTCoffs / (60 * 60));
1608     }
1609 
1610     printf("\n\nFinder Flags :                      %s  0x%x  %4d",
1611         sBit2Str(mi->MY_FNDRINFO.fdFlags),
1612         mi->MY_FNDRINFO.fdFlags,
1613         mi->MY_FNDRINFO.fdFlags);
1614 
1615     printf("\nFinder Icon Position =              X: %4d",
1616         mi->MY_FNDRINFO.fdLocation.h);
1617 
1618     printf("\n                                    Y: %4d",
1619         mi->MY_FNDRINFO.fdLocation.v);
1620 
1621     printf("\n\nText Encoding Base (System/MacZip)  \"%s\"",
1622         PrintTextEncoding(mi->TextEncodingBase));
1623 
1624     printf("\n%s\n", line);
1625 #undef MY_FNDRINFO
1626 }
1627 
1628 
1629 
1630 
1631 /*
1632 ** Decode mac extra-field and assign the data to the structure
1633 **
1634 */
1635 
GetExtraFieldData(short * MacZipMode,MACINFO * mi)1636 static Boolean GetExtraFieldData(short *MacZipMode, MACINFO *mi)
1637 {
1638 uch *ptr;
1639 int  retval = PK_OK;
1640 
1641 ptr = scanMacOSexfield(G.extra_field, G.lrec.extra_field_length, MacZipMode);
1642 
1643 /* MacOS is no preemptive OS therefore do some (small) event-handling */
1644 UserStop();
1645 
1646 if (uO.J_flag)
1647     {
1648     *MacZipMode = UnKnown_EF;
1649     IgnoreEF_Macfilename = true;
1650     return false;
1651     }
1652 
1653 if (ptr != NULL)
1654 {   /*   Collect the data from the extra field buffer. */
1655     mi->header    = makeword(ptr);    ptr += 2;
1656     mi->data      = makeword(ptr);    ptr += 2;
1657 
1658     switch (*MacZipMode)
1659         {
1660         case NewZipMode_EF:
1661            {
1662             mi->size      =  makelong(ptr); ptr += 4;
1663             mi->flags     =  makeword(ptr); ptr += 2;
1664                              /* Type/Creator are always uncompressed */
1665             mi->fpb.hFileInfo.ioFlFndrInfo.fdType    = makePPClong(ptr);
1666             ptr += 4;
1667             mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator = makePPClong(ptr);
1668             ptr += 4;
1669 
1670             if (!(mi->flags & EB_M3_FL_UNCMPR))
1671                 {
1672 
1673                 retval = memextract(__G__ attrbuff, mi->size, ptr,
1674                                     mi->data - EB_MAC3_HLEN);
1675 
1676                 if (retval != PK_OK)  /* error uncompressing attributes */
1677                     {
1678                     Info(slide, 0x201, ((char *)slide,
1679                          LoadFarString(ErrUncmpEF)));
1680                     *MacZipMode = UnKnown_EF;
1681                     return false;     /* EF-Block unusable, ignore it */
1682                     }
1683 
1684                 }
1685              else
1686                 {   /* file attributes are uncompressed */
1687                 attrbuff = ptr;
1688                 }
1689 
1690             DecodeMac3ExtraField(attrbuff, mi);
1691 
1692             return true;
1693             break;
1694             }
1695 
1696         case JohnnyLee_EF:
1697             {
1698             if (strncmp((char *)ptr, "JLEE", 4) == 0)
1699                 {   /* Johnny Lee's old MacZip e.f. was found */
1700                 attrbuff  = ptr + 4;
1701                 DecodeJLEEextraField(attrbuff, mi);
1702                 return true;
1703                 }
1704             else
1705                 {   /* second signature did not match, ignore EF block */
1706                 *MacZipMode = UnKnown_EF;
1707                 return false;
1708                 }
1709             break;
1710             }
1711 
1712 
1713         case TomBrownZipIt1_EF:
1714         case TomBrownZipIt2_EF:
1715             {
1716             if (strncmp((char *)ptr, "ZPIT", 4) == 0)
1717                 {   /* Johnny Lee's old MacZip e.f. was found */
1718                 attrbuff  = ptr + 4;
1719                 DecodeZPITextraField(attrbuff, mi);
1720                 return true;
1721                 }
1722             else
1723                 {   /* second signature did not match, ignore EF block */
1724                 *MacZipMode = UnKnown_EF;
1725                 return false;
1726                 }
1727             break;
1728             }
1729 
1730 
1731         default:
1732             {  /* just to make sure */
1733             *MacZipMode = UnKnown_EF;
1734             IgnoreEF_Macfilename = true;
1735             return false;
1736             break;
1737             }
1738         }
1739 }  /* if (ptr != NULL)  */
1740 
1741 /* no Mac extra field was found */
1742 return false;
1743 }
1744 
1745 
1746 
1747 
1748 /*
1749 ** Assign the new Mac3 Extra-Field to the structure
1750 **
1751 */
1752 
DecodeMac3ExtraField(ZCONST uch * buff,MACINFO * mi)1753 static void DecodeMac3ExtraField(ZCONST uch *buff, MACINFO *mi)
1754 {               /* extra-field info of the new MacZip implementation */
1755                 /* compresssed extra-field starts here (if compressed) */
1756 
1757 Assert_it(buff, "", "");
1758 
1759 mi->fpb.hFileInfo.ioFlFndrInfo.fdFlags        =  makeword(buff); buff += 2;
1760 mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.v   =  makeword(buff); buff += 2;
1761 mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.h   =  makeword(buff); buff += 2;
1762 mi->fpb.hFileInfo.ioFlFndrInfo.fdFldr         =  makeword(buff); buff += 2;
1763 
1764 mi->fpb.hFileInfo.ioFlXFndrInfo.fdIconID      =  makeword(buff); buff += 2;
1765 mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[0] =  makeword(buff); buff += 2;
1766 mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[1] =  makeword(buff); buff += 2;
1767 mi->fpb.hFileInfo.ioFlXFndrInfo.fdReserved[2] =  makeword(buff); buff += 2;
1768 mi->fpb.hFileInfo.ioFlXFndrInfo.fdScript      = *buff;           buff += 1;
1769 mi->fpb.hFileInfo.ioFlXFndrInfo.fdXFlags      = *buff;           buff += 1;
1770 mi->fpb.hFileInfo.ioFlXFndrInfo.fdComment     =  makeword(buff); buff += 2;
1771 mi->fpb.hFileInfo.ioFlXFndrInfo.fdPutAway     =  makelong(buff); buff += 4;
1772 
1773 mi->fpb.hFileInfo.ioFVersNum                  = *buff;           buff += 1;
1774 mi->fpb.hFileInfo.ioACUser                    = *buff;           buff += 1;
1775 
1776 /*
1777 This implementation does not use the 64 bit time values, therefore
1778 use the UT extra field instead
1779 */
1780 if (mi->flags & EB_M3_FL_TIME64)
1781     {
1782     Info(slide, 0x201, ((char *)slide, LoadFarString(No64Time)));
1783     UseUT_ExtraField = true;
1784     buff += 24; /* jump over the date values */
1785     }
1786 else
1787     {
1788     UseUT_ExtraField = false;
1789     mi->fpb.hFileInfo.ioFlCrDat   =  makelong(buff); buff += 4;
1790     mi->fpb.hFileInfo.ioFlMdDat   =  makelong(buff); buff += 4;
1791     mi->fpb.hFileInfo.ioFlBkDat   =  makelong(buff); buff += 4;
1792     }
1793 
1794 if (!(mi->flags & EB_M3_FL_NOUTC))
1795     {
1796     mi->Cr_UTCoffs =  makelong(buff); buff += 4;
1797     mi->Md_UTCoffs =  makelong(buff); buff += 4;
1798     mi->Bk_UTCoffs =  makelong(buff); buff += 4;
1799     }
1800 
1801 /* TextEncodingBase type & values */
1802 /* (values 0-32 correspond to the Script Codes defined in "Inside Macintosh",
1803     Text pages 6-52 and 6-53) */
1804 mi->TextEncodingBase =  makeword(buff); buff += 2;
1805 
1806 if (mi->TextEncodingBase >= kTextEncodingUnicodeV1_1)
1807     {
1808     Info(slide, 0x201, ((char *)slide, LoadFarString(NoUniCode)));
1809     IgnoreEF_Macfilename = true;
1810     }
1811 
1812 mi->FullPath      = (char *)buff; buff += strlen(mi->FullPath) + 1;
1813 mi->FinderComment = (char *)buff; buff += strlen(mi->FinderComment) + 1;
1814 
1815 if (uO.i_flag) IgnoreEF_Macfilename = true;
1816 
1817 }
1818 
1819 
1820 
1821 
1822 /*
1823 ** Assign the new JLEE Extra-Field to the structure
1824 **
1825 */
1826 
DecodeJLEEextraField(ZCONST uch * buff,MACINFO * mi)1827 static void DecodeJLEEextraField(ZCONST uch *buff, MACINFO *mi)
1828 { /*  extra-field info of Johnny Lee's old MacZip  */
1829 
1830 Assert_it(buff, "", "");
1831 
1832 mi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff); buff += 4;
1833 mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff); buff += 4;
1834 mi->fpb.hFileInfo.ioFlFndrInfo.fdFlags      = makePPCword(buff); buff += 2;
1835 mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.v = makePPCword(buff); buff += 2;
1836 mi->fpb.hFileInfo.ioFlFndrInfo.fdLocation.h = makePPCword(buff); buff += 2;
1837 mi->fpb.hFileInfo.ioFlFndrInfo.fdFldr       = makePPCword(buff); buff += 2;
1838 
1839 mi->fpb.hFileInfo.ioFlCrDat                =  makePPClong(buff); buff += 4;
1840 mi->fpb.hFileInfo.ioFlMdDat                =  makePPClong(buff); buff += 4;
1841 mi->flags                                  =  makePPClong(buff); buff += 4;
1842 
1843 newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = smSystemScript;
1844 }
1845 
1846 
1847 
1848 
1849 /*
1850 ** Assign the new JLEE Extra-Field to the structure
1851 **
1852 */
1853 
DecodeZPITextraField(ZCONST uch * buff,MACINFO * mi)1854 static void DecodeZPITextraField(ZCONST uch *buff, MACINFO *mi)
1855 { /*  extra-field info of Johnny Lee's old MacZip  */
1856 unsigned char filelen;
1857 
1858 Assert_it(buff, "", "");
1859 
1860 #ifdef SwitchZIPITefSupportOff
1861 MacZipMode = UnKnown_EF;
1862 Info(slide, 0x221, ((char *)slide,LoadFarString(ZitIt_EF)));
1863 return;
1864 #endif
1865 
1866 if (MacZipMode == TomBrownZipIt1_EF)
1867     {
1868     filelen = *buff;
1869     newExtraField.filename = buff;
1870     buff += 1;
1871     buff += filelen;
1872     mi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff);
1873     buff += 4;
1874     mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff);
1875     buff += 4;
1876     }
1877 else   /*  if (MacZipMode == TomBrownZipIt2_EF)  */
1878     {
1879     mi->fpb.hFileInfo.ioFlFndrInfo.fdType       = makePPClong(buff);
1880     buff += 4;
1881     mi->fpb.hFileInfo.ioFlFndrInfo.fdCreator    = makePPClong(buff);
1882     buff += 4;
1883     }
1884 
1885 newExtraField.fpb.hFileInfo.ioFlXFndrInfo.fdScript = smSystemScript;
1886 }
1887 
1888 
1889 
1890 /*
1891 ** Return char* to describe the text encoding
1892 **
1893 */
1894 
PrintTextEncoding(short script)1895 static char *PrintTextEncoding(short script)
1896 {
1897 char *info;
1898 static char buffer[14];
1899 /* TextEncodingBase type & values */
1900 /* (values 0-32 correspond to the Script Codes defined in
1901    Inside Macintosh: Text pages 6-52 and 6-53 */
1902 
1903 switch (script) {               /* Mac OS encodings*/
1904     case kTextEncodingMacRoman:         info = "Roman";             break;
1905     case kTextEncodingMacJapanese:      info = "Japanese";          break;
1906     case kTextEncodingMacChineseTrad:   info = "ChineseTrad";       break;
1907     case kTextEncodingMacKorean:        info = "Korean";            break;
1908     case kTextEncodingMacArabic:        info = "Arabic";            break;
1909     case kTextEncodingMacHebrew:        info = "Hebrew";            break;
1910     case kTextEncodingMacGreek:         info = "Greek";             break;
1911     case kTextEncodingMacCyrillic:      info = "Cyrillic";          break;
1912     case kTextEncodingMacDevanagari:    info = "Devanagari";        break;
1913     case kTextEncodingMacGurmukhi:      info = "Gurmukhi";          break;
1914     case kTextEncodingMacGujarati:      info = "Gujarati";          break;
1915     case kTextEncodingMacOriya:         info = "Oriya";             break;
1916     case kTextEncodingMacBengali:       info = "Bengali";           break;
1917     case kTextEncodingMacTamil:         info = "Tamil";             break;
1918     case kTextEncodingMacTelugu:        info = "Telugu";            break;
1919     case kTextEncodingMacKannada:       info = "Kannada";           break;
1920     case kTextEncodingMacMalayalam:     info = "Malayalam";         break;
1921     case kTextEncodingMacSinhalese:     info = "Sinhalese";         break;
1922     case kTextEncodingMacBurmese:       info = "Burmese";           break;
1923     case kTextEncodingMacKhmer:         info = "Khmer";             break;
1924     case kTextEncodingMacThai:          info = "Thai";              break;
1925     case kTextEncodingMacLaotian:       info = "Laotian";           break;
1926     case kTextEncodingMacGeorgian:      info = "Georgian";          break;
1927     case kTextEncodingMacArmenian:      info = "Armenian";          break;
1928     case kTextEncodingMacChineseSimp:   info = "ChineseSimp";       break;
1929     case kTextEncodingMacTibetan:       info = "Tibetan";           break;
1930     case kTextEncodingMacMongolian:     info = "Mongolian";         break;
1931     case kTextEncodingMacEthiopic:      info = "Ethiopic";          break;
1932     case kTextEncodingMacCentralEurRoman: info = "CentralEurRoman"; break;
1933     case kTextEncodingMacVietnamese:    info = "Vietnamese";        break;
1934     case kTextEncodingMacExtArabic:     info = "ExtArabic";         break;
1935 
1936     case kTextEncodingUnicodeV1_1:      info = "Unicode V 1.1";     break;
1937     case kTextEncodingUnicodeV2_0:      info = "Unicode V 2.0";     break;
1938 
1939     default:  {
1940         sprintf(buffer,"Code: 0x%x",(short) script);
1941         info = buffer;
1942         break;
1943         }
1944     }
1945 
1946 return info;
1947 }
1948 
1949 
1950 
1951 /*
1952 ** Init Globals
1953 **
1954 */
1955 
MacGlobalsInit(__GPRO)1956 void   MacGlobalsInit(__GPRO)
1957 {
1958 newExtraField.FullPath      = NULL;
1959 newExtraField.FinderComment = NULL;
1960 
1961 OpenZipFile = true;
1962 
1963 MacZipMode = UnKnown_EF;
1964 IgnoreEF_Macfilename = true;
1965 
1966 if (malloced_attrbuff == NULL)
1967     {
1968     /* make room for extra-field */
1969     attrbuff = (uch *)malloc(EB_MAX_OF_VARDATA);
1970 
1971     if (attrbuff == NULL)
1972         {             /* No memory to uncompress attributes */
1973         Info(slide, 0x201, ((char *)slide, LoadFarString(OutOfMemEF)));
1974         exit(PK_MEM);
1975         }
1976     else
1977         {
1978         malloced_attrbuff = attrbuff;
1979         }
1980     }
1981 else
1982     {
1983     attrbuff = malloced_attrbuff;
1984     }
1985 
1986 }
1987