📄 tclmacfcmd.c
字号:
CONST char *dst) /* Pathname of file to copy to (native). */{ OSErr err, dstErr; Boolean dstExists, dstIsDirectory, dstLocked; FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpFileSpec; Str31 tmpName; err = FSpLLocationFromPath(strlen(src), src, &srcFileSpec); if (err == noErr) { err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists, &dstIsDirectory); } if (dstExists) { if (dstIsDirectory) { errno = EISDIR; return TCL_ERROR; } err = FSpGetFLockCompat(&dstFileSpec, &dstLocked); if (dstLocked) { FSpRstFLockCompat(&dstFileSpec); } /* * Backup dest file. */ dstErr = GenerateUniqueName(dstFileSpec.vRefNum, &startSeed, dstFileSpec.parID, dstFileSpec.parID, tmpName); if (dstErr == noErr) { dstErr = FSpRenameCompat(&dstFileSpec, tmpName); } } if (err == noErr) { err = FSpFileCopy(&srcFileSpec, &dstDirSpec, (StringPtr) dstFileSpec.name, NULL, 0, true); } if ((dstExists != false) && (dstErr == noErr)) { FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID, tmpName, &tmpFileSpec); if (err == noErr) { /* * Delete backup file. */ FSpDeleteCompat(&tmpFileSpec); } else { /* * Restore backup file. */ FSpDeleteCompat(&dstFileSpec); FSpRenameCompat(&tmpFileSpec, dstFileSpec.name); if (dstLocked) { FSpSetFLockCompat(&dstFileSpec); } } } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); 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( CONST char *path) /* Pathname of file to be removed (native). */{ OSErr err; FSSpec fileSpec; Boolean isDirectory; long dirID; err = FSpLLocationFromPath(strlen(path), path, &fileSpec); if (err == noErr) { /* * Since FSpDeleteCompat will delete an empty directory, make sure * that this isn't a directory first. */ FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory); if (isDirectory == true) { errno = EISDIR; return TCL_ERROR; } } err = FSpDeleteCompat(&fileSpec); if (err == fLckdErr) { FSpRstFLockCompat(&fileSpec); err = FSpDeleteCompat(&fileSpec); if (err != noErr) { FSpSetFLockCompat(&fileSpec); } } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return TCL_ERROR; } return TCL_OK;}/* *--------------------------------------------------------------------------- * * TclpObjCreateDirectory, 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( CONST char *path) /* Pathname of directory to create (native). */{ OSErr err; FSSpec dirSpec; long outDirID; err = FSpLocationFromPath(strlen(path), path, &dirSpec); if (err == noErr) { err = dupFNErr; /* EEXIST. */ } else if (err == fnfErr) { err = FSpDirCreateCompat(&dirSpec, smSystemScript, &outDirID); } if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return TCL_ERROR; } return TCL_OK;}/* *--------------------------------------------------------------------------- * * TclpObjCopyDirectory, DoCopyDirectory -- * * 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. * *--------------------------------------------------------------------------- */int TclpObjCopyDirectory(srcPathPtr, destPathPtr, errorPtr) Tcl_Obj *srcPathPtr; Tcl_Obj *destPathPtr; Tcl_Obj **errorPtr;{ Tcl_DString ds; int ret; ret = DoCopyDirectory(Tcl_FSGetNativePath(srcPathPtr), Tcl_FSGetNativePath(destPathPtr), &ds); if (ret != TCL_OK) { *errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); Tcl_DStringFree(&ds); Tcl_IncrRefCount(*errorPtr); } return ret;}static intDoCopyDirectory( CONST char *src, /* Pathname of directory to be copied * (Native). */ CONST char *dst, /* Pathname of target directory (Native). */ Tcl_DString *errorPtr) /* If non-NULL, uninitialized or free * DString filled with UTF-8 name of file * causing error. */{ OSErr err, saveErr; long srcID, tmpDirID; FSSpec srcFileSpec, dstFileSpec, dstDirSpec, tmpDirSpec, tmpFileSpec; Boolean srcIsDirectory, srcLocked; Boolean dstIsDirectory, dstExists; Str31 tmpName; err = FSpLocationFromPath(strlen(src), src, &srcFileSpec); if (err == noErr) { err = FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory); } if (err == noErr) { if (srcIsDirectory == false) { err = afpObjectTypeErr; /* ENOTDIR. */ } } if (err == noErr) { err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists, &dstIsDirectory); } if (dstExists) { if (dstIsDirectory == false) { err = afpObjectTypeErr; /* ENOTDIR. */ } else { err = dupFNErr; /* EEXIST. */ } } if (err != noErr) { goto done; } if ((srcFileSpec.vRefNum == dstFileSpec.vRefNum) && (srcFileSpec.parID == dstFileSpec.parID) && (Pstrequal(srcFileSpec.name, dstFileSpec.name) != 0)) { /* * Copying on top of self. No-op. */ goto done; } /* * This algorthm will work making a copy of the source directory in * the current directory with a new name, in a new directory with the * same name, and in a new directory with a new name: * * 1. Make dstDir/tmpDir. * 2. Copy srcDir/src to dstDir/tmpDir/src * 3. Rename dstDir/tmpDir/src to dstDir/tmpDir/dst (if necessary). * 4. CatMove dstDir/tmpDir/dst to dstDir/dst. * 5. Remove dstDir/tmpDir. */ err = FSpGetFLockCompat(&srcFileSpec, &srcLocked); if (srcLocked) { FSpRstFLockCompat(&srcFileSpec); } if (err == noErr) { err = GenerateUniqueName(dstFileSpec.vRefNum, &startSeed, dstFileSpec.parID, dstFileSpec.parID, tmpName); } if (err == noErr) { FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID, tmpName, &tmpDirSpec); err = FSpDirCreateCompat(&tmpDirSpec, smSystemScript, &tmpDirID); } if (err == noErr) { err = FSpDirectoryCopy(&srcFileSpec, &tmpDirSpec, NULL, NULL, 0, true, CopyErrHandler); } /* * Even if the Copy failed, Rename/Move whatever did get copied to the * appropriate final destination, if possible. */ saveErr = err; err = noErr; if (Pstrequal(srcFileSpec.name, dstFileSpec.name) == 0) { err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID, srcFileSpec.name, &tmpFileSpec); if (err == noErr) { err = FSpRenameCompat(&tmpFileSpec, dstFileSpec.name); } } if (err == noErr) { err = FSMakeFSSpecCompat(tmpDirSpec.vRefNum, tmpDirID, dstFileSpec.name, &tmpFileSpec); } if (err == noErr) { err = FSpCatMoveCompat(&tmpFileSpec, &dstDirSpec); } if (err == noErr) { if (srcLocked) { FSpSetFLockCompat(&dstFileSpec); } } FSpDeleteCompat(&tmpDirSpec); if (saveErr != noErr) { err = saveErr; } done: if (err != noErr) { errno = TclMacOSErrorToPosixError(err); if (errorPtr != NULL) { Tcl_ExternalToUtfDString(NULL, dst, -1, errorPtr); } return TCL_ERROR; } return TCL_OK;}/* *---------------------------------------------------------------------- * * CopyErrHandler -- * * This procedure is called from the MoreFiles procedure * FSpDirectoryCopy whenever an error occurs. * * Results: * False if the condition should not be considered an error, true * otherwise. * * Side effects: * Since FSpDirectoryCopy() is called only after removing any * existing target directories, there shouldn't be any errors. * *---------------------------------------------------------------------- */static pascal Boolean CopyErrHandler( OSErr error, /* Error that occured */ short failedOperation, /* operation that caused the error */ short srcVRefNum, /* volume ref number of source */ long srcDirID, /* directory id of source */ ConstStr255Param srcName, /* name of source */ short dstVRefNum, /* volume ref number of dst */ long dstDirID, /* directory id of dst */ ConstStr255Param dstName) /* name of dst directory */{ return true;}/* *--------------------------------------------------------------------------- * * TclpObjRemoveDirectory, 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -