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

📄 tclwinfcmd.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * tclWinFCmd.c * *      This file implements the Windows specific portion of file manipulation  *      subcommands of the "file" command.  * * Copyright (c) 1996-1998 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: tclWinFCmd.c,v 1.34 2003/02/04 17:06:53 vincentdarley Exp $ */#include "tclWinInt.h"/* * The following constants specify the type of callback when * TraverseWinTree() calls the traverseProc() */#define DOTREE_PRED   1     /* pre-order directory  */#define DOTREE_POSTD  2     /* post-order directory */#define DOTREE_F      3     /* regular file *//* * Callbacks for file attributes code. */static int		GetWinFileAttributes _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetWinFileLongName _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetWinFileShortName _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj **attributePtrPtr));static int		SetWinFileAttributes _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj *attributePtr));static int		CannotSetAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj *attributePtr));/* * Constants and variables necessary for file attributes subcommand. */enum {    WIN_ARCHIVE_ATTRIBUTE,    WIN_HIDDEN_ATTRIBUTE,    WIN_LONGNAME_ATTRIBUTE,    WIN_READONLY_ATTRIBUTE,    WIN_SHORTNAME_ATTRIBUTE,    WIN_SYSTEM_ATTRIBUTE};static int attributeArray[] = {FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_HIDDEN,	0, FILE_ATTRIBUTE_READONLY, 0, FILE_ATTRIBUTE_SYSTEM};CONST char *tclpFileAttrStrings[] = {	"-archive", "-hidden", "-longname", "-readonly",	"-shortname", "-system", (char *) NULL};CONST TclFileAttrProcs tclpFileAttrProcs[] = {	{GetWinFileAttributes, SetWinFileAttributes},	{GetWinFileAttributes, SetWinFileAttributes},	{GetWinFileLongName, CannotSetAttribute},	{GetWinFileAttributes, SetWinFileAttributes},	{GetWinFileShortName, CannotSetAttribute},	{GetWinFileAttributes, SetWinFileAttributes}};#if defined(HAVE_NO_SEH) && defined(TCL_MEM_DEBUG)static void *INITIAL_ESP,            *INITIAL_EBP,            *INITIAL_HANDLER,            *RESTORED_ESP,            *RESTORED_EBP,            *RESTORED_HANDLER;#endif /* HAVE_NO_SEH && TCL_MEM_DEBUG *//* * Prototype for the TraverseWinTree callback function. */typedef int (TraversalProc)(CONST TCHAR *srcPtr, CONST TCHAR *dstPtr, 	int type, Tcl_DString *errorPtr);/* * Declarations for local procedures defined in this file: */static void		StatError(Tcl_Interp *interp, Tcl_Obj *fileName);static int		ConvertFileNameFormat(Tcl_Interp *interp, 			    int objIndex, Tcl_Obj *fileName, int longShort,			    Tcl_Obj **attributePtrPtr);static int		DoCopyFile(CONST TCHAR *srcPtr, CONST TCHAR *dstPtr);static int		DoCreateDirectory(CONST TCHAR *pathPtr);static int		DoRemoveJustDirectory(CONST TCHAR *nativeSrc, 			    int ignoreError, Tcl_DString *errorPtr);static int		DoRemoveDirectory(Tcl_DString *pathPtr, int recursive, 			    Tcl_DString *errorPtr);static int		DoRenameFile(CONST TCHAR *nativeSrc, CONST TCHAR *dstPtr);static int		TraversalCopy(CONST TCHAR *srcPtr, CONST TCHAR *dstPtr, 			    int type, Tcl_DString *errorPtr);static int		TraversalDelete(CONST TCHAR *srcPtr, CONST TCHAR *dstPtr, 			    int type, Tcl_DString *errorPtr);static int		TraverseWinTree(TraversalProc *traverseProc,			    Tcl_DString *sourcePtr, Tcl_DString *dstPtr, 			    Tcl_DString *errorPtr);/* *--------------------------------------------------------------------------- * * TclpObjRenameFile, DoRenameFile -- * *      Changes the name of an existing file or directory, from src to dst. *	If src and dst refer to the same file or directory, does nothing *	and returns success.  Otherwise if dst already exists, it will be *	deleted and replaced by src subject to the following conditions: *	    If src is a directory, dst may be an empty directory. *	    If src is a file, dst may be a file. *	In any other situation where dst already exists, the rename will *	fail.   * * Results: *	If the file or directory was successfully renamed, returns TCL_OK. *	Otherwise the return value is TCL_ERROR and errno is set to *	indicate the error.  Some possible values for errno are: * *	ENAMETOOLONG: src or dst names are too long. *	EACCES:     src or dst parent directory can't be read and/or written. *	EEXIST:	    dst is a non-empty directory. *	EINVAL:	    src is a root directory or dst is a subdirectory of src. *	EISDIR:	    dst is a directory, but src is not. *	ENOENT:	    src doesn't exist.  src or dst is "". *	ENOTDIR:    src is a directory, but dst is not.   *	EXDEV:	    src and dst are on different filesystems. * *	EACCES:     exists an open file already referring to src or dst. *	EACCES:     src or dst specify the current working directory (NT). *	EACCES:	    src specifies a char device (nul:, com1:, etc.)  *	EEXIST:	    dst specifies a char device (nul:, com1:, etc.) (NT) *	EACCES:	    dst specifies a char device (nul:, com1:, etc.) (95) *	 * Side effects: *	The implementation supports cross-filesystem renames of files, *	but the caller should be prepared to emulate cross-filesystem *	renames of directories if errno is EXDEV. * *--------------------------------------------------------------------------- */int TclpObjRenameFile(srcPathPtr, destPathPtr)    Tcl_Obj *srcPathPtr;    Tcl_Obj *destPathPtr;{    return DoRenameFile(Tcl_FSGetNativePath(srcPathPtr), 			Tcl_FSGetNativePath(destPathPtr));}static intDoRenameFile(    CONST TCHAR *nativeSrc,	/* Pathname of file or dir to be renamed				 * (native). */     CONST TCHAR *nativeDst)	/* New pathname for file or directory				 * (native). */{        DWORD srcAttr, dstAttr;    int retval = -1;    /*     * The MoveFile API acts differently under Win95/98 and NT     * WRT NULL and "". Avoid passing these values.     */    if (nativeSrc == NULL || nativeSrc[0] == '\0' ||        nativeDst == NULL || nativeDst[0] == '\0') {	Tcl_SetErrno(ENOENT);	return TCL_ERROR;    }    /*     * The MoveFile API would throw an exception under NT     * if one of the arguments is a char block device.     */#ifdef HAVE_NO_SEH# ifdef TCL_MEM_DEBUG    __asm__ __volatile__ (            "movl %%esp,  %0" "\n\t"            "movl %%ebp,  %1" "\n\t"            "movl %%fs:0, %2" "\n\t"            : "=m"(INITIAL_ESP),              "=m"(INITIAL_EBP),              "=r"(INITIAL_HANDLER) );# endif /* TCL_MEM_DEBUG */    __asm__ __volatile__ (            "pushl %ebp" "\n\t"            "pushl $__except_dorenamefile_handler" "\n\t"            "pushl %fs:0" "\n\t"            "movl  %esp, %fs:0");#else    __try {#endif /* HAVE_NO_SEH */	if ((*tclWinProcs->moveFileProc)(nativeSrc, nativeDst) != FALSE) {	    retval = TCL_OK;	}#ifdef HAVE_NO_SEH    __asm__ __volatile__ (            "jmp  dorenamefile_pop" "\n"        "dorenamefile_reentry:" "\n\t"            "movl %%fs:0, %%eax" "\n\t"            "movl 0x8(%%eax), %%esp" "\n\t"            "movl 0x8(%%esp), %%ebp" "\n"        "dorenamefile_pop:" "\n\t"            "movl (%%esp), %%eax" "\n\t"            "movl %%eax, %%fs:0" "\n\t"            "add  $12, %%esp" "\n\t"            :            :            : "%eax");# ifdef TCL_MEM_DEBUG    __asm__ __volatile__ (            "movl  %%esp,  %0" "\n\t"            "movl  %%ebp,  %1" "\n\t"            "movl  %%fs:0, %2" "\n\t"            : "=m"(RESTORED_ESP),              "=m"(RESTORED_EBP),              "=r"(RESTORED_HANDLER) );    if (INITIAL_ESP != RESTORED_ESP)        panic("ESP restored incorrectly");    if (INITIAL_EBP != RESTORED_EBP)        panic("EBP restored incorrectly");    if (INITIAL_HANDLER != RESTORED_HANDLER)        panic("HANDLER restored incorrectly");# endif /* TCL_MEM_DEBUG */#else    } __except (EXCEPTION_EXECUTE_HANDLER) {}#endif /* HAVE_NO_SEH */    /*     * Avoid using control flow statements in the SEH guarded block!     */    if (retval != -1)        return retval;    TclWinConvertError(GetLastError());    srcAttr = (*tclWinProcs->getFileAttributesProc)(nativeSrc);    dstAttr = (*tclWinProcs->getFileAttributesProc)(nativeDst);    if (srcAttr == 0xffffffff) {	if ((*tclWinProcs->getFullPathNameProc)(nativeSrc, 0, NULL, NULL) >= MAX_PATH) {	    errno = ENAMETOOLONG;	    return TCL_ERROR;	}	srcAttr = 0;    }    if (dstAttr == 0xffffffff) {	if ((*tclWinProcs->getFullPathNameProc)(nativeDst, 0, NULL, NULL) >= MAX_PATH) {	    errno = ENAMETOOLONG;	    return TCL_ERROR;	}	dstAttr = 0;    }    if (errno == EBADF) {	errno = EACCES;	return TCL_ERROR;    }    if (errno == EACCES) {	decode:	if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) {	    TCHAR *nativeSrcRest, *nativeDstRest;	    CONST char **srcArgv, **dstArgv;	    int size, srcArgc, dstArgc;	    WCHAR nativeSrcPath[MAX_PATH];	    WCHAR nativeDstPath[MAX_PATH];	    Tcl_DString srcString, dstString;	    CONST char *src, *dst;	    size = (*tclWinProcs->getFullPathNameProc)(nativeSrc, MAX_PATH, 		    nativeSrcPath, &nativeSrcRest);	    if ((size == 0) || (size > MAX_PATH)) {		return TCL_ERROR;	    }	    size = (*tclWinProcs->getFullPathNameProc)(nativeDst, MAX_PATH, 		    nativeDstPath, &nativeDstRest);	    if ((size == 0) || (size > MAX_PATH)) {		return TCL_ERROR;	    }	    (*tclWinProcs->charLowerProc)((TCHAR *) nativeSrcPath);	    (*tclWinProcs->charLowerProc)((TCHAR *) nativeDstPath);	    src = Tcl_WinTCharToUtf((TCHAR *) nativeSrcPath, -1, &srcString);	    dst = Tcl_WinTCharToUtf((TCHAR *) nativeDstPath, -1, &dstString);	    if (strncmp(src, dst, (size_t) Tcl_DStringLength(&srcString)) == 0) {		/*		 * Trying to move a directory into itself.		 */		errno = EINVAL;		Tcl_DStringFree(&srcString);		Tcl_DStringFree(&dstString);		return TCL_ERROR;	    }	    Tcl_SplitPath(src, &srcArgc, &srcArgv);	    Tcl_SplitPath(dst, &dstArgc, &dstArgv);	    Tcl_DStringFree(&srcString);	    Tcl_DStringFree(&dstString);	    if (srcArgc == 1) {		/*		 * They are trying to move a root directory.  Whether		 * or not it is across filesystems, this cannot be		 * done.		 */		Tcl_SetErrno(EINVAL);	    } else if ((srcArgc > 0) && (dstArgc > 0) &&		    (strcmp(srcArgv[0], dstArgv[0]) != 0)) {		/*		 * If src is a directory and dst filesystem != src		 * filesystem, errno should be EXDEV.  It is very		 * important to get this behavior, so that the caller		 * can respond to a cross filesystem rename by		 * simulating it with copy and delete.  The MoveFile		 * system call already handles the case of moving a		 * file between filesystems.		 */		Tcl_SetErrno(EXDEV);	    }	    ckfree((char *) srcArgv);	    ckfree((char *) dstArgv);	}	/*	 * Other types of access failure is that dst is a read-only	 * filesystem, that an open file referred to src or dest, or that	 * src or dest specified the current working directory on the	 * current filesystem.  EACCES is returned for those cases.	 */    } else if (Tcl_GetErrno() == EEXIST) {	/*	 * Reports EEXIST any time the target already exists.  If it makes	 * sense, remove the old file and try renaming again.	 */	if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) {	    if (dstAttr & FILE_ATTRIBUTE_DIRECTORY) {		/*		 * Overwrite empty dst directory with src directory.  The		 * following call will remove an empty directory.  If it		 * fails, it's because it wasn't empty.		 */		if (DoRemoveJustDirectory(nativeDst, 0, NULL) == TCL_OK) {		    /*		     * Now that that empty directory is gone, we can try		     * renaming again.  If that fails, we'll put this empty		     * directory back, for completeness.		     */		    if ((*tclWinProcs->moveFileProc)(nativeSrc, nativeDst) != FALSE) {			return TCL_OK;		    }		    /*		     * Some new error has occurred.  Don't know what it		     * could be, but report this one.		     */		    TclWinConvertError(GetLastError());		    (*tclWinProcs->createDirectoryProc)(nativeDst, NULL);		    (*tclWinProcs->setFileAttributesProc)(nativeDst, dstAttr);		    if (Tcl_GetErrno() == EACCES) {			/*			 * Decode the EACCES to a more meaningful error.			 */			goto decode;		    }		}	    } else {	/* (dstAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 */		Tcl_SetErrno(ENOTDIR);	    }	} else {    /* (srcAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 */	    if (dstAttr & FILE_ATTRIBUTE_DIRECTORY) {		Tcl_SetErrno(EISDIR);	    } else {		/*		 * Overwrite existing file by:		 * 		 * 1. Rename existing file to temp name.		 * 2. Rename old file to new name.		 * 3. If success, delete temp file.  If failure,		 *    put temp file back to old name.		 */		TCHAR *nativeRest, *nativeTmp, *nativePrefix;		int result, size;		WCHAR tempBuf[MAX_PATH];				size = (*tclWinProcs->getFullPathNameProc)(nativeDst, MAX_PATH, 			tempBuf, &nativeRest);		if ((size == 0) || (size > MAX_PATH) || (nativeRest == NULL)) {		    return TCL_ERROR;		}		nativeTmp = (TCHAR *) tempBuf;		((char *) nativeRest)[0] = '\0';		((char *) nativeRest)[1] = '\0';    /* In case it's Unicode. */		result = TCL_ERROR;		nativePrefix = (tclWinProcs->useWide) 			? (TCHAR *) L"tclr" : (TCHAR *) "tclr";		if ((*tclWinProcs->getTempFileNameProc)(nativeTmp, 			nativePrefix, 0, tempBuf) != 0) {		    /*		     * Strictly speaking, need the following DeleteFile and		     * MoveFile to be joined as an atomic operation so no		     * other app comes along in the meantime and creates the		     * same temp file.		     */		     		    nativeTmp = (TCHAR *) tempBuf;		    (*tclWinProcs->deleteFileProc)(nativeTmp);		    if ((*tclWinProcs->moveFileProc)(nativeDst, nativeTmp) != FALSE) {			if ((*tclWinProcs->moveFileProc)(nativeSrc, nativeDst) != FALSE) {			    (*tclWinProcs->setFileAttributesProc)(nativeTmp, 				    FILE_ATTRIBUTE_NORMAL);			    (*tclWinProcs->deleteFileProc)(nativeTmp);			    return TCL_OK;			} else {			    (*tclWinProcs->deleteFileProc)(nativeDst);			    (*tclWinProcs->moveFileProc)(nativeTmp, nativeDst);			}		    } 		    /*		     * Can't backup dst file or move src file.  Return that		     * error.  Could happen if an open file refers to dst.		     */		    TclWinConvertError(GetLastError());		    if (Tcl_GetErrno() == EACCES) {			/*			 * Decode the EACCES to a more meaningful error.			 */			goto decode;		    }		}		return result;	    }	}    }    return TCL_ERROR;}#ifdef HAVE_NO_SEHstatic__attribute__ ((cdecl)) __attribute__ ((used))EXCEPTION_DISPOSITION_except_dorenamefile_handler(

⌨️ 快捷键说明

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