1//go:build !js
  2// +build !js
  3
  4package osfs
  5
  6import (
  7	"os"
  8	"path/filepath"
  9
 10	"github.com/go-git/go-billy/v5"
 11	"github.com/go-git/go-billy/v5/helper/chroot"
 12)
 13
 14// ChrootOS is a legacy filesystem based on a "soft chroot" of the os filesystem.
 15// Although this is still the default os filesystem, consider using BoundOS instead.
 16//
 17// Deprecated: use New with WithBoundOS instead.
 18//
 19// Behaviours of note:
 20//  1. A "soft chroot" translates the base dir to "/" for the purposes of the
 21//     fs abstraction.
 22//  2. Symlinks targets may be modified to be kept within the chroot bounds.
 23//  3. Some file modes does not pass-through the fs abstraction.
 24//  4. The combination of 1 and 2 may cause go-git to think that a Git repository
 25//     is dirty, when in fact it isn't.
 26type ChrootOS struct{}
 27
 28func newChrootOS(baseDir string) billy.Filesystem {
 29	if baseDir != "" {
 30		resolved, err := filepath.EvalSymlinks(baseDir)
 31		if err != nil {
 32			return chroot.New(&ChrootOS{}, baseDir)
 33		}
 34		baseDir = resolved
 35	}
 36
 37	return chroot.New(&ChrootOS{}, baseDir)
 38}
 39
 40func (fs *ChrootOS) Create(filename string) (billy.File, error) {
 41	return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, defaultCreateMode)
 42}
 43
 44func (fs *ChrootOS) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
 45	return openFile(filename, flag, perm, fs.createDir)
 46}
 47
 48func (fs *ChrootOS) createDir(fullpath string) error {
 49	dir := filepath.Dir(fullpath)
 50	if dir != "." {
 51		if err := os.MkdirAll(dir, defaultDirectoryMode); err != nil {
 52			return err
 53		}
 54	}
 55
 56	return nil
 57}
 58
 59func (fs *ChrootOS) ReadDir(dir string) ([]os.FileInfo, error) {
 60	return readDir(dir)
 61}
 62
 63func (fs *ChrootOS) Rename(from, to string) error {
 64	if err := fs.createDir(to); err != nil {
 65		return err
 66	}
 67
 68	return rename(from, to)
 69}
 70
 71func (fs *ChrootOS) MkdirAll(path string, perm os.FileMode) error {
 72	return os.MkdirAll(path, defaultDirectoryMode)
 73}
 74
 75func (fs *ChrootOS) Open(filename string) (billy.File, error) {
 76	return fs.OpenFile(filename, os.O_RDONLY, 0)
 77}
 78
 79func (fs *ChrootOS) Stat(filename string) (os.FileInfo, error) {
 80	return os.Stat(filename)
 81}
 82
 83func (fs *ChrootOS) Remove(filename string) error {
 84	return os.Remove(filename)
 85}
 86
 87func (fs *ChrootOS) Chmod(path string, mode os.FileMode) error {
 88	return os.Chmod(path, mode)
 89}
 90
 91func (fs *ChrootOS) TempFile(dir, prefix string) (billy.File, error) {
 92	if err := fs.createDir(dir + string(os.PathSeparator)); err != nil {
 93		return nil, err
 94	}
 95
 96	return tempFile(dir, prefix)
 97}
 98
 99func (fs *ChrootOS) Join(elem ...string) string {
100	return filepath.Join(elem...)
101}
102
103func (fs *ChrootOS) RemoveAll(path string) error {
104	return os.RemoveAll(filepath.Clean(path))
105}
106
107func (fs *ChrootOS) Lstat(filename string) (os.FileInfo, error) {
108	return os.Lstat(filepath.Clean(filename))
109}
110
111func (fs *ChrootOS) Symlink(target, link string) error {
112	if err := fs.createDir(link); err != nil {
113		return err
114	}
115
116	return os.Symlink(target, link)
117}
118
119func (fs *ChrootOS) Readlink(link string) (string, error) {
120	return os.Readlink(link)
121}
122
123// Capabilities implements the Capable interface.
124func (fs *ChrootOS) Capabilities() billy.Capability {
125	return billy.DefaultCapabilities
126}