~ubuntu-branches/ubuntu/precise/boinc/precise

« back to all changes in this revision

Viewing changes to zip/zip/macos/source/macstuff.c

Tags: 6.12.8+dfsg-1
* New upstream release.
* Simplified debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
These Functions were originally part of More Files version 1.4.8
3
 
 
4
 
More Files fixes many of the broken or underfunctional
5
 
parts of the file system.
6
 
 
7
 
More Files
8
 
 
9
 
A collection of File Manager and related routines
10
 
 
11
 
by Jim Luther (Apple Macintosh Developer Technical Support Emeritus)
12
 
with significant code contributions by Nitin Ganatra
13
 
(Apple Macintosh Developer Technical Support Emeritus)
14
 
Copyright  1992-1998 Apple Computer, Inc.
15
 
Portions copyright  1995 Jim Luther
16
 
All rights reserved.
17
 
 
18
 
The Package "More Files" is distributed under the following
19
 
license terms:
20
 
 
21
 
         "You may incorporate this sample code into your
22
 
          applications without restriction, though the
23
 
          sample code has been provided "AS IS" and the
24
 
          responsibility for its operation is 100% yours.
25
 
          However, what you are not permitted to do is to
26
 
          redistribute the source as "DSC Sample Code" after
27
 
          having made changes. If you're going to
28
 
          redistribute the source, we require that you make
29
 
          it clear in the source that the code was descended
30
 
          from Apple Sample Code, but that you've made
31
 
          changes."
32
 
 
33
 
 
34
 
The following changes are made by Info-ZIP:
35
 
 
36
 
- The only changes are made by pasting the functions
37
 
  (mostly found in MoreFilesExtras.c / MoreFiles.c)
38
 
  directly into macstuff.c / macstuff.h and slightly
39
 
  reformatting the text (replacement of TABs by spaces,
40
 
  removal/replacement of non-ASCII characters).
41
 
  The code itself is NOT changed.
42
 
 
43
 
This file has been modified by Info-ZIP for use in MacZip.
44
 
This file is NOT part of the original package More Files.
45
 
 
46
 
More Files can be found on the MetroWerks CD and Developer CD from
47
 
Apple. You can also download the latest version from:
48
 
 
49
 
    http://members.aol.com/JumpLong/#MoreFiles
50
 
 
51
 
Jim Luther's Home-page:
52
 
    http://members.aol.com/JumpLong/
53
 
 
54
 
 
55
 
*/
56
 
 
57
 
#include <string.h>
58
 
 
59
 
 
60
 
#include "macstuff.h"
61
 
 
62
 
 
63
 
 
64
 
extern int errno;
65
 
 
66
 
static  OSErr   GetCommentFromDesktopFile(short vRefNum,
67
 
                                          long dirID,
68
 
                                          ConstStr255Param name,
69
 
                                          Str255 comment);
70
 
 
71
 
static  OSErr   GetCommentID(short vRefNum,
72
 
                             long dirID,
73
 
                             ConstStr255Param name,
74
 
                             short *commentID);
75
 
 
76
 
static  OSErr   GetDesktopFileName(short vRefNum,
77
 
                                   Str255 desktopName);
78
 
 
79
 
 
80
 
enum
81
 
{
82
 
    kBNDLResType    = 'BNDL',
83
 
    kFREFResType    = 'FREF',
84
 
    kIconFamResType = 'ICN#',
85
 
    kFCMTResType    = 'FCMT',
86
 
    kAPPLResType    = 'APPL'
87
 
};
88
 
 
89
 
 
90
 
/*****************************************************************************/
91
 
 
92
 
/*
93
 
**  File Manager FSp calls
94
 
*/
95
 
 
96
 
/*****************************************************************************/
97
 
 
98
 
pascal  OSErr   FSMakeFSSpecCompat(short vRefNum,
99
 
                                   long dirID,
100
 
                                   ConstStr255Param fileName,
101
 
                                   FSSpec *spec)
102
 
{
103
 
    OSErr   result;
104
 
 
105
 
#if !__MACOSSEVENORLATER
106
 
    if ( !FSHasFSSpecCalls() && !QTHasFSSpecCalls() )
107
 
    {
108
 
        Boolean isDirectory;
109
 
 
110
 
        result = GetObjectLocation(vRefNum, dirID, fileName,
111
 
                                    &(spec->vRefNum), &(spec->parID), spec->name,
112
 
                                    &isDirectory);
113
 
    }
114
 
    else
115
 
#endif  /* !__MACOSSEVENORLATER */
116
 
    {
117
 
     /* Let the file system create the FSSpec if it can since it does the job */
118
 
     /* much more efficiently than I can. */
119
 
        result = FSMakeFSSpec(vRefNum, dirID, fileName, spec);
120
 
 
121
 
        /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */
122
 
        /* returned in the parID field when making an FSSpec to the volume's */
123
 
        /* root directory by passing a full pathname in MakeFSSpec's */
124
 
        /* fileName parameter. Fixed in Mac OS 8.1 */
125
 
        if ( (result == noErr) && (spec->parID == 0) )
126
 
            spec->parID = fsRtParID;
127
 
    }
128
 
    return ( result );
129
 
}
130
 
 
131
 
 
132
 
/*****************************************************************************/
133
 
/* FSHasFSSpecCalls returns true if the file system provides FSSpec calls. */
134
 
 
135
 
#if !__MACOSSEVENORLATER
136
 
static  Boolean FSHasFSSpecCalls(void)
137
 
{
138
 
    long            response;
139
 
#if !GENERATENODATA
140
 
    static Boolean  tested = false;
141
 
    static Boolean  result = false;
142
 
#else
143
 
    Boolean result = false;
144
 
#endif
145
 
 
146
 
#if !GENERATENODATA
147
 
    if ( !tested )
148
 
    {
149
 
        tested = true;
150
 
#endif
151
 
        if ( Gestalt(gestaltFSAttr, &response) == noErr )
152
 
        {
153
 
            result = ((response & (1L << gestaltHasFSSpecCalls)) != 0);
154
 
        }
155
 
#if !GENERATENODATA
156
 
    }
157
 
#endif
158
 
    return ( result );
159
 
}
160
 
#endif  /* !__MACOSSEVENORLATER */
161
 
 
162
 
 
163
 
 
164
 
/*****************************************************************************/
165
 
/* QTHasFSSpecCalls returns true if QuickTime provides FSSpec calls */
166
 
/* except for FSpExchangeFiles. */
167
 
 
168
 
#if !__MACOSSEVENORLATER
169
 
static  Boolean QTHasFSSpecCalls(void)
170
 
{
171
 
    long            response;
172
 
#if !GENERATENODATA
173
 
    static Boolean  tested = false;
174
 
    static Boolean  result = false;
175
 
#else
176
 
    Boolean result = false;
177
 
#endif
178
 
 
179
 
#if !GENERATENODATA
180
 
    if ( !tested )
181
 
    {
182
 
        tested = true;
183
 
#endif
184
 
        result = (Gestalt(gestaltQuickTimeVersion, &response) == noErr);
185
 
#if !GENERATENODATA
186
 
    }
187
 
#endif
188
 
    return ( result );
189
 
}
190
 
#endif  /* !__MACOSSEVENORLATER */
191
 
 
192
 
 
193
 
 
194
 
 
195
 
/*
196
 
 *----------------------------------------------------------------------
197
 
 *
198
 
 * FSpGetDefaultDir --
199
 
 *
200
 
 *  This function gets the current default directory.
201
 
 *
202
 
 * Results:
203
 
 *  The provided FSSpec is changed to point to the "default"
204
 
 *  directory.  The function returns what ever errors
205
 
 *  FSMakeFSSpecCompat may encounter.
206
 
 *
207
 
 * Side effects:
208
 
 *  None.
209
 
 *
210
 
 *----------------------------------------------------------------------
211
 
 */
212
 
 
213
 
int FSpGetDefaultDir(FSSpecPtr dirSpec) /* On return the default directory. */
214
 
{
215
 
    OSErr err;
216
 
    short vRefNum = 0;
217
 
    long int dirID = 0;
218
 
 
219
 
    err = HGetVol(NULL, &vRefNum, &dirID);
220
 
 
221
 
    if (err == noErr) {
222
 
    err = FSMakeFSSpecCompat(vRefNum, dirID, (ConstStr255Param) NULL,
223
 
        dirSpec);
224
 
    }
225
 
 
226
 
    return err;
227
 
}
228
 
 
229
 
/*
230
 
 *----------------------------------------------------------------------
231
 
 *
232
 
 * FSpSetDefaultDir --
233
 
 *
234
 
 *  This function sets the default directory to the directory
235
 
 *  pointed to by the provided FSSpec.
236
 
 *
237
 
 * Results:
238
 
 *  The function returns what ever errors HSetVol may encounter.
239
 
 *
240
 
 * Side effects:
241
 
 *  None.
242
 
 *
243
 
 *----------------------------------------------------------------------
244
 
 */
245
 
 
246
 
int FSpSetDefaultDir(FSSpecPtr dirSpec) /* The new default directory. */
247
 
{
248
 
    OSErr err;
249
 
 
250
 
    /*
251
 
     * The following special case is needed to work around a bug
252
 
     * in the Macintosh OS.  (Acutally PC Exchange.)
253
 
     */
254
 
 
255
 
    if (dirSpec->parID == fsRtParID) {
256
 
    err = HSetVol(NULL, dirSpec->vRefNum, fsRtDirID);
257
 
    } else {
258
 
    err = HSetVol(dirSpec->name, dirSpec->vRefNum, dirSpec->parID);
259
 
    }
260
 
 
261
 
    return err;
262
 
}
263
 
 
264
 
/*
265
 
 *----------------------------------------------------------------------
266
 
 *
267
 
 * FSpFindFolder --
268
 
 *
269
 
 *  This function is a version of the FindFolder function that
270
 
 *  returns the result as a FSSpec rather than a vRefNum and dirID.
271
 
 *
272
 
 * Results:
273
 
 *  Results will be simaler to that of the FindFolder function.
274
 
 *
275
 
 * Side effects:
276
 
 *  None.
277
 
 *
278
 
 *----------------------------------------------------------------------
279
 
 */
280
 
 
281
 
OSErr
282
 
FSpFindFolder(
283
 
    short vRefNum,      /* Volume reference number. */
284
 
    OSType folderType,      /* Folder type taken by FindFolder. */
285
 
    Boolean createFolder,   /* Should we create it if non-existant. */
286
 
    FSSpec *spec)       /* Pointer to resulting directory. */
287
 
{
288
 
    short foundVRefNum;
289
 
    long foundDirID;
290
 
    OSErr err;
291
 
 
292
 
    err = FindFolder(vRefNum, folderType, createFolder,
293
 
        &foundVRefNum, &foundDirID);
294
 
    if (err != noErr) {
295
 
    return err;
296
 
    }
297
 
 
298
 
    err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec);
299
 
    return err;
300
 
}
301
 
 
302
 
 
303
 
 
304
 
/*
305
 
 *----------------------------------------------------------------------
306
 
 *
307
 
 * FSpPathFromLocation --
308
 
 *
309
 
 *  This function obtains a full path name for a given macintosh
310
 
 *  FSSpec.  Unlike the More Files function FSpGetFullPath, this
311
 
 *  function will return a C string in the Handle.  It also will
312
 
 *  create paths for FSSpec that do not yet exist.
313
 
 *
314
 
 * Results:
315
 
 *  OSErr code.
316
 
 *
317
 
 * Side effects:
318
 
 *  None.
319
 
 *
320
 
 *----------------------------------------------------------------------
321
 
 */
322
 
 
323
 
OSErr
324
 
FSpPathFromLocation(
325
 
    FSSpec *spec,       /* The location we want a path for. */
326
 
    int *length,        /* Length of the resulting path. */
327
 
    Handle *fullPath)       /* Handle to path. */
328
 
{
329
 
    OSErr err;
330
 
    FSSpec tempSpec;
331
 
    CInfoPBRec pb;
332
 
 
333
 
    *fullPath = NULL;
334
 
 
335
 
    /*
336
 
     * Make a copy of the input FSSpec that can be modified.
337
 
     */
338
 
    BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
339
 
 
340
 
    if (tempSpec.parID == fsRtParID) {
341
 
    /*
342
 
     * The object is a volume.  Add a colon to make it a full
343
 
     * pathname.  Allocate a handle for it and we are done.
344
 
     */
345
 
    tempSpec.name[0] += 2;
346
 
    tempSpec.name[tempSpec.name[0] - 1] = ':';
347
 
    tempSpec.name[tempSpec.name[0]] = '\0';
348
 
 
349
 
    err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
350
 
    } else {
351
 
    /*
352
 
     * The object isn't a volume.  Is the object a file or a directory?
353
 
     */
354
 
    pb.dirInfo.ioNamePtr = tempSpec.name;
355
 
    pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
356
 
    pb.dirInfo.ioDrDirID = tempSpec.parID;
357
 
    pb.dirInfo.ioFDirIndex = 0;
358
 
    err = PBGetCatInfoSync(&pb);
359
 
 
360
 
    if ((err == noErr) || (err == fnfErr)) {
361
 
        /*
362
 
         * If the file doesn't currently exist we start over.  If the
363
 
         * directory exists everything will work just fine.  Otherwise we
364
 
         * will just fail later.  If the object is a directory, append a
365
 
         * colon so full pathname ends with colon.
366
 
         */
367
 
        if (err == fnfErr) {
368
 
        BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
369
 
        } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) {
370
 
        tempSpec.name[0] += 1;
371
 
        tempSpec.name[tempSpec.name[0]] = ':';
372
 
        }
373
 
 
374
 
        /*
375
 
         * Create a new Handle for the object - make it a C string.
376
 
         */
377
 
        tempSpec.name[0] += 1;
378
 
        tempSpec.name[tempSpec.name[0]] = '\0';
379
 
        err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
380
 
        if (err == noErr) {
381
 
        /*
382
 
         * Get the ancestor directory names - loop until we have an
383
 
         * error or find the root directory.
384
 
         */
385
 
        pb.dirInfo.ioNamePtr = tempSpec.name;
386
 
        pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
387
 
        pb.dirInfo.ioDrParID = tempSpec.parID;
388
 
        do {
389
 
            pb.dirInfo.ioFDirIndex = -1;
390
 
            pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
391
 
            err = PBGetCatInfoSync(&pb);
392
 
            if (err == noErr) {
393
 
            /*
394
 
             * Append colon to directory name and add
395
 
             * directory name to beginning of fullPath.
396
 
             */
397
 
            ++tempSpec.name[0];
398
 
            tempSpec.name[tempSpec.name[0]] = ':';
399
 
 
400
 
            (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
401
 
                tempSpec.name[0]);
402
 
            err = MemError();
403
 
            }
404
 
        } while ( (err == noErr) &&
405
 
            (pb.dirInfo.ioDrDirID != fsRtDirID) );
406
 
        }
407
 
    }
408
 
    }
409
 
 
410
 
    /*
411
 
     * On error Dispose the handle, set it to NULL & return the err.
412
 
     * Otherwise, set the length & return.
413
 
     */
414
 
    if (err == noErr) {
415
 
    *length = GetHandleSize(*fullPath) - 1;
416
 
    } else {
417
 
    if ( *fullPath != NULL ) {
418
 
        DisposeHandle(*fullPath);
419
 
    }
420
 
    *fullPath = NULL;
421
 
    *length = 0;
422
 
    }
423
 
 
424
 
    return err;
425
 
}
426
 
 
427
 
 
428
 
 
429
 
/*****************************************************************************/
430
 
 
431
 
pascal  OSErr   FSpGetDirectoryID(const FSSpec *spec,
432
 
                                  long *theDirID,
433
 
                                  Boolean *isDirectory)
434
 
{
435
 
    return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name,
436
 
             theDirID, isDirectory) );
437
 
}
438
 
 
439
 
 
440
 
/*****************************************************************************/
441
 
 
442
 
pascal  OSErr   GetDirectoryID(short vRefNum,
443
 
                               long dirID,
444
 
                               ConstStr255Param name,
445
 
                               long *theDirID,
446
 
                               Boolean *isDirectory)
447
 
{
448
 
    CInfoPBRec pb;
449
 
    OSErr error;
450
 
 
451
 
    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
452
 
    if ( error == noErr )
453
 
    {
454
 
        *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0;
455
 
        if ( *isDirectory )
456
 
        {
457
 
            *theDirID = pb.dirInfo.ioDrDirID;
458
 
        }
459
 
        else
460
 
        {
461
 
            *theDirID = pb.hFileInfo.ioFlParID;
462
 
        }
463
 
    }
464
 
 
465
 
    return ( error );
466
 
}
467
 
 
468
 
 
469
 
/*****************************************************************************/
470
 
 
471
 
pascal  OSErr GetCatInfoNoName(short vRefNum,
472
 
                               long dirID,
473
 
                               ConstStr255Param name,
474
 
                               CInfoPBPtr pb)
475
 
{
476
 
    Str31 tempName;
477
 
    OSErr error;
478
 
 
479
 
    /* Protection against File Sharing problem */
480
 
    if ( (name == NULL) || (name[0] == 0) )
481
 
    {
482
 
        tempName[0] = 0;
483
 
        pb->dirInfo.ioNamePtr = tempName;
484
 
        pb->dirInfo.ioFDirIndex = -1;   /* use ioDirID */
485
 
    }
486
 
    else
487
 
    {
488
 
        pb->dirInfo.ioNamePtr = (StringPtr)name;
489
 
        pb->dirInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
490
 
    }
491
 
    pb->dirInfo.ioVRefNum = vRefNum;
492
 
    pb->dirInfo.ioDrDirID = dirID;
493
 
    error = PBGetCatInfoSync(pb);
494
 
    pb->dirInfo.ioNamePtr = NULL;
495
 
    return ( error );
496
 
}
497
 
 
498
 
 
499
 
 
500
 
/*****************************************************************************/
501
 
 
502
 
pascal  OSErr   GetObjectLocation(short vRefNum,
503
 
                                  long dirID,
504
 
                                  ConstStr255Param pathname,
505
 
                                  short *realVRefNum,
506
 
                                  long *realParID,
507
 
                                  Str255 realName,
508
 
                                  Boolean *isDirectory)
509
 
{
510
 
    OSErr error;
511
 
    CInfoPBRec pb;
512
 
    Str255 tempPathname;
513
 
 
514
 
    /* clear results */
515
 
    *realVRefNum = 0;
516
 
    *realParID = 0;
517
 
    realName[0] = 0;
518
 
 
519
 
    /*
520
 
    **  Get the real vRefNum
521
 
    */
522
 
    error = DetermineVRefNum(pathname, vRefNum, realVRefNum);
523
 
    if ( error == noErr )
524
 
    {
525
 
        /*
526
 
        **  Determine if the object already exists and if so,
527
 
        **  get the real parent directory ID if it's a file
528
 
        */
529
 
 
530
 
        /* Protection against File Sharing problem */
531
 
        if ( (pathname == NULL) || (pathname[0] == 0) )
532
 
        {
533
 
            tempPathname[0] = 0;
534
 
            pb.hFileInfo.ioNamePtr = tempPathname;
535
 
            pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */
536
 
        }
537
 
        else
538
 
        {
539
 
            pb.hFileInfo.ioNamePtr = (StringPtr)pathname;
540
 
            pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */
541
 
        }
542
 
        pb.hFileInfo.ioVRefNum = vRefNum;
543
 
        pb.hFileInfo.ioDirID = dirID;
544
 
        error = PBGetCatInfoSync(&pb);
545
 
        if ( error == noErr )
546
 
        {
547
 
            /*
548
 
            **  The file system object is present and we have the file's
549
 
            **  real parID
550
 
            */
551
 
 
552
 
            /*  Is it a directory or a file? */
553
 
            *isDirectory = (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0;
554
 
            if ( *isDirectory )
555
 
            {
556
 
                /*
557
 
                **  It's a directory, get its name and parent dirID, and then
558
 
                **  we're done
559
 
                */
560
 
 
561
 
                pb.dirInfo.ioNamePtr = realName;
562
 
                pb.dirInfo.ioVRefNum = *realVRefNum;
563
 
                /* pb.dirInfo.ioDrDirID already contains the dirID of the
564
 
                   directory object */
565
 
                pb.dirInfo.ioFDirIndex = -1;    /* get information about ioDirID */
566
 
                error = PBGetCatInfoSync(&pb);
567
 
 
568
 
                /* get the parent ID here, because the file system can return the */
569
 
                /* wrong parent ID from the last call. */
570
 
                *realParID = pb.dirInfo.ioDrParID;
571
 
            }
572
 
            else
573
 
            {
574
 
                /*
575
 
                **  It's a file - use the parent directory ID from the last call
576
 
                **  to GetCatInfoparse, get the file name, and then we're done
577
 
                */
578
 
                *realParID = pb.hFileInfo.ioFlParID;
579
 
                error = GetFilenameFromPathname(pathname, realName);
580
 
            }
581
 
        }
582
 
        else if ( error == fnfErr )
583
 
        {
584
 
            /*
585
 
            **  The file system object is not present - see if its parent is present
586
 
            */
587
 
 
588
 
            /*
589
 
            **  Parse to get the object name from end of pathname
590
 
            */
591
 
            error = GetFilenameFromPathname(pathname, realName);
592
 
 
593
 
            /* if we can't get the object name from the end, we can't continue */
594
 
            if ( error == noErr )
595
 
            {
596
 
                /*
597
 
                **  What we want now is the pathname minus the object name
598
 
                **  for example:
599
 
                **  if pathname is 'vol:dir:file' tempPathname becomes 'vol:dir:'
600
 
                **  if pathname is 'vol:dir:file:' tempPathname becomes 'vol:dir:'
601
 
                **  if pathname is ':dir:file' tempPathname becomes ':dir:'
602
 
                **  if pathname is ':dir:file:' tempPathname becomes ':dir:'
603
 
                **  if pathname is ':file' tempPathname becomes ':'
604
 
                **  if pathname is 'file or file:' tempPathname becomes ''
605
 
                */
606
 
 
607
 
                /* get a copy of the pathname */
608
 
                BlockMoveData(pathname, tempPathname, pathname[0] + 1);
609
 
 
610
 
                /* remove the object name */
611
 
                tempPathname[0] -= realName[0];
612
 
                /* and the trailing colon (if any) */
613
 
                if ( pathname[pathname[0]] == ':' )
614
 
                {
615
 
                    --tempPathname[0];
616
 
                }
617
 
 
618
 
                /* OK, now get the parent's directory ID */
619
 
 
620
 
                /* Protection against File Sharing problem */
621
 
                pb.hFileInfo.ioNamePtr = (StringPtr)tempPathname;
622
 
                if ( tempPathname[0] != 0 )
623
 
                {
624
 
                    pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */
625
 
                }
626
 
                else
627
 
                {
628
 
                    pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */
629
 
                }
630
 
                pb.hFileInfo.ioVRefNum = vRefNum;
631
 
                pb.hFileInfo.ioDirID = dirID;
632
 
                error = PBGetCatInfoSync(&pb);
633
 
                *realParID = pb.dirInfo.ioDrDirID;
634
 
 
635
 
                *isDirectory = false;   /* we don't know what the object is
636
 
                                           really going to be */
637
 
            }
638
 
 
639
 
            if ( error != noErr )
640
 
            {
641
 
                error = dirNFErr;   /* couldn't find parent directory */
642
 
            }
643
 
            else
644
 
            {
645
 
                error = fnfErr; /* we found the parent, but not the file */
646
 
            }
647
 
        }
648
 
    }
649
 
 
650
 
    return ( error );
651
 
}
652
 
 
653
 
 
654
 
 
655
 
/*****************************************************************************/
656
 
 
657
 
pascal  OSErr   DetermineVRefNum(ConstStr255Param pathname,
658
 
                                 short vRefNum,
659
 
                                 short *realVRefNum)
660
 
{
661
 
    HParamBlockRec pb;
662
 
    OSErr error;
663
 
 
664
 
    error = GetVolumeInfoNoName(pathname,vRefNum, &pb);
665
 
    if ( error == noErr )
666
 
    {
667
 
        *realVRefNum = pb.volumeParam.ioVRefNum;
668
 
    }
669
 
    return ( error );
670
 
}
671
 
 
672
 
 
673
 
/*****************************************************************************/
674
 
 
675
 
pascal  OSErr   GetFilenameFromPathname(ConstStr255Param pathname,
676
 
                                        Str255 filename)
677
 
{
678
 
    short   index;
679
 
    short   nameEnd;
680
 
    OSErr   error;
681
 
 
682
 
    /* default to no filename */
683
 
    filename[0] = 0;
684
 
 
685
 
    /* check for no pathname */
686
 
    if ( pathname != NULL )
687
 
    {
688
 
        /* get string length */
689
 
        index = pathname[0];
690
 
 
691
 
        /* check for empty string */
692
 
        if ( index != 0 )
693
 
        {
694
 
            /* skip over last trailing colon (if any) */
695
 
            if ( pathname[index] == ':' )
696
 
            {
697
 
                --index;
698
 
            }
699
 
 
700
 
            /* save the end of the string */
701
 
            nameEnd = index;
702
 
 
703
 
            /* if pathname ends with multiple colons, then this pathname refers */
704
 
            /* to a directory, not a file */
705
 
            if ( pathname[index] != ':' )
706
 
            {
707
 
                /* parse backwards until we find a colon or hit the beginning
708
 
                   of the pathname */
709
 
                while ( (index != 0) && (pathname[index] != ':') )
710
 
                {
711
 
                    --index;
712
 
                }
713
 
 
714
 
                /* if we parsed to the beginning of the pathname and the
715
 
                   pathname ended */
716
 
                /* with a colon, then pathname is a full pathname to a volume,
717
 
                   not a file */
718
 
                if ( (index != 0) || (pathname[pathname[0]] != ':') )
719
 
                {
720
 
                    /* get the filename and return noErr */
721
 
                    filename[0] = (char)(nameEnd - index);
722
 
                    BlockMoveData(&pathname[index+1], &filename[1], nameEnd - index);
723
 
                    error = noErr;
724
 
                }
725
 
                else
726
 
                {
727
 
                    /* pathname to a volume, not a file */
728
 
                    error = notAFileErr;
729
 
                }
730
 
            }
731
 
            else
732
 
            {
733
 
                /* directory, not a file */
734
 
                error = notAFileErr;
735
 
            }
736
 
        }
737
 
        else
738
 
        {
739
 
            /* empty string isn't a file */
740
 
            error = notAFileErr;
741
 
        }
742
 
    }
743
 
    else
744
 
    {
745
 
        /* NULL pathname isn't a file */
746
 
        error = notAFileErr;
747
 
    }
748
 
 
749
 
    return ( error );
750
 
}
751
 
 
752
 
 
753
 
 
754
 
/*****************************************************************************/
755
 
 
756
 
/*
757
 
**  GetVolumeInfoNoName uses pathname and vRefNum to call PBHGetVInfoSync
758
 
**  in cases where the returned volume name is not needed by the caller.
759
 
**  The pathname and vRefNum parameters are not touched, and the pb
760
 
**  parameter is initialized by PBHGetVInfoSync except that ioNamePtr in
761
 
**  the parameter block is always returned as NULL (since it might point
762
 
**  to the local tempPathname).
763
 
**
764
 
**  I noticed using this code in several places, so here it is once.
765
 
**  This reduces the code size of MoreFiles.
766
 
*/
767
 
pascal  OSErr   GetVolumeInfoNoName(ConstStr255Param pathname,
768
 
                                    short vRefNum,
769
 
                                    HParmBlkPtr pb)
770
 
{
771
 
    Str255 tempPathname;
772
 
    OSErr error;
773
 
 
774
 
    /* Make sure pb parameter is not NULL */
775
 
    if ( pb != NULL )
776
 
    {
777
 
        pb->volumeParam.ioVRefNum = vRefNum;
778
 
        if ( pathname == NULL )
779
 
        {
780
 
            pb->volumeParam.ioNamePtr = NULL;
781
 
            pb->volumeParam.ioVolIndex = 0;     /* use ioVRefNum only */
782
 
        }
783
 
        else
784
 
        {                                   /* make a copy of the string and */
785
 
            BlockMoveData(pathname, tempPathname, pathname[0] + 1);
786
 
                                    /* use the copy so original isn't trashed */
787
 
            pb->volumeParam.ioNamePtr = (StringPtr)tempPathname;
788
 
                                       /* use ioNamePtr/ioVRefNum combination */
789
 
            pb->volumeParam.ioVolIndex = -1;
790
 
        }
791
 
        error = PBHGetVInfoSync(pb);
792
 
        pb->volumeParam.ioNamePtr = NULL;   /* ioNamePtr may point to local
793
 
                                            tempPathname, so don't return it */
794
 
    }
795
 
    else
796
 
    {
797
 
        error = paramErr;
798
 
    }
799
 
    return ( error );
800
 
}
801
 
 
802
 
 
803
 
 
804
 
 
805
 
/*****************************************************************************/
806
 
 
807
 
pascal  OSErr   FSpGetFullPath(const FSSpec *spec,
808
 
                               short *fullPathLength,
809
 
                               Handle *fullPath)
810
 
{
811
 
    OSErr       result;
812
 
    OSErr       realResult;
813
 
    FSSpec      tempSpec;
814
 
    CInfoPBRec  pb;
815
 
 
816
 
    *fullPathLength = 0;
817
 
    *fullPath = NULL;
818
 
 
819
 
    /* Default to noErr */
820
 
    realResult = noErr;
821
 
 
822
 
    /* Make a copy of the input FSSpec that can be modified */
823
 
    BlockMoveData(spec, &tempSpec, sizeof(FSSpec));
824
 
 
825
 
    if ( tempSpec.parID == fsRtParID )
826
 
    {
827
 
        /* The object is a volume */
828
 
 
829
 
        /* Add a colon to make it a full pathname */
830
 
        ++tempSpec.name[0];
831
 
        tempSpec.name[tempSpec.name[0]] = ':';
832
 
 
833
 
        /* We're done */
834
 
        result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
835
 
    }
836
 
    else
837
 
    {
838
 
        /* The object isn't a volume */
839
 
 
840
 
        /* Is the object a file or a directory? */
841
 
        pb.dirInfo.ioNamePtr = tempSpec.name;
842
 
        pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
843
 
        pb.dirInfo.ioDrDirID = tempSpec.parID;
844
 
        pb.dirInfo.ioFDirIndex = 0;
845
 
        result = PBGetCatInfoSync(&pb);
846
 
        /* Allow file/directory name at end of path to not exist. */
847
 
        realResult = result;
848
 
        if ( (result == noErr) || (result == fnfErr) )
849
 
        {
850
 
            /* if the object is a directory, append a colon so full pathname
851
 
               ends with colon */
852
 
            if ( (result == noErr) && (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
853
 
            {
854
 
                ++tempSpec.name[0];
855
 
                tempSpec.name[tempSpec.name[0]] = ':';
856
 
            }
857
 
 
858
 
            /* Put the object name in first */
859
 
            result = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]);
860
 
            if ( result == noErr )
861
 
            {
862
 
                /* Get the ancestor directory names */
863
 
                pb.dirInfo.ioNamePtr = tempSpec.name;
864
 
                pb.dirInfo.ioVRefNum = tempSpec.vRefNum;
865
 
                pb.dirInfo.ioDrParID = tempSpec.parID;
866
 
                do  /* loop until we have an error or find the root directory */
867
 
                {
868
 
                    pb.dirInfo.ioFDirIndex = -1;
869
 
                    pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
870
 
                    result = PBGetCatInfoSync(&pb);
871
 
                    if ( result == noErr )
872
 
                    {
873
 
                        /* Append colon to directory name */
874
 
                        ++tempSpec.name[0];
875
 
                        tempSpec.name[tempSpec.name[0]] = ':';
876
 
 
877
 
                        /* Add directory name to beginning of fullPath */
878
 
                        (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1],
879
 
                                      tempSpec.name[0]);
880
 
                        result = MemError();
881
 
                    }
882
 
                } while ( (result == noErr) && (pb.dirInfo.ioDrDirID != fsRtDirID) );
883
 
            }
884
 
        }
885
 
    }
886
 
    if ( result == noErr )
887
 
    {
888
 
        /* Return the length */
889
 
        *fullPathLength = InlineGetHandleSize(*fullPath);
890
 
        result = realResult;    /* return realResult in case it was fnfErr */
891
 
    }
892
 
    else
893
 
    {
894
 
        /* Dispose of the handle and return NULL and zero length */
895
 
        if ( *fullPath != NULL )
896
 
        {
897
 
            DisposeHandle(*fullPath);
898
 
        }
899
 
        *fullPath = NULL;
900
 
        *fullPathLength = 0;
901
 
    }
902
 
 
903
 
    return ( result );
904
 
}
905
 
 
906
 
 
907
 
 
908
 
/*****************************************************************************/
909
 
 
910
 
pascal OSErr FSpLocationFromFullPath(short fullPathLength,
911
 
                                     const void *fullPath,
912
 
                                     FSSpec *spec)
913
 
{
914
 
    AliasHandle alias;
915
 
    OSErr       result;
916
 
    Boolean     wasChanged;
917
 
    Str32       nullString;
918
 
 
919
 
    /* Create a minimal alias from the full pathname */
920
 
    nullString[0] = 0;  /* null string to indicate no zone or server name */
921
 
    result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString,
922
 
                                         nullString, &alias);
923
 
 
924
 
    if ( result == noErr )
925
 
    {
926
 
        /* Let the Alias Manager resolve the alias. */
927
 
        result = ResolveAlias(NULL, alias, spec, &wasChanged);
928
 
 
929
 
        DisposeHandle((Handle)alias);   /* Free up memory used */
930
 
    }
931
 
 
932
 
    return ( result );
933
 
}
934
 
 
935
 
 
936
 
 
937
 
/*****************************************************************************/
938
 
 
939
 
pascal  OSErr   GetFullPath(short vRefNum,
940
 
                            long dirID,
941
 
                            ConstStr255Param name,
942
 
                            short *fullPathLength,
943
 
                            Handle *fullPath)
944
 
{
945
 
    OSErr       result;
946
 
    FSSpec      spec;
947
 
 
948
 
    *fullPathLength = 0;
949
 
    *fullPath = NULL;
950
 
 
951
 
    result = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec);
952
 
    if ( (result == noErr) || (result == fnfErr) )
953
 
    {
954
 
        result = FSpGetFullPath(&spec, fullPathLength, fullPath);
955
 
    }
956
 
 
957
 
    return ( result );
958
 
}
959
 
 
960
 
 
961
 
 
962
 
/*****************************************************************************/
963
 
 
964
 
pascal  OSErr   ChangeCreatorType(short vRefNum,
965
 
                                  long dirID,
966
 
                                  ConstStr255Param name,
967
 
                                  OSType creator,
968
 
                                  OSType fileType)
969
 
{
970
 
    CInfoPBRec pb;
971
 
    OSErr error;
972
 
    short realVRefNum;
973
 
    long parID;
974
 
 
975
 
    pb.hFileInfo.ioNamePtr = (StringPtr)name;
976
 
    pb.hFileInfo.ioVRefNum = vRefNum;
977
 
    pb.hFileInfo.ioDirID = dirID;
978
 
    pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */
979
 
    error = PBGetCatInfoSync(&pb);
980
 
    if ( error == noErr )
981
 
    {
982
 
        if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) == 0 )   /* if file */
983
 
        {                            /* save parent dirID for BumpDate call */
984
 
            parID = pb.hFileInfo.ioFlParID;
985
 
 
986
 
            /* If creator not 0x00000000, change creator */
987
 
            if ( creator != (OSType)0x00000000 )
988
 
            {
989
 
                pb.hFileInfo.ioFlFndrInfo.fdCreator = creator;
990
 
            }
991
 
 
992
 
            /* If fileType not 0x00000000, change fileType */
993
 
            if ( fileType != (OSType)0x00000000 )
994
 
            {
995
 
                pb.hFileInfo.ioFlFndrInfo.fdType = fileType;
996
 
            }
997
 
 
998
 
            pb.hFileInfo.ioDirID = dirID;
999
 
            error = PBSetCatInfoSync(&pb);  /* now, save the new information
1000
 
                                               back to disk */
1001
 
 
1002
 
            if ( (error == noErr) && (parID != fsRtParID) ) /* can't
1003
 
                                                            bump fsRtParID */
1004
 
            {
1005
 
                /* get the real vRefNum in case a full pathname was passed */
1006
 
                error = DetermineVRefNum(name, vRefNum, &realVRefNum);
1007
 
                if ( error == noErr )
1008
 
                {
1009
 
                    error = BumpDate(realVRefNum, parID, NULL);
1010
 
                        /* and bump the parent directory's mod date to wake
1011
 
                           up the Finder */
1012
 
                        /* to the change we just made */
1013
 
                }
1014
 
            }
1015
 
        }
1016
 
        else
1017
 
        {
1018
 
            /* it was a directory, not a file */
1019
 
            error = notAFileErr;
1020
 
        }
1021
 
    }
1022
 
 
1023
 
    return ( error );
1024
 
}
1025
 
 
1026
 
/*****************************************************************************/
1027
 
 
1028
 
pascal  OSErr   FSpChangeCreatorType(const FSSpec *spec,
1029
 
                                     OSType creator,
1030
 
                                     OSType fileType)
1031
 
{
1032
 
    return ( ChangeCreatorType(spec->vRefNum, spec->parID, spec->name,
1033
 
             creator, fileType) );
1034
 
}
1035
 
 
1036
 
/*****************************************************************************/
1037
 
 
1038
 
pascal  OSErr   BumpDate(short vRefNum,
1039
 
                         long dirID,
1040
 
                         ConstStr255Param name)
1041
 
/* Given a file or directory, change its modification date to the
1042
 
   current date/time. */
1043
 
{
1044
 
    CInfoPBRec pb;
1045
 
    Str31 tempName;
1046
 
    OSErr error;
1047
 
    unsigned long secs;
1048
 
 
1049
 
    /* Protection against File Sharing problem */
1050
 
    if ( (name == NULL) || (name[0] == 0) )
1051
 
    {
1052
 
        tempName[0] = 0;
1053
 
        pb.hFileInfo.ioNamePtr = tempName;
1054
 
        pb.hFileInfo.ioFDirIndex = -1;  /* use ioDirID */
1055
 
    }
1056
 
    else
1057
 
    {
1058
 
        pb.hFileInfo.ioNamePtr = (StringPtr)name;
1059
 
        pb.hFileInfo.ioFDirIndex = 0;   /* use ioNamePtr and ioDirID */
1060
 
    }
1061
 
    pb.hFileInfo.ioVRefNum = vRefNum;
1062
 
    pb.hFileInfo.ioDirID = dirID;
1063
 
    error = PBGetCatInfoSync(&pb);
1064
 
    if ( error == noErr )
1065
 
    {
1066
 
        GetDateTime(&secs);
1067
 
        /* set mod date to current date, or one second into the future
1068
 
            if mod date = current date */
1069
 
        pb.hFileInfo.ioFlMdDat =
1070
 
                          (secs == pb.hFileInfo.ioFlMdDat) ? (++secs) : (secs);
1071
 
        if ( pb.dirInfo.ioNamePtr == tempName )
1072
 
        {
1073
 
            pb.hFileInfo.ioDirID = pb.hFileInfo.ioFlParID;
1074
 
        }
1075
 
        else
1076
 
        {
1077
 
            pb.hFileInfo.ioDirID = dirID;
1078
 
        }
1079
 
        error = PBSetCatInfoSync(&pb);
1080
 
    }
1081
 
 
1082
 
    return ( error );
1083
 
}
1084
 
 
1085
 
/*****************************************************************************/
1086
 
 
1087
 
pascal  OSErr   FSpBumpDate(const FSSpec *spec)
1088
 
{
1089
 
    return ( BumpDate(spec->vRefNum, spec->parID, spec->name) );
1090
 
}
1091
 
 
1092
 
 
1093
 
/*****************************************************************************/
1094
 
 
1095
 
pascal  OSErr   OnLine(FSSpecPtr volumes,
1096
 
                       short reqVolCount,
1097
 
                       short *actVolCount,
1098
 
                       short *volIndex)
1099
 
{
1100
 
    HParamBlockRec pb;
1101
 
    OSErr error = noErr;
1102
 
    FSSpec *endVolArray;
1103
 
 
1104
 
    if ( *volIndex > 0 )
1105
 
    {
1106
 
        *actVolCount = 0;
1107
 
        for ( endVolArray = volumes + reqVolCount;
1108
 
              (volumes < endVolArray) && (error == noErr); ++volumes )
1109
 
        {
1110
 
            pb.volumeParam.ioNamePtr = (StringPtr) & volumes->name;
1111
 
            pb.volumeParam.ioVolIndex = *volIndex;
1112
 
            error = PBHGetVInfoSync(&pb);
1113
 
            if ( error == noErr )
1114
 
            {
1115
 
                volumes->parID = fsRtParID;     /* the root directory's
1116
 
                                                   parent is 1 */
1117
 
                volumes->vRefNum = pb.volumeParam.ioVRefNum;
1118
 
                ++*volIndex;
1119
 
                ++*actVolCount;
1120
 
            }
1121
 
        }
1122
 
    }
1123
 
    else
1124
 
    {
1125
 
        error = paramErr;
1126
 
    }
1127
 
 
1128
 
    return ( error );
1129
 
}
1130
 
 
1131
 
 
1132
 
/*****************************************************************************/
1133
 
 
1134
 
pascal  OSErr   DTGetComment(short vRefNum,
1135
 
                             long dirID,
1136
 
                             ConstStr255Param name,
1137
 
                             Str255 comment)
1138
 
{
1139
 
    DTPBRec pb;
1140
 
    OSErr error;
1141
 
    short dtRefNum;
1142
 
    Boolean newDTDatabase;
1143
 
 
1144
 
    if (comment != NULL)
1145
 
    {
1146
 
        comment[0] = 0; /* return nothing by default */
1147
 
 
1148
 
        /* attempt to open the desktop database */
1149
 
        error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);
1150
 
        if ( error == noErr )
1151
 
        {
1152
 
            /* There was a desktop database and it's now open */
1153
 
 
1154
 
            if ( !newDTDatabase )
1155
 
            {
1156
 
                pb.ioDTRefNum = dtRefNum;
1157
 
                pb.ioNamePtr = (StringPtr)name;
1158
 
                pb.ioDirID = dirID;
1159
 
                pb.ioDTBuffer = (Ptr)&comment[1];
1160
 
                /*
1161
 
                **  IMPORTANT NOTE #1: Inside Macintosh says that comments
1162
 
                **  are up to 200 characters. While that may be correct for
1163
 
                **  the HFS file system's Desktop Manager, other file
1164
 
                **  systems (such as Apple Photo Access) return up to
1165
 
                **  255 characters. Make sure the comment buffer is a Str255
1166
 
                **  or you'll regret it.
1167
 
                **
1168
 
                **  IMPORTANT NOTE #2: Although Inside Macintosh doesn't
1169
 
                **  mention it, ioDTReqCount is a input field to
1170
 
                **  PBDTGetCommentSync. Some file systems (like HFS) ignore
1171
 
                **  ioDTReqCount and always return the full comment --
1172
 
                **  others (like AppleShare) respect ioDTReqCount and only
1173
 
                **  return up to ioDTReqCount characters of the comment.
1174
 
                */
1175
 
                pb.ioDTReqCount = sizeof(Str255) - 1;
1176
 
                error = PBDTGetCommentSync(&pb);
1177
 
                if (error == noErr)
1178
 
                {
1179
 
                    comment[0] = (unsigned char)pb.ioDTActCount;
1180
 
                }
1181
 
            }
1182
 
        }
1183
 
        else
1184
 
        {
1185
 
            /* There is no desktop database - try the Desktop file */
1186
 
            error = GetCommentFromDesktopFile(vRefNum, dirID, name, comment);
1187
 
            if ( error != noErr )
1188
 
            {
1189
 
                error = afpItemNotFound;    /* return an expected error */
1190
 
            }
1191
 
        }
1192
 
    }
1193
 
    else
1194
 
    {
1195
 
        error = paramErr;
1196
 
    }
1197
 
 
1198
 
    return (error);
1199
 
}
1200
 
 
1201
 
/*****************************************************************************/
1202
 
 
1203
 
pascal  OSErr   FSpDTGetComment(const FSSpec *spec,
1204
 
                              Str255 comment)
1205
 
{
1206
 
    return (DTGetComment(spec->vRefNum, spec->parID, spec->name, comment));
1207
 
}
1208
 
 
1209
 
 
1210
 
/*****************************************************************************/
1211
 
 
1212
 
pascal  OSErr   DTSetComment(short vRefNum,
1213
 
                             long dirID,
1214
 
                             ConstStr255Param name,
1215
 
                             ConstStr255Param comment)
1216
 
{
1217
 
    DTPBRec pb;
1218
 
    OSErr error;
1219
 
    short dtRefNum;
1220
 
    Boolean newDTDatabase;
1221
 
 
1222
 
    error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);
1223
 
    if ( error == noErr )
1224
 
    {
1225
 
        pb.ioDTRefNum = dtRefNum;
1226
 
        pb.ioNamePtr = (StringPtr)name;
1227
 
        pb.ioDirID = dirID;
1228
 
        pb.ioDTBuffer = (Ptr)&comment[1];
1229
 
        /* Truncate the comment to 200 characters just in case */
1230
 
        /* some file system doesn't range check */
1231
 
        if ( comment[0] <= 200 )
1232
 
        {
1233
 
            pb.ioDTReqCount = comment[0];
1234
 
        }
1235
 
        else
1236
 
        {
1237
 
            pb.ioDTReqCount = 200;
1238
 
        }
1239
 
        error = PBDTSetCommentSync(&pb);
1240
 
    }
1241
 
    return (error);
1242
 
}
1243
 
 
1244
 
/*****************************************************************************/
1245
 
 
1246
 
pascal  OSErr   FSpDTSetComment(const FSSpec *spec,
1247
 
                              ConstStr255Param comment)
1248
 
{
1249
 
    return (DTSetComment(spec->vRefNum, spec->parID, spec->name, comment));
1250
 
}
1251
 
 
1252
 
 
1253
 
/*****************************************************************************/
1254
 
 
1255
 
pascal  OSErr   DTOpen(ConstStr255Param volName,
1256
 
                       short vRefNum,
1257
 
                       short *dtRefNum,
1258
 
                       Boolean *newDTDatabase)
1259
 
{
1260
 
    OSErr error;
1261
 
    GetVolParmsInfoBuffer volParmsInfo;
1262
 
    long infoSize;
1263
 
    DTPBRec pb;
1264
 
 
1265
 
    /* Check for volume Desktop Manager support before calling */
1266
 
    infoSize = sizeof(GetVolParmsInfoBuffer);
1267
 
    error = HGetVolParms(volName, vRefNum, &volParmsInfo, &infoSize);
1268
 
    if ( error == noErr )
1269
 
    {
1270
 
        if ( hasDesktopMgr(volParmsInfo) )
1271
 
        {
1272
 
            pb.ioNamePtr = (StringPtr)volName;
1273
 
            pb.ioVRefNum = vRefNum;
1274
 
            error = PBDTOpenInform(&pb);
1275
 
            /* PBDTOpenInform informs us if the desktop was just created */
1276
 
            /* by leaving the low bit of ioTagInfo clear (0) */
1277
 
            *newDTDatabase = ((pb.ioTagInfo & 1L) == 0);
1278
 
            if ( error == paramErr )
1279
 
            {
1280
 
                error = PBDTGetPath(&pb);
1281
 
                /* PBDTGetPath doesn't tell us if the database is new */
1282
 
                /* so assume it is not new */
1283
 
                *newDTDatabase = false;
1284
 
            }
1285
 
            *dtRefNum = pb.ioDTRefNum;
1286
 
        }
1287
 
        else
1288
 
        {
1289
 
            error = paramErr;
1290
 
        }
1291
 
    }
1292
 
    return ( error );
1293
 
}
1294
 
 
1295
 
/*****************************************************************************/
1296
 
 
1297
 
/*
1298
 
**  GetCommentFromDesktopFile
1299
 
**
1300
 
**  Get a file or directory's Finder comment field (if any) from the
1301
 
**  Desktop file's 'FCMT' resources.
1302
 
*/
1303
 
static  OSErr   GetCommentFromDesktopFile(short vRefNum,
1304
 
                                          long dirID,
1305
 
                                          ConstStr255Param name,
1306
 
                                          Str255 comment)
1307
 
{
1308
 
    OSErr error;
1309
 
    short commentID;
1310
 
    short realVRefNum;
1311
 
    Str255 desktopName;
1312
 
    short savedResFile;
1313
 
    short dfRefNum;
1314
 
    StringHandle commentHandle;
1315
 
 
1316
 
    /* Get the comment ID number */
1317
 
    error = GetCommentID(vRefNum, dirID, name, &commentID);
1318
 
    if ( error == noErr )
1319
 
    {
1320
 
        if ( commentID != 0 )   /* commentID == 0 means there's no comment */
1321
 
        {
1322
 
            error = DetermineVRefNum(name, vRefNum, &realVRefNum);
1323
 
            if ( error == noErr )
1324
 
            {
1325
 
                error = GetDesktopFileName(realVRefNum, desktopName);
1326
 
                if ( error == noErr )
1327
 
                {
1328
 
                    savedResFile = CurResFile();
1329
 
                    /*
1330
 
                    **  Open the 'Desktop' file in the root directory. (because
1331
 
                    **  opening the resource file could preload unwanted resources,
1332
 
                    **  bracket the call with SetResLoad(s))
1333
 
                    */
1334
 
                    SetResLoad(false);
1335
 
                    dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName,
1336
 
                                            fsRdPerm);
1337
 
                    SetResLoad(true);
1338
 
 
1339
 
                    if ( dfRefNum != -1)
1340
 
                    {
1341
 
                        /* Get the comment resource */
1342
 
                        commentHandle = (StringHandle)Get1Resource(kFCMTResType,
1343
 
                                                                   commentID);
1344
 
                        if ( commentHandle != NULL )
1345
 
                        {
1346
 
                            if ( InlineGetHandleSize((Handle)commentHandle) > 0 )
1347
 
                            {
1348
 
                                BlockMoveData(*commentHandle, comment,
1349
 
                                              *commentHandle[0] + 1);
1350
 
                            }
1351
 
                            else
1352
 
                            {                       /* no comment available */
1353
 
                                error = afpItemNotFound;
1354
 
                            }
1355
 
                        }
1356
 
                        else
1357
 
                        {                           /* no comment available */
1358
 
                            error = afpItemNotFound;
1359
 
                        }
1360
 
 
1361
 
                        /* restore the resource chain and close
1362
 
                           the Desktop file */
1363
 
                        UseResFile(savedResFile);
1364
 
                        CloseResFile(dfRefNum);
1365
 
                    }
1366
 
                    else
1367
 
                    {
1368
 
                        error = afpItemNotFound;
1369
 
                    }
1370
 
                }
1371
 
                else
1372
 
                {
1373
 
                    error = afpItemNotFound;
1374
 
                }
1375
 
            }
1376
 
        }
1377
 
        else
1378
 
        {
1379
 
            error = afpItemNotFound;    /* no comment available */
1380
 
        }
1381
 
    }
1382
 
 
1383
 
    return ( error );
1384
 
}
1385
 
 
1386
 
/*****************************************************************************/
1387
 
 
1388
 
pascal  OSErr   HGetVolParms(ConstStr255Param volName,
1389
 
                             short vRefNum,
1390
 
                             GetVolParmsInfoBuffer *volParmsInfo,
1391
 
                             long *infoSize)
1392
 
{
1393
 
    HParamBlockRec pb;
1394
 
    OSErr error;
1395
 
 
1396
 
    pb.ioParam.ioNamePtr = (StringPtr)volName;
1397
 
    pb.ioParam.ioVRefNum = vRefNum;
1398
 
    pb.ioParam.ioBuffer = (Ptr)volParmsInfo;
1399
 
    pb.ioParam.ioReqCount = *infoSize;
1400
 
    error = PBHGetVolParmsSync(&pb);
1401
 
    if ( error == noErr )
1402
 
    {
1403
 
        *infoSize = pb.ioParam.ioActCount;
1404
 
    }
1405
 
    return ( error );
1406
 
}
1407
 
 
1408
 
/*****************************************************************************/
1409
 
/*
1410
 
**  GetCommentID
1411
 
**
1412
 
**  Get the comment ID number for the Desktop file's 'FCMT' resource ID from
1413
 
**  the file or folders fdComment (frComment) field.
1414
 
*/
1415
 
static  OSErr   GetCommentID(short vRefNum,
1416
 
                             long dirID,
1417
 
                             ConstStr255Param name,
1418
 
                             short *commentID)
1419
 
{
1420
 
    CInfoPBRec pb;
1421
 
    OSErr error;
1422
 
 
1423
 
    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
1424
 
    *commentID = pb.hFileInfo.ioFlXFndrInfo.fdComment;
1425
 
    return ( error );
1426
 
}
1427
 
 
1428
 
/*****************************************************************************/
1429
 
 
1430
 
/*
1431
 
**  GetDesktopFileName
1432
 
**
1433
 
**  Get the name of the Desktop file.
1434
 
*/
1435
 
static  OSErr   GetDesktopFileName(short vRefNum,
1436
 
                                   Str255 desktopName)
1437
 
{
1438
 
    OSErr           error;
1439
 
    HParamBlockRec  pb;
1440
 
    short           index;
1441
 
    Boolean         found;
1442
 
 
1443
 
    pb.fileParam.ioNamePtr = desktopName;
1444
 
    pb.fileParam.ioVRefNum = vRefNum;
1445
 
    pb.fileParam.ioFVersNum = 0;
1446
 
    index = 1;
1447
 
    found = false;
1448
 
    do
1449
 
    {
1450
 
        pb.fileParam.ioDirID = fsRtDirID;
1451
 
        pb.fileParam.ioFDirIndex = index;
1452
 
        error = PBHGetFInfoSync(&pb);
1453
 
        if ( error == noErr )
1454
 
        {
1455
 
            if ( (pb.fileParam.ioFlFndrInfo.fdType == 'FNDR') &&
1456
 
                 (pb.fileParam.ioFlFndrInfo.fdCreator == 'ERIK') )
1457
 
            {
1458
 
                found = true;
1459
 
            }
1460
 
        }
1461
 
        ++index;
1462
 
    } while ( (error == noErr) && !found );
1463
 
 
1464
 
    return ( error );
1465
 
}
1466
 
 
1467
 
 
1468
 
/*****************************************************************************/
1469
 
 
1470
 
pascal  OSErr   XGetVInfo(short volReference,
1471
 
                          StringPtr volName,
1472
 
                          short *vRefNum,
1473
 
                          UnsignedWide *freeBytes,
1474
 
                          UnsignedWide *totalBytes)
1475
 
{
1476
 
    OSErr           result;
1477
 
    long            response;
1478
 
    XVolumeParam    pb;
1479
 
 
1480
 
    /* See if large volume support is available */
1481
 
    if ( ( Gestalt(gestaltFSAttr, &response) == noErr ) && ((response & (1L << gestaltFSSupports2TBVols)) != 0) )
1482
 
    {
1483
 
        /* Large volume support is available */
1484
 
        pb.ioVRefNum = volReference;
1485
 
        pb.ioNamePtr = volName;
1486
 
        pb.ioXVersion = 0;  /* this XVolumeParam version (0) */
1487
 
        pb.ioVolIndex = 0;  /* use ioVRefNum only, return volume name */
1488
 
        result = PBXGetVolInfoSync(&pb);
1489
 
        if ( result == noErr )
1490
 
        {
1491
 
            /* The volume name was returned in volName (if not NULL) and */
1492
 
            /* we have the volume's vRefNum and allocation block size */
1493
 
            *vRefNum = pb.ioVRefNum;
1494
 
 
1495
 
            /* return the freeBytes and totalBytes */
1496
 
            *totalBytes = pb.ioVTotalBytes;
1497
 
            *freeBytes = pb.ioVFreeBytes;
1498
 
        }
1499
 
    }
1500
 
    else
1501
 
    {
1502
 
        /* No large volume support */
1503
 
 
1504
 
        /* Use HGetVInfo to get the results */
1505
 
        result = HGetVInfo(volReference, volName, vRefNum, &freeBytes->lo, &totalBytes->lo);
1506
 
        if ( result == noErr )
1507
 
        {
1508
 
            /* zero the high longs of totalBytes and freeBytes */
1509
 
            totalBytes->hi = 0;
1510
 
            freeBytes->hi = 0;
1511
 
        }
1512
 
    }
1513
 
    return ( result );
1514
 
}
1515
 
 
1516
 
 
1517
 
 
1518
 
/*****************************************************************************/
1519
 
 
1520
 
pascal  OSErr   HGetVInfo(short volReference,
1521
 
                          StringPtr volName,
1522
 
                          short *vRefNum,
1523
 
                          unsigned long *freeBytes,
1524
 
                          unsigned long *totalBytes)
1525
 
{
1526
 
    HParamBlockRec  pb;
1527
 
    unsigned long   allocationBlockSize;
1528
 
    unsigned short  numAllocationBlocks;
1529
 
    unsigned short  numFreeBlocks;
1530
 
    VCB             *theVCB;
1531
 
    Boolean         vcbFound;
1532
 
    OSErr           result;
1533
 
 
1534
 
    /* Use the File Manager to get the real vRefNum */
1535
 
    pb.volumeParam.ioVRefNum = volReference;
1536
 
    pb.volumeParam.ioNamePtr = volName;
1537
 
    pb.volumeParam.ioVolIndex = 0;  /* use ioVRefNum only, return volume name */
1538
 
    result = PBHGetVInfoSync(&pb);
1539
 
 
1540
 
    if ( result == noErr )
1541
 
    {
1542
 
        /* The volume name was returned in volName (if not NULL) and */
1543
 
        /* we have the volume's vRefNum and allocation block size */
1544
 
        *vRefNum = pb.volumeParam.ioVRefNum;
1545
 
        allocationBlockSize = (unsigned long)pb.volumeParam.ioVAlBlkSiz;
1546
 
 
1547
 
        /* System 7.5 (and beyond) pins the number of allocation blocks and */
1548
 
        /* the number of free allocation blocks returned by PBHGetVInfo to */
1549
 
        /* a value so that when multiplied by the allocation block size, */
1550
 
        /* the volume will look like it has $7fffffff bytes or less. This */
1551
 
        /* was done so older applications that use signed math or that use */
1552
 
        /* the GetVInfo function (which uses signed math) will continue to work. */
1553
 
        /* However, the unpinned numbers (which we want) are always available */
1554
 
        /* in the volume's VCB so we'll get those values from the VCB if possible. */
1555
 
 
1556
 
        /* Find the volume's VCB */
1557
 
        vcbFound = false;
1558
 
        theVCB = (VCB *)(GetVCBQHdr()->qHead);
1559
 
        while ( (theVCB != NULL) && !vcbFound )
1560
 
        {
1561
 
            /* Check VCB signature before using VCB. Don't have to check for */
1562
 
            /* MFS (0xd2d7) because they can't get big enough to be pinned */
1563
 
            if ( theVCB->vcbSigWord == 0x4244 )
1564
 
            {
1565
 
                if ( theVCB->vcbVRefNum == *vRefNum )
1566
 
                {
1567
 
                    vcbFound = true;
1568
 
                }
1569
 
            }
1570
 
 
1571
 
            if ( !vcbFound )
1572
 
            {
1573
 
                theVCB = (VCB *)(theVCB->qLink);
1574
 
            }
1575
 
        }
1576
 
 
1577
 
        if ( theVCB != NULL )
1578
 
        {
1579
 
            /* Found a VCB we can use. Get the un-pinned number of allocation blocks */
1580
 
            /* and the number of free blocks from the VCB. */
1581
 
            numAllocationBlocks = (unsigned short)theVCB->vcbNmAlBlks;
1582
 
            numFreeBlocks = (unsigned short)theVCB->vcbFreeBks;
1583
 
        }
1584
 
        else
1585
 
        {
1586
 
            /* Didn't find a VCB we can use. Return the number of allocation blocks */
1587
 
            /* and the number of free blocks returned by PBHGetVInfoSync. */
1588
 
            numAllocationBlocks = (unsigned short)pb.volumeParam.ioVNmAlBlks;
1589
 
            numFreeBlocks = (unsigned short)pb.volumeParam.ioVFrBlk;
1590
 
        }
1591
 
 
1592
 
        /* Now, calculate freeBytes and totalBytes using unsigned values */
1593
 
        *freeBytes = numFreeBlocks * allocationBlockSize;
1594
 
        *totalBytes = numAllocationBlocks * allocationBlockSize;
1595
 
    }
1596
 
 
1597
 
    return ( result );
1598
 
}
1599
 
 
1600
 
 
1601
 
/*
1602
 
**  PBXGetVolInfoSync is the glue code needed to make PBXGetVolInfoSync
1603
 
**  File Manager requests from CFM-based programs. At some point, Apple
1604
 
**  will get around to adding this to the standard libraries you link with
1605
 
**  and you'll get a duplicate symbol link error. At that time, just delete
1606
 
**  this code (or comment it out).
1607
 
**
1608
 
**  Non-CFM 68K programs don't needs this glue (and won't get it) because
1609
 
**  they instead use the inline assembly glue found in the Files.h interface
1610
 
**  file.
1611
 
*/
1612
 
 
1613
 
#if __WANTPASCALELIMINATION
1614
 
#undef  pascal
1615
 
#endif
1616
 
 
1617
 
#if GENERATINGCFM
1618
 
pascal OSErr PBXGetVolInfoSync(XVolumeParamPtr paramBlock)
1619
 
{
1620
 
    enum
1621
 
    {
1622
 
        kXGetVolInfoSelector = 0x0012,  /* Selector for XGetVolInfo */
1623
 
 
1624
 
        uppFSDispatchProcInfo = kRegisterBased
1625
 
             | REGISTER_RESULT_LOCATION(kRegisterD0)
1626
 
             | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
1627
 
             | REGISTER_ROUTINE_PARAMETER(1, kRegisterD1, SIZE_CODE(sizeof(long)))  /* trap word */
1628
 
             | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0, SIZE_CODE(sizeof(long)))  /* selector */
1629
 
             | REGISTER_ROUTINE_PARAMETER(3, kRegisterA0, SIZE_CODE(sizeof(XVolumeParamPtr)))
1630
 
    };
1631
 
 
1632
 
    return ( CallOSTrapUniversalProc(NGetTrapAddress(_FSDispatch, OSTrap),
1633
 
                                        uppFSDispatchProcInfo,
1634
 
                                        _FSDispatch,
1635
 
                                        kXGetVolInfoSelector,
1636
 
                                        paramBlock) );
1637
 
}
1638
 
#endif
1639
 
 
1640
 
#if __WANTPASCALELIMINATION
1641
 
#define pascal
1642
 
#endif
1643
 
 
1644
 
/*****************************************************************************/
1645
 
 
1646
 
pascal  OSErr   GetDirName(short vRefNum,
1647
 
                           long dirID,
1648
 
                           Str31 name)
1649
 
{
1650
 
    CInfoPBRec pb;
1651
 
    OSErr error;
1652
 
 
1653
 
    if ( name != NULL )
1654
 
    {
1655
 
        pb.dirInfo.ioNamePtr = name;
1656
 
        pb.dirInfo.ioVRefNum = vRefNum;
1657
 
        pb.dirInfo.ioDrDirID = dirID;
1658
 
        pb.dirInfo.ioFDirIndex = -1;    /* get information about ioDirID */
1659
 
        error = PBGetCatInfoSync(&pb);
1660
 
    }
1661
 
    else
1662
 
    {
1663
 
        error = paramErr;
1664
 
    }
1665
 
 
1666
 
    return ( error );
1667
 
}
1668
 
 
1669
 
 
1670
 
/*****************************************************************************/
1671
 
 
1672
 
pascal  OSErr   GetVolFileSystemID(ConstStr255Param pathname,
1673
 
                                   short vRefNum,
1674
 
                                   short *fileSystemID)
1675
 
{
1676
 
    HParamBlockRec pb;
1677
 
    OSErr error;
1678
 
 
1679
 
    error = GetVolumeInfoNoName(pathname,vRefNum, &pb);
1680
 
    if ( error == noErr )
1681
 
    {
1682
 
        *fileSystemID = pb.volumeParam.ioVFSID;
1683
 
    }
1684
 
 
1685
 
    return ( error );
1686
 
}
1687
 
 
1688
 
/*****************************************************************************/
1689
 
 
1690
 
pascal  OSErr GetDInfo(short vRefNum,
1691
 
                       long dirID,
1692
 
                       ConstStr255Param name,
1693
 
                       DInfo *fndrInfo)
1694
 
{
1695
 
    CInfoPBRec pb;
1696
 
    OSErr error;
1697
 
 
1698
 
    error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
1699
 
    if ( error == noErr )
1700
 
    {
1701
 
        if ( (pb.dirInfo.ioFlAttrib & ioDirMask) != 0 )
1702
 
        {
1703
 
            /* it's a directory, return the DInfo */
1704
 
            *fndrInfo = pb.dirInfo.ioDrUsrWds;
1705
 
        }
1706
 
        else
1707
 
        {
1708
 
            /* oops, a file was passed */
1709
 
            error = dirNFErr;
1710
 
        }
1711
 
    }
1712
 
 
1713
 
    return ( error );
1714
 
}
1715
 
 
1716
 
/*****************************************************************************/
1717
 
 
1718
 
pascal  OSErr FSpGetDInfo(const FSSpec *spec,
1719
 
                          DInfo *fndrInfo)
1720
 
{
1721
 
    return ( GetDInfo(spec->vRefNum, spec->parID, spec->name, fndrInfo) );
1722
 
}
1723
 
 
1724
 
 
1725
 
 
1726
 
const char *BOINC_RCSID_fc2d06db64 = "$Id: macstuff.c 4979 2005-01-02 18:29:53Z ballen $";