123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726 |
- /*
- Copyright (c) 1990-2003 Info-ZIP. All rights reserved.
- See the accompanying file LICENSE, version 2000-Apr-09 or later
- (the contents of which are also included in zip.h) for terms of use.
- If, for some reason, all these files are missing, the Info-ZIP license
- also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
- */
- /*---------------------------------------------------------------------------
- pathname.c
- Function dealing with the pathname. Mostly C-string work.
- ---------------------------------------------------------------------------*/
- /*****************************************************************************/
- /* Includes */
- /*****************************************************************************/
- #include <string.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <sound.h>
- #include "pathname.h"
- #include "helpers.h"
- #include "macstuff.h"
- /*****************************************************************************/
- /* Global Vars */
- /*****************************************************************************/
- const char ResourceMark[] = "XtraStuf.mac:"; /* see also macos.c */
- #include "zip.h"
- /*****************************************************************************/
- /* Functions */
- /*****************************************************************************/
- /*
- *----------------------------------------------------------------------
- *
- * FSpFindFolder --
- *
- * This function is a version of the FindFolder function that
- * returns the result as a FSSpec rather than a vRefNum and dirID.
- *
- * Results:
- * Results will be simaler to that of the FindFolder function.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- OSErr
- FSpFindFolder(
- short vRefNum, /* Volume reference number. */
- OSType folderType, /* Folder type taken by FindFolder. */
- Boolean createFolder, /* Should we create it if non-existant. */
- FSSpec *spec) /* Pointer to resulting directory. */
- {
- short foundVRefNum;
- long foundDirID;
- OSErr err;
- err = FindFolder(vRefNum, folderType, createFolder,
- &foundVRefNum, &foundDirID);
- if (err != noErr) {
- return err;
- }
- err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
- return err;
- }
- /*
- ** return volumename from pathname
- **
- */
- unsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName)
- {
- const char *VolEnd, *tmpPtr1;
- char *tmpPtr2 = VolumeName;
- AssertStr(FullPath,"GetVolumeFromPath")
- for (VolEnd = FullPath; *VolEnd != '\0' && *VolEnd != ':'; VolEnd++)
- ;
- if (*VolEnd == '\0') return 0;
- for (tmpPtr1 = FullPath; tmpPtr1 != VolEnd;)
- {
- *tmpPtr2++ = *tmpPtr1++;
- }
- *tmpPtr2 = '\0';
- return (unsigned short) strlen(VolumeName);
- }
- /***********************************/
- /* Function FindNewExtractFolder() */
- /***********************************/
- char *FindNewExtractFolder(char *ExtractPath, Boolean uniqueFolder)
- {
- char buffer[NAME_MAX], *tmpPtr, *namePtr;
- char *last_dotpos = ExtractPath;
- short count = 0, folderCount = 0;
- OSErr err;
- FSSpec Spec;
- long theDirID;
- Boolean isDirectory;
- unsigned short namelen, pathlen = strlen(ExtractPath);
- unsigned long ext_length = 0;
- unsigned long num_to_cut = 0;
- long firstpart_length = pathlen;
- AssertStr(ExtractPath,"FindNewExtractFolder ExtractPath == NULL")
- for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)
- if (*tmpPtr == ':')
- {
- folderCount++;
- namePtr = tmpPtr;
- }
- if (folderCount > 1) {
- namelen = strlen(namePtr);
- } else {
- namelen = strlen(ExtractPath);
- }
- if (uniqueFolder) {
- for (count = 0; count < 99; count++)
- {
- memset(buffer,0,sizeof(buffer));
- if (namelen >= 28)
- ExtractPath[pathlen-2] = 0x0;
- else
- ExtractPath[pathlen-1] = 0x0;
- sprintf(buffer,"%s%d",ExtractPath,count);
- GetCompletePath(ExtractPath, buffer, &Spec,&err);
- err = FSpGetDirectoryID(&Spec, &theDirID, &isDirectory);
- if (err == -43) break;
- }
- } else {
- /* Look for the last extension pos */
- for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)
- if (*tmpPtr == '.') last_dotpos = tmpPtr;
- ext_length = strlen(last_dotpos);
- if (ext_length < 6) { /* up to 5 chars are treated as a */
- /* normal extension like ".html" or ".class" */
- int nameLength = last_dotpos - ExtractPath;
- if (nameLength > 1) {
- ExtractPath[nameLength] = 0x0;
- } else {
- ExtractPath[pathlen-1] = 0x0;
- }
- } else {
- ExtractPath[pathlen-1] = 0x0;
- }
- GetCompletePath(ExtractPath, ExtractPath, &Spec,&err);
- }
- /* Foldernames must always end with a colon */
- sstrcat(ExtractPath,":");
- return ExtractPath;
- }
- /*
- ** creates an archive file name
- **
- */
- void createArchiveName(char *thePath)
- {
- char *tmpPtr, *namePtr;
- short folderCount = 0;
- unsigned short namelen, pathlen = strlen(thePath);
- if (thePath[pathlen-1] == ':') thePath[pathlen-1] = 0x0;
- for (tmpPtr = thePath; *tmpPtr; tmpPtr++)
- if (*tmpPtr == ':')
- {
- folderCount++;
- namePtr = tmpPtr;
- }
- namelen = strlen(namePtr);
- /* 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(namePtr, '/', '_', '.', '-', -1);
- /* Avoid filenames like: "Archive..zip" */
- if (thePath[pathlen-1] == '.')
- {
- thePath[pathlen-1] = 0;
- }
- if (folderCount >= 1)
- { /* path contains at least one folder */
- if (namelen >= 28)
- {
- pathlen = pathlen-4;
- }
- thePath[pathlen] = '.';
- thePath[pathlen+1] = 'z';
- thePath[pathlen+2] = 'i';
- thePath[pathlen+3] = 'p';
- thePath[pathlen+4] = 0x0;
- return;
- }
- else
- { /* path contains no folder */
- FindDesktopFolder(thePath);
- createArchiveName(thePath);
- }
- }
- /*
- ** finds the desktop-folder on a volume with
- ** largest amount of free-space.
- */
- void FindDesktopFolder(char *Path)
- {
- char buffer[255];
- FSSpec volumes[50]; /* 50 Volumes should be enough */
- short actVolCount, volIndex = 1, VolCount = 0;
- OSErr err;
- short i, foundVRefNum;
- FSSpec spec;
- UInt64 freeBytes;
- UInt64 totalBytes;
- UInt64 MaxFreeBytes;
- err = OnLine(volumes, 50, &actVolCount, &volIndex);
- printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, "");
- MaxFreeBytes = 0;
- for (i=0; i < actVolCount; i++)
- {
- XGetVInfo(volumes[i].vRefNum,
- volumes[i].name,
- &volumes[i].vRefNum,
- &freeBytes,
- &totalBytes);
- if (MaxFreeBytes < freeBytes) {
- MaxFreeBytes = freeBytes;
- foundVRefNum = volumes[i].vRefNum;
- }
- if ((freeBytes == 0) && (MaxFreeBytes < freeBytes)) {
- MaxFreeBytes = freeBytes;
- foundVRefNum = volumes[i].vRefNum;
- }
- }
- FSpFindFolder(foundVRefNum, kDesktopFolderType,
- kDontCreateFolder,&spec);
- GetFullPathFromSpec(buffer, &spec , &err);
- sstrcat(buffer,Path);
- sstrcpy(Path,buffer);
- }
- /*
- ** return the path without the filename
- **
- */
- char *TruncFilename(char *DirPath, const char *FilePath)
- {
- char *tmpPtr;
- char *dirPtr = NULL;
- AssertStr(DirPath,"TruncFilename")
- Assert_it(Spec,"TruncFilename","")
- sstrcpy(DirPath, FilePath);
- for (tmpPtr = DirPath; *tmpPtr; tmpPtr++)
- if (*tmpPtr == ':')
- dirPtr = tmpPtr;
- if (dirPtr)
- *++dirPtr = '\0';
- else
- printerr("TruncFilename: FilePath has no Folders", -1,
- -1, __LINE__, __FILE__, FilePath);
- return DirPath;
- }
- /*
- ** return only filename
- **
- */
- char *GetFilename(char *FileName, const char *FilePath)
- {
- const char *tmpPtr;
- const char *dirPtr = NULL;
- Assert_it(FileName,"GetFilename","")
- Assert_it(FilePath,"GetFilename","")
- for (tmpPtr = FilePath; *tmpPtr; tmpPtr++)
- {
- if (*tmpPtr == ':')
- {
- dirPtr = tmpPtr;
- }
- }
- if (dirPtr)
- {
- ++dirPtr; /* jump over the ':' */
- }
- else
- {
- return strcpy(FileName, FilePath); /* FilePath has no Folders */
- }
- return strcpy(FileName, dirPtr);
- }
- /*
- ** return fullpathname from folder/dir-id
- **
- */
- char *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,
- ConstStr255Param name, OSErr *err)
- {
- FSSpec spec;
- *err = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
- printerr("FSMakeFSSpecCompat:", (*err != -43) && (*err != 0), *err,
- __LINE__, __FILE__, "");
- if ( (*err == noErr) || (*err == fnfErr) )
- {
- return GetFullPathFromSpec(CompletePath, &spec, err);
- }
- return NULL;
- }
- /*
- ** convert real-filename to archive-filename
- **
- */
- char *Real2RfDfFilen(char *RfDfFilen, const char *RealPath,
- short CurrentFork, short MacZipMode, Boolean DataForkOnly)
- {
- AssertStr(RealPath,"Real2RfDfFilen")
- AssertStr(RfDfFilen,"Real2RfDfFilen")
- if (DataForkOnly) /* make no changes */
- {
- return sstrcpy(RfDfFilen, RealPath);
- }
- switch (MacZipMode)
- {
- case JohnnyLee_EF:
- {
- sstrcpy(RfDfFilen, RealPath);
- if (CurrentFork == DataFork) /* data-fork */
- return sstrcat(RfDfFilen, "d");
- if (CurrentFork == ResourceFork) /* resource-fork */
- return sstrcat(RfDfFilen, "r");
- break;
- }
- case NewZipMode_EF:
- {
- switch (CurrentFork)
- {
- case DataFork:
- {
- sstrcpy(RfDfFilen, RealPath);
- return RfDfFilen; /* data-fork */
- break;
- }
- case ResourceFork:
- {
- sstrcpy(RfDfFilen, ResourceMark);
- sstrcat(RfDfFilen, RealPath); /* resource-fork */
- return RfDfFilen;
- break;
- }
- default:
- {
- printerr("Real2RfDfFilen:", -1, -1,
- __LINE__, __FILE__, RealPath);
- return NULL; /* function should never reach this point */
- }
- }
- break;
- }
- default:
- {
- printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
- return NULL; /* function should never reach this point */
- }
- }
- printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
- return NULL; /* function should never come reach this point */
- }
- /*
- ** convert archive-filename into a real filename
- **
- */
- char *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,
- Boolean DataForkOnly, short *CurrentFork)
- {
- short length;
- int result;
- AssertStr(RfDfFilen,"RfDfFilen2Real")
- if (DataForkOnly ||
- (MacZipMode == UnKnown_EF) ||
- (MacZipMode < JohnnyLee_EF))
- {
- *CurrentFork = DataFork;
- return sstrcpy(RealFn,RfDfFilen);
- }
- result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
- if (result == 0)
- {
- MacZipMode = NewZipMode_EF;
- }
- switch (MacZipMode)
- {
- case JohnnyLee_EF:
- {
- sstrcpy(RealFn, RfDfFilen);
- length = strlen(RealFn); /* determine Fork type */
- if (RealFn[length-1] == 'd') *CurrentFork = DataFork;
- else *CurrentFork = ResourceFork;
- RealFn[length-1] = '\0'; /* simply cut one char */
- return RealFn;
- break;
- }
- case NewZipMode_EF:
- { /* determine Fork type */
- result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
- if (result != 0)
- {
- *CurrentFork = DataFork;
- sstrcpy(RealFn, RfDfFilen);
- return RealFn; /* data-fork */
- }
- else
- {
- *CurrentFork = ResourceFork;
- if (strlen(RfDfFilen) > (sizeof(ResourceMark) - 1))
- {
- sstrcpy(RealFn, &RfDfFilen[sizeof(ResourceMark)-1]);
- }
- else RealFn[0] = '\0';
- return RealFn; /* resource-fork */
- }
- break;
- }
- default:
- {
- *CurrentFork = NoFork;
- printerr("RfDfFilen2Real():", -1, MacZipMode,
- __LINE__, __FILE__, RfDfFilen);
- return NULL; /* function should never reach this point */
- }
- }
- printerr("RfDfFilen2Real():", -1, MacZipMode, __LINE__, __FILE__, RfDfFilen);
- return NULL; /* function should never reach this point */
- }
- /*
- ** return the applications name (argv[0])
- **
- */
- char *GetAppName(void)
- {
- ProcessSerialNumber psn;
- static Str255 AppName;
- ProcessInfoRec pinfo;
- OSErr err;
- GetCurrentProcess(&psn);
- pinfo.processName = AppName;
- pinfo.processInfoLength = sizeof(pinfo);
- pinfo.processAppSpec = NULL;
- err = GetProcessInformation(&psn,&pinfo);
- AppName[AppName[0]+1] = 0x00;
- return (char *)&AppName[1];
- }
- /*
- ** return fullpathname from FSSpec
- **
- */
- char *GetFullPathFromSpec(char *FullPath, FSSpec *Spec, OSErr *err)
- {
- Handle hFullPath;
- short len;
- Assert_it(Spec,"GetFullPathFromSpec","")
- *err = FSpGetFullPath(Spec, &len, &hFullPath);
- printerr("FSpGetFullPath:", (*err != -43) && (*err != 0), *err,
- __LINE__, __FILE__, "");
- memmove(FullPath, (Handle) *hFullPath, len);
- FullPath[len] = '\0'; /* make c-string */
- DisposeHandle((Handle)hFullPath); /* we don't need it any more */
- printerr("Warning path length exceeds limit: ", len >= NAME_MAX, len,
- __LINE__, __FILE__, " chars ");
- return FullPath;
- }
- /*
- * This function expands a given partial path to a complete path.
- * Path expansions are relative to the running app.
- * This function follows the notation:
- * 1. relative path:
- * a: ":subfolder:filename" -> ":current folder:subfolder:filename"
- * b: "::folder2:filename" -> folder2 is beside the current
- * folder on the same level
- * c: "filename" -> in current folder
- *
- * An absolute path will be returned.
- The following characteristics of Macintosh pathnames should be noted:
- A full pathname never begins with a colon, but must contain at
- least one colon.
- A partial pathname always begins with a colon separator except in
- the case where the file partial pathname is a simple file or
- directory name.
- Single trailing separator colons in full or partial pathnames are
- ignored except in the case of full pathnames to volumes.
- In full pathnames to volumes, the trailing separator colon is required.
- Consecutive separator colons can be used to ascend a level from a
- directory to its parent directory. Two consecutive separator colons
- will ascend one level, three consecutive separator colons will ascend
- two levels, and so on. Ascending can only occur from a directory;
- not a file.
- */
- char *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,
- OSErr *err)
- {
- Boolean hasDirName = false;
- char currentdir[NAME_MAX];
- char *tmpPtr;
- unsigned short pathlen;
- AssertStr(name,"GetCompletePath")
- Assert_it(Spec,"GetCompletePath","")
- Assert_it((CompletePath != name),"GetCompletePath","")
- for (tmpPtr = name; *tmpPtr; tmpPtr++)
- if (*tmpPtr == ':') hasDirName = true;
- if (name[0] != ':') /* case c: path including volume name or only filename */
- {
- if (hasDirName)
- { /* okey, starts with volume name, so it must be a complete path */
- sstrcpy(CompletePath, name);
- }
- else
- { /* only filename: add cwd and return */
- getcwd(currentdir, NAME_MAX);
- sstrcat(currentdir, name);
- sstrcpy(CompletePath, currentdir);
- }
- }
- else if (name[1] == ':') /* it's case b: "::folder2:filename" */
- {
- printerr("GetCompletePath ", -1, *err, __LINE__, __FILE__, "not implemented");
- /* it's not yet implemented; do we really need this case ?*/
- return NULL;
- }
- else /* it's case a: ":subfolder:filename" */
- {
- getcwd(CompletePath, NAME_MAX); /* we don't need a second colon */
- CompletePath[strlen(CompletePath)-1] = '\0';
- sstrcat(CompletePath, name);
- }
- pathlen = strlen(CompletePath);
- *err = FSpLocationFromFullPath(pathlen, CompletePath, Spec);
- return CompletePath;
- }
- char *MakeFilenameShorter(const char *LongFilename)
- {
- static char filename[35]; /* contents should be never longer than 32 chars */
- static unsigned char Num = 0; /* change the number for every call */
- /* this var will rollover without a problem */
- char tempLongFilename[1024], charnum[5];
- char *last_dotpos = tempLongFilename;
- unsigned long full_length = strlen(LongFilename);
- unsigned long ext_length = 0;
- unsigned long num_to_cut = 0;
- long firstpart_length;
- char *tmpPtr;
- short MaxLength = 31;
- if (full_length <= MaxLength) /* filename is not long */
- {
- return strcpy(filename,LongFilename);
- }
- Num++;
- strcpy(tempLongFilename,LongFilename);
- /* Look for the last extension pos */
- for (tmpPtr = tempLongFilename; *tmpPtr; tmpPtr++)
- if (*tmpPtr == '.') last_dotpos = tmpPtr;
- ext_length = strlen(last_dotpos);
- firstpart_length = last_dotpos - tempLongFilename;
- if (ext_length > 6) /* up to 5 chars are treated as a */
- { /* normal extension like ".html" or ".class" */
- firstpart_length = 0;
- }
- num_to_cut = full_length - MaxLength;
- /* number the files to make the names unique */
- sprintf(charnum,"~%x", Num);
- num_to_cut += strlen(charnum);
- if (firstpart_length == 0)
- {
- firstpart_length = full_length;
- tempLongFilename[firstpart_length - num_to_cut] = 0;
- sprintf(filename,"%s%s", tempLongFilename, charnum);
- }
- else
- {
- tempLongFilename[firstpart_length - num_to_cut] = 0;
- sprintf(filename,"%s%s%s", tempLongFilename, charnum, last_dotpos);
- }
- return filename;
- }
|