OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [mac/] [tclMacFile.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tclMacFile.c --
3
 *
4
 *      This file implements the channel drivers for Macintosh
5
 *      files.  It also comtains Macintosh version of other Tcl
6
 *      functions that deal with the file system.
7
 *
8
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tclMacFile.c,v 1.1.1.1 2002-01-16 10:25:30 markom Exp $
14
 */
15
 
16
/*
17
 * Note: This code eventually needs to support async I/O.  In doing this
18
 * we will need to keep track of all current async I/O.  If exit to shell
19
 * is called - we shouldn't exit until all asyc I/O completes.
20
 */
21
 
22
#include "tclInt.h"
23
#include "tclPort.h"
24
#include "tclMacInt.h"
25
#include <Aliases.h>
26
#include <Errors.h>
27
#include <Processes.h>
28
#include <Strings.h>
29
#include <Types.h>
30
#include <MoreFiles.h>
31
#include <MoreFilesExtras.h>
32
#include <FSpCompat.h>
33
 
34
/*
35
 * Static variables used by the TclpStat function.
36
 */
37
static int initalized = false;
38
static long gmt_offset;
39
 
40
/*
41
 * The variable below caches the name of the current working directory
42
 * in order to avoid repeated calls to getcwd.  The string is malloc-ed.
43
 * NULL means the cache needs to be refreshed.
44
 */
45
 
46
static char *currentDir =  NULL;
47
 
48
/*
49
 *----------------------------------------------------------------------
50
 *
51
 * TclChdir --
52
 *
53
 *      Change the current working directory.
54
 *
55
 * Results:
56
 *      The result is a standard Tcl result.  If an error occurs and
57
 *      interp isn't NULL, an error message is left in interp->result.
58
 *
59
 * Side effects:
60
 *      The working directory for this application is changed.  Also
61
 *      the cache maintained used by TclGetCwd is deallocated and
62
 *      set to NULL.
63
 *
64
 *----------------------------------------------------------------------
65
 */
66
 
67
int
68
TclChdir(
69
    Tcl_Interp *interp,         /* If non NULL, used for error reporting. */
70
    char *dirName)              /* Path to new working directory. */
71
{
72
    FSSpec spec;
73
    OSErr err;
74
    Boolean isFolder;
75
    long dirID;
76
 
77
    if (currentDir != NULL) {
78
        ckfree(currentDir);
79
        currentDir = NULL;
80
    }
81
 
82
    err = FSpLocationFromPath(strlen(dirName), dirName, &spec);
83
    if (err != noErr) {
84
        errno = ENOENT;
85
        goto chdirError;
86
    }
87
 
88
    err = FSpGetDirectoryID(&spec, &dirID, &isFolder);
89
    if (err != noErr) {
90
        errno = ENOENT;
91
        goto chdirError;
92
    }
93
 
94
    if (isFolder != true) {
95
        errno = ENOTDIR;
96
        goto chdirError;
97
    }
98
 
99
    err = FSpSetDefaultDir(&spec);
100
    if (err != noErr) {
101
        switch (err) {
102
            case afpAccessDenied:
103
                errno = EACCES;
104
                break;
105
            default:
106
                errno = ENOENT;
107
        }
108
        goto chdirError;
109
    }
110
 
111
    return TCL_OK;
112
    chdirError:
113
    if (interp != NULL) {
114
        Tcl_AppendResult(interp, "couldn't change working directory to \"",
115
                dirName, "\": ", Tcl_PosixError(interp), (char *) NULL);
116
    }
117
    return TCL_ERROR;
118
}
119
 
120
/*
121
 *----------------------------------------------------------------------
122
 *
123
 * TclGetCwd --
124
 *
125
 *      Return the path name of the current working directory.
126
 *
127
 * Results:
128
 *      The result is the full path name of the current working
129
 *      directory, or NULL if an error occurred while figuring it
130
 *      out.  If an error occurs and interp isn't NULL, an error
131
 *      message is left in interp->result.
132
 *
133
 * Side effects:
134
 *      The path name is cached to avoid having to recompute it
135
 *      on future calls;  if it is already cached, the cached
136
 *      value is returned.
137
 *
138
 *----------------------------------------------------------------------
139
 */
140
 
141
char *
142
TclGetCwd(
143
    Tcl_Interp *interp)         /* If non NULL, used for error reporting. */
144
{
145
    FSSpec theSpec;
146
    int length;
147
    Handle pathHandle = NULL;
148
 
149
    if (currentDir == NULL) {
150
        if (FSpGetDefaultDir(&theSpec) != noErr) {
151
            if (interp != NULL) {
152
                interp->result = "error getting working directory name";
153
            }
154
            return NULL;
155
        }
156
        if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) {
157
            if (interp != NULL) {
158
                interp->result = "error getting working directory name";
159
            }
160
            return NULL;
161
        }
162
        HLock(pathHandle);
163
        currentDir = (char *) ckalloc((unsigned) (length + 1));
164
        strcpy(currentDir, *pathHandle);
165
        HUnlock(pathHandle);
166
        DisposeHandle(pathHandle);
167
    }
168
    return currentDir;
169
}
170
 
171
/*
172
 *----------------------------------------------------------------------
173
 *
174
 * Tcl_WaitPid --
175
 *
176
 *      Fakes a call to wait pid.
177
 *
178
 * Results:
179
 *      Always returns -1.
180
 *
181
 * Side effects:
182
 *      None.
183
 *
184
 *----------------------------------------------------------------------
185
 */
186
 
187
Tcl_Pid
188
Tcl_WaitPid(
189
    Tcl_Pid pid,
190
    int *statPtr,
191
    int options)
192
{
193
    return (Tcl_Pid) -1;
194
}
195
 
196
/*
197
 *----------------------------------------------------------------------
198
 *
199
 * Tcl_FindExecutable --
200
 *
201
 *      This procedure computes the absolute path name of the current
202
 *      application, given its argv[0] value.  However, this
203
 *      implementation doesn't use of need the argv[0] value.  NULL
204
 *      may be passed in its place.
205
 *
206
 * Results:
207
 *      None.
208
 *
209
 * Side effects:
210
 *      The variable tclExecutableName gets filled in with the file
211
 *      name for the application, if we figured it out.  If we couldn't
212
 *      figure it out, Tcl_FindExecutable is set to NULL.
213
 *
214
 *----------------------------------------------------------------------
215
 */
216
 
217
void
218
Tcl_FindExecutable(
219
    char *argv0)                /* The value of the application's argv[0]. */
220
{
221
    ProcessSerialNumber psn;
222
    ProcessInfoRec info;
223
    Str63 appName;
224
    FSSpec fileSpec;
225
    int pathLength;
226
    Handle pathName = NULL;
227
    OSErr err;
228
 
229
    GetCurrentProcess(&psn);
230
    info.processInfoLength = sizeof(ProcessInfoRec);
231
    info.processName = appName;
232
    info.processAppSpec = &fileSpec;
233
    GetProcessInformation(&psn, &info);
234
 
235
    if (tclExecutableName != NULL) {
236
        ckfree(tclExecutableName);
237
        tclExecutableName = NULL;
238
    }
239
 
240
    err = FSpPathFromLocation(&fileSpec, &pathLength, &pathName);
241
 
242
    tclExecutableName = (char *) ckalloc((unsigned) pathLength + 1);
243
    HLock(pathName);
244
    strcpy(tclExecutableName, *pathName);
245
    HUnlock(pathName);
246
    DisposeHandle(pathName);
247
}
248
 
249
/*
250
 *----------------------------------------------------------------------
251
 *
252
 * TclGetUserHome --
253
 *
254
 *      This function takes the passed in user name and finds the
255
 *      corresponding home directory specified in the password file.
256
 *
257
 * Results:
258
 *      On a Macintosh we always return a NULL.
259
 *
260
 * Side effects:
261
 *      None.
262
 *
263
 *----------------------------------------------------------------------
264
 */
265
 
266
char *
267
TclGetUserHome(
268
    char *name,                 /* User name to use to find home directory. */
269
    Tcl_DString *bufferPtr)     /* May be used to hold result.  Must not hold
270
                                 * anything at the time of the call, and need
271
                                 * not even be initialized. */
272
{
273
    return NULL;
274
}
275
 
276
/*
277
 *----------------------------------------------------------------------
278
 *
279
 * TclMatchFiles --
280
 *
281
 *      This routine is used by the globbing code to search a
282
 *      directory for all files which match a given pattern.
283
 *
284
 * Results:
285
 *      If the tail argument is NULL, then the matching files are
286
 *      added to the interp->result.  Otherwise, TclDoGlob is called
287
 *      recursively for each matching subdirectory.  The return value
288
 *      is a standard Tcl result indicating whether an error occurred
289
 *      in globbing.
290
 *
291
 * Side effects:
292
 *      None.
293
 *
294
 *---------------------------------------------------------------------- */
295
 
296
int
297
TclMatchFiles(
298
    Tcl_Interp *interp,         /* Interpreter to receive results. */
299
    char *separators,           /* Directory separators to pass to TclDoGlob. */
300
    Tcl_DString *dirPtr,        /* Contains path to directory to search. */
301
    char *pattern,              /* Pattern to match against. */
302
    char *tail)                 /* Pointer to end of pattern.  Tail must
303
                                 * point to a location in pattern. */
304
{
305
    char *dirName, *patternEnd = tail;
306
    char savedChar;
307
    int result = TCL_OK;
308
    int baseLength = Tcl_DStringLength(dirPtr);
309
    CInfoPBRec pb;
310
    OSErr err;
311
    FSSpec dirSpec;
312
    Boolean isDirectory;
313
    long dirID;
314
    short itemIndex;
315
    Str255 fileName;
316
 
317
 
318
    /*
319
     * Make sure that the directory part of the name really is a
320
     * directory.
321
     */
322
 
323
    dirName = dirPtr->string;
324
    FSpLocationFromPath(strlen(dirName), dirName, &dirSpec);
325
    err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory);
326
    if ((err != noErr) || !isDirectory) {
327
        return TCL_OK;
328
    }
329
 
330
    /*
331
     * Now open the directory for reading and iterate over the contents.
332
     */
333
 
334
    pb.hFileInfo.ioVRefNum = dirSpec.vRefNum;
335
    pb.hFileInfo.ioDirID = dirID;
336
    pb.hFileInfo.ioNamePtr = (StringPtr) fileName;
337
    pb.hFileInfo.ioFDirIndex = itemIndex = 1;
338
 
339
    /*
340
     * Clean up the end of the pattern and the tail pointer.  Leave
341
     * the tail pointing to the first character after the path separator
342
     * following the pattern, or NULL.  Also, ensure that the pattern
343
     * is null-terminated.
344
     */
345
 
346
    if (*tail == '\\') {
347
        tail++;
348
    }
349
    if (*tail == '\0') {
350
        tail = NULL;
351
    } else {
352
        tail++;
353
    }
354
    savedChar = *patternEnd;
355
    *patternEnd = '\0';
356
 
357
    while (1) {
358
        pb.hFileInfo.ioFDirIndex = itemIndex;
359
        pb.hFileInfo.ioDirID = dirID;
360
        err = PBGetCatInfoSync(&pb);
361
        if (err != noErr) {
362
            break;
363
        }
364
 
365
        /*
366
         * Now check to see if the file matches.  If there are more
367
         * characters to be processed, then ensure matching files are
368
         * directories before calling TclDoGlob. Otherwise, just add
369
         * the file to the result.
370
         */
371
 
372
        p2cstr(fileName);
373
        if (Tcl_StringMatch((char *) fileName, pattern)) {
374
            Tcl_DStringSetLength(dirPtr, baseLength);
375
            Tcl_DStringAppend(dirPtr, (char *) fileName, -1);
376
            if (tail == NULL) {
377
                if ((dirPtr->length > 1) &&
378
                        (strchr(dirPtr->string+1, ':') == NULL)) {
379
                    Tcl_AppendElement(interp, dirPtr->string+1);
380
                } else {
381
                    Tcl_AppendElement(interp, dirPtr->string);
382
                }
383
            } else if ((pb.hFileInfo.ioFlAttrib & ioDirMask) != 0) {
384
                Tcl_DStringAppend(dirPtr, ":", 1);
385
                result = TclDoGlob(interp, separators, dirPtr, tail);
386
                if (result != TCL_OK) {
387
                    break;
388
                }
389
            }
390
        }
391
 
392
        itemIndex++;
393
    }
394
    *patternEnd = savedChar;
395
 
396
    return result;
397
}
398
 
399
/*
400
 *----------------------------------------------------------------------
401
 *
402
 * TclpStat --
403
 *
404
 *      This function replaces the library version of stat.  The stat
405
 *      function provided by most Mac compiliers is rather broken and
406
 *      incomplete.
407
 *
408
 * Results:
409
 *      See stat documentation.
410
 *
411
 * Side effects:
412
 *      See stat documentation.
413
 *
414
 *----------------------------------------------------------------------
415
 */
416
 
417
int
418
TclpStat(
419
    CONST char *path,
420
    struct stat *buf)
421
{
422
    HFileInfo fpb;
423
    HVolumeParam vpb;
424
    OSErr err;
425
    FSSpec fileSpec;
426
    Boolean isDirectory;
427
    long dirID;
428
 
429
    err = FSpLocationFromPath(strlen(path), path, &fileSpec);
430
    if (err != noErr) {
431
        errno = TclMacOSErrorToPosixError(err);
432
        return -1;
433
    }
434
 
435
    /*
436
     * Fill the fpb & vpb struct up with info about file or directory.
437
     */
438
 
439
    FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
440
    vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum;
441
    vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name;
442
    if (isDirectory) {
443
        fpb.ioDirID = fileSpec.parID;
444
    } else {
445
        fpb.ioDirID = dirID;
446
    }
447
 
448
    fpb.ioFDirIndex = 0;
449
    err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
450
    if (err == noErr) {
451
        vpb.ioVolIndex = 0;
452
        err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
453
        if (err == noErr && buf != NULL) {
454
            /*
455
             * Files are always readable by everyone.
456
             */
457
 
458
            buf->st_mode = S_IRUSR | S_IRGRP | S_IROTH;
459
 
460
            /*
461
             * Use the Volume Info & File Info to fill out stat buf.
462
             */
463
            if (fpb.ioFlAttrib & 0x10) {
464
                buf->st_mode |= S_IFDIR;
465
                buf->st_nlink = 2;
466
            } else {
467
                buf->st_nlink = 1;
468
                if (fpb.ioFlFndrInfo.fdFlags & 0x8000) {
469
                    buf->st_mode |= S_IFLNK;
470
                } else {
471
                    buf->st_mode |= S_IFREG;
472
                }
473
            }
474
            if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) {
475
                /*
476
                 * Directories and applications are executable by everyone.
477
                 */
478
 
479
                buf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
480
            }
481
            if ((fpb.ioFlAttrib & 0x01) == 0){
482
                /*
483
                 * If not locked, then everyone has write acces.
484
                 */
485
 
486
                buf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
487
            }
488
            buf->st_ino = fpb.ioDirID;
489
            buf->st_dev = fpb.ioVRefNum;
490
            buf->st_uid = -1;
491
            buf->st_gid = -1;
492
            buf->st_rdev = 0;
493
            buf->st_size = fpb.ioFlLgLen;
494
            buf->st_blksize = vpb.ioVAlBlkSiz;
495
            buf->st_blocks = (buf->st_size + buf->st_blksize - 1)
496
                / buf->st_blksize;
497
 
498
            /*
499
             * The times returned by the Mac file system are in the
500
             * local time zone.  We convert them to GMT so that the
501
             * epoch starts from GMT.  This is also consistant with
502
             * what is returned from "clock seconds".
503
             */
504
            if (initalized == false) {
505
                MachineLocation loc;
506
 
507
                ReadLocation(&loc);
508
                gmt_offset = loc.u.gmtDelta & 0x00ffffff;
509
                if (gmt_offset & 0x00800000) {
510
                    gmt_offset = gmt_offset | 0xff000000;
511
                }
512
                initalized = true;
513
            }
514
            buf->st_atime = buf->st_mtime = fpb.ioFlMdDat - gmt_offset;
515
            buf->st_ctime = fpb.ioFlCrDat - gmt_offset;
516
 
517
        }
518
    }
519
 
520
    if (err != noErr) {
521
        errno = TclMacOSErrorToPosixError(err);
522
    }
523
 
524
    return (err == noErr ? 0 : -1);
525
}
526
 
527
/*
528
 *----------------------------------------------------------------------
529
 *
530
 * TclMacReadlink --
531
 *
532
 *      This function replaces the library version of readlink.
533
 *
534
 * Results:
535
 *      See readlink documentation.
536
 *
537
 * Side effects:
538
 *      None.
539
 *
540
 *----------------------------------------------------------------------
541
 */
542
 
543
int
544
TclMacReadlink(
545
    char *path,
546
    char *buf,
547
    int size)
548
{
549
    HFileInfo fpb;
550
    OSErr err;
551
    FSSpec fileSpec;
552
    Boolean isDirectory;
553
    Boolean wasAlias;
554
    long dirID;
555
    char fileName[256];
556
    char *end;
557
    Handle theString = NULL;
558
    int pathSize;
559
 
560
    /*
561
     * Remove ending colons if they exist.
562
     */
563
    while ((strlen(path) != 0) && (path[strlen(path) - 1] == ':')) {
564
        path[strlen(path) - 1] = NULL;
565
    }
566
 
567
    if (strchr(path, ':') == NULL) {
568
        strcpy(fileName, path);
569
        path = NULL;
570
    } else {
571
        end = strrchr(path, ':') + 1;
572
        strcpy(fileName, end);
573
        *end = NULL;
574
    }
575
    c2pstr(fileName);
576
 
577
    /*
578
     * Create the file spec for the directory of the file
579
     * we want to look at.
580
     */
581
    if (path != NULL) {
582
        err = FSpLocationFromPath(strlen(path), path, &fileSpec);
583
        if (err != noErr) {
584
            errno = EINVAL;
585
            return -1;
586
        }
587
    } else {
588
        FSMakeFSSpecCompat(0, 0, NULL, &fileSpec);
589
    }
590
 
591
    /*
592
     * Fill the fpb struct up with info about file or directory.
593
     */
594
    FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
595
    fpb.ioVRefNum = fileSpec.vRefNum;
596
    fpb.ioDirID = dirID;
597
    fpb.ioNamePtr = (StringPtr) fileName;
598
 
599
    fpb.ioFDirIndex = 0;
600
    err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
601
    if (err != noErr) {
602
        errno = TclMacOSErrorToPosixError(err);
603
        return -1;
604
    } else {
605
        if (fpb.ioFlAttrib & 0x10) {
606
            errno = EINVAL;
607
            return -1;
608
        } else {
609
            if (fpb.ioFlFndrInfo.fdFlags & 0x8000) {
610
                /*
611
                 * The file is a link!
612
                 */
613
            } else {
614
                errno = EINVAL;
615
                return -1;
616
            }
617
        }
618
    }
619
 
620
    /*
621
     * If we are here it's really a link - now find out
622
     * where it points to.
623
     */
624
    err = FSMakeFSSpecCompat(fileSpec.vRefNum, dirID, (StringPtr) fileName, &fileSpec);
625
    if (err == noErr) {
626
        err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias);
627
    }
628
    if ((err == fnfErr) || wasAlias) {
629
        err = FSpPathFromLocation(&fileSpec, &pathSize, &theString);
630
        if ((err != noErr) || (pathSize > size)) {
631
            DisposeHandle(theString);
632
            errno = ENAMETOOLONG;
633
            return -1;
634
        }
635
    } else {
636
        errno = EINVAL;
637
        return -1;
638
    }
639
 
640
    strncpy(buf, *theString, pathSize);
641
    DisposeHandle(theString);
642
 
643
    return pathSize;
644
}
645
 
646
/*
647
 *----------------------------------------------------------------------
648
 *
649
 * TclpAccess --
650
 *
651
 *      This function replaces the library version of access.  The
652
 *      access function provided by most Mac compiliers is rather
653
 *      broken or incomplete.
654
 *
655
 * Results:
656
 *      See access documentation.
657
 *
658
 * Side effects:
659
 *      See access documentation.
660
 *
661
 *----------------------------------------------------------------------
662
 */
663
 
664
int
665
TclpAccess(
666
    const char *path,
667
    int mode)
668
{
669
    HFileInfo fpb;
670
    HVolumeParam vpb;
671
    OSErr err;
672
    FSSpec fileSpec;
673
    Boolean isDirectory;
674
    long dirID;
675
    int full_mode = 0;
676
 
677
    err = FSpLocationFromPath(strlen(path), (char *) path, &fileSpec);
678
    if (err != noErr) {
679
        errno = TclMacOSErrorToPosixError(err);
680
        return -1;
681
    }
682
 
683
    /*
684
     * Fill the fpb & vpb struct up with info about file or directory.
685
     */
686
    FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
687
    vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum;
688
    vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name;
689
    if (isDirectory) {
690
        fpb.ioDirID = fileSpec.parID;
691
    } else {
692
        fpb.ioDirID = dirID;
693
    }
694
 
695
    fpb.ioFDirIndex = 0;
696
    err = PBGetCatInfoSync((CInfoPBPtr)&fpb);
697
    if (err == noErr) {
698
        vpb.ioVolIndex = 0;
699
        err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
700
        if (err == noErr) {
701
            /*
702
             * Use the Volume Info & File Info to determine
703
             * access information.  If we have got this far
704
             * we know the directory is searchable or the file
705
             * exists.  (We have F_OK)
706
             */
707
 
708
            /*
709
             * Check to see if the volume is hardware or
710
             * software locked.  If so we arn't W_OK.
711
             */
712
            if (mode & W_OK) {
713
                if ((vpb.ioVAtrb & 0x0080) || (vpb.ioVAtrb & 0x8000)) {
714
                    errno = EROFS;
715
                    return -1;
716
                }
717
                if (fpb.ioFlAttrib & 0x01) {
718
                    errno = EACCES;
719
                    return -1;
720
                }
721
            }
722
 
723
            /*
724
             * Directories are always searchable and executable.  But only
725
             * files of type 'APPL' are executable.
726
             */
727
            if (!(fpb.ioFlAttrib & 0x10) && (mode & X_OK)
728
                && (fpb.ioFlFndrInfo.fdType != 'APPL')) {
729
                return -1;
730
            }
731
        }
732
    }
733
 
734
    if (err != noErr) {
735
        errno = TclMacOSErrorToPosixError(err);
736
        return -1;
737
    }
738
 
739
    return 0;
740
}
741
 
742
/*
743
 *----------------------------------------------------------------------
744
 *
745
 * TclMacFOpenHack --
746
 *
747
 *      This function replaces fopen.  It supports paths with alises.
748
 *      Note, remember to undefine the fopen macro!
749
 *
750
 * Results:
751
 *      See fopen documentation.
752
 *
753
 * Side effects:
754
 *      See fopen documentation.
755
 *
756
 *----------------------------------------------------------------------
757
 */
758
 
759
#undef fopen
760
FILE *
761
TclMacFOpenHack(
762
    const char *path,
763
    const char *mode)
764
{
765
    OSErr err;
766
    FSSpec fileSpec;
767
    Handle pathString = NULL;
768
    int size;
769
    FILE * f;
770
 
771
    err = FSpLocationFromPath(strlen(path), (char *) path, &fileSpec);
772
    if ((err != noErr) && (err != fnfErr)) {
773
        return NULL;
774
    }
775
    err = FSpPathFromLocation(&fileSpec, &size, &pathString);
776
    if ((err != noErr) && (err != fnfErr)) {
777
        return NULL;
778
    }
779
 
780
    HLock(pathString);
781
    f = fopen(*pathString, mode);
782
    HUnlock(pathString);
783
    DisposeHandle(pathString);
784
    return f;
785
}
786
 
787
/*
788
 *----------------------------------------------------------------------
789
 *
790
 * TclMacOSErrorToPosixError --
791
 *
792
 *      Given a Macintosh OSErr return the appropiate POSIX error.
793
 *
794
 * Results:
795
 *      A Posix error.
796
 *
797
 * Side effects:
798
 *      None.
799
 *
800
 *----------------------------------------------------------------------
801
 */
802
 
803
int
804
TclMacOSErrorToPosixError(
805
    int error)  /* A Macintosh error. */
806
{
807
    switch (error) {
808
        case noErr:
809
            return 0;
810
        case bdNamErr:
811
            return ENAMETOOLONG;
812
        case afpObjectTypeErr:
813
            return ENOTDIR;
814
        case fnfErr:
815
        case dirNFErr:
816
            return ENOENT;
817
        case dupFNErr:
818
            return EEXIST;
819
        case dirFulErr:
820
        case dskFulErr:
821
            return ENOSPC;
822
        case fBsyErr:
823
            return EBUSY;
824
        case tmfoErr:
825
            return ENFILE;
826
        case fLckdErr:
827
        case permErr:
828
        case afpAccessDenied:
829
            return EACCES;
830
        case wPrErr:
831
        case vLckdErr:
832
            return EROFS;
833
        case badMovErr:
834
            return EINVAL;
835
        case diffVolErr:
836
            return EXDEV;
837
        default:
838
            return EINVAL;
839
    }
840
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.