Skip to content

Commit

Permalink
Extract SourcePath::followSymlinks()
Browse files Browse the repository at this point in the history
  • Loading branch information
roberth committed Nov 19, 2023
1 parent 1d86bb4 commit a1da214
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
16 changes: 16 additions & 0 deletions src/libfetchers/input-accessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,22 @@ SourcePath SourcePath::parent() const
return {accessor, std::move(*p)};
}

SourcePath SourcePath::followSymlinks() const {
SourcePath path = *this;
unsigned int followCount = 0, maxFollow = 1024;

/* If `path' is a symlink, follow it. This is so that relative
path references work. */
while (true) {
// Basic cycle/depth limit to avoid infinite loops.
if (++followCount >= maxFollow)
throw Error("too many symbolic links encountered while traversing the path '%s'", path);
if (path.lstat().type != InputAccessor::tSymlink) break;
path = {path.accessor, CanonPath(path.readLink(), path.path.parent().value_or(CanonPath::root))};
}
return path;
}

SourcePath SourcePath::resolveSymlinks() const
{
auto res = accessor->root();
Expand Down
13 changes: 11 additions & 2 deletions src/libfetchers/input-accessor.hh
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,19 @@ struct SourcePath

/**
* Resolve any symlinks in this `SourcePath` (including its
* parents). The result is a `SourcePath` in which no element is a
* symlink.
* parents).
*
* @return A `SourcePath` in which no element is a symlink.
*/
SourcePath resolveSymlinks() const;

/**
* If this `SourcePath` is a symlink, resolve it, but do not resolve
* symlinks in its parent paths.
*
* @return A `SourcePath` in which the final element is not a symlink.
*/
SourcePath followSymlinks() const;
};

std::ostream & operator << (std::ostream & str, const SourcePath & path);
Expand Down

0 comments on commit a1da214

Please sign in to comment.