mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-05 04:02:28 +00:00
1079 lines
25 KiB
C
1079 lines
25 KiB
C
/*
|
|
Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
|
|
|
|
See the accompanying file LICENSE, version 1999-Oct-05 or later
|
|
(the contents of which are also included in zip.h) for terms of use.
|
|
If, for some reason, both of these files are missing, the Info-ZIP license
|
|
also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
|
|
*/
|
|
/*---------------------------------------------------------------------------
|
|
|
|
macos.c
|
|
|
|
Macintosh-specific routines for use with Info-ZIP's Zip 2.3 and later.
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Includes */
|
|
/*****************************************************************************/
|
|
|
|
#include "zip.h"
|
|
|
|
#include "revision.h"
|
|
#include "crypt.h"
|
|
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sound.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <Strings.h>
|
|
#include <setjmp.h>
|
|
|
|
/* #include "charmap.h" */
|
|
#include "helpers.h"
|
|
#include "macstuff.h"
|
|
#include "pathname.h"
|
|
#include "recurse.h"
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Macros, typedefs */
|
|
/*****************************************************************************/
|
|
|
|
#define PATH_END MacPathEnd
|
|
|
|
/*****************************************************************************/
|
|
/* Global Vars */
|
|
/*****************************************************************************/
|
|
|
|
int error_level; /* used only in ziperr() */
|
|
|
|
|
|
/* Note: sizeof() returns the size of this allusion
|
|
13 is current length of "XtraStuf.mac:" */
|
|
extern const char ResourceMark[13]; /* var is initialized in file pathname.c */
|
|
|
|
|
|
extern jmp_buf EnvForExit;
|
|
MacZipGlobals MacZip;
|
|
|
|
unsigned long count_of_Zippedfiles = 0;
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Module level Vars */
|
|
/*****************************************************************************/
|
|
|
|
static const char MacPathEnd = ':'; /* the Macintosh dir separator */
|
|
|
|
/* Inform Progress vars */
|
|
long estTicksToFinish;
|
|
long createTime;
|
|
long updateTicks;
|
|
|
|
static char *Time_Est_strings[] = {
|
|
"Zipping Files; Items done:",
|
|
"More than 24 hours",
|
|
"More than %s hours",
|
|
"About %s hours, %s minutes",
|
|
"About an hour",
|
|
"Less than an hour",
|
|
"About %s minutes, %s seconds",
|
|
"About a minute",
|
|
"Less than a minute",
|
|
"About %s seconds",
|
|
"About a second",
|
|
"About 1 minute, %s seconds"};
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Prototypes */
|
|
/*****************************************************************************/
|
|
|
|
int DoCurrentDir(void);
|
|
|
|
void DoAboutBox(void);
|
|
void DoQuit(void);
|
|
void DoEventLoop(void);
|
|
|
|
void ZipInitAllVars(void);
|
|
void UserStop(void);
|
|
Boolean IsZipFile(char *name);
|
|
|
|
static long EstimateCompletionTime(const long progressMax,
|
|
const long progressSoFar, unsigned char percent);
|
|
static void UpdateTimeToComplete(void);
|
|
|
|
|
|
|
|
|
|
#ifdef USE_SIOUX
|
|
#include <sioux.h>
|
|
void DoWarnUserDupVol( char *FullPath );
|
|
|
|
/*****************************************************************************/
|
|
/* Functions */
|
|
/*****************************************************************************/
|
|
|
|
/*
|
|
** Standalone Unzip with Metrowerks SIOUX starts here
|
|
**
|
|
*/
|
|
int main(int argc, char **argv)
|
|
{
|
|
int return_code;
|
|
|
|
SIOUXSettings.asktosaveonclose = FALSE;
|
|
SIOUXSettings.showstatusline = TRUE;
|
|
|
|
SIOUXSettings.columns = 100;
|
|
SIOUXSettings.rows = 40;
|
|
|
|
/* 30 = MacZip Johnny Lee's; 40 = new (my) MacZip */
|
|
MacZip.MacZipMode = NewZipMode_EF;
|
|
|
|
argc = ccommand(&argv);
|
|
if (verbose) PrintArguments(argc, argv);
|
|
|
|
ZipInitAllVars();
|
|
|
|
return_code = zipmain(argc, argv);
|
|
|
|
if (verbose) printf("\n\n Finish");
|
|
return return_code;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** SIOUX needs no extra event handling
|
|
**
|
|
*/
|
|
|
|
void UserStop(void)
|
|
{
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Password enter function '*' printed for each char
|
|
**
|
|
*/
|
|
|
|
int macgetch(void)
|
|
{
|
|
WindowPtr whichWindow;
|
|
EventRecord theEvent;
|
|
char c; /* one-byte buffer for read() to use */
|
|
|
|
do {
|
|
SystemTask();
|
|
if (!GetNextEvent(everyEvent, &theEvent))
|
|
theEvent.what = nullEvent;
|
|
else {
|
|
switch (theEvent.what) {
|
|
case keyDown:
|
|
c = theEvent.message & charCodeMask;
|
|
break;
|
|
case mouseDown:
|
|
if (FindWindow(theEvent.where, &whichWindow) ==
|
|
inSysWindow)
|
|
SystemClick(&theEvent, whichWindow);
|
|
break;
|
|
case updateEvt:
|
|
break;
|
|
}
|
|
}
|
|
} while (theEvent.what != keyDown);
|
|
|
|
printf("*");
|
|
fflush(stdout);
|
|
|
|
return (int)c;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/******************************/
|
|
/* Function version_local() */
|
|
/******************************/
|
|
|
|
/*
|
|
** Print Compilers version and compile time/date
|
|
**
|
|
*/
|
|
|
|
void version_local()
|
|
{
|
|
/* prints e.g:
|
|
Compiled with Metrowerks CodeWarrior version 2000 for PowerPC Processor
|
|
compile time: Feb 4 1998 17:49:49.
|
|
*/
|
|
|
|
static ZCONST char CompiledWith[] =
|
|
"\n\nCompiled with %s %x for %s \n %s %s %s.\n\n";
|
|
|
|
printf(CompiledWith,
|
|
|
|
|
|
#ifdef __MWERKS__
|
|
" Metrowerks CodeWarrior version", __MWERKS__,
|
|
#endif
|
|
|
|
|
|
#ifdef __MC68K__
|
|
" MC68K Processor",
|
|
#else
|
|
" PowerPC Processor",
|
|
#endif
|
|
|
|
#ifdef __DATE__
|
|
"compile time: ", __DATE__, __TIME__
|
|
#else
|
|
"", "", ""
|
|
#endif
|
|
);
|
|
} /* end function version_local() */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Deletes a dir if the switch '-m' is used
|
|
**
|
|
*/
|
|
|
|
int deletedir(char *path)
|
|
{
|
|
static char Num = 0;
|
|
static FSSpec trashfolder;
|
|
static Boolean FirstCall = true;
|
|
static Boolean Immediate_File_Deletion = false;
|
|
OSErr err;
|
|
FSSpec dirToDelete;
|
|
char currpath[NAME_MAX], *envptr;
|
|
CInfoPBRec fpb;
|
|
|
|
/* init this function */
|
|
if ((path == NULL) ||
|
|
(strlen(path) == 0))
|
|
{
|
|
Num = 0;
|
|
FirstCall = true;
|
|
return -1;
|
|
}
|
|
|
|
UserStop();
|
|
|
|
GetCompletePath(currpath,path,&dirToDelete, &err);
|
|
|
|
if (FirstCall == true)
|
|
{
|
|
FirstCall = false;
|
|
envptr = getenv("Immediate_File_Deletion");
|
|
if (!(envptr == (char *)NULL || *envptr == '\0'))
|
|
{
|
|
if (stricmp(envptr,"yes") == 0)
|
|
Immediate_File_Deletion = true;
|
|
else
|
|
Immediate_File_Deletion = false;
|
|
}
|
|
err = FSpFindFolder(dirToDelete.vRefNum, kTrashFolderType,
|
|
kDontCreateFolder,&trashfolder);
|
|
printerr("FSpFindFolder:",err,err,__LINE__,__FILE__,path);
|
|
}
|
|
|
|
fpb.dirInfo.ioNamePtr = dirToDelete.name;
|
|
fpb.dirInfo.ioVRefNum = dirToDelete.vRefNum;
|
|
fpb.dirInfo.ioDrDirID = dirToDelete.parID;
|
|
fpb.dirInfo.ioFDirIndex = 0;
|
|
|
|
err = PBGetCatInfoSync(&fpb);
|
|
printerr("PBGetCatInfo deletedir ", err, err,
|
|
__LINE__, __FILE__, "");
|
|
|
|
if (fpb.dirInfo.ioDrNmFls > 0)
|
|
{
|
|
return 0; /* do not move / delete folders which are not empty */
|
|
}
|
|
|
|
if (Immediate_File_Deletion)
|
|
{
|
|
err = FSpDelete(&dirToDelete);
|
|
return err;
|
|
}
|
|
|
|
err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,
|
|
dirToDelete.name, trashfolder.parID, trashfolder.name);
|
|
|
|
/* -48 = file is already existing so we have to rename it before
|
|
moving the file */
|
|
if (err == -48)
|
|
{
|
|
Num++;
|
|
if (dirToDelete.name[0] >= 28) /* cut foldername if to long */
|
|
dirToDelete.name[0] = 28;
|
|
P2CStr(dirToDelete.name);
|
|
sprintf(currpath,"%s~%d",(char *)dirToDelete.name,Num);
|
|
C2PStr(currpath);
|
|
C2PStr((char *)dirToDelete.name);
|
|
err = HRename (dirToDelete.vRefNum, dirToDelete.parID,
|
|
dirToDelete.name, (unsigned char *) currpath);
|
|
|
|
err = CatMove (dirToDelete.vRefNum, dirToDelete.parID,
|
|
(unsigned char *) currpath, trashfolder.parID,
|
|
trashfolder.name);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Set the file-type so the archive will get the correct icon, type
|
|
** and creator code.
|
|
*/
|
|
|
|
void setfiletype(char *new_f, unsigned long Creator, unsigned long Type)
|
|
{
|
|
OSErr err;
|
|
|
|
if (strcmp(zipfile, new_f) == 0)
|
|
err = FSpChangeCreatorType(&MacZip.ZipFileSpec, Creator, Type);
|
|
printerr("FSpChangeCreatorType:", err, err, __LINE__, __FILE__, new_f);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Convert the external (native) filename into Zip's internal Unix compatible
|
|
** name space.
|
|
*/
|
|
|
|
char *ex2in(char *externalFilen, int isdir, int *pdosflag)
|
|
/* char *externalFilen external file name */
|
|
/* int isdir input: externalFilen is a directory */
|
|
/* int *pdosflag output: force MSDOS file attributes? */
|
|
/* Convert the external file name to a zip file name, returning the malloc'ed
|
|
string or NULL if not enough memory. */
|
|
{
|
|
char *internalFilen; /* internal file name (malloc'ed) */
|
|
char *t; /* shortened name */
|
|
char *Pathname;
|
|
char buffer[NAME_MAX];
|
|
int dosflag;
|
|
|
|
AssertStr(externalFilen, externalFilen)
|
|
AssertBool(isdir,"")
|
|
|
|
dosflag = dosify; /* default for non-DOS and non-OS/2 */
|
|
|
|
/* Find starting point in name before doing malloc */
|
|
for (t = externalFilen; *t == PATH_END; t++)
|
|
;
|
|
|
|
if (!MacZip.StoreFullPath)
|
|
{
|
|
Pathname = StripPartialDir(buffer, MacZip.SearchDir,t);
|
|
}
|
|
else
|
|
{
|
|
Pathname = t;
|
|
}
|
|
|
|
/* Make changes, if any, to the copied name (leave original intact) */
|
|
if (!pathput)
|
|
{
|
|
t = last(Pathname, PATH_END);
|
|
}
|
|
else t = Pathname;
|
|
|
|
/* Malloc space for internal name and copy it */
|
|
if ((internalFilen = malloc(strlen(t) + 10 + strlen(ResourceMark) )) == NULL)
|
|
return NULL;
|
|
|
|
sstrcpy(internalFilen, t);
|
|
|
|
/* we have to eliminate illegal chars:
|
|
* The name space for Mac filenames and Zip filenames (unix style names)
|
|
* do both include all printable extended-ASCII characters. The only
|
|
* difference we have to take care of is the single special character
|
|
* used as path delimiter:
|
|
* ':' on MacOS and '/' on Unix and '\' on Dos.
|
|
* So, to convert between Mac filenames and Unix filenames without any
|
|
* loss of information, we simply interchange ':' and '/'. Additionally,
|
|
* we try to convert the coding of the extended-ASCII characters into
|
|
* InfoZip's standard ISO 8859-1 codepage table.
|
|
*/
|
|
MakeCompatibleString(internalFilen, ':', '/', '/', ':',
|
|
MacZip.CurrTextEncodingBase);
|
|
|
|
/* Returned malloc'ed name */
|
|
if (pdosflag)
|
|
*pdosflag = dosflag;
|
|
|
|
if (isdir)
|
|
{
|
|
return internalFilen; /* avoid warning on unused variable */
|
|
}
|
|
|
|
if (dosify)
|
|
{
|
|
msname(internalFilen);
|
|
printf("\n ex2in: %s",internalFilen);
|
|
}
|
|
|
|
return internalFilen;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** Collect all filenames. Go through all directories
|
|
**
|
|
*/
|
|
|
|
int wild(char *Pathpat)
|
|
/* path/pattern to match */
|
|
/* If not in exclude mode, expand the pattern based on the contents of the
|
|
file system. Return an error code in the ZE_ class. */
|
|
{
|
|
FSSpec Spec;
|
|
char fullpath[NAME_MAX];
|
|
OSErr err;
|
|
|
|
AssertStr(Pathpat, Pathpat);
|
|
|
|
if (noisy) printf("%s \n\n",GetZipVersionsInfo());
|
|
|
|
if (extra_fields == 0)
|
|
{
|
|
MacZip.DataForkOnly = true;
|
|
}
|
|
|
|
/* for switch '-R' -> '.' means current dir */
|
|
if (strcmp(Pathpat,".") == 0) sstrcpy(Pathpat,"*");
|
|
|
|
sstrcpy(MacZip.Pattern,Pathpat);
|
|
|
|
if (recurse)
|
|
{
|
|
MacZip.StoreFoldersAlso = true;
|
|
MacZip.SearchLevels = 0; /* if 0 we aren't checking levels */
|
|
}
|
|
else
|
|
{
|
|
MacZip.StoreFoldersAlso = false;
|
|
MacZip.SearchLevels = 1;
|
|
}
|
|
|
|
/* make complete path */
|
|
GetCompletePath(fullpath, MacZip.Pattern, &Spec,&err);
|
|
err = PrintUserHFSerr((err != -43) && (err != 0), err, MacZip.Pattern);
|
|
printerr("GetCompletePath:", err, err, __LINE__, __FILE__, fullpath);
|
|
|
|
/* extract the filepattern */
|
|
GetFilename(MacZip.Pattern, fullpath);
|
|
|
|
/* extract Path and get FSSpec of search-path */
|
|
/* get FSSpec of search-path ; we need a dir to start
|
|
searching for filenames */
|
|
TruncFilename(MacZip.SearchDir, fullpath);
|
|
GetCompletePath(MacZip.SearchDir, MacZip.SearchDir, &Spec,&err);
|
|
|
|
if (noisy) {
|
|
if (MacZip.SearchLevels == 0)
|
|
{
|
|
printf("\nSearch Pattern: [%s] Levels: all", MacZip.Pattern);
|
|
}
|
|
else
|
|
{
|
|
printf("\nSearch Pattern: [%s] Levels: %d", MacZip.Pattern,
|
|
MacZip.SearchLevels);
|
|
}
|
|
printf("\nSearch Path: [%s]", MacZip.SearchDir);
|
|
printf("\nZip-File: [%s] \n",MacZip.ZipFullPath);
|
|
|
|
}
|
|
|
|
/* we are working only with pathnames;
|
|
* this can cause big problems on a mac ...
|
|
*/
|
|
if (CheckMountedVolumes(MacZip.SearchDir) > 1)
|
|
DoWarnUserDupVol(MacZip.SearchDir);
|
|
|
|
/* start getting all filenames */
|
|
err = FSpRecurseDirectory(&Spec, MacZip.SearchLevels);
|
|
printerr("FSpRecurseDirectory:", err, err, __LINE__, __FILE__, "");
|
|
|
|
return ZE_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** Convert the internal filename into a external (native).
|
|
** The user will see this modified filename.
|
|
** For more performance:
|
|
** I do not completly switch back to the native macos filename.
|
|
** The user will still see directory separator '/' and the converted
|
|
** charset.
|
|
*/
|
|
|
|
char *in2ex(char *n) /* internal file name */
|
|
/* Convert the zip file name to an external file name, returning the malloc'ed
|
|
string or NULL if not enough memory. */
|
|
{
|
|
char *x; /* external file name */
|
|
|
|
AssertStr(n,n)
|
|
|
|
if ((x = malloc(strlen(n) + 1)) == NULL)
|
|
return NULL;
|
|
|
|
RfDfFilen2Real(x, n, MacZip.MacZipMode, MacZip.DataForkOnly,
|
|
&MacZip.CurrentFork);
|
|
|
|
return x;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Process on filenames. This function will be called to collect
|
|
** the filenames.
|
|
*/
|
|
|
|
int procname(char *filename, /* name to process */
|
|
int caseflag) /* true to force case-sensitive match
|
|
(always false on a Mac) */
|
|
/* Process a name . Return
|
|
an error code in the ZE_ class. */
|
|
{
|
|
int rc; /* matched flag */
|
|
|
|
AssertBool(caseflag,"caseflag")
|
|
AssertStr(filename,filename)
|
|
|
|
/* add or remove name of file */
|
|
rc = newname(filename, MacZip.isDirectory, caseflag);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
ulg filetime(
|
|
char *f, /* name of file to get info on */
|
|
ulg *a, /* return value: file attributes */
|
|
long *n, /* return value: file size */
|
|
iztimes *t) /* return value: access, modific. and creation times */
|
|
/* If file *f does not exist, return 0. Else, return the file's last
|
|
modified date and time as an MSDOS date and time. The date and
|
|
time is returned in a long with the date most significant to allow
|
|
unsigned integer comparison of absolute times. Also, if a is not
|
|
a NULL pointer, store the file attributes there, with the high two
|
|
bytes being the Unix attributes, and the low byte being a mapping
|
|
of that to DOS attributes. If n is not NULL, store the file size
|
|
there. If t is not NULL, the file's access, modification and creation
|
|
times are stored there as UNIX time_t values.
|
|
If f is "-", use standard input as the file. If f is a device, return
|
|
a file size of -1 */
|
|
{
|
|
struct stat s; /* results of stat() */
|
|
|
|
AssertStr(f,f)
|
|
|
|
if (strlen(f) == 0) return 0;
|
|
|
|
if (SSTAT(f, &s) != 0)
|
|
/* Accept about any file kind including directories
|
|
* (stored with trailing : with -r option)
|
|
*/
|
|
return 0;
|
|
|
|
if (a != NULL) {
|
|
*a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
|
|
if (MacZip.isDirectory) {
|
|
*a |= MSDOS_DIR_ATTR;
|
|
}
|
|
}
|
|
if (n != NULL)
|
|
*n = (s.st_mode & UNX_IFMT) == UNX_IFREG ? s.st_size : -1L;
|
|
if (t != NULL) {
|
|
t->atime = s.st_atime;
|
|
t->mtime = s.st_mtime;
|
|
t->ctime = s.st_ctime; /* on Mac, st_ctime contains creation time! */
|
|
}
|
|
|
|
return unix2dostime(&s.st_mtime);
|
|
}
|
|
|
|
|
|
|
|
void stamp(char *f, ulg d)
|
|
/* char *f; name of file to change */
|
|
/* ulg d; dos-style time to change it to */
|
|
/* Set last updated and accessed time of file f to the DOS time d. */
|
|
{
|
|
time_t u[2]; /* argument for utime() */
|
|
|
|
f = f;
|
|
|
|
/* Convert DOS time to time_t format in u */
|
|
|
|
u[0] = u[1] = dos2unixtime(d);
|
|
/* utime(f, u); */
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
** return only the longest part of the path:
|
|
** second parameter: Volume:test folder:second folder:
|
|
** third parameter: Volume:test folder:second folder:third folder:file
|
|
** result will be: third folder:file
|
|
** first parameter: contains string buffer that will be used to prepend
|
|
** the "resource mark" part in front of the result when
|
|
** a resource fork is processed in "M3" mode.
|
|
**
|
|
*/
|
|
|
|
char *StripPartialDir(char *CompletePath,
|
|
const char *PartialPath, const char *FullPath)
|
|
{
|
|
const char *tmpPtr1 = PartialPath;
|
|
const char *tmpPtr2 = FullPath;
|
|
int result;
|
|
|
|
Assert_it(CompletePath,"StripPartialDir","")
|
|
AssertStrNoOverlap(FullPath,PartialPath,PartialPath)
|
|
|
|
if (MacZip.DataForkOnly)
|
|
{
|
|
tmpPtr2 += strlen(tmpPtr1);
|
|
return (char *)tmpPtr2;
|
|
}
|
|
|
|
switch (MacZip.MacZipMode)
|
|
{
|
|
case JohnnyLee_EF:
|
|
{
|
|
tmpPtr2 += strlen(tmpPtr1);
|
|
return (char *)tmpPtr2;
|
|
break;
|
|
}
|
|
|
|
case NewZipMode_EF:
|
|
{ /* determine Fork type */
|
|
result = strncmp(FullPath, ResourceMark, sizeof(ResourceMark)-2);
|
|
if (result != 0)
|
|
{ /* data fork */
|
|
MacZip.CurrentFork = DataFork;
|
|
tmpPtr2 += strlen(tmpPtr1);
|
|
return (char *)tmpPtr2;
|
|
}
|
|
else
|
|
{ /* resource fork */
|
|
MacZip.CurrentFork = ResourceFork;
|
|
sstrcpy(CompletePath, ResourceMark);
|
|
tmpPtr2 += strlen(tmpPtr1);
|
|
tmpPtr2 += sizeof(ResourceMark);
|
|
sstrcat(CompletePath, tmpPtr2);
|
|
return (char *)CompletePath;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NULL; /* function should never reach this point */
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Init all global variables
|
|
** Must be called for each zip-run
|
|
*/
|
|
|
|
void ZipInitAllVars(void)
|
|
{
|
|
getcwd(MacZip.CurrentPath, sizeof(MacZip.CurrentPath));
|
|
/* MacZip.MacZipMode = JohnnyLee_EF; */
|
|
MacZip.MacZipMode = NewZipMode_EF;
|
|
|
|
MacZip.DataForkOnly = false;
|
|
MacZip.CurrentFork = NoFork;
|
|
|
|
MacZip.StoreFoldersAlso = false;
|
|
|
|
MacZip.FoundFiles = 0;
|
|
MacZip.FoundDirectories = 0;
|
|
MacZip.RawCountOfItems = 0;
|
|
MacZip.BytesOfData = 0;
|
|
|
|
MacZip.StoreFullPath = false;
|
|
MacZip.StatingProgress = false;
|
|
MacZip.IncludeInvisible = false;
|
|
|
|
MacZip.isMacStatValid = false;
|
|
|
|
MacZip.CurrTextEncodingBase = FontScript();
|
|
|
|
MacZip.HaveGMToffset = false;
|
|
|
|
createTime = TickCount();
|
|
estTicksToFinish = -1;
|
|
updateTicks = 0;
|
|
|
|
/* init some functions */
|
|
IsZipFile(NULL);
|
|
|
|
destroy(NULL);
|
|
deletedir(NULL);
|
|
ShowCounter(true);
|
|
|
|
extra_fields = 1;
|
|
error_level = 0;
|
|
count_of_Zippedfiles = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Get the findercomment and store it as file-comment in the Zip-file
|
|
**
|
|
*/
|
|
char *GetComment(char *filename)
|
|
{
|
|
OSErr err;
|
|
static char buffer[NAME_MAX];
|
|
char buffer2[NAME_MAX];
|
|
char *tmpPtr;
|
|
|
|
if (filename == NULL) return NULL;
|
|
|
|
/* now we can convert Unix-Path in HFS-Path */
|
|
for (tmpPtr = filename; *tmpPtr; tmpPtr++)
|
|
if (*tmpPtr == '/')
|
|
*tmpPtr = ':';
|
|
|
|
if (MacZip.StoreFullPath)
|
|
{ /* filename is already a fullpath */
|
|
sstrcpy(buffer,filename);
|
|
}
|
|
else
|
|
{ /* make a fullpath */
|
|
sstrcpy(buffer,MacZip.SearchDir);
|
|
sstrcat(buffer,filename);
|
|
}
|
|
|
|
/* make fullpath and get FSSpec */
|
|
/* Unfortunately: I get only the converted filename here */
|
|
/* so filenames with extended characters can not be found */
|
|
GetCompletePath(buffer2,buffer, &MacZip.fileSpec, &err);
|
|
printerr("GetCompletePath:",(err != -43) && (err != -120) && (err != 0) ,
|
|
err,__LINE__,__FILE__,buffer);
|
|
|
|
err = FSpDTGetComment(&MacZip.fileSpec, (unsigned char *) buffer);
|
|
printerr("FSpDTGetComment:", (err != -5012) && (err != 0), err,
|
|
__LINE__, __FILE__, filename);
|
|
P2CStr((unsigned char *) buffer);
|
|
if (err == -5012) return NULL; /* no finder-comments found */
|
|
|
|
if (noisy) printf("\n%32s -> %s",filename, buffer);
|
|
/*
|
|
Beside the script change we need only to change 0x0d in 0x0a
|
|
so the last two arguments are not needed and does nothing.
|
|
*/
|
|
MakeCompatibleString(buffer, 0x0d, 0x0a, ' ', ' ',
|
|
MacZip.CurrTextEncodingBase);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Print a progress indicator for stating the files
|
|
**
|
|
*/
|
|
|
|
void PrintStatProgress(char *msg)
|
|
{
|
|
|
|
if (!noisy) return; /* do no output if noisy is false */
|
|
|
|
MacZip.StatingProgress = true;
|
|
|
|
if (strcmp(msg,"done") == 0)
|
|
{
|
|
MacZip.StatingProgress = false;
|
|
printf("\n ... done \n\n");
|
|
}
|
|
else printf("\n %s",msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InformProgress(const long progressMax, const long progressSoFar )
|
|
{
|
|
int curr_percent;
|
|
char no_time[5] = "...";
|
|
|
|
curr_percent = percent(progressMax, progressSoFar);
|
|
|
|
if (curr_percent < 95)
|
|
{
|
|
estTicksToFinish = EstimateCompletionTime(progressMax,
|
|
progressSoFar, curr_percent);
|
|
}
|
|
else
|
|
{
|
|
rightStatusString(no_time);
|
|
leftStatusString(no_time);
|
|
}
|
|
|
|
updateTicks = TickCount() + 60;
|
|
return;
|
|
}
|
|
|
|
|
|
void ShowCounter(Boolean reset)
|
|
{
|
|
static char statusline[100];
|
|
static unsigned long filecount = 0;
|
|
|
|
if (reset)
|
|
{
|
|
filecount = 0;
|
|
return;
|
|
}
|
|
|
|
if (noisy)
|
|
{
|
|
sprintf(statusline, "%6d", filecount++);
|
|
rightStatusString(statusline);
|
|
}
|
|
}
|
|
|
|
|
|
static long EstimateCompletionTime(const long progressMax,
|
|
const long progressSoFar,
|
|
unsigned char curr_percent)
|
|
{
|
|
long max = progressMax, value = progressSoFar;
|
|
static char buf[100];
|
|
unsigned long ticksTakenSoFar = TickCount() - createTime;
|
|
float currentRate = (float) ticksTakenSoFar / (float) value;
|
|
long newEst = (long)( currentRate * (float)( max - value ));
|
|
|
|
sprintf(buf, "%d [%d%%]",progressSoFar, curr_percent);
|
|
rightStatusString(buf);
|
|
|
|
estTicksToFinish = newEst;
|
|
|
|
UpdateTimeToComplete();
|
|
|
|
return estTicksToFinish;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void UpdateTimeToComplete(void)
|
|
{
|
|
short days, hours, minutes, seconds;
|
|
char estStr[255];
|
|
Str15 xx, yy;
|
|
short idx = 0;
|
|
|
|
if ( estTicksToFinish == -1 )
|
|
return;
|
|
|
|
days = estTicksToFinish / 5184000L;
|
|
hours = ( estTicksToFinish - ( days * 5184000L )) / 216000L;
|
|
minutes = ( estTicksToFinish - ( days * 5184000L ) -
|
|
( hours * 216000L )) / 3600L;
|
|
seconds = ( estTicksToFinish - ( days * 5184000L ) -
|
|
( hours * 216000L ) - ( minutes * 3600L )) / 60L;
|
|
|
|
xx[0] = 0;
|
|
yy[0] = 0;
|
|
|
|
if ( days )
|
|
{
|
|
/* "more than 24 hours" */
|
|
|
|
idx = 1;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
if ( hours >= 8 )
|
|
{
|
|
/* "more than x hours" */
|
|
|
|
NumToString( hours, xx );
|
|
idx = 2;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
if ( estTicksToFinish > 252000L ) /* > 1hr, 10 minutes */
|
|
{
|
|
/* "about x hours, y minutes" */
|
|
|
|
NumToString( hours, xx );
|
|
NumToString( minutes, yy );
|
|
idx = 3;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
if ( estTicksToFinish > 198000L ) /* > 55 minutes */
|
|
{
|
|
/* "about an hour" */
|
|
idx = 4;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
if ( estTicksToFinish > 144000L ) /* > 40 minutes */
|
|
{
|
|
/* "less than an hour" */
|
|
|
|
idx = 5;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
if ( estTicksToFinish > 4200L ) /* > 1 minute, 10 sec */
|
|
{
|
|
/* "about x minutes, y seconds */
|
|
|
|
NumToString( minutes, xx );
|
|
NumToString( seconds, yy );
|
|
|
|
if ( minutes == 1 )
|
|
idx = 11;
|
|
else
|
|
idx = 6;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
if ( estTicksToFinish > 3000L ) /* > 50 seconds */
|
|
{
|
|
/* "about a minute" */
|
|
|
|
idx = 7;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
if ( estTicksToFinish > 1500L ) /* > 25 seconds */
|
|
{
|
|
/* "less than a minute" */
|
|
|
|
idx = 8;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
if ( estTicksToFinish > 120L ) /* > 2 seconds */
|
|
{
|
|
NumToString( seconds, xx );
|
|
idx = 9;
|
|
goto setEstTimeStr;
|
|
}
|
|
|
|
idx = 10;
|
|
|
|
setEstTimeStr:
|
|
sprintf(estStr,Time_Est_strings[idx],P2CStr(xx),P2CStr(yy));
|
|
leftStatusString((char *)estStr);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Just return the zip version
|
|
**
|
|
*/
|
|
|
|
char *GetZipVersionsInfo(void)
|
|
{
|
|
static char ZipVersion[100];
|
|
|
|
sprintf(ZipVersion, "Zip Module\n%d.%d%d%s of %s", Z_MAJORVER, Z_MINORVER,
|
|
Z_PATCHLEVEL, Z_BETALEVEL, REVDATE);
|
|
|
|
return ZipVersion;
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef USE_SIOUX
|
|
|
|
/*
|
|
** Just return the copyright message
|
|
**
|
|
*/
|
|
|
|
char *GetZipCopyright(void)
|
|
{
|
|
static char CopyR[300];
|
|
|
|
sstrcpy(CopyR, copyright[0]);
|
|
sstrcat(CopyR, copyright[1]);
|
|
sstrcat(CopyR, "\r\rPlease send bug reports to the authors at\r"\
|
|
"Zip-Bugs@lists.wku.edu");
|
|
|
|
return CopyR;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
** Just return the compilers date/time
|
|
**
|
|
*/
|
|
|
|
char *GetZipVersionLocal(void)
|
|
{
|
|
static char ZipVersionLocal[50];
|
|
|
|
sprintf(ZipVersionLocal, "[%s %s]", __DATE__, __TIME__);
|
|
|
|
return ZipVersionLocal;
|
|
}
|
|
|
|
#endif /* #ifndef USE_SIOUX */
|
|
|
|
|
|
|
|
|