2
Copyright (c) 1990-2001 Info-ZIP. All rights reserved.
4
See the accompanying file LICENSE, version 2000-Apr-09 or later
5
(the contents of which are also included in zip.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
9
/*---------------------------------------------------------------------------
13
Function dealing with the pathname. Mostly C-string work.
15
---------------------------------------------------------------------------*/
17
/*****************************************************************************/
19
/*****************************************************************************/
31
/*****************************************************************************/
33
/*****************************************************************************/
35
const char ResourceMark[] = "XtraStuf.mac:"; /* see also macos.c */
43
/*****************************************************************************/
45
/*****************************************************************************/
49
*----------------------------------------------------------------------
53
* This function is a version of the FindFolder function that
54
* returns the result as a FSSpec rather than a vRefNum and dirID.
57
* Results will be simaler to that of the FindFolder function.
62
*----------------------------------------------------------------------
67
short vRefNum, /* Volume reference number. */
68
OSType folderType, /* Folder type taken by FindFolder. */
69
Boolean createFolder, /* Should we create it if non-existant. */
70
FSSpec *spec) /* Pointer to resulting directory. */
76
err = FindFolder(vRefNum, folderType, createFolder,
77
&foundVRefNum, &foundDirID);
82
err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
88
** return volumename from pathname
92
unsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName)
94
const char *VolEnd, *tmpPtr1;
95
char *tmpPtr2 = VolumeName;
97
AssertStr(FullPath,"GetVolumeFromPath")
99
for (VolEnd = FullPath; *VolEnd != '\0' && *VolEnd != ':'; VolEnd++)
101
if (*VolEnd == '\0') return 0;
103
for (tmpPtr1 = FullPath; tmpPtr1 != VolEnd;)
105
*tmpPtr2++ = *tmpPtr1++;
110
return (unsigned short) strlen(VolumeName);
115
/***********************************/
116
/* Function FindNewExtractFolder() */
117
/***********************************/
119
char *FindNewExtractFolder(char *ExtractPath, Boolean uniqueFolder)
121
char buffer[NAME_MAX], *tmpPtr, *namePtr;
122
char *last_dotpos = ExtractPath;
123
short count = 0, folderCount = 0;
128
unsigned short namelen, pathlen = strlen(ExtractPath);
129
unsigned long ext_length = 0;
130
unsigned long num_to_cut = 0;
131
long firstpart_length = pathlen;
133
AssertStr(ExtractPath,"FindNewExtractFolder ExtractPath == NULL")
135
for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)
142
if (folderCount > 1) {
143
namelen = strlen(namePtr);
145
namelen = strlen(ExtractPath);
149
for (count = 0; count < 99; count++)
151
memset(buffer,0,sizeof(buffer));
154
ExtractPath[pathlen-2] = 0x0;
156
ExtractPath[pathlen-1] = 0x0;
158
sprintf(buffer,"%s%d",ExtractPath,count);
159
GetCompletePath(ExtractPath, buffer, &Spec,&err);
160
err = FSpGetDirectoryID(&Spec, &theDirID, &isDirectory);
161
if (err == -43) break;
164
/* Look for the last extension pos */
165
for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)
166
if (*tmpPtr == '.') last_dotpos = tmpPtr;
168
ext_length = strlen(last_dotpos);
170
if (ext_length < 6) { /* up to 5 chars are treated as a */
171
/* normal extension like ".html" or ".class" */
172
int nameLength = last_dotpos - ExtractPath;
173
if (nameLength > 1) {
174
ExtractPath[nameLength] = 0x0;
176
ExtractPath[pathlen-1] = 0x0;
179
ExtractPath[pathlen-1] = 0x0;
182
GetCompletePath(ExtractPath, ExtractPath, &Spec,&err);
185
/* Foldernames must always end with a colon */
186
sstrcat(ExtractPath,":");
193
** creates an archive file name
197
void createArchiveName(char *thePath)
199
char *tmpPtr, *namePtr;
200
short folderCount = 0;
201
unsigned short namelen, pathlen = strlen(thePath);
203
if (thePath[pathlen-1] == ':') thePath[pathlen-1] = 0x0;
205
for (tmpPtr = thePath; *tmpPtr; tmpPtr++)
212
namelen = strlen(namePtr);
214
/* we have to eliminate illegal chars:
215
* The name space for Mac filenames and Zip filenames (unix style names)
216
* do both include all printable extended-ASCII characters. The only
217
* difference we have to take care of is the single special character
218
* used as path delimiter:
219
* ':' on MacOS and '/' on Unix and '\' on Dos.
220
* So, to convert between Mac filenames and Unix filenames without any
221
* loss of information, we simply interchange ':' and '/'. Additionally,
222
* we try to convert the coding of the extended-ASCII characters into
223
* InfoZip's standard ISO 8859-1 codepage table.
225
MakeCompatibleString(namePtr, '/', '_', '.', '-', -1);
227
/* Avoid filenames like: "Archive..zip" */
228
if (thePath[pathlen-1] == '.')
230
thePath[pathlen-1] = 0;
233
if (folderCount >= 1)
234
{ /* path contains at least one folder */
241
thePath[pathlen] = '.';
242
thePath[pathlen+1] = 'z';
243
thePath[pathlen+2] = 'i';
244
thePath[pathlen+3] = 'p';
245
thePath[pathlen+4] = 0x0;
249
{ /* path contains no folder */
250
FindDesktopFolder(thePath);
251
createArchiveName(thePath);
258
** finds the desktop-folder on a volume with
259
** largest amount of free-space.
262
void FindDesktopFolder(char *Path)
265
FSSpec volumes[50]; /* 50 Volumes should be enough */
266
short actVolCount, volIndex = 1, VolCount = 0;
268
short i, foundVRefNum;
274
err = OnLine(volumes, 50, &actVolCount, &volIndex);
275
printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, "");
279
for (i=0; i < actVolCount; i++)
281
XGetVInfo(volumes[i].vRefNum,
287
if (MaxFreeBytes < freeBytes) {
288
MaxFreeBytes = freeBytes;
289
foundVRefNum = volumes[i].vRefNum;
292
if ((freeBytes == 0) && (MaxFreeBytes < freeBytes)) {
293
MaxFreeBytes = freeBytes;
294
foundVRefNum = volumes[i].vRefNum;
299
FSpFindFolder(foundVRefNum, kDesktopFolderType,
300
kDontCreateFolder,&spec);
302
GetFullPathFromSpec(buffer, &spec , &err);
303
sstrcat(buffer,Path);
304
sstrcpy(Path,buffer);
309
** return the path without the filename
313
char *TruncFilename(char *DirPath, const char *FilePath)
318
AssertStr(DirPath,"TruncFilename")
319
Assert_it(Spec,"TruncFilename","")
321
sstrcpy(DirPath, FilePath);
323
for (tmpPtr = DirPath; *tmpPtr; tmpPtr++)
330
printerr("TruncFilename: FilePath has no Folders", -1,
331
-1, __LINE__, __FILE__, FilePath);
339
** return only filename
343
char *GetFilename(char *FileName, const char *FilePath)
346
const char *dirPtr = NULL;
348
Assert_it(FileName,"GetFilename","")
349
Assert_it(FilePath,"GetFilename","")
351
for (tmpPtr = FilePath; *tmpPtr; tmpPtr++)
361
++dirPtr; /* jump over the ':' */
365
return strcpy(FileName, FilePath); /* FilePath has no Folders */
368
return strcpy(FileName, dirPtr);
374
** return fullpathname from folder/dir-id
378
char *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,
379
ConstStr255Param name, OSErr *err)
383
*err = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
384
printerr("FSMakeFSSpecCompat:", (*err != -43) && (*err != 0), *err,
385
__LINE__, __FILE__, "");
386
if ( (*err == noErr) || (*err == fnfErr) )
388
return GetFullPathFromSpec(CompletePath, &spec, err);
397
** convert real-filename to archive-filename
401
char *Real2RfDfFilen(char *RfDfFilen, const char *RealPath,
402
short CurrentFork, short MacZipMode, Boolean DataForkOnly)
405
AssertStr(RealPath,"Real2RfDfFilen")
406
AssertStr(RfDfFilen,"Real2RfDfFilen")
408
if (DataForkOnly) /* make no changes */
410
return sstrcpy(RfDfFilen, RealPath);
417
sstrcpy(RfDfFilen, RealPath);
418
if (CurrentFork == DataFork) /* data-fork */
419
return sstrcat(RfDfFilen, "d");
420
if (CurrentFork == ResourceFork) /* resource-fork */
421
return sstrcat(RfDfFilen, "r");
431
sstrcpy(RfDfFilen, RealPath);
432
return RfDfFilen; /* data-fork */
437
sstrcpy(RfDfFilen, ResourceMark);
438
sstrcat(RfDfFilen, RealPath); /* resource-fork */
444
printerr("Real2RfDfFilen:", -1, -1,
445
__LINE__, __FILE__, RealPath);
446
return NULL; /* function should never reach this point */
453
printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
454
return NULL; /* function should never reach this point */
458
printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
459
return NULL; /* function should never come reach this point */
465
** convert archive-filename into a real filename
469
char *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,
470
Boolean DataForkOnly, short *CurrentFork)
475
AssertStr(RfDfFilen,"RfDfFilen2Real")
478
(MacZipMode == UnKnown_EF) ||
479
(MacZipMode < JohnnyLee_EF))
481
*CurrentFork = DataFork;
482
return sstrcpy(RealFn,RfDfFilen);
485
result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
488
MacZipMode = NewZipMode_EF;
495
sstrcpy(RealFn, RfDfFilen);
496
length = strlen(RealFn); /* determine Fork type */
497
if (RealFn[length-1] == 'd') *CurrentFork = DataFork;
498
else *CurrentFork = ResourceFork;
499
RealFn[length-1] = '\0'; /* simply cut one char */
505
{ /* determine Fork type */
506
result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
509
*CurrentFork = DataFork;
510
sstrcpy(RealFn, RfDfFilen);
511
return RealFn; /* data-fork */
515
*CurrentFork = ResourceFork;
516
if (strlen(RfDfFilen) > (sizeof(ResourceMark) - 1))
518
sstrcpy(RealFn, &RfDfFilen[sizeof(ResourceMark)-1]);
520
else RealFn[0] = '\0';
521
return RealFn; /* resource-fork */
527
*CurrentFork = NoFork;
528
printerr("RfDfFilen2Real():", -1, MacZipMode,
529
__LINE__, __FILE__, RfDfFilen);
530
return NULL; /* function should never reach this point */
534
printerr("RfDfFilen2Real():", -1, MacZipMode, __LINE__, __FILE__, RfDfFilen);
535
return NULL; /* function should never reach this point */
541
** return the applications name (argv[0])
545
char *GetAppName(void)
547
ProcessSerialNumber psn;
548
static Str255 AppName;
549
ProcessInfoRec pinfo;
552
GetCurrentProcess(&psn);
553
pinfo.processName = AppName;
554
pinfo.processInfoLength = sizeof(pinfo);
555
pinfo.processAppSpec = NULL;
557
err = GetProcessInformation(&psn,&pinfo);
558
AppName[AppName[0]+1] = 0x00;
560
return (char *)&AppName[1];
566
** return fullpathname from FSSpec
570
char *GetFullPathFromSpec(char *FullPath, FSSpec *Spec, OSErr *err)
575
Assert_it(Spec,"GetFullPathFromSpec","")
577
*err = FSpGetFullPath(Spec, &len, &hFullPath);
578
printerr("FSpGetFullPath:", (*err != -43) && (*err != 0), *err,
579
__LINE__, __FILE__, "");
581
memmove(FullPath, (Handle) *hFullPath, len);
582
FullPath[len] = '\0'; /* make c-string */
584
DisposeHandle((Handle)hFullPath); /* we don't need it any more */
586
printerr("Warning path length exceeds limit: ", len >= NAME_MAX, len,
587
__LINE__, __FILE__, " chars ");
596
* This function expands a given partial path to a complete path.
597
* Path expansions are relative to the running app.
598
* This function follows the notation:
600
* a: ":subfolder:filename" -> ":current folder:subfolder:filename"
601
* b: "::folder2:filename" -> folder2 is beside the current
602
* folder on the same level
603
* c: "filename" -> in current folder
605
* An absolute path will be returned.
607
The following characteristics of Macintosh pathnames should be noted:
609
A full pathname never begins with a colon, but must contain at
611
A partial pathname always begins with a colon separator except in
612
the case where the file partial pathname is a simple file or
614
Single trailing separator colons in full or partial pathnames are
615
ignored except in the case of full pathnames to volumes.
616
In full pathnames to volumes, the trailing separator colon is required.
617
Consecutive separator colons can be used to ascend a level from a
618
directory to its parent directory. Two consecutive separator colons
619
will ascend one level, three consecutive separator colons will ascend
620
two levels, and so on. Ascending can only occur from a directory;
624
char *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,
627
Boolean hasDirName = false;
628
char currentdir[NAME_MAX];
630
unsigned short pathlen;
632
AssertStr(name,"GetCompletePath")
633
Assert_it(Spec,"GetCompletePath","")
634
Assert_it((CompletePath != name),"GetCompletePath","")
636
for (tmpPtr = name; *tmpPtr; tmpPtr++)
637
if (*tmpPtr == ':') hasDirName = true;
639
if (name[0] != ':') /* case c: path including volume name or only filename */
642
{ /* okey, starts with volume name, so it must be a complete path */
643
sstrcpy(CompletePath, name);
646
{ /* only filename: add cwd and return */
647
getcwd(currentdir, NAME_MAX);
648
sstrcat(currentdir, name);
649
sstrcpy(CompletePath, currentdir);
652
else if (name[1] == ':') /* it's case b: "::folder2:filename" */
654
printerr("GetCompletePath ", -1, *err, __LINE__, __FILE__, "not implemented");
655
/* it's not yet implemented; do we really need this case ?*/
658
else /* it's case a: ":subfolder:filename" */
660
getcwd(CompletePath, NAME_MAX); /* we don't need a second colon */
661
CompletePath[strlen(CompletePath)-1] = '\0';
662
sstrcat(CompletePath, name);
665
pathlen = strlen(CompletePath);
666
*err = FSpLocationFromFullPath(pathlen, CompletePath, Spec);
673
char *MakeFilenameShorter(const char *LongFilename)
675
static char filename[35]; /* contents should be never longer than 32 chars */
676
static unsigned char Num = 0; /* change the number for every call */
677
/* this var will rollover without a problem */
678
char tempLongFilename[1024], charnum[5];
679
char *last_dotpos = tempLongFilename;
680
unsigned long full_length = strlen(LongFilename);
681
unsigned long ext_length = 0;
682
unsigned long num_to_cut = 0;
683
long firstpart_length;
685
short MaxLength = 31;
687
if (full_length <= MaxLength) /* filename is not long */
689
return strcpy(filename,LongFilename);
693
strcpy(tempLongFilename,LongFilename);
695
/* Look for the last extension pos */
696
for (tmpPtr = tempLongFilename; *tmpPtr; tmpPtr++)
697
if (*tmpPtr == '.') last_dotpos = tmpPtr;
699
ext_length = strlen(last_dotpos);
700
firstpart_length = last_dotpos - tempLongFilename;
702
if (ext_length > 6) /* up to 5 chars are treated as a */
703
{ /* normal extension like ".html" or ".class" */
704
firstpart_length = 0;
707
num_to_cut = full_length - MaxLength;
709
/* number the files to make the names unique */
710
sprintf(charnum,"~%x", Num);
711
num_to_cut += strlen(charnum);
713
if (firstpart_length == 0)
715
firstpart_length = full_length;
716
tempLongFilename[firstpart_length - num_to_cut] = 0;
717
sprintf(filename,"%s%s", tempLongFilename, charnum);
721
tempLongFilename[firstpart_length - num_to_cut] = 0;
722
sprintf(filename,"%s%s%s", tempLongFilename, charnum, last_dotpos);
728
const char *BOINC_RCSID_20a7780104 = "$Id: pathname.c 4979 2005-01-02 18:29:53Z ballen $";