int TclpRenameFile( char *src, /* Pathname of file or dir to be renamed. */ char *dst) /* New pathname for file or directory. */ { FSSpec srcFileSpec, dstFileSpec, dstDirSpec; OSErr err; long srcID, dummy; Boolean srcIsDirectory, dstIsDirectory, dstExists, dstLocked; err = FSpLocationFromPath(strlen(src), src, &srcFileSpec); if (err == noErr) { FSpGetDirectoryID(&srcFileSpec, &srcID, &srcIsDirectory); } if (err == noErr) { err = GetFileSpecs(dst, &dstFileSpec, &dstDirSpec, &dstExists, &dstIsDirectory); } if (err == noErr) { if (dstExists == 0) { err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name); goto end; } err = FSpGetFLockCompat(&dstFileSpec, &dstLocked); if (dstLocked) { FSpRstFLockCompat(&dstFileSpec); } } if (err == noErr) { if (srcIsDirectory) { if (dstIsDirectory) { /* * The following call will remove an empty directory. If it * fails, it's because it wasn't empty. */ if (TclpRemoveDirectory(dst, 0, NULL) != TCL_OK) { return TCL_ERROR; } /* * Now that that empty directory is gone, we can try * renaming src. If that fails, we'll put this empty * directory back, for completeness. */ err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name); if (err != noErr) { FSpDirCreateCompat(&dstFileSpec, smSystemScript, &dummy); if (dstLocked) { FSpSetFLockCompat(&dstFileSpec); } } } else { errno = ENOTDIR; return TCL_ERROR; } } else { if (dstIsDirectory) { errno = EISDIR; return TCL_ERROR; } else { /* * Overwrite existing file by: * * 1. Rename existing file to temp name. * 2. Rename old file to new name. * 3. If success, delete temp file. If failure, * put temp file back to old name. */ Str31 tmpName; FSSpec tmpFileSpec; err = GenerateUniqueName(dstFileSpec.vRefNum, dstFileSpec.parID, dstFileSpec.parID, tmpName); if (err == noErr) { err = FSpRenameCompat(&dstFileSpec, tmpName); } if (err == noErr) { err = FSMakeFSSpecCompat(dstFileSpec.vRefNum, dstFileSpec.parID, tmpName, &tmpFileSpec); } if (err == noErr) { err = MoveRename(&srcFileSpec, &dstDirSpec, dstFileSpec.name); } if (err == noErr) { FSpDeleteCompat(&tmpFileSpec); } else { FSpDeleteCompat(&dstFileSpec); FSpRenameCompat(&tmpFileSpec, dstFileSpec.name); if (dstLocked) { FSpSetFLockCompat(&dstFileSpec); } } } } } end: if (err != noErr) { errno = TclMacOSErrorToPosixError(err); return TCL_ERROR; } return TCL_OK; }
/* * Like rename() but will try to copy the file if the rename fails. * This is because under OS's with multiple physical volumes if the * source and destination are on different volumes the rename will fail */ int rename2(char *srcFile, char *destFile) { FILE *f, *g; #ifdef MACTC5 int copy=-1; #endif int status = 0; long fileLength; #ifdef MACTC5 copy=MoveRename(srcFile,destFile); if (copy) #else #if defined(VMS) || defined(C370) if (rename(srcFile, destFile) != 0) #else if (rename(srcFile, destFile) == -1) #endif #endif { /* Rename failed, try a copy */ if (((f = fopen(srcFile, FOPRBIN)) == NULL) || ((g = fopen(destFile, FOPWBIN)) == NULL)) /* Can't open files */ return -1; #ifdef MACTC5 { FInfo finderInfo; c2pstr(srcFile); c2pstr(destFile); if(GetFInfo((uchar *)srcFile,0,&finderInfo)==0) SetFInfo((uchar *)destFile,0,&finderInfo); p2cstr((uchar *)srcFile); p2cstr((uchar *)destFile); } #endif /* Get file length and copy it */ fseek(f, 0L, SEEK_END); fileLength = ftell(f); rewind(f); status = copyfile(f, g, fileLength); if (write_error(g)) status = -1; /* Zap source file if the copy went OK, otherwise zap the (possibly incomplete) destination file */ if (status >= 0) { wipeout(f); /* Zap source file */ fclose(f); remove(srcFile); fclose(g); } else { if (is_regular_file(destFile)) { wipeout(g); /* Zap destination file */ fclose(g); remove(destFile); } else { fclose(g); } fclose(f); } } return status; }