Tracker: deal with race condition in CopyFile

* If a user selects 2 files whose names differ only in case,
  right-drags them to a FAT volume Tracker window as a set, chooses
  the move option from the drop-down, and chooses to continue if an
  alert box appears, the second file in line to be copied will be lost
  (this is consistently reproducible on my system).
* Eliminate the option to continue in this situation, so that the move
  will always be aborted instead of progressing to deletion of the
  second file from the origin directory.

Change-Id: I52197945fe28072eeddcd68e91ce5e7b8534b184
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7623
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Jim906 2024-04-20 14:51:06 -04:00 committed by waddlesplash
parent 85ea044bdb
commit fd8513028f

View File

@ -1309,6 +1309,27 @@ CopyFile(BEntry* srcFile, StatStruct* srcStat, BDirectory* destDir,
if (err == kCopyCanceled)
throw (status_t)err;
if (err == B_FILE_EXISTS) {
// A file with the same name was created after BDirectory::FindEntry was called and
// before LowLevelCopy could finish. In a move operation, if the standard file error
// alert were displayed and the user chose to continue, the file that we just failed
// to copy would be lost. Don't offer the option to continue.
BString lowLevelExistsString(
B_TRANSLATE("Error copying file \"%name\":\n\t%error\n\n"));
// The error may have resulted from the user dragging a set of selected files to a
// case-insensitive volume, when 2 files in the set differ only in case.
node_ref destRef;
destDir->GetNodeRef(&destRef);
fs_info destInfo;
_kern_read_fs_info(destRef.device, &destInfo);
if (strcmp(destInfo.fsh_name, "fat") == 0) {
lowLevelExistsString += B_TRANSLATE("Note: file names in the destination file "
"system are not case-sensitive.\n");
}
loopControl->FileError(lowLevelExistsString.String(), destName, err, false);
throw (status_t)err;
}
if (err != B_OK) {
if (!loopControl->FileError(
B_TRANSLATE_NOCOLLECT(kFileErrorString), destName, err,