Skip to content

Commit

Permalink
osfs: Add WithDeduplicatePath
Browse files Browse the repository at this point in the history
In specific workflows within the BoundOS OS type, the
returned path may have the base dir duplicated.
By default such duplications are removed automatically,
the new WithDeduplicatePath allows users to toggle that
behaviour.

Signed-off-by: Paulo Gomes <pjbgf@linux.com>
  • Loading branch information
pjbgf committed Sep 11, 2023
1 parent e223a66 commit 3994cd7
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 66 deletions.
23 changes: 21 additions & 2 deletions osfs/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ const (
var Default = &ChrootOS{}

// New returns a new OS filesystem.
// By default paths are deduplicated, but still enforced
// under baseDir. For more info refer to WithDeduplicatePath.
func New(baseDir string, opts ...Option) billy.Filesystem {
o := &options{}
o := &options{
deduplicatePath: true,
}
for _, opt := range opts {
opt(o)
}

if o.Type == BoundOSFS {
return newBoundOS(baseDir)
return newBoundOS(baseDir, o.deduplicatePath)
}

return newChrootOS(baseDir)
Expand All @@ -49,8 +53,23 @@ func WithChrootOS() Option {
}
}

// WithDeduplicatePath toggles the deduplication of the base dir in the path.
// This occurs when absolute links are being used.
// Assuming base dir /base/dir and an absolute symlink /base/dir/target:
//
// With DeduplicatePath (default): /base/dir/target
// Without DeduplicatePath: /base/dir/base/dir/target
//
// This option is only used by the BoundOS OS type.
func WithDeduplicatePath(enabled bool) Option {
return func(o *options) {
o.deduplicatePath = enabled
}
}

type options struct {
Type
deduplicatePath bool
}

type Type int
Expand Down
24 changes: 18 additions & 6 deletions osfs/os_bound.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ import (
// 3. Readlink and Lstat ensures that the link file is located within the base
// dir, evaluating any symlinks that file or base dir may contain.
type BoundOS struct {
baseDir string
baseDir string
deduplicatePath bool
}

func newBoundOS(d string) billy.Filesystem {
return &BoundOS{baseDir: d}
func newBoundOS(d string, deduplicatePath bool) billy.Filesystem {
return &BoundOS{baseDir: d, deduplicatePath: deduplicatePath}
}

func (fs *BoundOS) Create(filename string) (billy.File, error) {
Expand Down Expand Up @@ -212,10 +213,21 @@ func (fs *BoundOS) createDir(fullpath string) error {
func (fs *BoundOS) abs(filename string) (string, error) {
if filename == fs.baseDir {
filename = string(filepath.Separator)
} else if cw := fs.baseDir + string(filepath.Separator); strings.HasPrefix(filename, cw) {
filename = strings.TrimPrefix(filename, cw)
}
return securejoin.SecureJoin(fs.baseDir, filename)

path, err := securejoin.SecureJoin(fs.baseDir, filename)
if err != nil {
return "", nil
}

if fs.deduplicatePath {
vol := filepath.VolumeName(fs.baseDir)
dup := filepath.Join(fs.baseDir, fs.baseDir[len(vol):])
if strings.HasPrefix(path, dup+string(filepath.Separator)) {
return fs.abs(path[len(dup):])
}
}
return path, nil
}

// insideBaseDir checks whether filename is located within
Expand Down
Loading

0 comments on commit 3994cd7

Please sign in to comment.