Files
overlayfs/mergefs_iofs.go
Matheus Sampaio Queiroga bdaebacbf1
Some checks failed
Golang test / go-test (ubuntu-latest) (push) Successful in 16s
Golang test / go-test (windows-latest) (push) Failing after 6m56s
Refactor overlayfs: improve path validation and clean up code structure; add comprehensive tests for read/write operations.
Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
2025-07-13 01:11:54 -03:00

95 lines
3.2 KiB
Go

package overlayfs
import (
"io/fs"
"path/filepath"
)
var (
_ fs.FS = &FsMergeFs{}
_ fs.ReadFileFS = &FsMergeFs{}
_ fs.ReadDirFS = &FsMergeFs{}
_ fs.StatFS = &FsMergeFs{}
_ fs.SubFS = &FsMergeFs{}
)
// Implementes [io/fs.FS] to Overlayfs
type FsMergeFs struct {
MergedFS *Overlayfs // Overlayfs
Subdir string // Sub dir to find files
}
// Return [io/fs.FS] from Overlayfs
func (fs *Overlayfs) Mergefs() fs.FS {
return &FsMergeFs{
MergedFS: fs,
Subdir: "",
}
}
// Sub returns an [FS] corresponding to the subtree rooted at fsys's dir.
//
// If dir is ".", Sub returns fsys unchanged.
// Otherwise, if fs implements [SubFS], Sub returns fsys.Sub(dir).
// Otherwise, Sub returns a new [FS] implementation sub that,
// in effect, implements sub.Open(name) as fsys.Open(path.Join(dir, name)).
// The implementation also translates calls to ReadDir, ReadFile, and Glob appropriately.
//
// Note that Sub(os.DirFS("/"), "prefix") is equivalent to os.DirFS("/prefix")
// and that neither of them guarantees to avoid operating system
// accesses outside "/prefix", because the implementation of [os.DirFS]
// does not check for symbolic links inside "/prefix" that point to
// other directories. That is, [os.DirFS] is not a general substitute for a
// chroot-style security mechanism, and Sub does not change that fact.
func (fss FsMergeFs) Sub(dir string) (fs.FS, error) {
return &FsMergeFs{MergedFS: fss.MergedFS, Subdir: filepath.Join(fss.Subdir, filepath.Clean(dir))}, nil
}
// Open opens the named file.
//
// When Open returns an error, it should be of type *PathError
// with the Op field set to "open", the Path field set to name,
// and the Err field describing the problem.
//
// Open should reject attempts to open names that do not satisfy
// ValidPath(name), returning a *PathError with Err set to
// ErrInvalid or ErrNotExist.
func (fss FsMergeFs) Open(name string) (fs.File, error) {
if fss.MergedFS == nil {
return nil, fs.ErrInvalid
}
return fss.MergedFS.Open(filepath.Join(fss.Subdir, filepath.Clean(name)))
}
// ReadDir reads the named directory
// and returns a list of directory entries sorted by filename.
func (fss FsMergeFs) ReadDir(name string) ([]fs.DirEntry, error) {
if fss.MergedFS == nil {
return nil, fs.ErrInvalid
}
return fss.MergedFS.ReadDir(filepath.Join(fss.Subdir, filepath.Clean(name)))
}
// Stat returns a FileInfo describing the file.
// If there is an error, it should be of type *PathError.
func (fss FsMergeFs) Stat(name string) (fs.FileInfo, error) {
if fss.MergedFS == nil {
return nil, fs.ErrInvalid
}
return fss.MergedFS.Stat(filepath.Join(fss.Subdir, filepath.Clean(name)))
}
// ReadFile reads the named file and returns its contents.
// A successful call returns a nil error, not io.EOF.
// (Because ReadFile reads the whole file, the expected EOF
// from the final Read is not treated as an error to be reported.)
//
// The caller is permitted to modify the returned byte slice.
// This method should return a copy of the underlying data.
func (fss FsMergeFs) ReadFile(name string) ([]byte, error) {
if fss.MergedFS == nil {
return nil, fs.ErrInvalid
}
return fss.MergedFS.ReadFile(filepath.Join(fss.Subdir, filepath.Clean(name)))
}