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

📄 tclunixfcmd.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 4 页
字号:
	return TCL_ERROR;    }#ifdef HAVE_ST_BLKSIZE    blockSize = statBufPtr->st_blksize;#else#ifndef NO_FSTATFS    {	struct statfs fs;	if (fstatfs(srcFd, &fs, sizeof(fs), 0) == 0) {	    blockSize = fs.f_bsize;	} else {	    blockSize = 4096;	}    }#else     blockSize = 4096;#endif#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);					/* INTL: Native. */	return TCL_ERROR;    }    if (CopyFileAtts(src, dst, statBufPtr) == 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);					/* INTL: Native. */	return TCL_ERROR;    }    return TCL_OK;}/* *--------------------------------------------------------------------------- * * 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 "". * * Side effects: *      The file is deleted, even if it is read-only. * *--------------------------------------------------------------------------- */int TclpObjDeleteFile(pathPtr)    Tcl_Obj *pathPtr;{    return TclpDeleteFile(Tcl_FSGetNativePath(pathPtr));}intTclpDeleteFile(path)    CONST char *path;	/* Pathname of file to be removed (native). */{    if (unlink(path) != 0) {				/* INTL: Native. */	return TCL_ERROR;    }    return TCL_OK;}/* *--------------------------------------------------------------------------- * * TclpCreateDirectory, DoCreateDirectory -- * *      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 with the current umask, except that *	permission for u+rwx will always be added. * *--------------------------------------------------------------------------- */int TclpObjCreateDirectory(pathPtr)    Tcl_Obj *pathPtr;{    return DoCreateDirectory(Tcl_FSGetNativePath(pathPtr));}static intDoCreateDirectory(path)    CONST char *path;	/* Pathname of directory to create (native). */{    mode_t mode;    mode = umask(0);    umask(mode);    /*     * umask return value is actually the inverse of the permissions.     */    mode = (0777 & ~mode) | S_IRUSR | S_IWUSR | S_IXUSR;    if (mkdir(path, mode) != 0) {			/* INTL: Native. */	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 TclpObjCreateDirectory and  *	TclpObjCopyFile 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_UtfToExternalDString(NULL, 			     Tcl_FSGetTranslatedStringPath(NULL,srcPathPtr), 			     -1, &srcString);    Tcl_UtfToExternalDString(NULL, 			     Tcl_FSGetTranslatedStringPath(NULL,destPathPtr), 			     -1, &dstString);    ret = TraverseUnixTree(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;}/* *--------------------------------------------------------------------------- * * TclpRemoveDirectory, 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 a root directory. *	ENOENT:	    path doesn't exist or is "". * 	ENOTDIR:    path is not a directory. * * 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;    Tcl_DString pathString;    int ret;    Tcl_UtfToExternalDString(NULL, Tcl_FSGetTranslatedStringPath(NULL, pathPtr), 			     -1, &pathString);    ret = DoRemoveDirectory(&pathString, recursive, &ds);    Tcl_DStringFree(&pathString);    if (ret != TCL_OK) {	*errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);	Tcl_DStringFree(&ds);	Tcl_IncrRefCount(*errorPtr);    }    return ret;}static intDoRemoveDirectory(pathPtr, recursive, errorPtr)    Tcl_DString *pathPtr;	/* Pathname of directory to be removed				 * (native). */    int recursive;		/* If non-zero, removes directories that				 * are nonempty.  Otherwise, will only remove				 * empty directories. */    Tcl_DString *errorPtr;	/* If non-NULL, uninitialized or free				 * DString filled with UTF-8 name of file				 * causing error. */{    CONST char *path;    mode_t oldPerm = 0;    int result;        path = Tcl_DStringValue(pathPtr);        if (recursive != 0) {	/* We should try to change permissions so this can be deleted */	Tcl_StatBuf statBuf;	int newPerm;	if (TclOSstat(path, &statBuf) == 0) {	    oldPerm = (mode_t) (statBuf.st_mode & 0x00007FFF);	}		newPerm = oldPerm | (64+128+256);	chmod(path, (mode_t) newPerm);    }        if (rmdir(path) == 0) {				/* INTL: Native. */	return TCL_OK;    }    if (errno == ENOTEMPTY) {	errno = EEXIST;    }    result = TCL_OK;    if ((errno != EEXIST) || (recursive == 0)) {	if (errorPtr != NULL) {	    Tcl_ExternalToUtfDString(NULL, path, -1, errorPtr);	}	result = TCL_ERROR;    }        /*     * The directory is nonempty, but the recursive flag has been     * specified, so we recursively remove all the files in the directory.     */    if (result == TCL_OK) {	result = TraverseUnixTree(TraversalDelete, pathPtr, NULL, errorPtr);    }        if ((result != TCL_OK) && (recursive != 0)) {        /* Try to restore permissions */        chmod(path, oldPerm);    }    return result;}	/* *--------------------------------------------------------------------------- * * TraverseUnixTree -- * *      Traverse directory tree specified by sourcePtr, calling the function  *	traverseProc for each file and directory encountered.  If destPtr  *	is non-null, each of name in the sourcePtr directory is appended to  *	the directory specified by destPtr and passed as the second argument  *	to traverseProc() . * * Results: *      Standard Tcl result. * * Side effects: *      None caused by TraverseUnixTree, however the user specified  *	traverseProc() may change state.  If an error occurs, the error will *      be returned immediately, and remaining files will not be processed. * *--------------------------------------------------------------------------- */static int TraverseUnixTree(traverseProc, sourcePtr, targetPtr, errorPtr)    TraversalProc *traverseProc;/* Function to call for every file and				 * directory in source hierarchy. */    Tcl_DString *sourcePtr;	/* Pathname of source directory to be				 * traversed (native). */    Tcl_DString *targetPtr;	/* Pathname of directory to traverse in				 * parallel with source directory (native). */    Tcl_DString *errorPtr;	/* If non-NULL, uninitialized or free				 * DString filled with UTF-8 name of file				 * causing error. */{    Tcl_StatBuf statBuf;    CONST char *source, *errfile;    int result, sourceLen;    int targetLen;    Tcl_DirEntry *dirEntPtr;    DIR *dirPtr;    errfile = NULL;    result = TCL_OK;    targetLen = 0;		/* lint. */    source = Tcl_DStringValue(sourcePtr);    if (TclOSlstat(source, &statBuf) != 0) {		/* INTL: Native. */	errfile = source;	goto end;    }    if (!S_ISDIR(statBuf.st_mode)) {	/*	 * Process the regular file	 */	return (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_F,		errorPtr);    }    dirPtr = opendir(source);				/* INTL: Native. */    if (dirPtr == NULL) {	/* 	 * Can't read directory	 */	errfile = source;	goto end;    }    result = (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_PRED,	    errorPtr);    if (result != TCL_OK) {	closedir(dirPtr);	return result;    }        Tcl_DStringAppend(sourcePtr, "/", 1);    sourceLen = Tcl_DStringLength(sourcePtr);	    if (targetPtr != NULL) {	Tcl_DStringAppend(targetPtr, "/", 1);	targetLen = Tcl_DStringLength(targetPtr);    }    while ((dirEntPtr = TclOSreaddir(dirPtr)) != NULL) { /* INTL: Native. */	if ((dirEntPtr->d_name[0] == '.')		&& ((dirEntPtr->d_name[1] == '\0')			|| (strcmp(dirEntPtr->d_name, "..") == 0))) {	    continue;	}	/* 	 * Append name after slash, and recurse on the file.	 */	Tcl_DStringAppend(sourcePtr, dirEntPtr->d_name, -1);	if (targetPtr != NULL) {	    Tcl_DStringAppend(targetPtr, dirEntPtr->d_name, -1);	}	result = TraverseUnixTree(traverseProc, sourcePtr, targetPtr,		errorPtr);	if (result != TCL_OK) {	    break;	}		/*	 * Remove name after slash.	 */	Tcl_DStringSetLength(sourcePtr, sourceLen);	if (targetPtr != NULL) {	    Tcl_DStringSetLength(targetPtr, targetLen);	}    }    closedir(dirPtr);        /*     * Strip off the trailing slash we added     */    Tcl_DStringSetLength(sourcePtr, sourceLen - 1);    if (targetPtr != NULL) {	Tcl_DStringSetLength(targetPtr, targetLen - 1);    }    if (result == TCL_OK) {	/*	 * Call traverseProc() on a directory after visiting all the	 * files in that directory.	 */	result = (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_POSTD,		errorPtr);    }    end:    if (errfile != NULL) {	if (errorPtr != NULL) {	    Tcl_ExternalToUtfDString(NULL, errfile, -1, errorPtr);

⌨️ 快捷键说明

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