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

📄 tclmacfcmd.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  * tclMacFCmd.c -- * * Implements the Macintosh specific portions of the 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: tclMacFCmd.c,v 1.19 2003/02/04 17:06:51 vincentdarley Exp $ */#include "tclInt.h"#include "tclMac.h"#include "tclMacInt.h"#include "tclPort.h"#include <FSpCompat.h>#include <MoreFilesExtras.h>#include <Strings.h>#include <Errors.h>#include <FileCopy.h>#include <DirectoryCopy.h>#include <Script.h>#include <string.h>#include <Finder.h>#include <Aliases.h>/* * Callback for the file attributes code. */static int		GetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj **readOnlyPtrPtr));static int		SetFileFinderAttributes _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj *attributePtr));static int		SetFileReadOnly _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj *readOnlyPtr));/* * These are indeces into the tclpFileAttrsStrings table below. */#define MAC_CREATOR_ATTRIBUTE	0#define MAC_HIDDEN_ATTRIBUTE	1#define MAC_READONLY_ATTRIBUTE	2#define MAC_TYPE_ATTRIBUTE	3/* * Global variables for the file attributes code. */CONST char *tclpFileAttrStrings[] = {"-creator", "-hidden", "-readonly",	"-type", (char *) NULL};CONST TclFileAttrProcs tclpFileAttrProcs[] = {	{GetFileFinderAttributes, SetFileFinderAttributes},	{GetFileFinderAttributes, SetFileFinderAttributes},	{GetFileReadOnly, SetFileReadOnly},	{GetFileFinderAttributes, SetFileFinderAttributes}};/* * File specific static data */static long startSeed = 248923489;/* * Prototypes for procedure only used in this file */static pascal Boolean 	CopyErrHandler _ANSI_ARGS_((OSErr error, 			    short failedOperation,			    short srcVRefNum, long srcDirID,			    ConstStr255Param srcName, short dstVRefNum,			    long dstDirID,ConstStr255Param dstName));static int		DoCopyDirectory _ANSI_ARGS_((CONST char *src,			    CONST char *dst, Tcl_DString *errorPtr));static int		DoCopyFile _ANSI_ARGS_((CONST char *src, 			    CONST char *dst));static int		DoCreateDirectory _ANSI_ARGS_((CONST char *path));static int		DoRemoveDirectory _ANSI_ARGS_((CONST char *path, 			    int recursive, Tcl_DString *errorPtr));static int		DoRenameFile _ANSI_ARGS_((CONST char *src,			    CONST char *dst));OSErr			FSpGetFLockCompat _ANSI_ARGS_((const FSSpec *specPtr, 			    Boolean *lockedPtr));static OSErr		GetFileSpecs _ANSI_ARGS_((CONST char *path, 			    FSSpec *pathSpecPtr, FSSpec *dirSpecPtr,				    Boolean *pathExistsPtr, 			    Boolean *pathIsDirectoryPtr));static OSErr		MoveRename _ANSI_ARGS_((const FSSpec *srcSpecPtr, 			    const FSSpec *dstSpecPtr, StringPtr copyName));static int		Pstrequal _ANSI_ARGS_((ConstStr255Param stringA, 			    ConstStr255Param stringB));                 /* *--------------------------------------------------------------------------- * * 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 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. *	 * Side effects: *	The implementation of rename may allow cross-filesystem renames, *	but the caller should be prepared to emulate it with copy and *	delete 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 char *src,		/* Pathname of file or dir to be renamed				 * (native). */    CONST char *dst)		/* New pathname of file or directory				 * (native). */{    FSSpec srcFileSpec, dstFileSpec, dstDirSpec;    OSErr err;     long srcID, dummy;    Boolean srcIsDirectory, dstIsDirectory, dstExists, dstLocked;    err = FSpLLocationFromPath(strlen(src), src, &srcFileSpec);    if (err == noErr) {	FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory);    }    if (err == noErr) {        err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists,         	&dstIsDirectory);    }    if (err == noErr) {	if (dstExists == 0) {            err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name);            goto end;        }        err = FSpGetFLockCompat(&dstFileSpec, &dstLocked);        if (dstLocked) {            FSpRstFLockCompat(&dstFileSpec);        }    }    if (err == noErr) {        if (srcIsDirectory) {	    if (dstIsDirectory) {		/*		 * The following call will remove an empty directory.  If it		 * fails, it's because it wasn't empty.		 */		                 if (DoRemoveDirectory(dst, 0, NULL) != TCL_OK) {                    return TCL_ERROR;                }                                /*		 * Now that that empty directory is gone, we can try		 * renaming src.  If that fails, we'll put this empty		 * directory back, for completeness.		 */		err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name);                if (err != noErr) {		    FSpDirCreateCompat(&dstFileSpec, smSystemScript, &dummy);		    if (dstLocked) {		        FSpSetFLockCompat(&dstFileSpec);		    }		}	    } else {	        errno = ENOTDIR;	        return TCL_ERROR;	    }	} else {   	    if (dstIsDirectory) {		errno = EISDIR;		return TCL_ERROR;	    } 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.		 */	        Str31 tmpName;	        FSSpec tmpFileSpec;	        err = GenerateUniqueName(dstFileSpec.vRefNum, &startSeed,	        	dstFileSpec.parID, dstFileSpec.parID, tmpName);	        if (err == noErr) {	            err = FSpRenameCompat(&dstFileSpec, tmpName);	        }	        if (err == noErr) {	            err = FSMakeFSSpecCompat(dstFileSpec.vRefNum,	            	    dstFileSpec.parID, tmpName, &tmpFileSpec);	        }	        if (err == noErr) {	            err = MoveRename(&srcFileSpec, &dstDirSpec, 	            	    dstFileSpec.name);	        }	        if (err == noErr) {		    FSpDeleteCompat(&tmpFileSpec);		} else {		    FSpDeleteCompat(&dstFileSpec);		    FSpRenameCompat(&tmpFileSpec, dstFileSpec.name);	            if (dstLocked) {	            	FSpSetFLockCompat(&dstFileSpec);	            }	        }	    }   	}    }        end:        if (err != noErr) {	errno = TclMacOSErrorToPosixError(err);	return TCL_ERROR;    }    return TCL_OK;}/* *-------------------------------------------------------------------------- * * MoveRename -- * *	Helper function for TclpRenameFile.  Renames a file or directory *	into the same directory or another directory.  The target name * 	must not already exist in the destination directory. * *	Don't use FSpMoveRenameCompat because it doesn't work with *	directories or with locked files.  * * Results: *	Returns a mac error indicating the cause of the failure. * * Side effects: *	Creates a temp file in the target directory to handle a rename *	between directories. * *-------------------------------------------------------------------------- */  static OSErr		MoveRename(    const FSSpec *srcFileSpecPtr,   /* Source object. */    const FSSpec *dstDirSpecPtr,    /* Destination directory. */    StringPtr copyName)		    /* New name for object in destination     				     * directory. */{    OSErr err;    long srcID, dstID;    Boolean srcIsDir, dstIsDir;    Str31 tmpName;    FSSpec dstFileSpec, srcDirSpec, tmpSrcFileSpec, tmpDstFileSpec;    Boolean locked;        if (srcFileSpecPtr->parID == 1) {        /*         * Trying to rename a volume.         */                  return badMovErr;    }    if (srcFileSpecPtr->vRefNum != dstDirSpecPtr->vRefNum) {	/*	 * Renaming across volumes.	 */	         return diffVolErr;    }    err = FSpGetFLockCompat(srcFileSpecPtr, &locked);    if (locked) {        FSpRstFLockCompat(srcFileSpecPtr);    }    if (err == noErr) {	err = FSpGetDirectoryID(dstDirSpecPtr, &dstID, &dstIsDir);    }    if (err == noErr) {        if (srcFileSpecPtr->parID == dstID) {            /*             * Renaming object within directory.              */                        err = FSpRenameCompat(srcFileSpecPtr, copyName);            goto done;         }        if (Pstrequal(srcFileSpecPtr->name, copyName)) {	    /*	     * Moving object to another directory (under same name). 	     */	 	    err = FSpCatMoveCompat(srcFileSpecPtr, dstDirSpecPtr);	    goto done;         }         err = FSpGetDirectoryID(srcFileSpecPtr, &srcID, &srcIsDir);    }     if (err == noErr) {        /*         * Fullblown: rename source object to temp name, move temp to         * dest directory, and rename temp to target.         */                  err = GenerateUniqueName(srcFileSpecPtr->vRefNum, &startSeed,       		srcFileSpecPtr->parID, dstID, tmpName);        FSMakeFSSpecCompat(srcFileSpecPtr->vRefNum, srcFileSpecPtr->parID,         	tmpName, &tmpSrcFileSpec);        FSMakeFSSpecCompat(dstDirSpecPtr->vRefNum, dstID, tmpName,         	&tmpDstFileSpec);    }    if (err == noErr) {        err = FSpRenameCompat(srcFileSpecPtr, tmpName);    }    if (err == noErr) {        err = FSpCatMoveCompat(&tmpSrcFileSpec, dstDirSpecPtr);        if (err == noErr) {            err = FSpRenameCompat(&tmpDstFileSpec, copyName);            if (err == noErr) {                goto done;            }            FSMakeFSSpecCompat(srcFileSpecPtr->vRefNum, srcFileSpecPtr->parID,             	    NULL, &srcDirSpec);            FSpCatMoveCompat(&tmpDstFileSpec, &srcDirSpec);        }                         FSpRenameCompat(&tmpSrcFileSpec, srcFileSpecPtr->name);    }        done:    if (locked != false) {    	if (err == noErr) {	    FSMakeFSSpecCompat(dstDirSpecPtr->vRefNum, 	    	    dstID, copyName, &dstFileSpec);            FSpSetFLockCompat(&dstFileSpec);        } else {            FSpSetFLockCompat(srcFileSpecPtr);        }    }    return err;}     /* *--------------------------------------------------------------------------- * * 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 "". * * Side effects: *      This procedure will also copy symbolic links, block, and *      character devices, and fifos.  For symbolic links, the links  *      themselves will be copied and not what they point to.  For the *	other special file types, the directory entry will be copied and *	not the contents of the device that it refers to. * *--------------------------------------------------------------------------- */ int TclpObjCopyFile(srcPathPtr, destPathPtr)    Tcl_Obj *srcPathPtr;    Tcl_Obj *destPathPtr;{    return DoCopyFile(Tcl_FSGetNativePath(srcPathPtr),		      Tcl_FSGetNativePath(destPathPtr));}static intDoCopyFile(    CONST char *src,		/* Pathname of file to be copied (native). */

⌨️ 快捷键说明

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