Skip to content

Commit a36923b

Browse files
authored
Add rename support for Windows (#201)
1 parent 6215560 commit a36923b

13 files changed

+159
-15
lines changed

pkgs/io_file/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ See
2727
| read file (bytes) | [ ] | [ ] | [ ] | [ ] | [ ] |
2828
| read file (lines) | [ ] | [ ] | [ ] | [ ] | [ ] |
2929
| read file (string) | [ ] | [ ] | [ ] | [ ] | [ ] |
30-
| rename | [ ] | [X] | [ ] | [X] | [ ] |
30+
| rename | [ ] | [X] | [ ] | [X] | [X] |
3131
| set permissions | [ ] | [ ] | [ ] | [ ] | [ ] |
3232
| write file (bytes) | [ ] | [ ] | [ ] | [ ] | [ ] |
3333
| write file (string) | [ ] | [ ] | [ ] | [ ] | [ ] |

pkgs/io_file/lib/io_file.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
export 'src/file_system.dart';
6+
export 'src/vm_file_system_property.dart'
7+
if (dart.library.html) 'src/web_file_system_property.dart';

pkgs/io_file/lib/posix_file_system.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
export 'src/posix_file_system.dart';
5+
export 'src/vm_posix_file_system.dart'
6+
if (dart.library.html) 'src/web_posix_file_system.dart';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:io';
6+
7+
import 'file_system.dart';
8+
import 'vm_posix_file_system.dart';
9+
import 'vm_windows_file_system.dart';
10+
11+
/// Return the default [FileSystem] for the current platform.
12+
FileSystem get fileSystem =>
13+
Platform.isWindows ? WindowsFileSystem() : PosixFileSystem();
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:ffi';
6+
import 'dart:io' as io;
7+
8+
import 'package:ffi/ffi.dart';
9+
import 'package:win32/win32.dart' as win32;
10+
11+
import 'file_system.dart';
12+
13+
String _formatMessage(int errorCode) {
14+
final buffer = win32.wsalloc(1024);
15+
try {
16+
final result = win32.FormatMessage(
17+
win32.FORMAT_MESSAGE_FROM_SYSTEM | win32.FORMAT_MESSAGE_IGNORE_INSERTS,
18+
nullptr,
19+
errorCode,
20+
0, // default language
21+
buffer,
22+
1024,
23+
nullptr,
24+
);
25+
if (result == 0) {
26+
return '';
27+
} else {
28+
return buffer.toDartString();
29+
}
30+
} finally {
31+
win32.free(buffer);
32+
}
33+
}
34+
35+
Exception _getError(int errorCode, String message, String path) {
36+
final osError = io.OSError(_formatMessage(errorCode), errorCode);
37+
38+
switch (errorCode) {
39+
case win32.ERROR_ACCESS_DENIED:
40+
case win32.ERROR_CURRENT_DIRECTORY:
41+
case win32.ERROR_WRITE_PROTECT:
42+
case win32.ERROR_BAD_LENGTH:
43+
case win32.ERROR_SHARING_VIOLATION:
44+
case win32.ERROR_LOCK_VIOLATION:
45+
case win32.ERROR_NETWORK_ACCESS_DENIED:
46+
case win32.ERROR_DRIVE_LOCKED:
47+
return io.PathAccessException(path, osError, message);
48+
case win32.ERROR_FILE_EXISTS:
49+
case win32.ERROR_ALREADY_EXISTS:
50+
return io.PathExistsException(path, osError, message);
51+
case win32.ERROR_FILE_NOT_FOUND:
52+
case win32.ERROR_PATH_NOT_FOUND:
53+
case win32.ERROR_INVALID_DRIVE:
54+
case win32.ERROR_INVALID_NAME:
55+
case win32.ERROR_NO_MORE_FILES:
56+
case win32.ERROR_BAD_NETPATH:
57+
case win32.ERROR_BAD_NET_NAME:
58+
case win32.ERROR_BAD_PATHNAME:
59+
return io.PathNotFoundException(path, osError, message);
60+
default:
61+
return io.FileSystemException(message, path, osError);
62+
}
63+
}
64+
65+
/// A [FileSystem] implementation for Windows systems.
66+
base class WindowsFileSystem extends FileSystem {
67+
@override
68+
void rename(String oldPath, String newPath) => using((arena) {
69+
// Calling `GetLastError` for the first time causes the `GetLastError`
70+
// symbol to be loaded, which resets `GetLastError`. So make a harmless
71+
// call before the value is needed.
72+
win32.GetLastError();
73+
if (win32.MoveFileEx(
74+
oldPath.toNativeUtf16(allocator: arena),
75+
newPath.toNativeUtf16(allocator: arena),
76+
win32.MOVEFILE_WRITE_THROUGH | win32.MOVEFILE_REPLACE_EXISTING,
77+
) ==
78+
win32.FALSE) {
79+
final errorCode = win32.GetLastError();
80+
throw _getError(errorCode, 'rename failed', oldPath);
81+
}
82+
});
83+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'file_system.dart';
6+
7+
/// Return the default [FileSystem] for the current platform.
8+
FileSystem get fileSystem {
9+
throw UnsupportedError('fileSystem');
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'file_system.dart';
6+
7+
/// A [FileSystem] implementation for POSIX systems (e.g. Android, iOS, Linux,
8+
/// macOS).
9+
base class PosixFileSystem extends FileSystem {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'file_system.dart';
6+
7+
/// A [FileSystem] implementation for Windows systems.
8+
base class WindowsFileSystem extends FileSystem {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
export 'src/vm_windows_file_system.dart'
6+
if (dart.library.html) 'src/web_windows_file_system.dart';

0 commit comments

Comments
 (0)