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

📄 tclunixfcmd.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * tclUnixFCmd.c * *      This file implements the unix specific portion of file manipulation  *      subcommands of the "file" command.  All filename arguments should *	already be translated to native format. * * 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: tclUnixFCmd.c,v 1.28 2003/02/10 12:50:31 vincentdarley Exp $ * * Portions of this code were derived from NetBSD source code which has * the following copyright notice: * * Copyright (c) 1988, 1993, 1994 *      The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by the University of *      California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "tclInt.h"#include "tclPort.h"#include <utime.h>#include <grp.h>#ifndef HAVE_ST_BLKSIZE#ifndef NO_FSTATFS#include <sys/statfs.h>#endif#endif/* * The following constants specify the type of callback when * TraverseUnixTree() 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		GetGroupAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetOwnerAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetPermissionsAttribute _ANSI_ARGS_((			    Tcl_Interp *interp, int objIndex,			    Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr));static int		SetGroupAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj *attributePtr));static int		SetOwnerAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, Tcl_Obj *fileName,			    Tcl_Obj *attributePtr));static int		SetPermissionsAttribute _ANSI_ARGS_((			    Tcl_Interp *interp, int objIndex,			    Tcl_Obj *fileName, Tcl_Obj *attributePtr));static int		GetModeFromPermString _ANSI_ARGS_((			    Tcl_Interp *interp, char *modeStringPtr,			    mode_t *modePtr));/* * Prototype for the TraverseUnixTree callback function. */typedef int (TraversalProc) _ANSI_ARGS_((Tcl_DString *srcPtr,	Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr, int type,	Tcl_DString *errorPtr));/* * Constants and variables necessary for file attributes subcommand. */enum {    UNIX_GROUP_ATTRIBUTE,    UNIX_OWNER_ATTRIBUTE,    UNIX_PERMISSIONS_ATTRIBUTE};CONST char *tclpFileAttrStrings[] = {    "-group",    "-owner",    "-permissions",    (char *) NULL};CONST TclFileAttrProcs tclpFileAttrProcs[] = {    {GetGroupAttribute,		SetGroupAttribute},    {GetOwnerAttribute,		SetOwnerAttribute},    {GetPermissionsAttribute,	SetPermissionsAttribute}};/* * Declarations for local procedures defined in this file: */static int		CopyFile _ANSI_ARGS_((CONST char *src,			    CONST char *dst, CONST Tcl_StatBuf *statBufPtr));static int		CopyFileAtts _ANSI_ARGS_((CONST char *src,			    CONST char *dst, CONST Tcl_StatBuf *statBufPtr));static int		DoCopyFile _ANSI_ARGS_((CONST char *srcPtr,			    CONST char *dstPtr));static int		DoCreateDirectory _ANSI_ARGS_((CONST char *pathPtr));static int		DoRemoveDirectory _ANSI_ARGS_((Tcl_DString *pathPtr,			    int recursive, Tcl_DString *errorPtr));static int		DoRenameFile _ANSI_ARGS_((CONST char *src,			    CONST char *dst));static int		TraversalCopy _ANSI_ARGS_((Tcl_DString *srcPtr,			    Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr,			    int type, Tcl_DString *errorPtr));static int		TraversalDelete _ANSI_ARGS_((Tcl_DString *srcPtr,			    Tcl_DString *dstPtr, CONST Tcl_StatBuf *statBufPtr,			    int type, Tcl_DString *errorPtr));static int		TraverseUnixTree _ANSI_ARGS_((			    TraversalProc *traversalProc,			    Tcl_DString *sourcePtr, Tcl_DString *destPtr,			    Tcl_DString *errorPtr));#ifdef PURIFY/* * realpath and purify don't mix happily.  It has been noted that realpath * should not be used with purify because of bogus warnings, but just * memset'ing the resolved path will squelch those.  This assumes we are * passing the standard MAXPATHLEN size resolved arg. */static char *		Realpath _ANSI_ARGS_((CONST char *path,			    char *resolved));char *Realpath(path, resolved)    CONST char *path;    char *resolved;{    memset(resolved, 0, MAXPATHLEN);    return realpath(path, resolved);}#else#define Realpath realpath#endif/* *--------------------------------------------------------------------------- * * 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, or 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(src, dst)    CONST char *src;		/* Pathname of file or dir to be renamed				 * (native). */    CONST char *dst;		/* New pathname of file or directory				 * (native). */{    if (rename(src, dst) == 0) {			/* INTL: Native. */	return TCL_OK;    }    if (errno == ENOTEMPTY) {	errno = EEXIST;    }    /*     * IRIX returns EIO when you attept to move a directory into     * itself.  We just map EIO to EINVAL get the right message on SGI.     * Most platforms don't return EIO except in really strange cases.     */        if (errno == EIO) {	errno = EINVAL;    }    #ifndef NO_REALPATH    /*     * SunOS 4.1.4 reports overwriting a non-empty directory with a     * directory as EINVAL instead of EEXIST (first rule out the correct     * EINVAL result code for moving a directory into itself).  Must be     * conditionally compiled because realpath() not defined on all systems.     */    if (errno == EINVAL) {	char srcPath[MAXPATHLEN], dstPath[MAXPATHLEN];	DIR *dirPtr;	Tcl_DirEntry *dirEntPtr;	if ((Realpath((char *) src, srcPath) != NULL)	/* INTL: Native. */		&& (Realpath((char *) dst, dstPath) != NULL) /* INTL: Native. */		&& (strncmp(srcPath, dstPath, strlen(srcPath)) != 0)) {	    dirPtr = opendir(dst);			/* INTL: Native. */	    if (dirPtr != NULL) {		while (1) {		    dirEntPtr = TclOSreaddir(dirPtr); /* INTL: Native. */		    if (dirEntPtr == NULL) {			break;		    }		    if ((strcmp(dirEntPtr->d_name, ".") != 0) &&			    (strcmp(dirEntPtr->d_name, "..") != 0)) {			errno = EEXIST;			closedir(dirPtr);			return TCL_ERROR;		    }		}		closedir(dirPtr);	    }	}	errno = EINVAL;    }#endif	/* !NO_REALPATH */    if (strcmp(src, "/") == 0) {	/*	 * Alpha reports renaming / as EBUSY and Linux reports it as EACCES,	 * instead of EINVAL.	 */	 	errno = EINVAL;    }    /*     * DEC Alpha OSF1 V3.0 returns EACCES when attempting to move a     * file across filesystems and the parent directory of that file is     * not writable.  Most other systems return EXDEV.  Does nothing to     * correct this behavior.     */    return TCL_ERROR;}/* *--------------------------------------------------------------------------- * * 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(src, dst)    CONST char *src;	/* Pathname of file to be copied (native). */    CONST char *dst;	/* Pathname of file to copy to (native). */{    Tcl_StatBuf srcStatBuf, dstStatBuf;    /*     * Have to do a stat() to determine the filetype.     */        if (TclOSlstat(src, &srcStatBuf) != 0) {		/* INTL: Native. */	return TCL_ERROR;    }    if (S_ISDIR(srcStatBuf.st_mode)) {	errno = EISDIR;	return TCL_ERROR;    }    /*     * symlink, and some of the other calls will fail if the target      * exists, so we remove it first     */        if (TclOSlstat(dst, &dstStatBuf) == 0) {		/* INTL: Native. */	if (S_ISDIR(dstStatBuf.st_mode)) {	    errno = EISDIR;	    return TCL_ERROR;	}    }    if (unlink(dst) != 0) {				/* INTL: Native. */	if (errno != ENOENT) {	    return TCL_ERROR;	}     }    switch ((int) (srcStatBuf.st_mode & S_IFMT)) {#ifndef DJGPP        case S_IFLNK: {	    char link[MAXPATHLEN];	    int length;	    length = readlink(src, link, sizeof(link)); /* INTL: Native. */	    if (length == -1) {		return TCL_ERROR;	    }	    link[length] = '\0';	    if (symlink(link, dst) < 0) {		/* INTL: Native. */		return TCL_ERROR;	    }	    break;	}#endif        case S_IFBLK:        case S_IFCHR: {	    if (mknod(dst, srcStatBuf.st_mode,		/* INTL: Native. */		    srcStatBuf.st_rdev) < 0) {		return TCL_ERROR;	    }	    return CopyFileAtts(src, dst, &srcStatBuf);	}        case S_IFIFO: {	    if (mkfifo(dst, srcStatBuf.st_mode) < 0) {	/* INTL: Native. */		return TCL_ERROR;	    }	    return CopyFileAtts(src, dst, &srcStatBuf);	}        default: {	    return CopyFile(src, dst, &srcStatBuf);	}    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * CopyFile -  * *      Helper function for TclpCopyFile.  Copies one regular file, *	using read() and write(). * * Results: *	A standard Tcl result. * * Side effects: *      A file is copied.  Dst will be overwritten if it exists. * *---------------------------------------------------------------------- */static int CopyFile(src, dst, statBufPtr)     CONST char *src;		/* Pathname of file to copy (native). */    CONST char *dst;		/* Pathname of file to create/overwrite				 * (native). */    CONST Tcl_StatBuf *statBufPtr;				/* Used to determine mode and blocksize. */{    int srcFd;    int dstFd;    u_int blockSize;   /* Optimal I/O blocksize for filesystem */    char *buffer;      /* Data buffer for copy */    size_t nread;    if ((srcFd = TclOSopen(src, O_RDONLY, 0)) < 0) {	/* INTL: Native. */	return TCL_ERROR;    }    dstFd = TclOSopen(dst, O_CREAT|O_TRUNC|O_WRONLY,	/* INTL: Native. */	    statBufPtr->st_mode);    if (dstFd < 0) {	close(srcFd); 

⌨️ 快捷键说明

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