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

📄 tclfcmd.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * vice-versa.  This is a policy decision based on the fact that	 * existing implementations of copy and rename on all platforms	 * also prevent this.	 */	if (S_ISDIR(sourceStatBuf.st_mode)                && !S_ISDIR(targetStatBuf.st_mode)) {	    errno = EISDIR;	    Tcl_AppendResult(interp, "can't overwrite file \"", 		    Tcl_GetString(target), "\" with directory \"", 		    Tcl_GetString(source), "\"", (char *) NULL);	    goto done;	}	if (!S_ISDIR(sourceStatBuf.st_mode)	        && S_ISDIR(targetStatBuf.st_mode)) {	    errno = EISDIR;	    Tcl_AppendResult(interp, "can't overwrite directory \"", 		    Tcl_GetString(target), "\" with file \"", 		    Tcl_GetString(source), "\"", (char *) NULL);	    goto done;	}    }    if (copyFlag == 0) {	result = Tcl_FSRenameFile(source, target);	if (result == TCL_OK) {	    goto done;	}	    	if (errno == EINVAL) {	    Tcl_AppendResult(interp, "error renaming \"", 		    Tcl_GetString(source), "\" to \"",		    Tcl_GetString(target), "\": trying to rename a volume or ",		    "move a directory into itself", (char *) NULL);	    goto done;	} else if (errno != EXDEV) {	    errfile = target;	    goto done;	}		/*	 * The rename failed because the move was across file systems.	 * Fall through to copy file and then remove original.  Note that	 * the low-level Tcl_FSRenameFileProc in the filesystem is allowed 	 * to implement cross-filesystem moves itself, if it desires.	 */    }    actualSource = source;    Tcl_IncrRefCount(actualSource);#if 0#ifdef S_ISLNK    /*      * To add a flag to make 'copy' copy links instead of files, we could     * add a condition to ignore this 'if' here.     */    if (copyFlag && S_ISLNK(sourceStatBuf.st_mode)) {	/* 	 * We want to copy files not links.  Therefore we must follow the	 * link.  There are two purposes to this 'stat' call here.  First	 * we want to know if the linked-file/dir actually exists, and	 * second, in the block of code which follows, some 20 lines	 * down, we want to check if the thing is a file or directory.	 */	if (Tcl_FSStat(source, &sourceStatBuf) != 0) {	    /* Actual file doesn't exist */	    Tcl_AppendResult(interp, 		    "error copying \"", Tcl_GetString(source), 		    "\": the target of this link doesn't exist",		    (char *) NULL);	    goto done;	} else {	    int counter = 0;	    while (1) {		Tcl_Obj *path = Tcl_FSLink(actualSource, NULL, 0);		if (path == NULL) {		    break;		}		Tcl_DecrRefCount(actualSource);		actualSource = path;		counter++;		/* Arbitrary limit of 20 links to follow */		if (counter > 20) {		    /* Too many links */		    Tcl_SetErrno(EMLINK);		    errfile = source;		    goto done;		}	    }	    /* Now 'actualSource' is the correct file */	}    }#endif#endif    if (S_ISDIR(sourceStatBuf.st_mode)) {	result = Tcl_FSCopyDirectory(actualSource, target, &errorBuffer);	if (result != TCL_OK) {	    if (errno == EXDEV) {		/* 		 * The copy failed because we're trying to do a		 * cross-filesystem copy.  We do this through our Tcl		 * library.		 */		Tcl_SavedResult savedResult;		Tcl_Obj *copyCommand = Tcl_NewListObj(0,NULL);		Tcl_IncrRefCount(copyCommand);		Tcl_ListObjAppendElement(interp, copyCommand, 			Tcl_NewStringObj("::tcl::CopyDirectory",-1));		if (copyFlag) {		    Tcl_ListObjAppendElement(interp, copyCommand, 					     Tcl_NewStringObj("copying",-1));		} else {		    Tcl_ListObjAppendElement(interp, copyCommand, 					     Tcl_NewStringObj("renaming",-1));		}		Tcl_ListObjAppendElement(interp, copyCommand, source);		Tcl_ListObjAppendElement(interp, copyCommand, target);		Tcl_SaveResult(interp, &savedResult);		result = Tcl_EvalObjEx(interp, copyCommand, 				       TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);		Tcl_DecrRefCount(copyCommand);		if (result != TCL_OK) {		    /* 		     * There was an error in the Tcl-level copy.		     * We will pass on the Tcl error message and		     * can ensure this by setting errfile to NULL		     */		    Tcl_DiscardResult(&savedResult);		    errfile = NULL;		} else {		    /* The copy was successful */		    Tcl_RestoreResult(interp, &savedResult);		}	    } else {		errfile = errorBuffer;		if (Tcl_FSEqualPaths(errfile, source)) {		    errfile = source;		} else if (Tcl_FSEqualPaths(errfile, target)) {		    errfile = target;		}	    }	}    } else {	result = Tcl_FSCopyFile(actualSource, target);	if ((result != TCL_OK) && (errno == EXDEV)) {	    result = TclCrossFilesystemCopy(interp, source, target);	}	if (result != TCL_OK) {	    /* 	     * We could examine 'errno' to double-check if the problem	     * was with the target, but we checked the source above,	     * so it should be quite clear 	     */	    errfile = target;	}    }    if ((copyFlag == 0) && (result == TCL_OK)) {	if (S_ISDIR(sourceStatBuf.st_mode)) {	    result = Tcl_FSRemoveDirectory(source, 1, &errorBuffer);	    if (result != TCL_OK) {		if (Tcl_FSEqualPaths(errfile, source) == 0) {		    errfile = source;		}	    }	} else {	    result = Tcl_FSDeleteFile(source);	    if (result != TCL_OK) {		errfile = source;	    }	}	if (result != TCL_OK) {	    Tcl_AppendResult(interp, "can't unlink \"", 		Tcl_GetString(errfile), "\": ",		Tcl_PosixError(interp), (char *) NULL);	    errfile = NULL;	}    }        done:    if (errfile != NULL) {	Tcl_AppendResult(interp, 		((copyFlag) ? "error copying \"" : "error renaming \""),		 Tcl_GetString(source), (char *) NULL);	if (errfile != source) {	    Tcl_AppendResult(interp, "\" to \"", Tcl_GetString(target), 			     (char *) NULL);	    if (errfile != target) {		Tcl_AppendResult(interp, "\": \"", Tcl_GetString(errfile), 				 (char *) NULL);	    }	}	Tcl_AppendResult(interp, "\": ", Tcl_PosixError(interp),		(char *) NULL);    }    if (errorBuffer != NULL) {        Tcl_DecrRefCount(errorBuffer);    }    if (actualSource != NULL) {	Tcl_DecrRefCount(actualSource);    }    return result;}/* *--------------------------------------------------------------------------- * * FileForceOption -- * *	Helps parse command line options for file commands that take *	the "-force" and "--" options. * * Results: *	The return value is how many arguments from argv were consumed *	by this function, or -1 if there was an error parsing the *	options.  If an error occurred, an error message is left in the *	interp's result. * * Side effects: *	None. * *--------------------------------------------------------------------------- */static intFileForceOption(interp, objc, objv, forcePtr)    Tcl_Interp *interp;		/* Interp, for error return. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument strings.  First command line				 * option, if it exists, begins at 0. */    int *forcePtr;		/* If the "-force" was specified, *forcePtr				 * is filled with 1, otherwise with 0. */{    int force, i;        force = 0;    for (i = 0; i < objc; i++) {	if (Tcl_GetString(objv[i])[0] != '-') {	    break;	}	if (strcmp(Tcl_GetString(objv[i]), "-force") == 0) {	    force = 1;	} else if (strcmp(Tcl_GetString(objv[i]), "--") == 0) {	    i++;	    break;	} else {	    Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[i]), 		    "\": should be -force or --", (char *)NULL);	    return -1;	}    }    *forcePtr = force;    return i;}/* *--------------------------------------------------------------------------- * * FileBasename -- * *	Given a path in either tcl format (with / separators), or in the *	platform-specific format for the current platform, return all the *	characters in the path after the last directory separator.  But, *	if path is the root directory, returns no characters. * * Results: *	Returns the string object that represents the basename.  If there  *	is an error, an error message is left in interp, and NULL is  *	returned. * * Side effects: *	None. * *--------------------------------------------------------------------------- */static Tcl_Obj *FileBasename(interp, pathPtr)    Tcl_Interp *interp;		/* Interp, for error return. */    Tcl_Obj *pathPtr;		/* Path whose basename to extract. */{    int objc;    Tcl_Obj *splitPtr;    Tcl_Obj *resultPtr = NULL;        splitPtr = Tcl_FSSplitPath(pathPtr, &objc);    if (objc != 0) {	if ((objc == 1) && (*Tcl_GetString(pathPtr) == '~')) {	    Tcl_DecrRefCount(splitPtr);	    if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {		return NULL;	    }	    splitPtr = Tcl_FSSplitPath(pathPtr, &objc);	}	/*	 * Return the last component, unless it is the only component, and it	 * is the root of an absolute path.	 */	if (objc > 0) {	    Tcl_ListObjIndex(NULL, splitPtr, objc-1, &resultPtr);	    if ((objc == 1) &&	      (Tcl_FSGetPathType(resultPtr) != TCL_PATH_RELATIVE)) {		resultPtr = NULL;	    }	}    }    if (resultPtr == NULL) {	resultPtr = Tcl_NewObj();    }    Tcl_IncrRefCount(resultPtr);    Tcl_DecrRefCount(splitPtr);    return resultPtr;}/* *---------------------------------------------------------------------- * * TclFileAttrsCmd -- * *      Sets or gets the platform-specific attributes of a file.  The *      objc-objv points to the file name with the rest of the command *      line following.  This routine uses platform-specific tables of *      option strings and callbacks.  The callback to get the *      attributes take three parameters: *	    Tcl_Interp *interp;	    The interp to report errors with. *				    Since this is an object-based API, *				    the object form of the result should  *				    be used. *	    CONST char *fileName;   This is extracted using *				    Tcl_TranslateFileName. *	    TclObj **attrObjPtrPtr; A new object to hold the attribute *				    is allocated and put here. *	The first two parameters of the callback used to write out the *	attributes are the same. The third parameter is: *	    CONST *attrObjPtr;	    A pointer to the object that has *				    the new attribute. *	They both return standard TCL errors; if the routine to get *	an attribute fails, no object is allocated and *attrObjPtrPtr *	is unchanged. * * Results: *      Standard TCL error. * * Side effects: *      May set file attributes for the file name. *       *---------------------------------------------------------------------- */intTclFileAttrsCmd(interp, objc, objv)    Tcl_Interp *interp;		/* The interpreter for error reporting. */    int objc;			/* Number of command line arguments. */    Tcl_Obj *CONST objv[];	/* The command line objects. */{    int result;    CONST char ** attributeStrings;    Tcl_Obj* objStrings = NULL;    int numObjStrings = -1;    Tcl_Obj *filePtr;        if (objc < 3) {	Tcl_WrongNumArgs(interp, 2, objv,		"name ?option? ?value? ?option value ...?");	return TCL_ERROR;    }    filePtr = objv[2];    if (Tcl_FSConvertToPathType(interp, filePtr) != TCL_OK) {    	return TCL_ERROR;    }        objc -= 3;    objv += 3;    result = TCL_ERROR;    Tcl_SetErrno(0);    attributeStrings = Tcl_FSFileAttrStrings(filePtr, &objStrings);    if (attributeStrings == NULL) {	int index;	Tcl_Obj *objPtr;	if (objStrings == NULL) {	    if (Tcl_GetErrno() != 0) {		/* 		 * There was an error, probably that the filePtr is		 * not accepted by any filesystem		 */		Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 			"could not read \"", Tcl_GetString(filePtr), 			"\": ", Tcl_PosixError(interp), 			(char *) NULL);		return TCL_ERROR;	    }	    goto end;	}	/* We own the object now */	Tcl_IncrRefCount(objStrings);        /* Use objStrings as a list object */	if (Tcl_ListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) {	    goto end;	}	attributeStrings = (CONST char **)		ckalloc ((1+numObjStrings) * sizeof(char*));	for (index = 0; index < numObjStrings; index++) {	    Tcl_ListObjIndex(interp, objStrings, index, &objPtr);	    attributeStrings[index] = Tcl_GetString(objPtr);	}	attributeStrings[index] = NULL;    }    if (objc == 0) {	/*	 * Get all attributes.	 */	int index;	Tcl_Obj *listPtr;	 	listPtr = Tcl_NewListObj(0, NULL);	for (index = 0; attributeStrings[index] != NULL; index++) {	    Tcl_Obj *objPtr = Tcl_NewStringObj(attributeStrings[index], -1);	    Tcl_ListObjAppendElement(interp, listPtr, objPtr);	    /* We now forget about objPtr, it is in the list */	    objPtr = NULL;	    if (Tcl_FSFileAttrsGet(interp, index, filePtr,		    &objPtr) != TCL_OK) {		Tcl_DecrRefCount(listPtr);		goto end;	    }	    Tcl_ListObjAppendElement(interp, listPtr, objPtr);	}    	Tcl_SetObjResult(interp, listPtr);    } else if (objc == 1) {	/*	 * Get one attribute.	 */	int index;	Tcl_Obj *objPtr = NULL;	if (numObjStrings == 0) {	    Tcl_AppendResult(interp, "bad option \"",		    Tcl_GetString(objv[0]), "\", there are no file attributes"			     " in this filesystem.", (char *) NULL);	    goto end;	}	if (Tcl_GetIndexFromObj(interp, objv[0], attributeStrings,		"option", 0, &index) != TCL_OK) {	    goto end;	}	if (Tcl_FSFileAttrsGet(interp, index, filePtr,		&objPtr) != TCL_OK) {	    goto end;	}	Tcl_SetObjResult(interp, objPtr);    } else {	/*	 * Set option/value pairs.	 */	int i, index;        	if (numObjStrings == 0) {	    Tcl_AppendResult(interp, "bad option \"",		    Tcl_GetString(objv[0]), "\", there are no file attributes"			     " in this filesystem.", (char *) NULL);	    goto end;	}    	for (i = 0; i < objc ; i += 2) {    	    if (Tcl_GetIndexFromObj(interp, objv[i], attributeStrings,		    "option", 0, &index) != TCL_OK) {		goto end;    	    }	    if (i + 1 == objc) {		Tcl_AppendResult(interp, "value for \"",			Tcl_GetString(objv[i]), "\" missing",			(char *) NULL);		goto end;	    }    	    if (Tcl_FSFileAttrsSet(interp, index, filePtr,    	    	    objv[i + 1]) != TCL_OK) {		goto end;    	    }    	}    }    result = TCL_OK;    end:    if (numObjStrings != -1) {	/* Free up the array we allocated */	ckfree((char*)attributeStrings);	/* 	 * We don't need this object that was passed to us	 * any more.	 */	if (objStrings != NULL) {	    Tcl_DecrRefCount(objStrings);	}    }    return result;}

⌨️ 快捷键说明

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