📄 tclmacfile.c
字号:
/* * tclMacFile.c -- * * This file implements the channel drivers for Macintosh * files. It also comtains Macintosh version of other Tcl * functions that deal with the file system. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclMacFile.c 1.57 97/04/23 16:23:05 *//* * Note: This code eventually needs to support async I/O. In doing this * we will need to keep track of all current async I/O. If exit to shell * is called - we shouldn't exit until all asyc I/O completes. */#include "tclInt.h"#include "tclPort.h"#include "tclMacInt.h"#include <Aliases.h>#include <Errors.h>#include <Processes.h>#include <Strings.h>#include <Types.h>#include <MoreFiles.h>#include <MoreFilesExtras.h>#include <FSpCompat.h>/* * Static variables used by the TclpStat function. */static int initalized = false;static long gmt_offset;/* * The variable below caches the name of the current working directory * in order to avoid repeated calls to getcwd. The string is malloc-ed. * NULL means the cache needs to be refreshed. */static char *currentDir = NULL;/* *---------------------------------------------------------------------- * * TclChdir -- * * Change the current working directory. * * Results: * The result is a standard Tcl result. If an error occurs and * interp isn't NULL, an error message is left in interp->result. * * Side effects: * The working directory for this application is changed. Also * the cache maintained used by TclGetCwd is deallocated and * set to NULL. * *---------------------------------------------------------------------- */intTclChdir( Tcl_Interp *interp, /* If non NULL, used for error reporting. */ char *dirName) /* Path to new working directory. */{ FSSpec spec; OSErr err; Boolean isFolder; long dirID; if (currentDir != NULL) { ckfree(currentDir); currentDir = NULL; } err = FSpLocationFromPath(strlen(dirName), dirName, &spec); if (err != noErr) { errno = ENOENT; goto chdirError; } err = FSpGetDirectoryID(&spec, &dirID, &isFolder); if (err != noErr) { errno = ENOENT; goto chdirError; } if (isFolder != true) { errno = ENOTDIR; goto chdirError; } err = FSpSetDefaultDir(&spec); if (err != noErr) { switch (err) { case afpAccessDenied: errno = EACCES; break; default: errno = ENOENT; } goto chdirError; } return TCL_OK; chdirError: if (interp != NULL) { Tcl_AppendResult(interp, "couldn't change working directory to \"", dirName, "\": ", Tcl_PosixError(interp), (char *) NULL); } return TCL_ERROR;}/* *---------------------------------------------------------------------- * * TclGetCwd -- * * Return the path name of the current working directory. * * Results: * The result is the full path name of the current working * directory, or NULL if an error occurred while figuring it * out. If an error occurs and interp isn't NULL, an error * message is left in interp->result. * * Side effects: * The path name is cached to avoid having to recompute it * on future calls; if it is already cached, the cached * value is returned. * *---------------------------------------------------------------------- */char *TclGetCwd( Tcl_Interp *interp) /* If non NULL, used for error reporting. */{ FSSpec theSpec; int length; Handle pathHandle = NULL; if (currentDir == NULL) { if (FSpGetDefaultDir(&theSpec) != noErr) { if (interp != NULL) { interp->result = "error getting working directory name"; } return NULL; } if (FSpPathFromLocation(&theSpec, &length, &pathHandle) != noErr) { if (interp != NULL) { interp->result = "error getting working directory name"; } return NULL; } HLock(pathHandle); currentDir = (char *) ckalloc((unsigned) (length + 1)); strcpy(currentDir, *pathHandle); HUnlock(pathHandle); DisposeHandle(pathHandle); } return currentDir;}/* *---------------------------------------------------------------------- * * Tcl_WaitPid -- * * Fakes a call to wait pid. * * Results: * Always returns -1. * * Side effects: * None. * *---------------------------------------------------------------------- */Tcl_PidTcl_WaitPid( Tcl_Pid pid, int *statPtr, int options){ return (Tcl_Pid) -1;}/* *---------------------------------------------------------------------- * * Tcl_FindExecutable -- * * This procedure computes the absolute path name of the current * application, given its argv[0] value. However, this * implementation doesn't use of need the argv[0] value. NULL * may be passed in its place. * * Results: * None. * * Side effects: * The variable tclExecutableName gets filled in with the file * name for the application, if we figured it out. If we couldn't * figure it out, Tcl_FindExecutable is set to NULL. * *---------------------------------------------------------------------- */voidTcl_FindExecutable( char *argv0) /* The value of the application's argv[0]. */{ ProcessSerialNumber psn; ProcessInfoRec info; Str63 appName; FSSpec fileSpec; int pathLength; Handle pathName = NULL; OSErr err; GetCurrentProcess(&psn); info.processInfoLength = sizeof(ProcessInfoRec); info.processName = appName; info.processAppSpec = &fileSpec; GetProcessInformation(&psn, &info); if (tclExecutableName != NULL) { ckfree(tclExecutableName); tclExecutableName = NULL; } err = FSpPathFromLocation(&fileSpec, &pathLength, &pathName); tclExecutableName = (char *) ckalloc((unsigned) pathLength + 1); HLock(pathName); strcpy(tclExecutableName, *pathName); HUnlock(pathName); DisposeHandle(pathName); }/* *---------------------------------------------------------------------- * * TclGetUserHome -- * * This function takes the passed in user name and finds the * corresponding home directory specified in the password file. * * Results: * On a Macintosh we always return a NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */char *TclGetUserHome( char *name, /* User name to use to find home directory. */ Tcl_DString *bufferPtr) /* May be used to hold result. Must not hold * anything at the time of the call, and need * not even be initialized. */{ return NULL;}/* *---------------------------------------------------------------------- * * TclMatchFiles -- * * This routine is used by the globbing code to search a * directory for all files which match a given pattern. * * Results: * If the tail argument is NULL, then the matching files are * added to the interp->result. Otherwise, TclDoGlob is called * recursively for each matching subdirectory. The return value * is a standard Tcl result indicating whether an error occurred * in globbing. * * Side effects: * None. * *---------------------------------------------------------------------- */intTclMatchFiles( Tcl_Interp *interp, /* Interpreter to receive results. */ char *separators, /* Directory separators to pass to TclDoGlob. */ Tcl_DString *dirPtr, /* Contains path to directory to search. */ char *pattern, /* Pattern to match against. */ char *tail) /* Pointer to end of pattern. Tail must * point to a location in pattern. */{ char *dirName, *patternEnd = tail; char savedChar; int result = TCL_OK; int baseLength = Tcl_DStringLength(dirPtr); CInfoPBRec pb; OSErr err; FSSpec dirSpec; Boolean isDirectory; long dirID; short itemIndex; Str255 fileName; /* * Make sure that the directory part of the name really is a * directory. */ dirName = dirPtr->string; FSpLocationFromPath(strlen(dirName), dirName, &dirSpec); err = FSpGetDirectoryID(&dirSpec, &dirID, &isDirectory); if ((err != noErr) || !isDirectory) { return TCL_OK; } /* * Now open the directory for reading and iterate over the contents. */ pb.hFileInfo.ioVRefNum = dirSpec.vRefNum; pb.hFileInfo.ioDirID = dirID; pb.hFileInfo.ioNamePtr = (StringPtr) fileName; pb.hFileInfo.ioFDirIndex = itemIndex = 1; /* * Clean up the end of the pattern and the tail pointer. Leave * the tail pointing to the first character after the path separator * following the pattern, or NULL. Also, ensure that the pattern * is null-terminated. */ if (*tail == '\\') { tail++; } if (*tail == '\0') { tail = NULL; } else { tail++; } savedChar = *patternEnd; *patternEnd = '\0'; while (1) { pb.hFileInfo.ioFDirIndex = itemIndex; pb.hFileInfo.ioDirID = dirID; err = PBGetCatInfoSync(&pb); if (err != noErr) { break; } /* * Now check to see if the file matches. If there are more * characters to be processed, then ensure matching files are * directories before calling TclDoGlob. Otherwise, just add * the file to the result. */ p2cstr(fileName); if (Tcl_StringMatch((char *) fileName, pattern)) { Tcl_DStringSetLength(dirPtr, baseLength); Tcl_DStringAppend(dirPtr, (char *) fileName, -1); if (tail == NULL) { if ((dirPtr->length > 1) && (strchr(dirPtr->string+1, ':') == NULL)) { Tcl_AppendElement(interp, dirPtr->string+1); } else { Tcl_AppendElement(interp, dirPtr->string); } } else if ((pb.hFileInfo.ioFlAttrib & ioDirMask) != 0) { Tcl_DStringAppend(dirPtr, ":", 1); result = TclDoGlob(interp, separators, dirPtr, tail); if (result != TCL_OK) { break; } } } itemIndex++; } *patternEnd = savedChar; return result;}/* *---------------------------------------------------------------------- * * TclpStat -- * * This function replaces the library version of stat. The stat * function provided by most Mac compiliers is rather broken and * incomplete. * * Results: * See stat documentation. * * Side effects: * See stat documentation. * *---------------------------------------------------------------------- */intTclpStat( CONST char *path, struct stat *buf){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -