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}