📄 tclunixfcmd.c
字号:
* 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. * *--------------------------------------------------------------------------- */intTclpDeleteFile(path) char *path; /* Pathname of file to be removed. */{ if (unlink(path) != 0) { return TCL_ERROR; } return TCL_OK;}/* *--------------------------------------------------------------------------- * * TclpCreateDirectory -- * * 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. * *--------------------------------------------------------------------------- */intTclpCreateDirectory(path) char *path; /* Pathname of directory to create. */{ mode_t mode; mode = umask(0); umask(mode); /* * umask return value is actually the inverse of the permissions. */ mode = (0777 & ~mode); if (mkdir(path, mode | S_IRUSR | S_IWUSR | S_IXUSR) != 0) { return TCL_ERROR; } return TCL_OK;}/* *--------------------------------------------------------------------------- * * TclpCopyDirectory -- * * 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 TclpCreateDirectory and TclpCopyFile * 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. * *--------------------------------------------------------------------------- */intTclpCopyDirectory(src, dst, errorPtr) char *src; /* Pathname of directory to be copied. */ char *dst; /* Pathname of target directory. */ Tcl_DString *errorPtr; /* If non-NULL, initialized DString for * error reporting. */{ int result; Tcl_DString srcBuffer; Tcl_DString dstBuffer; Tcl_DStringInit(&srcBuffer); Tcl_DStringInit(&dstBuffer); Tcl_DStringAppend(&srcBuffer, src, -1); Tcl_DStringAppend(&dstBuffer, dst, -1); result = TraverseUnixTree(TraversalCopy, &srcBuffer, &dstBuffer, errorPtr); Tcl_DStringFree(&srcBuffer); Tcl_DStringFree(&dstBuffer); return result;}/* *--------------------------------------------------------------------------- * * TclpRemoveDirectory -- * * 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. * *--------------------------------------------------------------------------- */ intTclpRemoveDirectory(path, recursive, errorPtr) char *path; /* Pathname of directory to be removed. */ int recursive; /* If non-zero, removes directories that * are nonempty. Otherwise, will only remove * empty directories. */ Tcl_DString *errorPtr; /* If non-NULL, initialized DString for * error reporting. */{ int result; Tcl_DString buffer; if (rmdir(path) == 0) { return TCL_OK; } if (errno == ENOTEMPTY) { errno = EEXIST; } if ((errno != EEXIST) || (recursive == 0)) { if (errorPtr != NULL) { Tcl_DStringAppend(errorPtr, path, -1); } return TCL_ERROR; } /* * The directory is nonempty, but the recursive flag has been * specified, so we recursively remove all the files in the directory. */ Tcl_DStringInit(&buffer); Tcl_DStringAppend(&buffer, path, -1); result = TraverseUnixTree(TraversalDelete, &buffer, NULL, errorPtr); Tcl_DStringFree(&buffer); 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. */ Tcl_DString *targetPtr; /* Pathname of directory to traverse in * parallel with source directory. */ Tcl_DString *errorPtr; /* If non-NULL, an initialized DString for * error reporting. */{ struct stat statbuf; char *source, *target, *errfile; int result, sourceLen; int targetLen = 0; /* Initialization needed only to prevent * warning in gcc. */ struct dirent *dirp; DIR *dp; result = TCL_OK; source = Tcl_DStringValue(sourcePtr); if (targetPtr != NULL) { target = Tcl_DStringValue(targetPtr); } else { target = NULL; } errfile = NULL; if (lstat(source, &statbuf) != 0) { errfile = source; goto end; } if (!S_ISDIR(statbuf.st_mode)) { /* * Process the regular file */ return (*traverseProc)(source, target, &statbuf, DOTREE_F, errorPtr); } dp = opendir(source); if (dp == NULL) { /* * Can't read directory */ errfile = source; goto end; } result = (*traverseProc)(source, target, &statbuf, DOTREE_PRED, errorPtr); if (result != TCL_OK) { closedir(dp); return result; } Tcl_DStringAppend(sourcePtr, "/", 1); source = Tcl_DStringValue(sourcePtr); sourceLen = Tcl_DStringLength(sourcePtr); if (targetPtr != NULL) { Tcl_DStringAppend(targetPtr, "/", 1); target = Tcl_DStringValue(targetPtr); targetLen = Tcl_DStringLength(targetPtr); } while ((dirp = readdir(dp)) != NULL) { if ((strcmp(dirp->d_name, ".") == 0) || (strcmp(dirp->d_name, "..") == 0)) { continue; } /* * Append name after slash, and recurse on the file. */ Tcl_DStringAppend(sourcePtr, dirp->d_name, -1); if (targetPtr != NULL) { Tcl_DStringAppend(targetPtr, dirp->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(dp); /* * Strip off the trailing slash we added */ Tcl_DStringSetLength(sourcePtr, sourceLen - 1); source = Tcl_DStringValue(sourcePtr); if (targetPtr != NULL) { Tcl_DStringSetLength(targetPtr, targetLen - 1); target = Tcl_DStringValue(targetPtr); } if (result == TCL_OK) { /* * Call traverseProc() on a directory after visiting all the * files in that directory. */ result = (*traverseProc)(source, target, &statbuf, DOTREE_POSTD, errorPtr); } end: if (errfile != NULL) { if (errorPtr != NULL) { Tcl_DStringAppend(errorPtr, errfile, -1); } result = TCL_ERROR; } return result;}/* *---------------------------------------------------------------------- * * TraversalCopy * * Called from TraverseUnixTree in order to execute a recursive copy of a * directory. * * Results: * Standard Tcl result. * * Side effects: * The file or directory src may be copied to dst, depending on * the value of type. * *---------------------------------------------------------------------- */static int TraversalCopy(src, dst, sbPtr, type, errorPtr) char *src; /* Source pathname to copy. */ char *dst; /* Destination pathname of copy. */ struct stat *sbPtr; /* Stat info for file specified by src. */ int type; /* Reason for call - see TraverseUnixTree(). */ Tcl_DString *errorPtr; /* If non-NULL, initialized DString for * error return. */{ switch (type) { case DOTREE_F: if (TclpCopyFile(src, dst) == TCL_OK) { return TCL_OK; } break; case DOTREE_PRED: if (TclpCreateDirectory(dst) == TCL_OK) { return TCL_OK; } break; case DOTREE_POSTD: if (CopyFileAtts(src, dst, sbPtr) == TCL_OK) { return TCL_OK; } break; } /* * There shouldn't be a problem with src, because we already * checked it to get here. */ if (errorPtr != NULL) { Tcl_DStringAppend(errorPtr, dst, -1); } return TCL_ERROR;}/* *--------------------------------------------------------------------------- * * TraversalDelete -- * * Called by procedure TraverseUnixTree for every file and directory * that it encounters in a directory hierarchy. This procedure unlinks * files, and removes directories after all the containing files * have been processed. * * Results: * Standard Tcl result. * * Side effects: * Files or directory specified by src will be deleted. * *---------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -