public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/113246] New: Behavior of std::filesystem::weakly_canonical with non-existing relative paths
@ 2024-01-05 21:31 davidepesa at gmail dot com
  2024-01-05 21:56 ` [Bug libstdc++/113246] " davidepesa at gmail dot com
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: davidepesa at gmail dot com @ 2024-01-05 21:31 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113246

            Bug ID: 113246
           Summary: Behavior of std::filesystem::weakly_canonical with
                    non-existing relative paths
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: davidepesa at gmail dot com
  Target Milestone: ---

I initially reported this as a Boost.Filesystem issue
(https://github.com/boostorg/filesystem/issues/300), but std::filesystem in
libstdc++ has the same behavior.

With -std=c++17, weakly_canonical("foo/bar") returns "foo/bar" when "foo" does
not exist in the current working directory.

Conversely, when at least one leading element of the input path exists, the
returned path is absolute, e.g., weakly_canonical("existing/foo/bar") ==
"/home/existing/foo/bar".

It's not clear to me how to interpret the standard wording
(https://eel.is/c++draft/fs.op.weakly.canonical#1) in this case. It says:

> return a path composed by operator/= from the result of calling canonical() with a path argument composed of the leading elements of p that exist, if any, ...

If there are no leading elements of p that exist, should canonical() be called
with an empty path? or should it not be called at all? (if it's the former,
note that canonical("") currently throws a filesystem_error)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/113246] Behavior of std::filesystem::weakly_canonical with non-existing relative paths
  2024-01-05 21:31 [Bug libstdc++/113246] New: Behavior of std::filesystem::weakly_canonical with non-existing relative paths davidepesa at gmail dot com
@ 2024-01-05 21:56 ` davidepesa at gmail dot com
  2024-01-06  0:29 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: davidepesa at gmail dot com @ 2024-01-05 21:56 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113246

--- Comment #1 from Davide Pesavento <davidepesa at gmail dot com> ---
Another interesting(?) behavior, when run from a non-existing (deleted) working
directory:

weakly_canonical("foo") returns "foo", while weakly_canonical("./foo") throws:

> terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
>   what():  filesystem error: cannot make canonical path: No such file or directory [.]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/113246] Behavior of std::filesystem::weakly_canonical with non-existing relative paths
  2024-01-05 21:31 [Bug libstdc++/113246] New: Behavior of std::filesystem::weakly_canonical with non-existing relative paths davidepesa at gmail dot com
  2024-01-05 21:56 ` [Bug libstdc++/113246] " davidepesa at gmail dot com
@ 2024-01-06  0:29 ` redi at gcc dot gnu.org
  2024-01-06  0:36 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2024-01-06  0:29 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113246

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Davide Pesavento from comment #0)
> note that canonical("") currently throws a filesystem_error)

That's clearly correct, as canonical says that !exists(p) is an error.

> If there are no leading elements of p that exist, should canonical() be
> called with an empty path? or should it not be called at all?

It makes no sense for weakly_canonical to ever call canonical with an empty
path, since that would always report an error (i.e. throw or set ec and return
an empty path). That would make it completely useless for paths with no prefix
that already exists. So if there are no leading elements of p that exist, then
obviously canonical should not be called. The alternative makes no sense.

So the behaviour of weakly_canonical seems correct to me. If any leading
elements exist, then canonical is called on them, which returns an absolute
path, and then the non-existing elements are appended to that. If there are no
existing elements, then you get a relative path.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/113246] Behavior of std::filesystem::weakly_canonical with non-existing relative paths
  2024-01-05 21:31 [Bug libstdc++/113246] New: Behavior of std::filesystem::weakly_canonical with non-existing relative paths davidepesa at gmail dot com
  2024-01-05 21:56 ` [Bug libstdc++/113246] " davidepesa at gmail dot com
  2024-01-06  0:29 ` redi at gcc dot gnu.org
@ 2024-01-06  0:36 ` redi at gcc dot gnu.org
  2024-01-06  1:01 ` redi at gcc dot gnu.org
  2024-01-06  1:12 ` davidepesa at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2024-01-06  0:36 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113246

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Davide Pesavento from comment #1)
> Another interesting(?) behavior, when run from a non-existing (deleted)
> working directory:
> 
> weakly_canonical("foo") returns "foo", while weakly_canonical("./foo")
> throws:
> 
> > terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
> >   what():  filesystem error: cannot make canonical path: No such file or directory [.]

This case is a bit more interesting. I'll have to investigate further.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/113246] Behavior of std::filesystem::weakly_canonical with non-existing relative paths
  2024-01-05 21:31 [Bug libstdc++/113246] New: Behavior of std::filesystem::weakly_canonical with non-existing relative paths davidepesa at gmail dot com
                   ` (2 preceding siblings ...)
  2024-01-06  0:36 ` redi at gcc dot gnu.org
@ 2024-01-06  1:01 ` redi at gcc dot gnu.org
  2024-01-06  1:12 ` davidepesa at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: redi at gcc dot gnu.org @ 2024-01-06  1:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113246

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I think the exception for a deleted pwd is also correct.

weakly_canonical uses status(".") to check if the current directory exists.
That returns true, even if the directory has been deleted (it still exists
because there are open descriptors referring to it, you just can't find it by
name any longer). Because the directory exists, we call canonical(".") to get
its absolute name. But that fails, because it uses current_path()/p and
absolute_path uses getcwd() which fails with ENOENT.

The directory exists, but you can't get its name, so you can't canonicalize it.

So I think the libstdc++ behaviour conforms to the standard.

I think it might also be conforming if weakly_canonical detected that
exists(".") is insufficient to guarantee that we can call canonical. Since the
point of weakly_canonical is to handle non-existing directories, I think it
would be useful to add a special case for relative paths explicitly beginning
with "." if current_path() fails. But I don't think the standard requires us to
do that.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Bug libstdc++/113246] Behavior of std::filesystem::weakly_canonical with non-existing relative paths
  2024-01-05 21:31 [Bug libstdc++/113246] New: Behavior of std::filesystem::weakly_canonical with non-existing relative paths davidepesa at gmail dot com
                   ` (3 preceding siblings ...)
  2024-01-06  1:01 ` redi at gcc dot gnu.org
@ 2024-01-06  1:12 ` davidepesa at gmail dot com
  4 siblings, 0 replies; 6+ messages in thread
From: davidepesa at gmail dot com @ 2024-01-06  1:12 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113246

--- Comment #5 from Davide Pesavento <davidepesa at gmail dot com> ---
(In reply to Jonathan Wakely from comment #2)
> > If there are no leading elements of p that exist, should canonical() be
> > called with an empty path? or should it not be called at all?
> 
> It makes no sense for weakly_canonical to ever call canonical with an empty
> path, since that would always report an error (i.e. throw or set ec and
> return an empty path). That would make it completely useless for paths with
> no prefix that already exists. So if there are no leading elements of p that
> exist, then obviously canonical should not be called. The alternative makes
> no sense.
> 
> So the behaviour of weakly_canonical seems correct to me. If any leading
> elements exist, then canonical is called on them, which returns an absolute
> path, and then the non-existing elements are appended to that. If there are
> no existing elements, then you get a relative path.

Thanks. Not the answer I was hoping for(*) but I guess it does make sense
logically.

(*) because it means that weakly_canonical("foo") and weakly_canonical("./foo")
give different results. I guess weakly_canonical(absolute(whatever)) is what I
need (in most cases).

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-01-06  1:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-05 21:31 [Bug libstdc++/113246] New: Behavior of std::filesystem::weakly_canonical with non-existing relative paths davidepesa at gmail dot com
2024-01-05 21:56 ` [Bug libstdc++/113246] " davidepesa at gmail dot com
2024-01-06  0:29 ` redi at gcc dot gnu.org
2024-01-06  0:36 ` redi at gcc dot gnu.org
2024-01-06  1:01 ` redi at gcc dot gnu.org
2024-01-06  1:12 ` davidepesa at gmail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).