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