Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Odd behavior of file.statSync() when file is a symlink #20389

Open
sethladd opened this issue Aug 6, 2014 · 13 comments
Open

Odd behavior of file.statSync() when file is a symlink #20389

sethladd opened this issue Aug 6, 2014 · 13 comments
Assignees
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@sethladd
Copy link
Contributor

sethladd commented Aug 6, 2014

Consider this code:

(assume real == a string path to a symlink on a Mac)

  var file = new File(real);
  print(file);
  var stat = file.statSync();
  print(stat); // <===== here's the bug. it says FILE, but I would imagine it to say LINK
  var isLink = stat.type == FileSystemEntityType.LINK;
  print("this should be true: $isLink"); // <=== isLink is false

Expected: isLink is true

@andersjohnsen
Copy link

I suggest we add a 'followLinks' argument to stat/statSync, to it matches how we do it other places, where we want to differentiate between working on the path directly and working on the resolved path.

In this case it should default to 'true' for backward compatibility.

Thoughts?


cc @lrhn.

@sethladd
Copy link
Contributor Author

sethladd commented Aug 6, 2014

Removed Priority-Unassigned label.
Added Priority-Medium label.

@sgjesse
Copy link
Contributor

sgjesse commented Aug 7, 2014

We actually do what we promise, the documentation in file.dart says:

 * ## If path is a link
 *
 * If [path] is a symbolic link, rather than a file,
 * then the methods of File operate on the ultimate target of the
 * link, except for [delete] and [deleteSync], which operate on
 * the link.

so currently stat and statSync cannot return a FileStat object with type LINK. The only way to check for link is using FileSystemEntity.type and FileSystemEntity.typeSync with 'followLinks' set to true.

Adding 'followLinks' to stat/statSync fits well with this pattern already used.

@sethladd
Copy link
Contributor Author

sethladd commented Aug 7, 2014

Can we add a note or two to the statSync method, reminding the developer about the "if path is a link" ? That's really useful info, but it's "far away" from statSync. :)

@sethladd sethladd added Type-Defect library-io area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. labels Aug 7, 2014
@kevmoo kevmoo added P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) and removed triaged labels Mar 1, 2016
@jamesderlin
Copy link
Contributor

jamesderlin commented Nov 19, 2019

FWIW, in POSIX, following symlinks is the normal behavior for stat. There is traditionally a separate lstat function for operating on links.

Personally I'd prefer a followLinks named parameter on the existing FileSystemEntity.stat/statSync and FileStat.stat functions, but a separate FileStat.lstat function would be acceptable too if there are compatibility concerns.

@brianquinlan brianquinlan self-assigned this Oct 28, 2021
@brianquinlan
Copy link
Contributor

On Windows we are currently not resolving symlinks. I'll fix that and update the docs as my first step.

copybara-service bot pushed a commit that referenced this issue Nov 1, 2021
… calls.

Also clarify documentation.

TEST=Updated tests to cover stats() calls on symlinks.
Bug: #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>
@brianquinlan
Copy link
Contributor

Adding a followLinks named parameter isn't feasible because it would break any subclasses of FileSystemEntity (of which there are many). Likewise for IOOverrides.

I think that @jamesderlin 's proposal of having a lstat method is reasonable.

Any thoughts?

@eernstg
Copy link
Member

eernstg commented Nov 10, 2021

lstat might have to be an extension method, because it's a breaking change to add a new instance method to a widely used class.

@brianquinlan
Copy link
Contributor

@eernstg Making lstat an extension method would work but how would we add it to IOOverrides?

@eernstg
Copy link
Member

eernstg commented Nov 11, 2021

I don't know any details about IOOverrides, but taking a look at it I would expect that the lstat method would have to use a similar technique as the existing implementation of, say, statSync:

  static FileStat statSync(String path) {
    final IOOverrides? overrides = IOOverrides.current;
    if (overrides == null) {
      return _statSyncInternal(path);
    }
    return overrides.statSync(path);
  }

IOOverrides.current is accessible from the extension method, and overrides.lstatSync(path) should work from there as well, so it looks like there is nothing that prevents using the same technique in an extension method.

@brianquinlan
Copy link
Contributor

Let me take a step back - I don't understand why we can't add a new method to a widely used class. Is that because a subclass might already define the same method but, for example, with a different signature?

If that is the issue, then wouldn't the same issue exist when adding lstat to IOOverrides? Or would we also implement that as an extension method?

@jamesderlin
Copy link
Contributor

jamesderlin commented Nov 11, 2021

The typical problem with adding methods is if there is a derived class that implements the interface. Adding a method to the interface would be a breaking change since all implementers would need to add the new method.

In this case, a notable implementation of dart:io's File class is the File class from package:file.

@eernstg
Copy link
Member

eernstg commented Nov 16, 2021

It might be OK to implement lstat/lstatSync as new instance methods on class IOOverrides, because that class is intended to have subclasses (so extends IOOverrides is OK), but not other subtypes (so implements IOOverrides does not seem to be recommended, and also does not seem to be used anywhere that I could spot right now).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io P2 A bug or feature request we're likely to work on type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

7 participants