Fix a bug where windows would not currently follow symlinks in stat() calls.

Also clarify documentation.

TEST=Updated tests to cover stats() calls on symlinks.
Bug: https://github.com/dart-lang/sdk/issues/20389
Change-Id: I8555bacc2f83cad024ad8ef7c2f23aa97069ed2e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/218671
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Brian Quinlan <bquinlan@google.com>
This commit is contained in:
Brian Quinlan
2021-11-01 16:33:01 +00:00
committed by commit-bot@chromium.org
parent 65d157b5bb
commit 5e990591b9
4 changed files with 38 additions and 3 deletions
+1 -1
View File
@@ -896,7 +896,7 @@ const char* File::LinkTarget(Namespace* namespc,
void File::Stat(Namespace* namespc, const char* name, int64_t* data) {
const char* prefixed_name = PrefixLongFilePath(name);
File::Type type = GetType(namespc, prefixed_name, false);
File::Type type = GetType(namespc, prefixed_name, true);
data[kType] = type;
if (type != kDoesNotExist) {
struct _stat64 st;
+12
View File
@@ -93,6 +93,9 @@ class FileStat {
/// Calls the operating system's `stat()` function (or equivalent) on [path].
///
/// If [path] is a symbolic link then it is resolved and results for the
/// resulting file are returned.
///
/// Returns a [FileStat] object containing the data returned by `stat()`.
/// If the call fails, returns a [FileStat] object with [FileStat.type] set to
/// [FileSystemEntityType.notFound] and the other fields invalid.
@@ -123,6 +126,9 @@ class FileStat {
/// Asynchronously calls the operating system's `stat()` function (or
/// equivalent) on [path].
///
/// If [path] is a symbolic link then it is resolved and results for the
/// resulting file are returned.
///
/// Returns a [Future] which completes with the same results as [statSync].
static Future<FileStat> stat(String path) {
final IOOverrides? overrides = IOOverrides.current;
@@ -356,6 +362,9 @@ abstract class FileSystemEntity {
/// Returns a `Future<FileStat>` object containing the data returned by
/// `stat()`.
///
/// If [path] is a symbolic link then it is resolved and results for the
/// resulting file are returned.
///
/// If the call fails, completes the future with a [FileStat] object
/// with `.type` set to [FileSystemEntityType.notFound] and the other fields
/// invalid.
@@ -367,6 +376,9 @@ abstract class FileSystemEntity {
///
/// Returns a [FileStat] object containing the data returned by `stat()`.
///
/// If [path] is a symbolic link then it is resolved and results for the
/// resulting file are returned.
///
/// If the call fails, returns a [FileStat] object with `.type` set to
/// [FileSystemEntityType.notFound] and the other fields invalid.
FileStat statSync() => FileStat.statSync(path);
+12
View File
@@ -19,11 +19,16 @@ void testStat() {
Expect.equals(FileSystemEntityType.notFound, fileStat.type);
Expect.equals(FileSystemEntityType.notFound, fileStatDirect.type);
file.writeAsStringSync("Dart IO library test of FileStat");
Link link = new Link(join(directory.path, "link"));
link.createSync(file.path);
new Timer(const Duration(seconds: 2), () {
file.readAsStringSync();
directory.listSync();
FileStat fileStat = FileStat.statSync(file.path);
FileStat fileStatDirect = file.statSync();
FileStat linkStat = FileStat.statSync(link.path);
FileStat linkStatDirect = link.statSync();
Expect.equals(FileSystemEntityType.file, fileStat.type);
Expect.equals(32, fileStat.size);
Expect.equals(FileSystemEntityType.file, fileStatDirect.type);
@@ -44,6 +49,13 @@ void testStat() {
directoryStat.changed.compareTo(directoryStat.accessed) < 0);
}
Expect.equals(7 << 6, directoryStat.mode & (7 << 6)); // Includes +urwx.
// Verify that statSync resolves the link.
Expect.equals(FileSystemEntityType.file, linkStat.type);
Expect.equals(32, linkStat.size);
Expect.equals(FileSystemEntityType.file, linkStatDirect.type);
Expect.equals(32, linkStatDirect.size);
directory.deleteSync(recursive: true);
});
}
+13 -2
View File
@@ -21,11 +21,16 @@ void testStat() {
Expect.equals(FileSystemEntityType.notFound, fileStat.type);
Expect.equals(FileSystemEntityType.notFound, fileStatDirect.type);
file.writeAsStringSync("Dart IO library test of FileStat");
Link link = new Link(join(directory.path, "link"));
link.createSync(file.path);
new Timer(const Duration(seconds: 2), () {
file.readAsStringSync();
directory.listSync();
FileStat fileStat = FileStat.statSync(file.path);
FileStat fileStatDirect = file.statSync();
FileStat linkStat = FileStat.statSync(link.path);
FileStat linkStatDirect = link.statSync();
Expect.equals(FileSystemEntityType.file, fileStat.type);
Expect.equals(32, fileStat.size);
Expect.equals(FileSystemEntityType.file, fileStatDirect.type);
@@ -46,6 +51,13 @@ void testStat() {
.isTrue(directoryStat.changed.compareTo(directoryStat.accessed) < 0);
}
Expect.equals(7 << 6, directoryStat.mode & (7 << 6)); // Includes +urwx.
// Verify that statSync resolves the link.
Expect.equals(FileSystemEntityType.file, linkStat.type);
Expect.equals(32, linkStat.size);
Expect.equals(FileSystemEntityType.file, linkStatDirect.type);
Expect.equals(32, linkStatDirect.size);
directory.deleteSync(recursive: true);
});
}
@@ -53,8 +65,7 @@ void testStat() {
Future testStatAsync() {
return Directory.systemTemp.createTemp('dart_file_stat').then((directory) {
File file = new File(join(directory.path, "file"));
return FileStat
.stat(file.path)
return FileStat.stat(file.path)
.then((fileStat) =>
Expect.equals(FileSystemEntityType.notFound, fileStat.type))
.then((_) => file.stat())