Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6725 siemargl 1
/*
2
  Copyright (c) 1990-2003 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 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
8
*/
9
/*---------------------------------------------------------------------------
10
 
11
  pathname.c
12
 
13
  Function dealing with the pathname. Mostly C-string work.
14
 
15
  ---------------------------------------------------------------------------*/
16
 
17
/*****************************************************************************/
18
/*  Includes                                                                 */
19
/*****************************************************************************/
20
 
21
#include 
22
#include 
23
#include 
24
#include 
25
 
26
#include "pathname.h"
27
#include "helpers.h"
28
#include "macstuff.h"
29
 
30
 
31
/*****************************************************************************/
32
/*  Global Vars                                                              */
33
/*****************************************************************************/
34
 
35
const char  ResourceMark[] = "XtraStuf.mac:";  /* see also macos.c */
36
 
37
 
38
#include "zip.h"
39
 
40
 
41
 
42
 
43
/*****************************************************************************/
44
/*  Functions                                                                */
45
/*****************************************************************************/
46
 
47
 
48
/*
49
 *----------------------------------------------------------------------
50
 *
51
 * FSpFindFolder --
52
 *
53
 *  This function is a version of the FindFolder function that
54
 *  returns the result as a FSSpec rather than a vRefNum and dirID.
55
 *
56
 * Results:
57
 *  Results will be simaler to that of the FindFolder function.
58
 *
59
 * Side effects:
60
 *  None.
61
 *
62
 *----------------------------------------------------------------------
63
 */
64
 
65
OSErr
66
FSpFindFolder(
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. */
71
{
72
    short foundVRefNum;
73
    long foundDirID;
74
    OSErr err;
75
 
76
    err = FindFolder(vRefNum, folderType, createFolder,
77
        &foundVRefNum, &foundDirID);
78
    if (err != noErr) {
79
    return err;
80
    }
81
 
82
    err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
83
    return err;
84
}
85
 
86
 
87
/*
88
**  return volumename from pathname
89
**
90
*/
91
 
92
unsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName)
93
{
94
const char *VolEnd, *tmpPtr1;
95
char *tmpPtr2 = VolumeName;
96
 
97
AssertStr(FullPath,"GetVolumeFromPath")
98
 
99
for (VolEnd = FullPath; *VolEnd != '\0' && *VolEnd != ':'; VolEnd++)
100
      ;
101
if (*VolEnd == '\0') return 0;
102
 
103
for (tmpPtr1 = FullPath; tmpPtr1 != VolEnd;)
104
    {
105
    *tmpPtr2++ = *tmpPtr1++;
106
    }
107
 
108
*tmpPtr2 = '\0';
109
 
110
return (unsigned short) strlen(VolumeName);
111
}
112
 
113
 
114
 
115
/***********************************/
116
/* Function FindNewExtractFolder() */
117
/***********************************/
118
 
119
char *FindNewExtractFolder(char *ExtractPath, Boolean uniqueFolder)
120
{
121
char buffer[NAME_MAX], *tmpPtr, *namePtr;
122
char *last_dotpos         = ExtractPath;
123
short count = 0, folderCount = 0;
124
OSErr err;
125
FSSpec Spec;
126
long theDirID;
127
Boolean isDirectory;
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;
132
 
133
AssertStr(ExtractPath,"FindNewExtractFolder ExtractPath == NULL")
134
 
135
for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)
136
    if (*tmpPtr == ':')
137
        {
138
        folderCount++;
139
        namePtr = tmpPtr;
140
        }
141
 
142
if (folderCount > 1) {
143
    namelen = strlen(namePtr);
144
} else {
145
    namelen = strlen(ExtractPath);
146
}
147
 
148
if (uniqueFolder) {
149
    for (count = 0; count < 99; count++)
150
        {
151
        memset(buffer,0,sizeof(buffer));
152
 
153
        if (namelen >= 28)
154
            ExtractPath[pathlen-2] = 0x0;
155
        else
156
            ExtractPath[pathlen-1] = 0x0;
157
 
158
        sprintf(buffer,"%s%d",ExtractPath,count);
159
        GetCompletePath(ExtractPath, buffer, &Spec,&err);
160
        err = FSpGetDirectoryID(&Spec, &theDirID, &isDirectory);
161
        if (err == -43) break;
162
        }
163
} else {
164
    /* Look for the last extension pos */
165
    for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++)
166
        if (*tmpPtr == '.') last_dotpos = tmpPtr;
167
 
168
    ext_length = strlen(last_dotpos);
169
 
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;
175
        } else {
176
            ExtractPath[pathlen-1] = 0x0;
177
        }
178
    } else {
179
        ExtractPath[pathlen-1] = 0x0;
180
    }
181
 
182
    GetCompletePath(ExtractPath, ExtractPath, &Spec,&err);
183
}
184
 
185
/* Foldernames must always end with a colon  */
186
sstrcat(ExtractPath,":");
187
return ExtractPath;
188
}
189
 
190
 
191
 
192
/*
193
**  creates an archive file name
194
**
195
*/
196
 
197
void createArchiveName(char *thePath)
198
{
199
char *tmpPtr, *namePtr;
200
short folderCount = 0;
201
unsigned short namelen, pathlen = strlen(thePath);
202
 
203
if (thePath[pathlen-1] == ':') thePath[pathlen-1] = 0x0;
204
 
205
for (tmpPtr = thePath; *tmpPtr; tmpPtr++)
206
    if (*tmpPtr == ':')
207
        {
208
        folderCount++;
209
        namePtr = tmpPtr;
210
        }
211
 
212
namelen = strlen(namePtr);
213
 
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.
224
     */
225
  MakeCompatibleString(namePtr, '/', '_', '.', '-', -1);
226
 
227
 /* Avoid filenames like: "Archive..zip"  */
228
if (thePath[pathlen-1] == '.')
229
    {
230
    thePath[pathlen-1] = 0;
231
    }
232
 
233
if (folderCount >= 1)
234
    { /* path contains at least one folder */
235
 
236
    if (namelen >= 28)
237
        {
238
        pathlen = pathlen-4;
239
        }
240
 
241
    thePath[pathlen]   = '.';
242
    thePath[pathlen+1] = 'z';
243
    thePath[pathlen+2] = 'i';
244
    thePath[pathlen+3] = 'p';
245
    thePath[pathlen+4] = 0x0;
246
    return;
247
    }
248
else
249
    {  /* path contains no folder */
250
    FindDesktopFolder(thePath);
251
    createArchiveName(thePath);
252
    }
253
}
254
 
255
 
256
 
257
/*
258
** finds the desktop-folder on a volume with
259
** largest amount of free-space.
260
*/
261
 
262
void FindDesktopFolder(char *Path)
263
{
264
char buffer[255];
265
FSSpec  volumes[50];        /* 50 Volumes should be enough */
266
short   actVolCount, volIndex = 1, VolCount = 0;
267
OSErr   err;
268
short     i, foundVRefNum;
269
FSSpec spec;
270
UInt64 freeBytes;
271
UInt64 totalBytes;
272
UInt64 MaxFreeBytes;
273
 
274
err = OnLine(volumes, 50, &actVolCount, &volIndex);
275
printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, "");
276
 
277
MaxFreeBytes = 0;
278
 
279
for (i=0; i < actVolCount; i++)
280
    {
281
    XGetVInfo(volumes[i].vRefNum,
282
              volumes[i].name,
283
              &volumes[i].vRefNum,
284
              &freeBytes,
285
              &totalBytes);
286
 
287
    if (MaxFreeBytes < freeBytes) {
288
        MaxFreeBytes = freeBytes;
289
        foundVRefNum = volumes[i].vRefNum;
290
    }
291
 
292
    if ((freeBytes == 0) && (MaxFreeBytes < freeBytes)) {
293
        MaxFreeBytes = freeBytes;
294
        foundVRefNum = volumes[i].vRefNum;
295
    }
296
 
297
}
298
 
299
 FSpFindFolder(foundVRefNum, kDesktopFolderType,
300
            kDontCreateFolder,&spec);
301
 
302
 GetFullPathFromSpec(buffer, &spec , &err);
303
 sstrcat(buffer,Path);
304
 sstrcpy(Path,buffer);
305
}
306
 
307
 
308
/*
309
**  return the path without the filename
310
**
311
*/
312
 
313
char *TruncFilename(char *DirPath, const char *FilePath)
314
{
315
char *tmpPtr;
316
char *dirPtr = NULL;
317
 
318
AssertStr(DirPath,"TruncFilename")
319
Assert_it(Spec,"TruncFilename","")
320
 
321
sstrcpy(DirPath, FilePath);
322
 
323
for (tmpPtr = DirPath; *tmpPtr; tmpPtr++)
324
    if (*tmpPtr == ':')
325
        dirPtr = tmpPtr;
326
 
327
if (dirPtr)
328
    *++dirPtr = '\0';
329
else
330
    printerr("TruncFilename: FilePath has no Folders", -1,
331
         -1, __LINE__, __FILE__, FilePath);
332
 
333
return DirPath;
334
}
335
 
336
 
337
 
338
/*
339
**  return only filename
340
**
341
*/
342
 
343
char *GetFilename(char *FileName, const char *FilePath)
344
{
345
const char *tmpPtr;
346
const char *dirPtr = NULL;
347
 
348
Assert_it(FileName,"GetFilename","")
349
Assert_it(FilePath,"GetFilename","")
350
 
351
for (tmpPtr = FilePath; *tmpPtr; tmpPtr++)
352
    {
353
    if (*tmpPtr == ':')
354
        {
355
        dirPtr = tmpPtr;
356
        }
357
    }
358
 
359
if (dirPtr)
360
    {
361
    ++dirPtr;  /* jump over the ':' */
362
    }
363
else
364
    {
365
    return strcpy(FileName, FilePath); /* FilePath has no Folders */
366
    }
367
 
368
return strcpy(FileName, dirPtr);
369
}
370
 
371
 
372
 
373
/*
374
**  return fullpathname from folder/dir-id
375
**
376
*/
377
 
378
char *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID,
379
                        ConstStr255Param name, OSErr *err)
380
{
381
FSSpec      spec;
382
 
383
    *err = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
384
    printerr("FSMakeFSSpecCompat:", (*err != -43) && (*err != 0), *err,
385
             __LINE__, __FILE__, "");
386
    if ( (*err == noErr) || (*err == fnfErr) )
387
        {
388
        return GetFullPathFromSpec(CompletePath, &spec, err);
389
        }
390
 
391
return NULL;
392
}
393
 
394
 
395
 
396
/*
397
**  convert real-filename to archive-filename
398
**
399
*/
400
 
401
char *Real2RfDfFilen(char *RfDfFilen, const char *RealPath,
402
                    short CurrentFork, short MacZipMode, Boolean DataForkOnly)
403
{
404
 
405
AssertStr(RealPath,"Real2RfDfFilen")
406
AssertStr(RfDfFilen,"Real2RfDfFilen")
407
 
408
if (DataForkOnly) /* make no changes */
409
    {
410
    return sstrcpy(RfDfFilen, RealPath);
411
    }
412
 
413
switch (MacZipMode)
414
    {
415
    case JohnnyLee_EF:
416
        {
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");
422
        break;
423
        }
424
 
425
    case NewZipMode_EF:
426
        {
427
        switch (CurrentFork)
428
            {
429
            case DataFork:
430
                {
431
                sstrcpy(RfDfFilen, RealPath);
432
                return RfDfFilen;  /* data-fork  */
433
                break;
434
                }
435
            case ResourceFork:
436
                {
437
                sstrcpy(RfDfFilen, ResourceMark);
438
                sstrcat(RfDfFilen, RealPath);  /* resource-fork */
439
                return RfDfFilen;
440
                break;
441
                }
442
            default:
443
                {
444
                printerr("Real2RfDfFilen:", -1, -1,
445
                         __LINE__, __FILE__, RealPath);
446
                return NULL;  /* function should never reach this point */
447
                }
448
            }
449
        break;
450
        }
451
    default:
452
        {
453
        printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
454
        return NULL;  /* function should never reach this point */
455
        }
456
    }
457
 
458
printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath);
459
return NULL;  /* function should never come reach this point */
460
}
461
 
462
 
463
 
464
/*
465
**  convert archive-filename into a real filename
466
**
467
*/
468
 
469
char *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode,
470
                     Boolean DataForkOnly, short *CurrentFork)
471
{
472
short   length;
473
int     result;
474
 
475
AssertStr(RfDfFilen,"RfDfFilen2Real")
476
 
477
if (DataForkOnly ||
478
    (MacZipMode == UnKnown_EF) ||
479
    (MacZipMode < JohnnyLee_EF))
480
    {
481
    *CurrentFork = DataFork;
482
    return sstrcpy(RealFn,RfDfFilen);
483
    }
484
 
485
result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
486
if (result == 0)
487
    {
488
    MacZipMode = NewZipMode_EF;
489
    }
490
 
491
switch (MacZipMode)
492
    {
493
    case JohnnyLee_EF:
494
        {
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  */
500
        return RealFn;
501
        break;
502
        }
503
 
504
    case NewZipMode_EF:
505
        {                                   /* determine Fork type */
506
        result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2);
507
        if (result != 0)
508
            {
509
            *CurrentFork = DataFork;
510
            sstrcpy(RealFn, RfDfFilen);
511
            return RealFn;  /* data-fork  */
512
            }
513
        else
514
            {
515
            *CurrentFork = ResourceFork;
516
            if (strlen(RfDfFilen) > (sizeof(ResourceMark) - 1))
517
                {
518
                sstrcpy(RealFn, &RfDfFilen[sizeof(ResourceMark)-1]);
519
                }
520
            else RealFn[0] = '\0';
521
            return RealFn;  /* resource-fork */
522
            }
523
        break;
524
        }
525
    default:
526
        {
527
        *CurrentFork = NoFork;
528
        printerr("RfDfFilen2Real():", -1, MacZipMode,
529
                 __LINE__, __FILE__, RfDfFilen);
530
        return NULL;  /* function should never reach this point */
531
        }
532
    }
533
 
534
printerr("RfDfFilen2Real():", -1, MacZipMode, __LINE__, __FILE__, RfDfFilen);
535
return NULL;  /* function should never reach this point */
536
}
537
 
538
 
539
 
540
/*
541
**  return the applications name (argv[0])
542
**
543
*/
544
 
545
char *GetAppName(void)
546
{
547
ProcessSerialNumber psn;
548
static Str255       AppName;
549
ProcessInfoRec      pinfo;
550
OSErr               err;
551
 
552
GetCurrentProcess(&psn);
553
pinfo.processName = AppName;
554
pinfo.processInfoLength = sizeof(pinfo);
555
pinfo.processAppSpec = NULL;
556
 
557
err = GetProcessInformation(&psn,&pinfo);
558
AppName[AppName[0]+1] = 0x00;
559
 
560
return (char *)&AppName[1];
561
}
562
 
563
 
564
 
565
/*
566
**  return fullpathname from FSSpec
567
**
568
*/
569
 
570
char *GetFullPathFromSpec(char *FullPath, FSSpec *Spec, OSErr *err)
571
{
572
Handle hFullPath;
573
short len;
574
 
575
Assert_it(Spec,"GetFullPathFromSpec","")
576
 
577
*err = FSpGetFullPath(Spec, &len, &hFullPath);
578
printerr("FSpGetFullPath:", (*err != -43) && (*err != 0), *err,
579
         __LINE__, __FILE__, "");
580
 
581
memmove(FullPath, (Handle) *hFullPath, len);
582
FullPath[len] = '\0';  /* make c-string */
583
 
584
DisposeHandle((Handle)hFullPath);   /* we don't need it any more */
585
 
586
printerr("Warning path length exceeds limit: ", len >= NAME_MAX, len,
587
         __LINE__, __FILE__, " chars ");
588
 
589
return FullPath;
590
}
591
 
592
 
593
 
594
 
595
/*
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:
599
*   1. relative path:
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
604
*
605
* An absolute path will be returned.
606
 
607
The following characteristics of Macintosh pathnames should be noted:
608
 
609
       A full pathname never begins with a colon, but must contain at
610
       least one colon.
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
613
       directory name.
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;
621
       not a file.
622
*/
623
 
624
char *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec,
625
                      OSErr *err)
626
{
627
Boolean hasDirName = false;
628
char currentdir[NAME_MAX];
629
char *tmpPtr;
630
unsigned short pathlen;
631
 
632
AssertStr(name,"GetCompletePath")
633
Assert_it(Spec,"GetCompletePath","")
634
Assert_it((CompletePath != name),"GetCompletePath","")
635
 
636
for (tmpPtr = name; *tmpPtr; tmpPtr++)
637
    if (*tmpPtr == ':') hasDirName = true;
638
 
639
if (name[0] != ':')   /* case c: path including volume name or only filename */
640
    {
641
    if (hasDirName)
642
        {   /* okey, starts with volume name, so it must be a complete path */
643
        sstrcpy(CompletePath, name);
644
        }
645
    else
646
        {   /* only filename: add cwd and return */
647
        getcwd(currentdir, NAME_MAX);
648
        sstrcat(currentdir, name);
649
        sstrcpy(CompletePath, currentdir);
650
        }
651
    }
652
else if (name[1] == ':')    /* it's case b: "::folder2:filename"  */
653
    {
654
    printerr("GetCompletePath ", -1, *err, __LINE__, __FILE__, "not implemented");
655
            /* it's not yet implemented; do we really need this case ?*/
656
    return NULL;
657
    }
658
else                        /* it's case a: ":subfolder:filename" */
659
    {
660
    getcwd(CompletePath, NAME_MAX);     /* we don't need a second colon */
661
    CompletePath[strlen(CompletePath)-1] = '\0';
662
    sstrcat(CompletePath, name);
663
    }
664
 
665
pathlen = strlen(CompletePath);
666
*err = FSpLocationFromFullPath(pathlen, CompletePath, Spec);
667
 
668
return CompletePath;
669
}
670
 
671
 
672
 
673
char *MakeFilenameShorter(const char *LongFilename)
674
{
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;
684
char *tmpPtr;
685
short MaxLength = 31;
686
 
687
if (full_length <= MaxLength) /* filename is not long */
688
    {
689
    return strcpy(filename,LongFilename);
690
    }
691
 
692
Num++;
693
strcpy(tempLongFilename,LongFilename);
694
 
695
/* Look for the last extension pos */
696
for (tmpPtr = tempLongFilename; *tmpPtr; tmpPtr++)
697
    if (*tmpPtr == '.') last_dotpos = tmpPtr;
698
 
699
ext_length = strlen(last_dotpos);
700
firstpart_length = last_dotpos - tempLongFilename;
701
 
702
if (ext_length > 6)  /* up to 5 chars are treated as a */
703
    {                /* normal extension like ".html" or ".class"  */
704
    firstpart_length = 0;
705
    }
706
 
707
num_to_cut = full_length - MaxLength;
708
 
709
/* number the files to make the names unique */
710
sprintf(charnum,"~%x", Num);
711
num_to_cut += strlen(charnum);
712
 
713
if (firstpart_length == 0)
714
    {
715
    firstpart_length = full_length;
716
    tempLongFilename[firstpart_length - num_to_cut] = 0;
717
    sprintf(filename,"%s%s", tempLongFilename, charnum);
718
    }
719
else
720
    {
721
    tempLongFilename[firstpart_length - num_to_cut] = 0;
722
    sprintf(filename,"%s%s%s", tempLongFilename, charnum, last_dotpos);
723
    }
724
 
725
return filename;
726
}