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

📄 tclunixfcmd.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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-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: @(#) tclUnixFCmd.c 1.31 97/10/13 16:51:14 * * 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>/* * 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, char *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetOwnerAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *fileName,			    Tcl_Obj **attributePtrPtr));static int		GetPermissionsAttribute _ANSI_ARGS_((			    Tcl_Interp *interp, int objIndex, char *fileName,			    Tcl_Obj **attributePtrPtr));static int		SetGroupAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *fileName,			    Tcl_Obj *attributePtr));static int		SetOwnerAttribute _ANSI_ARGS_((Tcl_Interp *interp,			    int objIndex, char *fileName,			    Tcl_Obj *attributePtr));static int		SetPermissionsAttribute _ANSI_ARGS_((			    Tcl_Interp *interp, int objIndex, char *fileName,			    Tcl_Obj *attributePtr));			  /* * Prototype for the TraverseUnixTree callback function. */typedef int (TraversalProc) _ANSI_ARGS_((char *src, char *dst,         struct stat *sb, int type, Tcl_DString *errorPtr));/* * Constants and variables necessary for file attributes subcommand. */enum {    UNIX_GROUP_ATTRIBUTE,    UNIX_OWNER_ATTRIBUTE,    UNIX_PERMISSIONS_ATTRIBUTE};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_((char *src, char *dst, 			    struct stat *srcStatBufPtr));static int		CopyFileAtts _ANSI_ARGS_((char *src, char *dst, 			    struct stat *srcStatBufPtr));static int		TraversalCopy _ANSI_ARGS_((char *src, char *dst, 			    struct stat *sbPtr, int type,			    Tcl_DString *errorPtr));static int		TraversalDelete _ANSI_ARGS_((char *src, char *dst, 			    struct stat *sbPtr, int type,			    Tcl_DString *errorPtr));static int		TraverseUnixTree _ANSI_ARGS_((			    TraversalProc *traversalProc,			    Tcl_DString *sourcePath, Tcl_DString *destPath,			    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, 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. * *--------------------------------------------------------------------------- */intTclpRenameFile(src, dst)    char *src;			/* Pathname of file or dir to be renamed. */    char *dst;			/* New pathname of file or directory. */{    if (rename(src, dst) == 0) {	return TCL_OK;    }    if (errno == ENOTEMPTY) {	errno = EEXIST;    }#ifdef sparc    /*     * 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() is only defined on SunOS.     */    if (errno == EINVAL) {	char srcPath[MAXPATHLEN], dstPath[MAXPATHLEN];	DIR *dirPtr;	struct dirent *dirEntPtr;	if ((realpath(src, srcPath) != NULL)		&& (realpath(dst, dstPath) != NULL)		&& (strncmp(srcPath, dstPath, strlen(srcPath)) != 0)) {	    dirPtr = opendir(dst);	    if (dirPtr != NULL) {		while ((dirEntPtr = readdir(dirPtr)) != NULL) {		    if ((strcmp(dirEntPtr->d_name, ".") != 0) &&			    (strcmp(dirEntPtr->d_name, "..") != 0)) {			errno = EEXIST;			closedir(dirPtr);			return TCL_ERROR;		    }		}		closedir(dirPtr);	    }	}	errno = EINVAL;    }#endif	/* sparc */    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;}/* *--------------------------------------------------------------------------- * * 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 "". * * 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 TclpCopyFile(src, dst)    char *src;			/* Pathname of file to be copied. */    char *dst;			/* Pathname of file to copy to. */{    struct stat srcStatBuf, dstStatBuf;    char link[MAXPATHLEN];    int length;    /*     * Have to do a stat() to determine the filetype.     */        if (lstat(src, &srcStatBuf) != 0) {	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 (lstat(dst, &dstStatBuf) == 0) {	if (S_ISDIR(dstStatBuf.st_mode)) {	    errno = EISDIR;	    return TCL_ERROR;	}    }    if (unlink(dst) != 0) {	if (errno != ENOENT) {	    return TCL_ERROR;	}     }    switch ((int) (srcStatBuf.st_mode & S_IFMT)) {        case S_IFLNK:	    length = readlink(src, link, sizeof(link)); 	    if (length == -1) {		return TCL_ERROR;	    }	    link[length] = '\0';	    if (symlink(link, dst) < 0) {		return TCL_ERROR;	    }	    break;        case S_IFBLK:        case S_IFCHR:	    if (mknod(dst, srcStatBuf.st_mode, srcStatBuf.st_rdev) < 0) {		return TCL_ERROR;	    }	    return CopyFileAtts(src, dst, &srcStatBuf);        case S_IFIFO:	    if (mkfifo(dst, srcStatBuf.st_mode) < 0) {		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, srcStatBufPtr)     char *src;                   /* Pathname of file to copy. */    char *dst;                   /* Pathname of file to create/overwrite. */    struct stat *srcStatBufPtr;  /* 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 = open(src, O_RDONLY, 0)) < 0) { 	return TCL_ERROR;    }    dstFd = open(dst, O_CREAT | O_TRUNC | O_WRONLY, srcStatBufPtr->st_mode);    if (dstFd < 0) {	close(srcFd); 	return TCL_ERROR;    }#if HAVE_ST_BLKSIZE    blockSize = srcStatBufPtr->st_blksize;#else    blockSize = 4096;#endif    buffer = ckalloc(blockSize);    while (1) {	nread = read(srcFd, buffer, blockSize);	if ((nread == -1) || (nread == 0)) {	    break;	}	if (write(dstFd, buffer, nread) != nread) {	    nread = (size_t) -1;	    break;	}    }	    ckfree(buffer);    close(srcFd);    if ((close(dstFd) != 0) || (nread == -1)) {	unlink(dst);	return TCL_ERROR;    }    if (CopyFileAtts(src, dst, srcStatBufPtr) == TCL_ERROR) {	/*	 * The copy succeeded, but setting the permissions failed, so be in	 * a consistent state, we remove the file that was created by the	 * copy.	 */	unlink(dst);	return TCL_ERROR;    }    return TCL_OK;}/* *--------------------------------------------------------------------------- * * TclpDeleteFile -- * *      Removes a single file (not a directory). *

⌨️ 快捷键说明

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