Skip to content

Commit a3eacf7

Browse files
zichanggcommit-bot@chromium.org
authored andcommitted
Revert "File::Copy avoids direct copying on Windows"
This reverts commit 391d3bc. Reason for revert: #42291 Original change's description: > File::Copy avoids direct copying on Windows > > There is a race condition for copying file on Windows, where CopyFile() > returns success but data has not been populated into destination file. > E.g process is killed or died in the middle. > > This cl will change File::Copy as > 1. Copy file to a temp file in the same directory of destination file. > 2. Rename the file to the target file. > > Bug: #42119 > Change-Id: I39b6d451f6ace970bc554501148259d33de232c7 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/149667 > Commit-Queue: Zichang Guo <[email protected]> > Reviewed-by: Zach Anderson <[email protected]> [email protected],[email protected],[email protected] # Not skipping CQ checks because original CL landed > 1 day ago. Bug: #42119 Change-Id: I816611107498f41ab4af7c065ac2162af585ae95 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151028 Reviewed-by: Zichang Guo <[email protected]> Commit-Queue: Zichang Guo <[email protected]>
1 parent bbeda37 commit a3eacf7

File tree

3 files changed

+5
-113
lines changed

3 files changed

+5
-113
lines changed

runtime/bin/file_win.cc

Lines changed: 5 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include <sys/utime.h> // NOLINT
1818

1919
#include "bin/builtin.h"
20-
#include "bin/crypto.h"
2120
#include "bin/directory.h"
2221
#include "bin/namespace.h"
2322
#include "bin/utils.h"
@@ -504,85 +503,6 @@ bool File::RenameLink(Namespace* namespc,
504503
return (move_status != 0);
505504
}
506505

507-
static wchar_t* CopyToDartScopeString(wchar_t* string) {
508-
wchar_t* wide_path = reinterpret_cast<wchar_t*>(
509-
Dart_ScopeAllocate(MAX_PATH * sizeof(wchar_t) + 1));
510-
wcscpy(wide_path, string);
511-
return wide_path;
512-
}
513-
514-
static wchar_t* CopyIntoTempFile(const char* src, const char* dest) {
515-
// This function will copy the file to a temp file in the destination
516-
// directory and return the path of temp file.
517-
// Creating temp file name has the same logic as Directory::CreateTemp(),
518-
// which tries with the rng and falls back to a uuid if it failed.
519-
const char* last_backslash = strrchr(dest, '\\');
520-
if (last_backslash == NULL) {
521-
return NULL;
522-
}
523-
int length_of_parent_dir = last_backslash - dest + 1;
524-
if (length_of_parent_dir + 8 > MAX_PATH) {
525-
return NULL;
526-
}
527-
uint32_t suffix_bytes = 0;
528-
const int kSuffixSize = sizeof(suffix_bytes);
529-
if (Crypto::GetRandomBytes(kSuffixSize,
530-
reinterpret_cast<uint8_t*>(&suffix_bytes))) {
531-
PathBuffer buffer;
532-
char* dir = reinterpret_cast<char*>(
533-
Dart_ScopeAllocate(1 + sizeof(char) * length_of_parent_dir));
534-
memmove(dir, dest, length_of_parent_dir);
535-
dir[length_of_parent_dir] = '\0';
536-
if (!buffer.Add(dir)) {
537-
return NULL;
538-
}
539-
540-
char suffix[8 + 1];
541-
Utils::SNPrint(suffix, sizeof(suffix), "%x", suffix_bytes);
542-
Utf8ToWideScope source_path(src);
543-
if (!buffer.Add(suffix)) {
544-
return NULL;
545-
}
546-
if (CopyFileExW(source_path.wide(), buffer.AsStringW(), NULL, NULL, NULL,
547-
0) != 0) {
548-
return CopyToDartScopeString(buffer.AsStringW());
549-
}
550-
}
551-
// UUID has a total of 36 characters in the form of
552-
// xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx.
553-
if (length_of_parent_dir + 36 > MAX_PATH) {
554-
return NULL;
555-
}
556-
UUID uuid;
557-
RPC_STATUS status = UuidCreateSequential(&uuid);
558-
if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) {
559-
return NULL;
560-
}
561-
RPC_WSTR uuid_string;
562-
status = UuidToStringW(&uuid, &uuid_string);
563-
if (status != RPC_S_OK) {
564-
return NULL;
565-
}
566-
PathBuffer buffer;
567-
char* dir = reinterpret_cast<char*>(
568-
Dart_ScopeAllocate(1 + sizeof(char) * length_of_parent_dir));
569-
memmove(dir, dest, length_of_parent_dir);
570-
dir[length_of_parent_dir] = '\0';
571-
Utf8ToWideScope dest_path(dir);
572-
if (!buffer.AddW(dest_path.wide()) ||
573-
!buffer.AddW(reinterpret_cast<wchar_t*>(uuid_string))) {
574-
return NULL;
575-
}
576-
577-
RpcStringFreeW(&uuid_string);
578-
Utf8ToWideScope source_path(src);
579-
if (CopyFileExW(source_path.wide(), buffer.AsStringW(), NULL, NULL, NULL,
580-
0) != 0) {
581-
return CopyToDartScopeString(buffer.AsStringW());
582-
}
583-
return NULL;
584-
}
585-
586506
bool File::Copy(Namespace* namespc,
587507
const char* old_path,
588508
const char* new_path) {
@@ -591,23 +511,11 @@ bool File::Copy(Namespace* namespc,
591511
SetLastError(ERROR_FILE_NOT_FOUND);
592512
return false;
593513
}
594-
595-
wchar_t* temp_file = CopyIntoTempFile(old_path, new_path);
596-
if (temp_file == NULL) {
597-
return false;
598-
}
599-
Utf8ToWideScope system_new_dest(new_path);
600-
601-
// Remove the existing file. Otherwise, renaming will fail.
602-
if (Exists(namespc, new_path)) {
603-
DeleteFileW(system_new_dest.wide());
604-
}
605-
606-
if (!MoveFileW(temp_file, system_new_dest.wide())) {
607-
DeleteFileW(temp_file);
608-
return false;
609-
}
610-
return true;
514+
Utf8ToWideScope system_old_path(old_path);
515+
Utf8ToWideScope system_new_path(new_path);
516+
bool success = CopyFileExW(system_old_path.wide(), system_new_path.wide(),
517+
NULL, NULL, NULL, 0) != 0;
518+
return success;
611519
}
612520

613521
int64_t File::LengthFromPath(Namespace* namespc, const char* name) {

tests/standalone/io/file_copy_test.dart

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,6 @@ void testCopySync() {
3030
Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
3131
Expect.equals(FILE_CONTENT2, file2.readAsStringSync());
3232

33-
// Check there is no temporary files existing.
34-
var list = tmp.listSync();
35-
Expect.equals(2, list.length);
36-
for (var file in list) {
37-
final fileName = file.path.toString();
38-
Expect.isTrue(fileName.contains("file1") || fileName.contains("file2"));
39-
}
40-
4133
// Fail when coping to directory.
4234
var dir = new Directory('${tmp.path}/dir')..createSync();
4335
Expect.throws(() => file1.copySync(dir.path));

tests/standalone_2/io/file_copy_test.dart

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,6 @@ void testCopySync() {
3030
Expect.equals(FILE_CONTENT2, file1.readAsStringSync());
3131
Expect.equals(FILE_CONTENT2, file2.readAsStringSync());
3232

33-
// Check there is no temporary files existing.
34-
var list = tmp.listSync();
35-
Expect.equals(2, list.length);
36-
for (var file in list) {
37-
final fileName = file.path.toString();
38-
Expect.isTrue(fileName.contains("file1") || fileName.contains("file2"));
39-
}
40-
4133
// Fail when coping to directory.
4234
var dir = new Directory('${tmp.path}/dir')..createSync();
4335
Expect.throws(() => file1.copySync(dir.path));

0 commit comments

Comments
 (0)