⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclioutil.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclIOUtil.c -- * *	This file contains the implementation of Tcl's generic *	filesystem code, which supports a pluggable filesystem *	architecture allowing both platform specific filesystems and *	'virtual filesystems'.  All filesystem access should go through *	the functions defined in this file.  Most of this code was *	contributed by Vince Darley. * *	Parts of this file are based on code contributed by Karl *	Lehenbauer, Mark Diekhans and Peter da Silva. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-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. * * RCS: @(#) $Id: tclIOUtil.c,v 1.77 2003/03/03 20:22:41 das Exp $ */#include "tclInt.h"#include "tclPort.h"#ifdef MAC_TCL#include "tclMacInt.h"#endif#ifdef __WIN32__/* for tclWinProcs->useWide */#include "tclWinInt.h"#endif/* * Prototypes for procedures defined later in this file. */static void		DupFsPathInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,			    Tcl_Obj *copyPtr));static void		FreeFsPathInternalRep _ANSI_ARGS_((Tcl_Obj *listPtr));static void             UpdateStringOfFsPath _ANSI_ARGS_((Tcl_Obj *objPtr));static int		SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,			    Tcl_Obj *objPtr));static Tcl_Obj*         MakeFsPathFromRelative _ANSI_ARGS_((Tcl_Interp *interp, 			    Tcl_Obj *objPtr, Tcl_Obj *cwdPtr));static Tcl_Obj*         FSNormalizeAbsolutePath                             _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));static int              TclNormalizeToUniquePath                             _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *pathPtr,					 int startAt));static int		SetFsPathFromAbsoluteNormalized                             _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr));static int 		FindSplitPos _ANSI_ARGS_((char *path, char *separator));static Tcl_PathType     FSGetPathType  _ANSI_ARGS_((Tcl_Obj *pathObjPtr, 			    Tcl_Filesystem **filesystemPtrPtr, 			    int *driveNameLengthPtr));static Tcl_PathType     GetPathType  _ANSI_ARGS_((Tcl_Obj *pathObjPtr, 			    Tcl_Filesystem **filesystemPtrPtr, 			    int *driveNameLengthPtr, Tcl_Obj **driveNameRef));/* * Define the 'path' object type, which Tcl uses to represent * file paths internally. */Tcl_ObjType tclFsPathType = {    "path",				/* name */    FreeFsPathInternalRep,		/* freeIntRepProc */    DupFsPathInternalRep,	        /* dupIntRepProc */    UpdateStringOfFsPath,		/* updateStringProc */    SetFsPathFromAny			/* setFromAnyProc */};/*  * These form part of the native filesystem support.  They are needed * here because we have a few native filesystem functions (which are * the same for mac/win/unix) in this file.  There is no need to place * them in tclInt.h, because they are not (and should not be) used * anywhere else. */extern CONST char *		tclpFileAttrStrings[];extern CONST TclFileAttrProcs	tclpFileAttrProcs[];/*  * The following functions are obsolete string based APIs, and should * be removed in a future release (Tcl 9 would be a good time). *//* Obsolete */intTcl_Stat(path, oldStyleBuf)    CONST char *path;		/* Path of file to stat (in current CP). */    struct stat *oldStyleBuf;	/* Filled with results of stat call. */{    int ret;    Tcl_StatBuf buf;    Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1);    Tcl_IncrRefCount(pathPtr);    ret = Tcl_FSStat(pathPtr, &buf);    Tcl_DecrRefCount(pathPtr);    if (ret != -1) {#ifndef TCL_WIDE_INT_IS_LONG#   define OUT_OF_RANGE(x) \	(((Tcl_WideInt)(x)) < Tcl_LongAsWide(LONG_MIN) || \	 ((Tcl_WideInt)(x)) > Tcl_LongAsWide(LONG_MAX))#   define OUT_OF_URANGE(x) \	(((Tcl_WideUInt)(x)) > (Tcl_WideUInt)ULONG_MAX)	/*	 * Perform the result-buffer overflow check manually.	 *	 * Note that ino_t/ino64_t is unsigned...	 */        if (OUT_OF_URANGE(buf.st_ino) || OUT_OF_RANGE(buf.st_size)#ifdef HAVE_ST_BLOCKS		|| OUT_OF_RANGE(buf.st_blocks)#endif	    ) {#ifdef EFBIG	    errno = EFBIG;#else#  ifdef EOVERFLOW	    errno = EOVERFLOW;#  else#    error  "What status should be returned for file size out of range?"#  endif#endif	    return -1;	}#   undef OUT_OF_RANGE#   undef OUT_OF_URANGE#endif /* !TCL_WIDE_INT_IS_LONG */	/*	 * Copy across all supported fields, with possible type	 * coercions on those fields that change between the normal	 * and lf64 versions of the stat structure (on Solaris at	 * least.)  This is slow when the structure sizes coincide,	 * but that's what you get for using an obsolete interface.	 */	oldStyleBuf->st_mode    = buf.st_mode;	oldStyleBuf->st_ino     = (ino_t) buf.st_ino;	oldStyleBuf->st_dev     = buf.st_dev;	oldStyleBuf->st_rdev    = buf.st_rdev;	oldStyleBuf->st_nlink   = buf.st_nlink;	oldStyleBuf->st_uid     = buf.st_uid;	oldStyleBuf->st_gid     = buf.st_gid;	oldStyleBuf->st_size    = (off_t) buf.st_size;	oldStyleBuf->st_atime   = buf.st_atime;	oldStyleBuf->st_mtime   = buf.st_mtime;	oldStyleBuf->st_ctime   = buf.st_ctime;#ifdef HAVE_ST_BLOCKS	oldStyleBuf->st_blksize = buf.st_blksize;	oldStyleBuf->st_blocks  = (blkcnt_t) buf.st_blocks;#endif    }    return ret;}/* Obsolete */intTcl_Access(path, mode)    CONST char *path;		/* Path of file to access (in current CP). */    int mode;                   /* Permission setting. */{    int ret;    Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1);    Tcl_IncrRefCount(pathPtr);    ret = Tcl_FSAccess(pathPtr,mode);    Tcl_DecrRefCount(pathPtr);    return ret;}/* Obsolete */Tcl_ChannelTcl_OpenFileChannel(interp, path, modeString, permissions)    Tcl_Interp *interp;                 /* Interpreter for error reporting;					 * can be NULL. */    CONST char *path;                   /* Name of file to open. */    CONST char *modeString;             /* A list of POSIX open modes or					 * a string such as "rw". */    int permissions;                    /* If the open involves creating a					 * file, with what modes to create					 * it? */{    Tcl_Channel ret;    Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1);    Tcl_IncrRefCount(pathPtr);    ret = Tcl_FSOpenFileChannel(interp, pathPtr, modeString, permissions);    Tcl_DecrRefCount(pathPtr);    return ret;}/* Obsolete */intTcl_Chdir(dirName)    CONST char *dirName;{    int ret;    Tcl_Obj *pathPtr = Tcl_NewStringObj(dirName,-1);    Tcl_IncrRefCount(pathPtr);    ret = Tcl_FSChdir(pathPtr);    Tcl_DecrRefCount(pathPtr);    return ret;}/* Obsolete */char *Tcl_GetCwd(interp, cwdPtr)    Tcl_Interp *interp;    Tcl_DString *cwdPtr;{    Tcl_Obj *cwd;    cwd = Tcl_FSGetCwd(interp);    if (cwd == NULL) {	return NULL;    } else {	Tcl_DStringInit(cwdPtr);	Tcl_DStringAppend(cwdPtr, Tcl_GetString(cwd), -1);	Tcl_DecrRefCount(cwd);	return Tcl_DStringValue(cwdPtr);    }}/* Obsolete */intTcl_EvalFile(interp, fileName)    Tcl_Interp *interp;		/* Interpreter in which to process file. */    CONST char *fileName;	/* Name of file to process.  Tilde-substitution				 * will be performed on this name. */{    int ret;    Tcl_Obj *pathPtr = Tcl_NewStringObj(fileName,-1);    Tcl_IncrRefCount(pathPtr);    ret = Tcl_FSEvalFile(interp, pathPtr);    Tcl_DecrRefCount(pathPtr);    return ret;}/*  * The 3 hooks for Stat, Access and OpenFileChannel are obsolete.  The * complete, general hooked filesystem APIs should be used instead. * This define decides whether to include the obsolete hooks and * related code.  If these are removed, we'll also want to remove them * from stubs/tclInt.  The only known users of these APIs are prowrap * and mktclapp.  New code/extensions should not use them, since they * do not provide as full support as the full filesystem API. *  * As soon as prowrap and mktclapp are updated to use the full * filesystem support, I suggest all these hooks are removed. */#define USE_OBSOLETE_FS_HOOKS#ifdef USE_OBSOLETE_FS_HOOKS/* * The following typedef declarations allow for hooking into the chain * of functions maintained for 'Tcl_Stat(...)', 'Tcl_Access(...)' & * 'Tcl_OpenFileChannel(...)'.  Basically for each hookable function * a linked list is defined. */typedef struct StatProc {    TclStatProc_ *proc;		 /* Function to process a 'stat()' call */    struct StatProc *nextPtr;    /* The next 'stat()' function to call */} StatProc;typedef struct AccessProc {    TclAccessProc_ *proc;	 /* Function to process a 'access()' call */    struct AccessProc *nextPtr;  /* The next 'access()' function to call */} AccessProc;typedef struct OpenFileChannelProc {    TclOpenFileChannelProc_ *proc;  /* Function to process a				     * 'Tcl_OpenFileChannel()' call */    struct OpenFileChannelProc *nextPtr;				    /* The next 'Tcl_OpenFileChannel()'				     * function to call */} OpenFileChannelProc;/* * For each type of (obsolete) hookable function, a static node is * declared to hold the function pointer for the "built-in" routine * (e.g. 'TclpStat(...)') and the respective list is initialized as a * pointer to that node. *  * The "delete" functions (e.g. 'TclStatDeleteProc(...)') ensure that * these statically declared list entry cannot be inadvertently removed. * * This method avoids the need to call any sort of "initialization" * function. * * All three lists are protected by a global obsoleteFsHookMutex. */static StatProc *statProcList = NULL;static AccessProc *accessProcList = NULL;static OpenFileChannelProc *openFileChannelProcList = NULL;TCL_DECLARE_MUTEX(obsoleteFsHookMutex)#endif /* USE_OBSOLETE_FS_HOOKS *//*  * A filesystem record is used to keep track of each * filesystem currently registered with the core, * in a linked list. */typedef struct FilesystemRecord {    ClientData	     clientData;  /* Client specific data for the new				   * filesystem (can be NULL) */    Tcl_Filesystem *fsPtr;        /* Pointer to filesystem dispatch                                   * table. */    int fileRefCount;             /* How many Tcl_Obj's use this                                   * filesystem. */    struct FilesystemRecord *nextPtr;                                    /* The next filesystem registered                                   * to Tcl, or NULL if no more. */} FilesystemRecord;static FilesystemRecord* GetFilesystemRecord 	_ANSI_ARGS_((Tcl_Filesystem *fromFilesystem, int *epoch));/*  * Declare the native filesystem support.  These functions should * be considered private to Tcl, and should really not be called * directly by any code other than this file (i.e. neither by * Tcl's core nor by extensions).  Similarly, the old string-based * Tclp... native filesystem functions should not be called. *  * The correct API to use now is the Tcl_FS... set of functions, * which ensure correct and complete virtual filesystem support. *  * We cannot make all of these static, since some of them * are implemented in the platform-specific directories. */static Tcl_FSPathInFilesystemProc NativePathInFilesystem;static Tcl_FSFilesystemSeparatorProc NativeFilesystemSeparator;static Tcl_FSFreeInternalRepProc NativeFreeInternalRep;static Tcl_FSDupInternalRepProc NativeDupInternalRep;static Tcl_FSCreateInternalRepProc NativeCreateNativeRep;static Tcl_FSFileAttrStringsProc NativeFileAttrStrings;static Tcl_FSFileAttrsGetProc NativeFileAttrsGet;static Tcl_FSFileAttrsSetProc NativeFileAttrsSet;/*  * The only reason these functions are not static is that they * are either called by code in the native (win/unix/mac) directories * or they are actually implemented in those directories.  They * should simply not be called by code outside Tcl's native * filesystem core.  i.e. they should be considered 'static' to * Tcl's filesystem code (if we ever built the native filesystem * support into a separate code library, this could actually be * enforced). */Tcl_FSFilesystemPathTypeProc TclpFilesystemPathType;Tcl_FSInternalToNormalizedProc TclpNativeToNormalized;Tcl_FSStatProc TclpObjStat;Tcl_FSAccessProc TclpObjAccess;	    Tcl_FSMatchInDirectoryProc TclpMatchInDirectory;  Tcl_FSGetCwdProc TclpObjGetCwd;     Tcl_FSChdirProc TclpObjChdir;	    Tcl_FSLstatProc TclpObjLstat;	    Tcl_FSCopyFileProc TclpObjCopyFile; Tcl_FSDeleteFileProc TclpObjDeleteFile;	    Tcl_FSRenameFileProc TclpObjRenameFile;	    Tcl_FSCreateDirectoryProc TclpObjCreateDirectory;	    Tcl_FSCopyDirectoryProc TclpObjCopyDirectory;	    Tcl_FSRemoveDirectoryProc TclpObjRemoveDirectory;	    Tcl_FSUnloadFileProc TclpUnloadFile;	    Tcl_FSLinkProc TclpObjLink; Tcl_FSListVolumesProc TclpObjListVolumes;	    /*  * Define the native filesystem dispatch table.  If necessary, it * is ok to make this non-static, but it should only be accessed * by the functions actually listed within it (or perhaps other * helper functions of them).  Anything which is not part of this * 'native filesystem implementation' should not be delving inside * here! */static Tcl_Filesystem tclNativeFilesystem = {    "native",    sizeof(Tcl_Filesystem),    TCL_FILESYSTEM_VERSION_1,    &NativePathInFilesystem,    &NativeDupInternalRep,    &NativeFreeInternalRep,    &TclpNativeToNormalized,    &NativeCreateNativeRep,    &TclpObjNormalizePath,    &TclpFilesystemPathType,    &NativeFilesystemSeparator,    &TclpObjStat,    &TclpObjAccess,    &TclpOpenFileChannel,    &TclpMatchInDirectory,    &TclpUtime,#ifndef S_IFLNK    NULL,#else    &TclpObjLink,#endif /* S_IFLNK */    &TclpObjListVolumes,    &NativeFileAttrStrings,    &NativeFileAttrsGet,    &NativeFileAttrsSet,    &TclpObjCreateDirectory,    &TclpObjRemoveDirectory,     &TclpObjDeleteFile,    &TclpObjCopyFile,    &TclpObjRenameFile,    &TclpObjCopyDirectory,     &TclpObjLstat,    &TclpDlopen,    &TclpObjGetCwd,    &TclpObjChdir};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -