2
Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
4
See the accompanying file LICENSE, version 1999-Oct-05 or later
5
(the contents of which are also included in zip.h) for terms of use.
6
If, for some reason, both of these files are missing, the Info-ZIP license
7
also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
9
/*---------------------------------------------------------------------------
13
Macintosh-specific routines for use with Info-ZIP's Zip 2.3 and later.
15
---------------------------------------------------------------------------*/
18
/*****************************************************************************/
20
/*****************************************************************************/
37
/* #include "charmap.h" */
44
/*****************************************************************************/
45
/* Macros, typedefs */
46
/*****************************************************************************/
48
#define PATH_END MacPathEnd
50
/*****************************************************************************/
52
/*****************************************************************************/
54
int error_level; /* used only in ziperr() */
57
/* Note: sizeof() returns the size of this allusion
58
13 is current length of "XtraStuf.mac:" */
59
extern const char ResourceMark[13]; /* var is initialized in file pathname.c */
62
extern jmp_buf EnvForExit;
65
unsigned long count_of_Zippedfiles = 0;
68
/*****************************************************************************/
69
/* Module level Vars */
70
/*****************************************************************************/
72
static const char MacPathEnd = ':'; /* the Macintosh dir separator */
74
/* Inform Progress vars */
75
long estTicksToFinish;
79
static char *Time_Est_strings[] = {
80
"Zipping Files; Items done:",
83
"About %s hours, %s minutes",
86
"About %s minutes, %s seconds",
91
"About 1 minute, %s seconds"};
95
/*****************************************************************************/
97
/*****************************************************************************/
99
int DoCurrentDir(void);
101
void DoAboutBox(void);
103
void DoEventLoop(void);
105
void ZipInitAllVars(void);
107
Boolean IsZipFile(char *name);
109
static long EstimateCompletionTime(const long progressMax,
110
const long progressSoFar, unsigned char percent);
111
static void UpdateTimeToComplete(void);
118
void DoWarnUserDupVol( char *FullPath );
120
/*****************************************************************************/
122
/*****************************************************************************/
125
** Standalone Unzip with Metrowerks SIOUX starts here
128
int main(int argc, char **argv)
132
SIOUXSettings.asktosaveonclose = FALSE;
133
SIOUXSettings.showstatusline = TRUE;
135
SIOUXSettings.columns = 100;
136
SIOUXSettings.rows = 40;
138
/* 30 = MacZip Johnny Lee's; 40 = new (my) MacZip */
139
MacZip.MacZipMode = NewZipMode_EF;
141
argc = ccommand(&argv);
142
if (verbose) PrintArguments(argc, argv);
146
return_code = zipmain(argc, argv);
148
if (verbose) printf("\n\n Finish");
155
** SIOUX needs no extra event handling
167
** Password enter function '*' printed for each char
173
WindowPtr whichWindow;
174
EventRecord theEvent;
175
char c; /* one-byte buffer for read() to use */
179
if (!GetNextEvent(everyEvent, &theEvent))
180
theEvent.what = nullEvent;
182
switch (theEvent.what) {
184
c = theEvent.message & charCodeMask;
187
if (FindWindow(theEvent.where, &whichWindow) ==
189
SystemClick(&theEvent, whichWindow);
195
} while (theEvent.what != keyDown);
208
/******************************/
209
/* Function version_local() */
210
/******************************/
213
** Print Compilers version and compile time/date
220
Compiled with Metrowerks CodeWarrior version 2000 for PowerPC Processor
221
compile time: Feb 4 1998 17:49:49.
224
static ZCONST char CompiledWith[] =
225
"\n\nCompiled with %s %x for %s \n %s %s %s.\n\n";
231
" Metrowerks CodeWarrior version", __MWERKS__,
238
" PowerPC Processor",
242
"compile time: ", __DATE__, __TIME__
247
} /* end function version_local() */
254
** Deletes a dir if the switch '-m' is used
258
int deletedir(char *path)
261
static FSSpec trashfolder;
262
static Boolean FirstCall = true;
263
static Boolean Immediate_File_Deletion = false;
266
char currpath[NAME_MAX], *envptr;
269
/* init this function */
270
if ((path == NULL) ||
280
GetCompletePath(currpath,path,&dirToDelete, &err);
282
if (FirstCall == true)
285
envptr = getenv("Immediate_File_Deletion");
286
if (!(envptr == (char *)NULL || *envptr == '\0'))
288
if (stricmp(envptr,"yes") == 0)
289
Immediate_File_Deletion = true;
291
Immediate_File_Deletion = false;
293
err = FSpFindFolder(dirToDelete.vRefNum, kTrashFolderType,
294
kDontCreateFolder,&trashfolder);
295
printerr("FSpFindFolder:",err,err,__LINE__,__FILE__,path);
298
fpb.dirInfo.ioNamePtr = dirToDelete.name;
299
fpb.dirInfo.ioVRefNum = dirToDelete.vRefNum;
300
fpb.dirInfo.ioDrDirID = dirToDelete.parID;
301
fpb.dirInfo.ioFDirIndex = 0;
303
err = PBGetCatInfoSync(&fpb);
304
printerr("PBGetCatInfo deletedir ", err, err,
305
__LINE__, __FILE__, "");
307
if (fpb.dirInfo.ioDrNmFls > 0)
309
return 0; /* do not move / delete folders which are not empty */
312
if (Immediate_File_Deletion)
314
err = FSpDelete(&dirToDelete);
318
err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,
319
dirToDelete.name, trashfolder.parID, trashfolder.name);
321
/* -48 = file is already existing so we have to rename it before
326
if (dirToDelete.name[0] >= 28) /* cut foldername if to long */
327
dirToDelete.name[0] = 28;
328
P2CStr(dirToDelete.name);
329
sprintf(currpath,"%s~%d",(char *)dirToDelete.name,Num);
331
C2PStr((char *)dirToDelete.name);
332
err = HRename (dirToDelete.vRefNum, dirToDelete.parID,
333
dirToDelete.name, (unsigned char *) currpath);
335
err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,
336
(unsigned char *) currpath, trashfolder.parID,
347
** Set the file-type so the archive will get the correct icon, type
351
void setfiletype(char *new_f, unsigned long Creator, unsigned long Type)
355
if (strcmp(zipfile, new_f) == 0)
356
err = FSpChangeCreatorType(&MacZip.ZipFileSpec, Creator, Type);
357
printerr("FSpChangeCreatorType:", err, err, __LINE__, __FILE__, new_f);
367
** Convert the external (native) filename into Zip's internal Unix compatible
371
char *ex2in(char *externalFilen, int isdir, int *pdosflag)
372
/* char *externalFilen external file name */
373
/* int isdir input: externalFilen is a directory */
374
/* int *pdosflag output: force MSDOS file attributes? */
375
/* Convert the external file name to a zip file name, returning the malloc'ed
376
string or NULL if not enough memory. */
378
char *internalFilen; /* internal file name (malloc'ed) */
379
char *t; /* shortened name */
381
char buffer[NAME_MAX];
384
AssertStr(externalFilen, externalFilen)
387
dosflag = dosify; /* default for non-DOS and non-OS/2 */
389
/* Find starting point in name before doing malloc */
390
for (t = externalFilen; *t == PATH_END; t++)
393
if (!MacZip.StoreFullPath)
395
Pathname = StripPartialDir(buffer, MacZip.SearchDir,t);
402
/* Make changes, if any, to the copied name (leave original intact) */
405
t = last(Pathname, PATH_END);
409
/* Malloc space for internal name and copy it */
410
if ((internalFilen = malloc(strlen(t) + 10 + strlen(ResourceMark) )) == NULL)
413
sstrcpy(internalFilen, t);
415
/* we have to eliminate illegal chars:
416
* The name space for Mac filenames and Zip filenames (unix style names)
417
* do both include all printable extended-ASCII characters. The only
418
* difference we have to take care of is the single special character
419
* used as path delimiter:
420
* ':' on MacOS and '/' on Unix and '\' on Dos.
421
* So, to convert between Mac filenames and Unix filenames without any
422
* loss of information, we simply interchange ':' and '/'. Additionally,
423
* we try to convert the coding of the extended-ASCII characters into
424
* InfoZip's standard ISO 8859-1 codepage table.
426
MakeCompatibleString(internalFilen, ':', '/', '/', ':',
427
MacZip.CurrTextEncodingBase);
429
/* Returned malloc'ed name */
435
return internalFilen; /* avoid warning on unused variable */
440
msname(internalFilen);
441
printf("\n ex2in: %s",internalFilen);
444
return internalFilen;
450
** Collect all filenames. Go through all directories
454
int wild(char *Pathpat)
455
/* path/pattern to match */
456
/* If not in exclude mode, expand the pattern based on the contents of the
457
file system. Return an error code in the ZE_ class. */
460
char fullpath[NAME_MAX];
463
AssertStr(Pathpat, Pathpat);
465
if (noisy) printf("%s \n\n",GetZipVersionsInfo());
467
if (extra_fields == 0)
469
MacZip.DataForkOnly = true;
472
/* for switch '-R' -> '.' means current dir */
473
if (strcmp(Pathpat,".") == 0) sstrcpy(Pathpat,"*");
475
sstrcpy(MacZip.Pattern,Pathpat);
479
MacZip.StoreFoldersAlso = true;
480
MacZip.SearchLevels = 0; /* if 0 we aren't checking levels */
484
MacZip.StoreFoldersAlso = false;
485
MacZip.SearchLevels = 1;
488
/* make complete path */
489
GetCompletePath(fullpath, MacZip.Pattern, &Spec,&err);
490
err = PrintUserHFSerr((err != -43) && (err != 0), err, MacZip.Pattern);
491
printerr("GetCompletePath:", err, err, __LINE__, __FILE__, fullpath);
493
/* extract the filepattern */
494
GetFilename(MacZip.Pattern, fullpath);
496
/* extract Path and get FSSpec of search-path */
497
/* get FSSpec of search-path ; we need a dir to start
498
searching for filenames */
499
TruncFilename(MacZip.SearchDir, fullpath);
500
GetCompletePath(MacZip.SearchDir, MacZip.SearchDir, &Spec,&err);
503
if (MacZip.SearchLevels == 0)
505
printf("\nSearch Pattern: [%s] Levels: all", MacZip.Pattern);
509
printf("\nSearch Pattern: [%s] Levels: %d", MacZip.Pattern,
510
MacZip.SearchLevels);
512
printf("\nSearch Path: [%s]", MacZip.SearchDir);
513
printf("\nZip-File: [%s] \n",MacZip.ZipFullPath);
517
/* we are working only with pathnames;
518
* this can cause big problems on a mac ...
520
if (CheckMountedVolumes(MacZip.SearchDir) > 1)
521
DoWarnUserDupVol(MacZip.SearchDir);
523
/* start getting all filenames */
524
err = FSpRecurseDirectory(&Spec, MacZip.SearchLevels);
525
printerr("FSpRecurseDirectory:", err, err, __LINE__, __FILE__, "");
533
** Convert the internal filename into a external (native).
534
** The user will see this modified filename.
535
** For more performance:
536
** I do not completly switch back to the native macos filename.
537
** The user will still see directory separator '/' and the converted
541
char *in2ex(char *n) /* internal file name */
542
/* Convert the zip file name to an external file name, returning the malloc'ed
543
string or NULL if not enough memory. */
545
char *x; /* external file name */
549
if ((x = malloc(strlen(n) + 1)) == NULL)
552
RfDfFilen2Real(x, n, MacZip.MacZipMode, MacZip.DataForkOnly,
553
&MacZip.CurrentFork);
562
** Process on filenames. This function will be called to collect
566
int procname(char *filename, /* name to process */
567
int caseflag) /* true to force case-sensitive match
568
(always false on a Mac) */
569
/* Process a name . Return
570
an error code in the ZE_ class. */
572
int rc; /* matched flag */
574
AssertBool(caseflag,"caseflag")
575
AssertStr(filename,filename)
577
/* add or remove name of file */
578
rc = newname(filename, MacZip.isDirectory, caseflag);
587
char *f, /* name of file to get info on */
588
ulg *a, /* return value: file attributes */
589
long *n, /* return value: file size */
590
iztimes *t) /* return value: access, modific. and creation times */
591
/* If file *f does not exist, return 0. Else, return the file's last
592
modified date and time as an MSDOS date and time. The date and
593
time is returned in a long with the date most significant to allow
594
unsigned integer comparison of absolute times. Also, if a is not
595
a NULL pointer, store the file attributes there, with the high two
596
bytes being the Unix attributes, and the low byte being a mapping
597
of that to DOS attributes. If n is not NULL, store the file size
598
there. If t is not NULL, the file's access, modification and creation
599
times are stored there as UNIX time_t values.
600
If f is "-", use standard input as the file. If f is a device, return
603
struct stat s; /* results of stat() */
612
if (len == 0) return 0;
614
if (SSTAT(name, &s) != 0)
615
/* Accept about any file kind including directories
616
* (stored with trailing : with -r option)
621
*a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
622
if (MacZip.isDirectory) {
623
*a |= MSDOS_DIR_ATTR;
627
*n = (s.st_mode & UNX_IFMT) == UNX_IFREG ? s.st_size : -1L;
629
t->atime = s.st_atime;
630
t->mtime = s.st_mtime;
631
t->ctime = s.st_ctime; /* on Mac, st_ctime contains creation time! */
634
return unix2dostime(&s.st_mtime);
639
void stamp(char *f, ulg d)
640
/* char *f; name of file to change */
641
/* ulg d; dos-style time to change it to */
642
/* Set last updated and accessed time of file f to the DOS time d. */
644
time_t u[2]; /* argument for utime() */
648
/* Convert DOS time to time_t format in u */
650
u[0] = u[1] = dos2unixtime(d);
658
** return only the longest part of the path:
659
** second parameter: Volume:test folder:second folder:
660
** third parameter: Volume:test folder:second folder:third folder:file
661
** result will be: third folder:file
662
** first parameter: contains string buffer that will be used to prepend
663
** the "resource mark" part in front of the result when
664
** a resource fork is processed in "M3" mode.
668
char *StripPartialDir(char *CompletePath,
669
const char *PartialPath, const char *FullPath)
671
const char *tmpPtr1 = PartialPath;
672
const char *tmpPtr2 = FullPath;
675
Assert_it(CompletePath,"StripPartialDir","")
676
AssertStrNoOverlap(FullPath,PartialPath,PartialPath)
678
if (MacZip.DataForkOnly)
680
tmpPtr2 += strlen(tmpPtr1);
681
return (char *)tmpPtr2;
684
switch (MacZip.MacZipMode)
688
tmpPtr2 += strlen(tmpPtr1);
689
return (char *)tmpPtr2;
694
{ /* determine Fork type */
695
result = strncmp(FullPath, ResourceMark, sizeof(ResourceMark)-2);
698
MacZip.CurrentFork = DataFork;
699
tmpPtr2 += strlen(tmpPtr1);
700
return (char *)tmpPtr2;
703
{ /* resource fork */
704
MacZip.CurrentFork = ResourceFork;
705
sstrcpy(CompletePath, ResourceMark);
706
tmpPtr2 += strlen(tmpPtr1);
707
tmpPtr2 += sizeof(ResourceMark);
708
sstrcat(CompletePath, tmpPtr2);
709
return (char *)CompletePath;
715
return NULL; /* function should never reach this point */
722
** Init all global variables
723
** Must be called for each zip-run
726
void ZipInitAllVars(void)
728
getcwd(MacZip.CurrentPath, sizeof(MacZip.CurrentPath));
729
/* MacZip.MacZipMode = JohnnyLee_EF; */
730
MacZip.MacZipMode = NewZipMode_EF;
732
MacZip.DataForkOnly = false;
733
MacZip.CurrentFork = NoFork;
735
MacZip.StoreFoldersAlso = false;
737
MacZip.FoundFiles = 0;
738
MacZip.FoundDirectories = 0;
739
MacZip.RawCountOfItems = 0;
740
MacZip.BytesOfData = 0;
742
MacZip.StoreFullPath = false;
743
MacZip.StatingProgress = false;
744
MacZip.IncludeInvisible = false;
746
MacZip.isMacStatValid = false;
748
MacZip.CurrTextEncodingBase = FontScript();
750
MacZip.HaveGMToffset = false;
752
createTime = TickCount();
753
estTicksToFinish = -1;
756
/* init some functions */
765
count_of_Zippedfiles = 0;
772
** Get the findercomment and store it as file-comment in the Zip-file
775
char *GetComment(char *filename)
778
static char buffer[NAME_MAX];
779
char buffer2[NAME_MAX];
782
if (filename == NULL) return NULL;
784
/* now we can convert Unix-Path in HFS-Path */
785
for (tmpPtr = filename; *tmpPtr; tmpPtr++)
789
if (MacZip.StoreFullPath)
790
{ /* filename is already a fullpath */
791
sstrcpy(buffer,filename);
794
{ /* make a fullpath */
795
sstrcpy(buffer,MacZip.SearchDir);
796
sstrcat(buffer,filename);
799
/* make fullpath and get FSSpec */
800
/* Unfortunately: I get only the converted filename here */
801
/* so filenames with extended characters can not be found */
802
GetCompletePath(buffer2,buffer, &MacZip.fileSpec, &err);
803
printerr("GetCompletePath:",(err != -43) && (err != -120) && (err != 0) ,
804
err,__LINE__,__FILE__,buffer);
806
err = FSpDTGetComment(&MacZip.fileSpec, (unsigned char *) buffer);
807
printerr("FSpDTGetComment:", (err != -5012) && (err != 0), err,
808
__LINE__, __FILE__, filename);
809
P2CStr((unsigned char *) buffer);
810
if (err == -5012) return NULL; /* no finder-comments found */
812
if (noisy) printf("\n%32s -> %s",filename, buffer);
814
Beside the script change we need only to change 0x0d in 0x0a
815
so the last two arguments are not needed and does nothing.
817
MakeCompatibleString(buffer, 0x0d, 0x0a, ' ', ' ',
818
MacZip.CurrTextEncodingBase);
827
** Print a progress indicator for stating the files
831
void PrintStatProgress(char *msg)
834
if (!noisy) return; /* do no output if noisy is false */
836
MacZip.StatingProgress = true;
838
if (strcmp(msg,"done") == 0)
840
MacZip.StatingProgress = false;
841
printf("\n ... done \n\n");
843
else printf("\n %s",msg);
850
void InformProgress(const long progressMax, const long progressSoFar )
853
char no_time[5] = "...";
855
curr_percent = percent(progressMax, progressSoFar);
857
if (curr_percent < 95)
859
estTicksToFinish = EstimateCompletionTime(progressMax,
860
progressSoFar, curr_percent);
864
rightStatusString(no_time);
865
leftStatusString(no_time);
868
updateTicks = TickCount() + 60;
873
void ShowCounter(Boolean reset)
875
static char statusline[100];
876
static unsigned long filecount = 0;
886
sprintf(statusline, "%6d", filecount++);
887
rightStatusString(statusline);
892
static long EstimateCompletionTime(const long progressMax,
893
const long progressSoFar,
894
unsigned char curr_percent)
896
long max = progressMax, value = progressSoFar;
897
static char buf[100];
898
unsigned long ticksTakenSoFar = TickCount() - createTime;
899
float currentRate = (float) ticksTakenSoFar / (float) value;
900
long newEst = (long)( currentRate * (float)( max - value ));
902
sprintf(buf, "%d [%d%%]",progressSoFar, curr_percent);
903
rightStatusString(buf);
905
estTicksToFinish = newEst;
907
UpdateTimeToComplete();
909
return estTicksToFinish;
916
static void UpdateTimeToComplete(void)
918
short days, hours, minutes, seconds;
923
if ( estTicksToFinish == -1 )
926
days = estTicksToFinish / 5184000L;
927
hours = ( estTicksToFinish - ( days * 5184000L )) / 216000L;
928
minutes = ( estTicksToFinish - ( days * 5184000L ) -
929
( hours * 216000L )) / 3600L;
930
seconds = ( estTicksToFinish - ( days * 5184000L ) -
931
( hours * 216000L ) - ( minutes * 3600L )) / 60L;
938
/* "more than 24 hours" */
946
/* "more than x hours" */
948
NumToString( hours, xx );
953
if ( estTicksToFinish > 252000L ) /* > 1hr, 10 minutes */
955
/* "about x hours, y minutes" */
957
NumToString( hours, xx );
958
NumToString( minutes, yy );
963
if ( estTicksToFinish > 198000L ) /* > 55 minutes */
965
/* "about an hour" */
970
if ( estTicksToFinish > 144000L ) /* > 40 minutes */
972
/* "less than an hour" */
978
if ( estTicksToFinish > 4200L ) /* > 1 minute, 10 sec */
980
/* "about x minutes, y seconds */
982
NumToString( minutes, xx );
983
NumToString( seconds, yy );
992
if ( estTicksToFinish > 3000L ) /* > 50 seconds */
994
/* "about a minute" */
1000
if ( estTicksToFinish > 1500L ) /* > 25 seconds */
1002
/* "less than a minute" */
1008
if ( estTicksToFinish > 120L ) /* > 2 seconds */
1010
NumToString( seconds, xx );
1018
sprintf(estStr,Time_Est_strings[idx],P2CStr(xx),P2CStr(yy));
1019
leftStatusString((char *)estStr);
1027
** Just return the zip version
1031
char *GetZipVersionsInfo(void)
1033
static char ZipVersion[100];
1035
sprintf(ZipVersion, "Zip Module\n%d.%d%d%s of %s", Z_MAJORVER, Z_MINORVER,
1036
Z_PATCHLEVEL, Z_BETALEVEL, REVDATE);
1047
** Just return the copyright message
1051
char *GetZipCopyright(void)
1053
static char CopyR[300];
1055
sstrcpy(CopyR, copyright[0]);
1056
sstrcat(CopyR, copyright[1]);
1057
sstrcat(CopyR, "\r\rPlease send bug reports to the authors at\r"\
1058
"Zip-Bugs@lists.wku.edu");
1067
** Just return the compilers date/time
1071
char *GetZipVersionLocal(void)
1073
static char ZipVersionLocal[50];
1075
sprintf(ZipVersionLocal, "[%s %s]", __DATE__, __TIME__);
1077
return ZipVersionLocal;
1080
#endif /* #ifndef USE_SIOUX */
1086
const char *BOINC_RCSID_6f264625be = "$Id: macos.c 4979 2005-01-02 18:29:53Z ballen $";