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

📄 tclioutil.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 5 页
字号:
	    retVal = TCL_OK;	} else {	    prevFsRecPtr = tmpFsRecPtr;	    tmpFsRecPtr = tmpFsRecPtr->nextPtr;	}    }    Tcl_MutexUnlock(&filesystemMutex);    return (retVal);}/* *---------------------------------------------------------------------- * * Tcl_FSMountsChanged -- * *    Notify the filesystem that the available mounted filesystems *    (or within any one filesystem type, the number or location of *    mount points) have changed. * * Results: *    None. * * Side effects: *    The global filesystem variable 'theFilesystemEpoch' is *    incremented.  The effect of this is to make all cached *    path representations invalid.  Clearly it should only therefore *    be called when it is really required!  There are a few  *    circumstances when it should be called: *     *    (1) when a new filesystem is registered or unregistered.   *    Strictly speaking this is only necessary if the new filesystem *    accepts file paths as is (normally the filesystem itself is *    really a shell which hasn't yet had any mount points established *    and so its 'pathInFilesystem' proc will always fail).  However, *    for safety, Tcl always calls this for you in these circumstances. *  *    (2) when additional mount points are established inside any *    existing filesystem (except the native fs) *     *    (3) when any filesystem (except the native fs) changes the list *    of available volumes. *     *    (4) when the mapping from a string representation of a file to *    a full, normalized path changes.  For example, if 'env(HOME)'  *    is modified, then any path containing '~' will map to a different *    filesystem location.  Therefore all such paths need to have *    their internal representation invalidated. *     *    Tcl has no control over (2) and (3), so any registered filesystem *    must make sure it calls this function when those situations *    occur. *     *    (Note: the reason for the exception in 2,3 for the native *    filesystem is that the native filesystem by default claims all *    unknown files even if it really doesn't understand them or if *    they don't exist). * *---------------------------------------------------------------------- */voidTcl_FSMountsChanged(fsPtr)    Tcl_Filesystem *fsPtr;{    /*      * We currently don't do anything with this parameter.  We     * could in the future only invalidate files for this filesystem     * or otherwise take more advanced action.     */    (void)fsPtr;    /*      * Increment the filesystem epoch counter, since existing paths     * might now belong to different filesystems.     */    Tcl_MutexLock(&filesystemMutex);    theFilesystemEpoch++;    Tcl_MutexUnlock(&filesystemMutex);}/* *---------------------------------------------------------------------- * * Tcl_FSData -- * *    Retrieve the clientData field for the filesystem given, *    or NULL if that filesystem is not registered. * * Results: *    A clientData value, or NULL.  Note that if the filesystem *    was registered with a NULL clientData field, this function *    will return that NULL value. * * Side effects: *    None. * *---------------------------------------------------------------------- */ClientDataTcl_FSData(fsPtr)    Tcl_Filesystem  *fsPtr;   /* The filesystem record to query. */{    ClientData retVal = NULL;    FilesystemRecord *tmpFsRecPtr;    tmpFsRecPtr = FsGetIterator();    /*     * Traverse the 'filesystemList' looking for the particular node     * whose 'fsPtr' member matches 'fsPtr' and remove that one from     * the list.  Ensure that the "default" node cannot be removed.     */    while ((retVal == NULL) && (tmpFsRecPtr != NULL)) {	if (tmpFsRecPtr->fsPtr == fsPtr) {	    retVal = tmpFsRecPtr->clientData;	}	tmpFsRecPtr = tmpFsRecPtr->nextPtr;    }    FsReleaseIterator();    return (retVal);}/* *--------------------------------------------------------------------------- * * FSNormalizeAbsolutePath -- * * Description: *	Takes an absolute path specification and computes a 'normalized' *	path from it. *	 *	A normalized path is one which has all '../', './' removed. *	Also it is one which is in the 'standard' format for the native *	platform.  On MacOS, Unix, this means the path must be free of *	symbolic links/aliases, and on Windows it means we want the *	long form, with that long form's case-dependence (which gives *	us a unique, case-dependent path). *	 *	The behaviour of this function if passed a non-absolute path *	is NOT defined. * * Results: *	The result is returned in a Tcl_Obj with a refCount of 1, *	which is therefore owned by the caller.  It must be *	freed (with Tcl_DecrRefCount) by the caller when no longer needed. * * Side effects: *	None (beyond the memory allocation for the result). * * Special note: *	This code is based on code from Matt Newman and Jean-Claude *	Wippler, with additions from Vince Darley and is copyright  *	those respective authors. * *--------------------------------------------------------------------------- */static Tcl_Obj*FSNormalizeAbsolutePath(interp, pathPtr)    Tcl_Interp* interp;    /* Interpreter to use */    Tcl_Obj *pathPtr;      /* Absolute path to normalize */{    int splen = 0, nplen, eltLen, i;    char *eltName;    Tcl_Obj *retVal;    Tcl_Obj *split;    Tcl_Obj *elt;        /* Split has refCount zero */    split = Tcl_FSSplitPath(pathPtr, &splen);    /*      * Modify the list of entries in place, by removing '.', and     * removing '..' and the entry before -- unless that entry before     * is the top-level entry, i.e. the name of a volume.     */    nplen = 0;    for (i = 0; i < splen; i++) {	Tcl_ListObjIndex(NULL, split, nplen, &elt);	eltName = Tcl_GetStringFromObj(elt, &eltLen);	if ((eltLen == 1) && (eltName[0] == '.')) {	    Tcl_ListObjReplace(NULL, split, nplen, 1, 0, NULL);	} else if ((eltLen == 2)		&& (eltName[0] == '.') && (eltName[1] == '.')) {	    if (nplen > 1) {	        nplen--;		Tcl_ListObjReplace(NULL, split, nplen, 2, 0, NULL);	    } else {		Tcl_ListObjReplace(NULL, split, nplen, 1, 0, NULL);	    }	} else {	    nplen++;	}    }    if (nplen > 0) {	retVal = Tcl_FSJoinPath(split, nplen);	/* 	 * Now we have an absolute path, with no '..', '.' sequences,	 * but it still may not be in 'unique' form, depending on the	 * platform.  For instance, Unix is case-sensitive, so the	 * path is ok.  Windows is case-insensitive, and also has the	 * weird 'longname/shortname' thing (e.g. C:/Program Files/ and	 * C:/Progra~1/ are equivalent).  MacOS is case-insensitive.	 * 	 * Virtual file systems which may be registered may have	 * other criteria for normalizing a path.	 */	Tcl_IncrRefCount(retVal);	TclNormalizeToUniquePath(interp, retVal, 0);	/* 	 * Since we know it is a normalized path, we can	 * actually convert this object into an FsPath for	 * greater efficiency 	 */	SetFsPathFromAbsoluteNormalized(interp, retVal);    } else {	/* Init to an empty string */	retVal = Tcl_NewStringObj("",0);	Tcl_IncrRefCount(retVal);    }    /*      * We increment and then decrement the refCount of split to free     * it.  We do this right at the end, in case there are     * optimisations in Tcl_FSJoinPath(split, nplen) above which would     * let it make use of split more effectively if it has a refCount     * of zero.  Also we can't just decrement the ref count, in case     * 'split' was actually returned by the join call above, in a     * single-element optimisation when nplen == 1.     */    Tcl_IncrRefCount(split);    Tcl_DecrRefCount(split);    /* This has a refCount of 1 for the caller */    return retVal;}/* *--------------------------------------------------------------------------- * * TclNormalizeToUniquePath -- * * Description: *	Takes a path specification containing no ../, ./ sequences, *	and converts it into a unique path for the given platform. *      On MacOS, Unix, this means the path must be free of *	symbolic links/aliases, and on Windows it means we want the *	long form, with that long form's case-dependence (which gives *	us a unique, case-dependent path). * * Results: *	The pathPtr is modified in place.  The return value is *	the last byte offset which was recognised in the path *	string. * * Side effects: *	None (beyond the memory allocation for the result). * * Special notes: *	If the filesystem-specific normalizePathProcs can re-introduce *	../, ./ sequences into the path, then this function will *	not return the correct result.  This may be possible with *	symbolic links on unix/macos. * *      Important assumption: if startAt is non-zero, it must point *      to a directory separator that we know exists and is already *      normalized (so it is important not to point to the char just *      after the separator). *--------------------------------------------------------------------------- */static intTclNormalizeToUniquePath(interp, pathPtr, startAt)    Tcl_Interp *interp;    Tcl_Obj *pathPtr;    int startAt;{    FilesystemRecord *fsRecPtr;    /*     * Call each of the "normalise path" functions in succession. This is     * a special case, in which if we have a native filesystem handler,     * we call it first.  This is because the root of Tcl's filesystem     * is always a native filesystem (i.e. '/' on unix is native).     */    fsRecPtr = FsGetIterator();    while (fsRecPtr != NULL) {        if (fsRecPtr == &nativeFilesystemRecord) {	    Tcl_FSNormalizePathProc *proc = fsRecPtr->fsPtr->normalizePathProc;	    if (proc != NULL) {		startAt = (*proc)(interp, pathPtr, startAt);	    }	    break;        }	fsRecPtr = fsRecPtr->nextPtr;    }    FsReleaseIterator();        fsRecPtr = FsGetIterator();    while (fsRecPtr != NULL) {	/* Skip the native system next time through */	if (fsRecPtr != &nativeFilesystemRecord) {	    Tcl_FSNormalizePathProc *proc = fsRecPtr->fsPtr->normalizePathProc;	    if (proc != NULL) {		startAt = (*proc)(interp, pathPtr, startAt);	    }	    /* 	     * We could add an efficiency check like this:	     * 	     *   if (retVal == length-of(pathPtr)) {break;}	     * 	     * but there's not much benefit.	     */	}	fsRecPtr = fsRecPtr->nextPtr;    }    FsReleaseIterator();    return (startAt);}/* *--------------------------------------------------------------------------- * * TclGetOpenMode -- * * Description: *	Computes a POSIX mode mask for opening a file, from a given string, *	and also sets a flag to indicate whether the caller should seek to *	EOF after opening the file. * * Results: *	On success, returns mode to pass to "open". If an error occurs, the *	return value is -1 and if interp is not NULL, sets interp's result *	object to an error message. * * Side effects: *	Sets the integer referenced by seekFlagPtr to 1 to tell the caller *	to seek to EOF after opening the file. * * Special note: *	This code is based on a prototype implementation contributed *	by Mark Diekhans. * *--------------------------------------------------------------------------- */intTclGetOpenMode(interp, string, seekFlagPtr)    Tcl_Interp *interp;			/* Interpreter to use for error					 * reporting - may be NULL. */    CONST char *string;			/* Mode string, e.g. "r+" or					 * "RDONLY CREAT". */    int *seekFlagPtr;			/* Set this to 1 if the caller                                         * should seek to EOF during the                                         * opening of the file. */{    int mode, modeArgc, c, i, gotRW;    CONST char **modeArgv, *flag;#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)    /*     * Check for the simpler fopen-like access modes (e.g. "r").  They     * are distinguished from the POSIX access modes by the presence     * of a lower-case first letter.     */    *seekFlagPtr = 0;    mode = 0;    /*     * Guard against international characters before using byte oriented     * routines.     */    if (!(string[0] & 0x80)	    && islower(UCHAR(string[0]))) { /* INTL: ISO only. */	switch (string[0]) {	    case 'r':		mode = O_RDONLY;		break;	    case 'w':		mode = O_WRONLY|O_CREAT|O_TRUNC;		break;	    case 'a':		mode = O_WRONLY|O_CREAT;                *seekFlagPtr = 1;		break;	    default:		error:                if (interp != (Tcl_Interp *) NULL) {                    Tcl_AppendResult(interp,                            "illegal access mode \"", string, "\"",                            (char *) NULL);                }		return -1;	}	if (string[1] == '+') {	    mode &= ~(O_RDONLY|O_WRONLY);	    mode |= O_RDWR;	    if (string[2] != 0) {		goto error;	    }	} else if (string[1] != 0) {	    goto error;	}        return mode;    }    /*     * The access modes are specified using a list of POSIX modes     * such as O_CREAT.     *     * IMPORTANT NOTE: We rely on Tcl_SplitList working correctly when     * a NULL interpreter is passed in.     */    if (Tcl_SplitList(interp, string, &modeArgc, &modeArgv) != TCL_OK) {        if (interp != (Tcl_Interp *) NULL) {            Tcl_AddErrorInfo(interp,                    "\n    while processing open access modes \"");

⌨️ 快捷键说明

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