the documentation boost::filesystem::canonical(const path& p) states:
overview: converts p, must exist, absolute path has no symbolic link, dot, or dot-dot elements.
...
remarks: !exists(p) error.
the consequence of if p identifies symbolic link target not exist, function fails file not found , not return path.
this seems overly restrictive me: because target of link doesn't exist, see no reason why function can't resolve path of non-existent target. (in comparison, absolute() imposes no such restriction.)
(clearly, if symbolic link within path broken, target path can't resolved.)
so, there legitimate justification restriction?
and if there is, there not justification creation of variant of function not have restriction? (without such variant, obtaining path requires error-prone manual replication of 99% of canonical() does.)
i appreciate semantic subtleties exist between stat() , lstat() apply equally case - precisely why think variant of function equally justified.
nb: question equally applicable std::experimental::filesystem library (n4100), based on boost::filesystem.
edit:
after @jonathan wakeley's knowledgeable answer below, i'm still left essence of original questions, i'll reframe slightly:
is there underlying technical or logical reason why
boost::filesystem::canonical()requires target exist? mean, non-existence of target somehow make impossible resolve path canonical form?if not, there technical or logical reason not propose variation of function differs existing form in not require target exist?
in transformation (as understand case) of
boost::filesystemproposed n4100std::experimental::filesystem, has restriction oncanonical()been adopted after due consideration, or 'falling through' boost definition?
edit 2:
i notice boost 1.60 provides function weakly_canonical(): "returns p symlinks resolved , result normalized. returns: path composed of result of calling canonical() function on path composed of leading elements of p exist, if any, followed elements of p not exist, if any."
edit 3:
more discussion of this in relation std::filesystem.
basically because it's wrapper realpath has same requirement.
you ask same question of realpath, think answer if you're trying find out real, physical file or directory pathname refers to, if broken symlink there no answer, doesn't refer real file or directory, want error.
the op's comment below questions claim filesystem::canonical , realpath implement same operation, definitions in n4100 , posix seem identical me, compare:
the
realpath()function shall derive, pathname pointedfile_name, absolute pathname resolves same directory entry, resolution not involve'.','..', or symbolic links.
and:
converts
p, must exist, absolute path has no symbolic link,".", or".."elements.
in both cases requirements are:
no symbolic links, if returned path last component symbolic link requirement not met.
the canonical path refers exists, explicit in n4100, , implicit in posix in points directory entry (i.e. exists) , directory entry not symbolic link (because of first requirement).
as why should requirements, note in n4100 helpful:
[note: canonical pathnames allow security checking of path (e.g. path live in
/home/goodguyor/home/badguy?) —end note]
as said above, if returns when path symlink doesn't point anything, need work check if resolves real file or not, making intended use case less convenient.
and if there is, there not justification creation of variant of function not have restriction? (without such variant, obtaining path requires error-prone manual replication of 99% of canonical() does.)
arguably variant less commonly useful, , should not default, if need it's not difficult do:
// canonical() allows last component of p broken symlink filesystem::path resolve_most_symlinks(filesystem::path const& p, filesystem::path const& base = filesystem::current_path()) { if (is_symlink(p) && !exists(p)) return canonical(absolute(p, base).remove_filename()) / p.filename(); return canonical(p); }
Comments
Post a Comment