📄 tclwinfcmd.c
字号:
struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext){ __asm__ __volatile__ ( "jmp dorenamefile_reentry"); /* Nuke compiler warning about unused static function */ _except_dorenamefile_handler(NULL, NULL, NULL, NULL); return 0; /* Function does not return */}#endif /* HAVE_NO_SEH *//* *--------------------------------------------------------------------------- * * TclpObjCopyFile, DoCopyFile -- * * Copy a single file (not a directory). If dst already exists and * is not a directory, it is removed. * * Results: * If the file was successfully copied, returns TCL_OK. Otherwise * the return value is TCL_ERROR and errno is set to indicate the * error. Some possible values for errno are: * * EACCES: src or dst parent directory can't be read and/or written. * EISDIR: src or dst is a directory. * ENOENT: src doesn't exist. src or dst is "". * * EACCES: exists an open file already referring to dst (95). * EACCES: src specifies a char device (nul:, com1:, etc.) (NT) * ENOENT: src specifies a char device (nul:, com1:, etc.) (95) * * Side effects: * It is not an error to copy to a char device. * *--------------------------------------------------------------------------- */int TclpObjCopyFile(srcPathPtr, destPathPtr) Tcl_Obj *srcPathPtr; Tcl_Obj *destPathPtr;{ return DoCopyFile(Tcl_FSGetNativePath(srcPathPtr), Tcl_FSGetNativePath(destPathPtr));}static intDoCopyFile( CONST TCHAR *nativeSrc, /* Pathname of file to be copied (native). */ CONST TCHAR *nativeDst) /* Pathname of file to copy to (native). */{ int retval = -1; /* * The CopyFile 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 CopyFile 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_docopyfile_handler" "\n\t" "pushl %fs:0" "\n\t" "movl %esp, %fs:0");#else __try {#endif /* HAVE_NO_SEH */ if ((*tclWinProcs->copyFileProc)(nativeSrc, nativeDst, 0) != FALSE) { retval = TCL_OK; }#ifdef HAVE_NO_SEH __asm__ __volatile__ ( "jmp docopyfile_pop" "\n" "docopyfile_reentry:" "\n\t" "movl %%fs:0, %%eax" "\n\t" "movl 0x8(%%eax), %%esp" "\n\t" "movl 0x8(%%esp), %%ebp" "\n" "docopyfile_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()); if (Tcl_GetErrno() == EBADF) { Tcl_SetErrno(EACCES); return TCL_ERROR; } if (Tcl_GetErrno() == EACCES) { DWORD srcAttr, dstAttr; srcAttr = (*tclWinProcs->getFileAttributesProc)(nativeSrc); dstAttr = (*tclWinProcs->getFileAttributesProc)(nativeDst); if (srcAttr != 0xffffffff) { if (dstAttr == 0xffffffff) { dstAttr = 0; } if ((srcAttr & FILE_ATTRIBUTE_DIRECTORY) || (dstAttr & FILE_ATTRIBUTE_DIRECTORY)) { if (srcAttr & FILE_ATTRIBUTE_REPARSE_POINT) { /* Source is a symbolic link -- copy it */ if (TclWinSymLinkCopyDirectory(nativeSrc, nativeDst) == 0) { return TCL_OK; } } Tcl_SetErrno(EISDIR); } if (dstAttr & FILE_ATTRIBUTE_READONLY) { (*tclWinProcs->setFileAttributesProc)(nativeDst, dstAttr & ~((DWORD)FILE_ATTRIBUTE_READONLY)); if ((*tclWinProcs->copyFileProc)(nativeSrc, nativeDst, 0) != FALSE) { return TCL_OK; } /* * Still can't copy onto dst. Return that error, and * restore attributes of dst. */ TclWinConvertError(GetLastError()); (*tclWinProcs->setFileAttributesProc)(nativeDst, dstAttr); } } } return TCL_ERROR;}#ifdef HAVE_NO_SEHstatic__attribute__ ((cdecl)) __attribute__ ((used))EXCEPTION_DISPOSITION_except_docopyfile_handler( struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext){ __asm__ __volatile__ ( "jmp docopyfile_reentry"); _except_docopyfile_handler(NULL,NULL,NULL,NULL); return 0; /* Function does not return */}#endif /* HAVE_NO_SEH *//* *--------------------------------------------------------------------------- * * TclpObjDeleteFile, TclpDeleteFile -- * * Removes a single file (not a directory). * * Results: * If the file was successfully deleted, returns TCL_OK. Otherwise * the return value is TCL_ERROR and errno is set to indicate the * error. Some possible values for errno are: * * EACCES: a parent directory can't be read and/or written. * EISDIR: path is a directory. * ENOENT: path doesn't exist or is "". * * EACCES: exists an open file already referring to path. * EACCES: path is a char device (nul:, com1:, etc.) * * Side effects: * The file is deleted, even if it is read-only. * *--------------------------------------------------------------------------- */int TclpObjDeleteFile(pathPtr) Tcl_Obj *pathPtr;{ return TclpDeleteFile(Tcl_FSGetNativePath(pathPtr));}intTclpDeleteFile( CONST TCHAR *nativePath) /* Pathname of file to be removed (native). */{ DWORD attr; /* * The DeleteFile API acts differently under Win95/98 and NT * WRT NULL and "". Avoid passing these values. */ if (nativePath == NULL || nativePath[0] == '\0') { Tcl_SetErrno(ENOENT); return TCL_ERROR; } if ((*tclWinProcs->deleteFileProc)(nativePath) != FALSE) { return TCL_OK; } TclWinConvertError(GetLastError()); if (Tcl_GetErrno() == EACCES) { attr = (*tclWinProcs->getFileAttributesProc)(nativePath); if (attr != 0xffffffff) { if (attr & FILE_ATTRIBUTE_DIRECTORY) { if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { /* It is a symbolic link -- remove it */ if (TclWinSymLinkDelete(nativePath, 0) == 0) { return TCL_OK; } } /* * If we fall through here, it is a directory. * * Windows NT reports removing a directory as EACCES instead * of EISDIR. */ Tcl_SetErrno(EISDIR); } else if (attr & FILE_ATTRIBUTE_READONLY) { int res = (*tclWinProcs->setFileAttributesProc)(nativePath, attr & ~((DWORD)FILE_ATTRIBUTE_READONLY)); if ((res != 0) && ((*tclWinProcs->deleteFileProc)(nativePath) != FALSE)) { return TCL_OK; } TclWinConvertError(GetLastError()); if (res != 0) { (*tclWinProcs->setFileAttributesProc)(nativePath, attr); } } } } else if (Tcl_GetErrno() == ENOENT) { attr = (*tclWinProcs->getFileAttributesProc)(nativePath); if (attr != 0xffffffff) { if (attr & FILE_ATTRIBUTE_DIRECTORY) { /* * Windows 95 reports removing a directory as ENOENT instead * of EISDIR. */ Tcl_SetErrno(EISDIR); } } } else if (Tcl_GetErrno() == EINVAL) { /* * Windows NT reports removing a char device as EINVAL instead of * EACCES. */ Tcl_SetErrno(EACCES); } return TCL_ERROR;}/* *--------------------------------------------------------------------------- * * TclpObjCreateDirectory -- * * Creates the specified directory. All parent directories of the * specified directory must already exist. The directory is * automatically created with permissions so that user can access * the new directory and create new files or subdirectories in it. * * Results: * If the directory was successfully created, returns TCL_OK. * Otherwise the return value is TCL_ERROR and errno is set to * indicate the error. Some possible values for errno are: * * EACCES: a parent directory can't be read and/or written. * EEXIST: path already exists. * ENOENT: a parent directory doesn't exist. * * Side effects: * A directory is created. * *--------------------------------------------------------------------------- */int TclpObjCreateDirectory(pathPtr) Tcl_Obj *pathPtr;{ return DoCreateDirectory(Tcl_FSGetNativePath(pathPtr));}static intDoCreateDirectory( CONST TCHAR *nativePath) /* Pathname of directory to create (native). */{ DWORD error; if ((*tclWinProcs->createDirectoryProc)(nativePath, NULL) == 0) { error = GetLastError(); TclWinConvertError(error); return TCL_ERROR; } return TCL_OK;}/* *--------------------------------------------------------------------------- * * TclpObjCopyDirectory -- * * Recursively copies a directory. The target directory dst must * not already exist. Note that this function does not merge two * directory hierarchies, even if the target directory is an an * empty directory. * * Results: * If the directory was successfully copied, returns TCL_OK. * Otherwise the return value is TCL_ERROR, errno is set to indicate * the error, and the pathname of the file that caused the error * is stored in errorPtr. See TclpCreateDirectory and TclpCopyFile * for a description of possible values for errno. * * Side effects: * An exact copy of the directory hierarchy src will be created * with the name dst. If an error occurs, the error will * be returned immediately, and remaining files will not be * processed. * *--------------------------------------------------------------------------- */int TclpObjCopyDirectory(srcPathPtr, destPathPtr, errorPtr) Tcl_Obj *srcPathPtr; Tcl_Obj *destPathPtr; Tcl_Obj **errorPtr;{ Tcl_DString ds; Tcl_DString srcString, dstString; int ret; Tcl_WinUtfToTChar(Tcl_FSGetTranslatedStringPath(NULL,srcPathPtr), -1, &srcString); Tcl_WinUtfToTChar(Tcl_FSGetTranslatedStringPath(NULL,destPathPtr), -1, &dstString); ret = TraverseWinTree(TraversalCopy, &srcString, &dstString, &ds); Tcl_DStringFree(&srcString); Tcl_DStringFree(&dstString); if (ret != TCL_OK) { *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); Tcl_DStringFree(&ds); Tcl_IncrRefCount(*errorPtr); } return ret;}/* *---------------------------------------------------------------------- * * TclpObjRemoveDirectory, DoRemoveDirectory -- * * Removes directory (and its contents, if the recursive flag is set). * * Results: * If the directory was successfully removed, returns TCL_OK. * Otherwise the return value is TCL_ERROR, errno is set to indicate * the error, and the pathname of the file that caused the error * is stored in errorPtr. Some possible values for errno are: * * EACCES: path directory can't be read and/or written. * EEXIST: path is a non-empty directory. * EINVAL: path is root directory or current directory. * ENOENT: path doesn't exist or is "". * ENOTDIR: path is not a directory. * * EACCES: path is a char device (nul:, com1:, etc.) (95) * EINVAL: path is a char device (nul:, com1:, etc.) (NT) * * Side effects: * Directory removed. If an error occurs, the error will be returned * immediately, and remaining files will not be deleted. * *---------------------------------------------------------------------- */int TclpObjRemoveDirectory(pathPtr, recursive, errorPtr) Tcl_Obj *pathPtr; int recursive; Tcl_Obj **errorPtr;{ Tcl_DString ds; int ret; if (recursive) { /* * In the recursive case, the string rep is used to construct a * Tcl_DString which may be used extensively, so we can't * optimize this case easily. */ Tcl_DString native; Tcl_WinUtfToTChar(Tcl_FSGetTranslatedStringPath(NULL, pathPtr), -1, &native); ret = DoRemoveDirectory(&native, recursive, &ds); Tcl_DStringFree(&native); } else { ret = DoRemoveJustDirectory(Tcl_FSGetNativePath(pathPtr), 0, &ds); } if (ret != TCL_OK) { int len = Tcl_DStringLength(&ds); if (len > 0) { *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); Tcl_IncrRefCount(*errorPtr); } Tcl_DStringFree(&ds); } return ret;}static intDoRemoveJustDirectory( CONST TCHAR *nativePath, /* Pathname of directory to be removed * (native). */ int ignoreError, /* If non-zero, don't initialize the * errorPtr under some circumstances * on return. */ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free * DString filled with UTF-8 name of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -