📄 tclmacfile.c
字号:
HFileInfo fpb; HVolumeParam vpb; OSErr err; FSSpec fileSpec; Boolean isDirectory; long dirID; err = FSpLocationFromPath(strlen(path), path, &fileSpec); if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return -1; } /* * Fill the fpb & vpb struct up with info about file or directory. */ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum; vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name; if (isDirectory) { fpb.ioDirID = fileSpec.parID; } else { fpb.ioDirID = dirID; } fpb.ioFDirIndex = 0; err = PBGetCatInfoSync((CInfoPBPtr)&fpb); if (err == noErr) { vpb.ioVolIndex = 0; err = PBHGetVInfoSync((HParmBlkPtr)&vpb); if (err == noErr && buf != NULL) { /* * Files are always readable by everyone. */ buf->st_mode = S_IRUSR | S_IRGRP | S_IROTH; /* * Use the Volume Info & File Info to fill out stat buf. */ if (fpb.ioFlAttrib & 0x10) { buf->st_mode |= S_IFDIR; buf->st_nlink = 2; } else { buf->st_nlink = 1; if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { buf->st_mode |= S_IFLNK; } else { buf->st_mode |= S_IFREG; } } if ((fpb.ioFlAttrib & 0x10) || (fpb.ioFlFndrInfo.fdType == 'APPL')) { /* * Directories and applications are executable by everyone. */ buf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; } if ((fpb.ioFlAttrib & 0x01) == 0){ /* * If not locked, then everyone has write acces. */ buf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; } buf->st_ino = fpb.ioDirID; buf->st_dev = fpb.ioVRefNum; buf->st_uid = -1; buf->st_gid = -1; buf->st_rdev = 0; buf->st_size = fpb.ioFlLgLen; buf->st_blksize = vpb.ioVAlBlkSiz; buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; /* * The times returned by the Mac file system are in the * local time zone. We convert them to GMT so that the * epoch starts from GMT. This is also consistant with * what is returned from "clock seconds". */ if (initalized == false) { MachineLocation loc; ReadLocation(&loc); gmt_offset = loc.u.gmtDelta & 0x00ffffff; if (gmt_offset & 0x00800000) { gmt_offset = gmt_offset | 0xff000000; } initalized = true; } buf->st_atime = buf->st_mtime = fpb.ioFlMdDat - gmt_offset; buf->st_ctime = fpb.ioFlCrDat - gmt_offset; } } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); } return (err == noErr ? 0 : -1);}/* *---------------------------------------------------------------------- * * TclMacReadlink -- * * This function replaces the library version of readlink. * * Results: * See readlink documentation. * * Side effects: * None. * *---------------------------------------------------------------------- */intTclMacReadlink( char *path, char *buf, int size){ HFileInfo fpb; OSErr err; FSSpec fileSpec; Boolean isDirectory; Boolean wasAlias; long dirID; char fileName[256]; char *end; Handle theString = NULL; int pathSize; /* * Remove ending colons if they exist. */ while ((strlen(path) != 0) && (path[strlen(path) - 1] == ':')) { path[strlen(path) - 1] = NULL; } if (strchr(path, ':') == NULL) { strcpy(fileName, path); path = NULL; } else { end = strrchr(path, ':') + 1; strcpy(fileName, end); *end = NULL; } c2pstr(fileName); /* * Create the file spec for the directory of the file * we want to look at. */ if (path != NULL) { err = FSpLocationFromPath(strlen(path), path, &fileSpec); if (err != noErr) { errno = EINVAL; return -1; } } else { FSMakeFSSpecCompat(0, 0, NULL, &fileSpec); } /* * Fill the fpb struct up with info about file or directory. */ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); fpb.ioVRefNum = fileSpec.vRefNum; fpb.ioDirID = dirID; fpb.ioNamePtr = (StringPtr) fileName; fpb.ioFDirIndex = 0; err = PBGetCatInfoSync((CInfoPBPtr)&fpb); if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return -1; } else { if (fpb.ioFlAttrib & 0x10) { errno = EINVAL; return -1; } else { if (fpb.ioFlFndrInfo.fdFlags & 0x8000) { /* * The file is a link! */ } else { errno = EINVAL; return -1; } } } /* * If we are here it's really a link - now find out * where it points to. */ err = FSMakeFSSpecCompat(fileSpec.vRefNum, dirID, (StringPtr) fileName, &fileSpec); if (err == noErr) { err = ResolveAliasFile(&fileSpec, true, &isDirectory, &wasAlias); } if ((err == fnfErr) || wasAlias) { err = FSpPathFromLocation(&fileSpec, &pathSize, &theString); if ((err != noErr) || (pathSize > size)) { DisposeHandle(theString); errno = ENAMETOOLONG; return -1; } } else { errno = EINVAL; return -1; } strncpy(buf, *theString, pathSize); DisposeHandle(theString); return pathSize;}/* *---------------------------------------------------------------------- * * TclpAccess -- * * This function replaces the library version of access. The * access function provided by most Mac compiliers is rather * broken or incomplete. * * Results: * See access documentation. * * Side effects: * See access documentation. * *---------------------------------------------------------------------- */intTclpAccess( const char *path, int mode){ HFileInfo fpb; HVolumeParam vpb; OSErr err; FSSpec fileSpec; Boolean isDirectory; long dirID; int full_mode = 0; err = FSpLocationFromPath(strlen(path), (char *) path, &fileSpec); if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return -1; } /* * Fill the fpb & vpb struct up with info about file or directory. */ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); vpb.ioVRefNum = fpb.ioVRefNum = fileSpec.vRefNum; vpb.ioNamePtr = fpb.ioNamePtr = fileSpec.name; if (isDirectory) { fpb.ioDirID = fileSpec.parID; } else { fpb.ioDirID = dirID; } fpb.ioFDirIndex = 0; err = PBGetCatInfoSync((CInfoPBPtr)&fpb); if (err == noErr) { vpb.ioVolIndex = 0; err = PBHGetVInfoSync((HParmBlkPtr)&vpb); if (err == noErr) { /* * Use the Volume Info & File Info to determine * access information. If we have got this far * we know the directory is searchable or the file * exists. (We have F_OK) */ /* * Check to see if the volume is hardware or * software locked. If so we arn't W_OK. */ if (mode & W_OK) { if ((vpb.ioVAtrb & 0x0080) || (vpb.ioVAtrb & 0x8000)) { errno = EROFS; return -1; } if (fpb.ioFlAttrib & 0x01) { errno = EACCES; return -1; } } /* * Directories are always searchable and executable. But only * files of type 'APPL' are executable. */ if (!(fpb.ioFlAttrib & 0x10) && (mode & X_OK) && (fpb.ioFlFndrInfo.fdType != 'APPL')) { return -1; } } } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return -1; } return 0;}/* *---------------------------------------------------------------------- * * TclMacFOpenHack -- * * This function replaces fopen. It supports paths with alises. * Note, remember to undefine the fopen macro! * * Results: * See fopen documentation. * * Side effects: * See fopen documentation. * *---------------------------------------------------------------------- */#undef fopenFILE *TclMacFOpenHack( const char *path, const char *mode){ OSErr err; FSSpec fileSpec; Handle pathString = NULL; int size; FILE * f; err = FSpLocationFromPath(strlen(path), (char *) path, &fileSpec); if ((err != noErr) && (err != fnfErr)) { return NULL; } err = FSpPathFromLocation(&fileSpec, &size, &pathString); if ((err != noErr) && (err != fnfErr)) { return NULL; } HLock(pathString); f = fopen(*pathString, mode); HUnlock(pathString); DisposeHandle(pathString); return f;}/* *---------------------------------------------------------------------- * * TclMacOSErrorToPosixError -- * * Given a Macintosh OSErr return the appropiate POSIX error. * * Results: * A Posix error. * * Side effects: * None. * *---------------------------------------------------------------------- */intTclMacOSErrorToPosixError( int error) /* A Macintosh error. */{ switch (error) { case noErr: return 0; case bdNamErr: return ENAMETOOLONG; case afpObjectTypeErr: return ENOTDIR; case fnfErr: case dirNFErr: return ENOENT; case dupFNErr: return EEXIST; case dirFulErr: case dskFulErr: return ENOSPC; case fBsyErr: return EBUSY; case tmfoErr: return ENFILE; case fLckdErr: case permErr: case afpAccessDenied: return EACCES; case wPrErr: case vLckdErr: return EROFS; case badMovErr: return EINVAL; case diffVolErr: return EXDEV; default: return EINVAL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -