Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 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 |
||
50 | #include |
||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | */ |
||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | |||
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 | }><>><>><>><>=>=>=>=>=>=> |