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

Provide a way of getting a file's real path #35370

Open
nex3 opened this issue Dec 10, 2018 · 16 comments
Open

Provide a way of getting a file's real path #35370

nex3 opened this issue Dec 10, 2018 · 16 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. customer-dart-sass library-io type-enhancement A request for a change that isn't a bug

Comments

@nex3
Copy link
Member

nex3 commented Dec 10, 2018

Right now, given a user-provided file path, there's no (efficient) way of getting that file's real path on disk. On Linux et al these are always the same thing (modulo . and .. path components which p.normalize() can handle), but Windows and some OS X systems have case-insensitive filesystems where a file named FILE.TXT can be referred to by the path file.txt. Worse yet, some servers appear to only serve the files in question if the case matches exactly, even when the underlying filesystem is case sensitive (see sass/dart-sass#540).

It's possible to work around this today using Directory.list() on the parent directory, but that's much more expensive than a single call. I believe you can use FindFirstFileA for this on Windows and fcntl with F_GETPATH on Unixes.

@nex3 nex3 added area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-io type-enhancement A request for a change that isn't a bug customer-dart-sass labels Dec 10, 2018
@nex3
Copy link
Member Author

nex3 commented Dec 10, 2018

Note that something like realpath() is not sufficient here, because I explicitly do not want to resolve symbolic links.

@ghost
Copy link

ghost commented Jan 15, 2020

You dont want to resolve symbolic links? I think that the norm for this type of thing. Personally I dont have a preference either way, but do you have something youre looking to as an example?

Just as one data point, PHP does resolve symlinks:

https://php.net/function.realpath

what about:

https://api.dart.dev/stable/dart-io/File/absolute.html

@nex3
Copy link
Member Author

nex3 commented Jan 15, 2020

From File.absolute()'s documentation:

The absolute path is computed by prefixing a relative path with the current working directory, and returning an absolute path unchanged.

That doesn't handle the case where the input path uses different capitalization than the path on disk.

@ghost
Copy link

ghost commented Jan 15, 2020

That doesn't handle the case where the input path uses different
capitalization than the path on disk.

Honestly I am not sure what the expected result is here. As an example using
Cygwin realpath with Windows doesnt concern itself with case, even when
comparing against the filesystem:

$ cd /tmp
$ touch sunday.txt
$ ls
sunday.txt

$ realpath monday.txt
/tmp/monday.txt

$ realpath -e monday.txt
realpath: monday.txt: No such file or directory

$ realpath -e SUNDAY.TXT
/tmp/SUNDAY.TXT

Why does Dart realpath need to care about the resultant case if the underlying
operating system doesnt?

@nex3
Copy link
Member Author

nex3 commented Jan 15, 2020

The expected result, as I explained in the original comment, is the output of FindFirstFileA on Windows and fcntl with F_GETPATH on Unixes.

Why does Dart realpath need to care about the resultant case if the underlying
operating system doesnt?

In my case, because I need to canonicalize files based on their paths, and canonicalizing Foo differently than foo on Windows is not acceptable.

@ghost
Copy link

ghost commented Jan 15, 2020

@nex3 I get that for your case its needed, but have you come across an implementation in any other programming language that does what you expect?

If not, maybe this would make more sense in a personal library than in the official SDK.

@nex3
Copy link
Member Author

nex3 commented Jan 15, 2020

I get that for your case its needed, but have you come across an implementation in any other programming language that does what you expect?

Yes, C and C++, as well as any language that provides access to the underlying operating system's APIs (such as Ruby).

If not, maybe this would make more sense in a personal library than in the official SDK.

How would I go about doing this, exactly? dart:io has a monopoly on access to system APIs.

@ghost
Copy link

ghost commented Jan 15, 2020

Yes, C and C++, as well as any language that provides access to the underlying
operating system's APIs (such as Ruby).

@nex3 are you sure about that?

$ ls
sunday.txt

$ ruby -e 'p File.realpath("monday.txt")'
Traceback (most recent call last):
   from -e:1:in `<main>'
-e:1:in `realpath': No such file or directory @ realpath_rec - /tmp/monday.txt
   (Errno::ENOENT)

$ ruby -e 'p File.realpath("SUNDAY.TXT")'
"/tmp/SUNDAY.TXT"

@nex3
Copy link
Member Author

nex3 commented Jan 15, 2020

But the old Win32API standard library provided direct access to the APIs in question.

@ghost
Copy link

ghost commented Jan 15, 2020

The Windows API is not a programming language, its a method to access low level system calls, similar to the Linux API:

https://en.wikipedia.org/wiki/Linux_kernel_interfaces

It does make sense to have support for this with certain programming languages. For example Go has the syscall library:

https://golang.org/pkg/syscall

I dont know if it makes sense for Dart to have something like this, as I consider it more high level. But even if Dart has syscall support at the user level, thats not really an implementation of a particular task so to speak. For example, if you want to open a file with Go, youre going to use the os package, not the syscall package.

All this is to say that I dont think pointing to programming languages that have a syscall library is a good justification of why the issue in the original post should be implemented.

With that justification, you could say really anything in the Windows API should be implemented in the Dart standard library.

@nex3
Copy link
Member Author

nex3 commented Jan 15, 2020

I do indeed think that Dart should provide a way to do pretty much anything supported by native OS APIs, especially when it's supported across all platforms that Dart supports. Whether that's a syscall library, an encapsulation of this particular syscall, or a portable means of writing our own syscalls, I don't really care—all I asked for was a way to make this possible.

@ghost
Copy link

ghost commented Jan 15, 2020

Fair enough. However unless we can point to other languages that have a realpath method that behaves like you describe, or some other method that behaves like you describe, or alternatively some good justification as to why Dart should have this in core, I think it would be better suited to a Dart syscall package or similar.

I havent done thorough testing, but the languages I have tested dont act the way you propose, so I agree with you that it makes sense for it to be possible, just maybe not the default.

@nex3
Copy link
Member Author

nex3 commented Jan 15, 2020

I'm not sure why you think I want this to be part of realpath(). All I asked for was some way of doing this.

@ghost
Copy link

ghost commented Jan 15, 2020

What you do think about Dart creating a syscall package? That way your use case would be available as well as others

@nex3
Copy link
Member Author

nex3 commented Jan 15, 2020

That would be great. I think it would need to be a core library, though, not a package.

@ghost
Copy link

ghost commented Jan 15, 2020

That sounds good to me

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. customer-dart-sass library-io type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

1 participant