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

📄 tclwinfcmd.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * tclWinFCmd.c * *      This file implements the Windows specific portion of file manipulation  *      subcommands of the "file" command.  * * Copyright (c) 1996-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. * * SCCS: @(#) tclWinFCmd.c 1.20 97/10/10 11:50:14 */#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, char *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetWinFileLongName _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetWinFileShortName _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *fileName,			    Tcl_Obj **attributePtrPtr));static int		SetWinFileAttributes _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *fileName,			    Tcl_Obj *attributePtr));static int		CannotSetAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *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};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}};/* * Prototype for the TraverseWinTree callback function. */typedef int (TraversalProc)(char *src, char *dst, DWORD attr, int type, 	Tcl_DString *errorPtr);/* * Declarations for local procedures defined in this file: */static void		AttributesPosixError _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *fileName, int getOrSet));static int		ConvertFileNameFormat _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *fileName, int longShort,			    Tcl_Obj **attributePtrPtr));static int		TraversalCopy(char *src, char *dst, DWORD attr, 				int type, Tcl_DString *errorPtr);static int		TraversalDelete(char *src, char *dst, DWORD attr,				int type, Tcl_DString *errorPtr);static int		TraverseWinTree(TraversalProc *traverseProc,			    Tcl_DString *sourcePtr, Tcl_DString *destPtr,			    Tcl_DString *errorPtr);/* *--------------------------------------------------------------------------- * * TclpRenameFile -- * *      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 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:     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. * *--------------------------------------------------------------------------- */intTclpRenameFile(    char *src,			/* Pathname of file or dir to be renamed. */     char *dst)			/* New pathname for file or directory. */{    DWORD srcAttr, dstAttr;        /*     * Would throw an exception under NT if one of the arguments is a      * char block device.     */    try {	if (MoveFile(src, dst) != FALSE) {	    return TCL_OK;	}    } except (-1) {}    TclWinConvertError(GetLastError());    srcAttr = GetFileAttributes(src);    dstAttr = GetFileAttributes(dst);    if (srcAttr == (DWORD) -1) {	srcAttr = 0;    }    if (dstAttr == (DWORD) -1) {	dstAttr = 0;    }    if (errno == EBADF) {	errno = EACCES;	return TCL_ERROR;    }    if ((errno == EACCES) && (TclWinGetPlatformId() == VER_PLATFORM_WIN32s)) {	if ((srcAttr != 0) && (dstAttr != 0)) {	    /*	     * Win32s reports trying to overwrite an existing file or directory	     * as EACCES.	     */	    errno = EEXIST;	}    }    if (errno == EACCES) {	decode:	if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) {	    char srcPath[MAX_PATH], dstPath[MAX_PATH];	    int srcArgc, dstArgc;	    char **srcArgv, **dstArgv;	    char *srcRest, *dstRest;	    int size;	    size = GetFullPathName(src, sizeof(srcPath), srcPath, &srcRest);	    if ((size == 0) || (size > sizeof(srcPath))) {		return TCL_ERROR;	    }	    size = GetFullPathName(dst, sizeof(dstPath), dstPath, &dstRest);	    if ((size == 0) || (size > sizeof(dstPath))) {		return TCL_ERROR;	    }	    if (srcRest == NULL) {		srcRest = srcPath + strlen(srcPath);	    }	    if (strnicmp(srcPath, dstPath, srcRest - srcPath) == 0) {		/*		 * Trying to move a directory into itself.		 */		errno = EINVAL;		return TCL_ERROR;	    }	    Tcl_SplitPath(srcPath, &srcArgc, &srcArgv);	    Tcl_SplitPath(dstPath, &dstArgc, &dstArgv);	    if (srcArgc == 1) {		/*		 * They are trying to move a root directory.  Whether		 * or not it is across filesystems, this cannot be		 * done.		 */		errno = EINVAL;	    } else if ((srcArgc > 0) && (dstArgc > 0) &&		    (stricmp(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.		 */		errno = 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 (errno == 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 (TclpRemoveDirectory(dst, 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 (MoveFile(src, dst) != FALSE) {			return TCL_OK;		    }		    /*		     * Some new error has occurred.  Don't know what it		     * could be, but report this one.		     */		    TclWinConvertError(GetLastError());		    CreateDirectory(dst, NULL);		    SetFileAttributes(dst, dstAttr);		    if (errno == EACCES) {			/*			 * Decode the EACCES to a more meaningful error.			 */			goto decode;		    }		}	    } else {	/* (dstAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 */		errno = ENOTDIR;	    }	} else {    /* (srcAttr & FILE_ATTRIBUTE_DIRECTORY) == 0 */	    if (dstAttr & FILE_ATTRIBUTE_DIRECTORY) {		errno = 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.		 */		char tempName[MAX_PATH];		int result, size;		char *rest;				size = GetFullPathName(dst, sizeof(tempName), tempName, &rest);		if ((size == 0) || (size > sizeof(tempName)) || (rest == NULL)) {		    return TCL_ERROR;		}		*rest = '\0';		result = TCL_ERROR;		if (GetTempFileName(tempName, "tclr", 0, tempName) != 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.		     */		     		    DeleteFile(tempName);		    if (MoveFile(dst, tempName) != FALSE) {			if (MoveFile(src, dst) != FALSE) {			    SetFileAttributes(tempName, FILE_ATTRIBUTE_NORMAL);			    DeleteFile(tempName);			    return TCL_OK;			} else {			    DeleteFile(dst);			    MoveFile(tempName, dst);			}		    } 		    /*		     * Can't backup dst file or move src file.  Return that		     * error.  Could happen if an open file refers to dst.		     */		    TclWinConvertError(GetLastError());		    if (errno == EACCES) {			/*			 * Decode the EACCES to a more meaningful error.			 */			goto decode;		    }		}		return result;	    }	}    }    return TCL_ERROR;}/* *--------------------------------------------------------------------------- * * TclpCopyFile -- * *      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 TclpCopyFile(    char *src,			/* Pathname of file to be copied. */    char *dst)			/* Pathname of file to copy to. */{    /*     * Would throw an exception under NT if one of the arguments is a char     * block device.     */    try {	if (CopyFile(src, dst, 0) != FALSE) {	    return TCL_OK;	}    } except (-1) {}    TclWinConvertError(GetLastError());    if (errno == EBADF) {	errno = EACCES;	return TCL_ERROR;    }    if (errno == EACCES) {	DWORD srcAttr, dstAttr;	srcAttr = GetFileAttributes(src);	dstAttr = GetFileAttributes(dst);	if (srcAttr != (DWORD) -1) {	    if (dstAttr == (DWORD) -1) {		dstAttr = 0;	    }	    if ((srcAttr & FILE_ATTRIBUTE_DIRECTORY) ||		    (dstAttr & FILE_ATTRIBUTE_DIRECTORY)) {		errno = EISDIR;	    }	    if (dstAttr & FILE_ATTRIBUTE_READONLY) {		SetFileAttributes(dst, dstAttr & ~FILE_ATTRIBUTE_READONLY);		if (CopyFile(src, dst, 0) != FALSE) {		    return TCL_OK;		}		/*		 * Still can't copy onto dst.  Return that error, and		 * restore attributes of dst.		 */		TclWinConvertError(GetLastError());		SetFileAttributes(dst, dstAttr);	    }	}    }    return TCL_ERROR;}/* *--------------------------------------------------------------------------- * * 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. * *--------------------------------------------------------------------------- */intTclpDeleteFile(    char *path)			/* Pathname of file to be removed. */{    DWORD attr;    if (DeleteFile(path) != FALSE) {	return TCL_OK;    }    TclWinConvertError(GetLastError());    if (path[0] == '\0') {

⌨️ 快捷键说明

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