Skip to content

Commit 3c59de8

Browse files
committed
osfs: Add new BoundOS type
Create the new BoundOS osfs type, which works as a pass-through filesystem for files descending from base dir. For backwards compatibility the previous behaviour is still the default and is now represented by the ChrootOS type. Signed-off-by: Paulo Gomes <[email protected]>
1 parent dafe8bc commit 3c59de8

File tree

13 files changed

+1665
-115
lines changed

13 files changed

+1665
-115
lines changed

go.mod

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,20 @@ module github.com/go-git/go-billy/v5
33
// go-git supports the last 3 stable Go versions.
44
go 1.19
55

6+
replace github.com/cyphar/filepath-securejoin => github.com/pjbgf/filepath-securejoin v0.0.0-20230821001828-0ca74e6d4bf8
7+
68
require (
7-
golang.org/x/sys v0.8.0
9+
github.com/cyphar/filepath-securejoin v0.2.3
10+
github.com/onsi/gomega v1.27.10
11+
golang.org/x/sys v0.11.0
812
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
913
)
1014

1115
require (
16+
github.com/google/go-cmp v0.5.9 // indirect
1217
github.com/kr/pretty v0.2.1 // indirect
1318
github.com/kr/text v0.2.0 // indirect
19+
golang.org/x/net v0.12.0 // indirect
20+
golang.org/x/text v0.11.0 // indirect
21+
gopkg.in/yaml.v3 v3.0.1 // indirect
1422
)

go.sum

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2+
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
3+
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
4+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
5+
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
6+
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
27
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
38
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
49
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
510
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
611
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
712
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
8-
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
9-
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
13+
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
14+
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
15+
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
16+
github.com/pjbgf/filepath-securejoin v0.0.0-20230821001828-0ca74e6d4bf8 h1:nqjCeQ2TVnccihhBoVBd0p+70hCFT4yqJKhfc8l1D50=
17+
github.com/pjbgf/filepath-securejoin v0.0.0-20230821001828-0ca74e6d4bf8/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
18+
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
19+
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
20+
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
21+
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
22+
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
23+
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
24+
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
25+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1026
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
1127
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
28+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
29+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

osfs/os.go

Lines changed: 56 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,140 +1,101 @@
1+
//go:build !js
12
// +build !js
23

34
// Package osfs provides a billy filesystem for the OS.
4-
package osfs // import "github.com/go-git/go-billy/v5/osfs"
5+
package osfs
56

67
import (
7-
"io/ioutil"
8+
"fmt"
9+
"io/fs"
810
"os"
9-
"path/filepath"
1011
"sync"
1112

1213
"github.com/go-git/go-billy/v5"
13-
"github.com/go-git/go-billy/v5/helper/chroot"
1414
)
1515

1616
const (
17-
defaultDirectoryMode = 0755
18-
defaultCreateMode = 0666
17+
defaultDirectoryMode = 0o755
18+
defaultCreateMode = 0o666
1919
)
2020

21-
// Default Filesystem representing the root of the os filesystem.
22-
var Default = &OS{}
23-
24-
// OS is a filesystem based on the os filesystem.
25-
type OS struct{}
26-
2721
// New returns a new OS filesystem.
28-
func New(baseDir string) billy.Filesystem {
29-
return chroot.New(Default, baseDir)
30-
}
31-
32-
func (fs *OS) Create(filename string) (billy.File, error) {
33-
return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, defaultCreateMode)
34-
}
35-
36-
func (fs *OS) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
37-
if flag&os.O_CREATE != 0 {
38-
if err := fs.createDir(filename); err != nil {
39-
return nil, err
40-
}
41-
}
42-
43-
f, err := os.OpenFile(filename, flag, perm)
44-
if err != nil {
45-
return nil, err
22+
func New(baseDir string, opts ...Option) billy.Filesystem {
23+
o := &options{}
24+
for _, opt := range opts {
25+
opt(o)
4626
}
47-
return &file{File: f}, err
48-
}
4927

50-
func (fs *OS) createDir(fullpath string) error {
51-
dir := filepath.Dir(fullpath)
52-
if dir != "." {
53-
if err := os.MkdirAll(dir, defaultDirectoryMode); err != nil {
54-
return err
55-
}
28+
if o.Type == BoundOSFS {
29+
return newBoundOS(baseDir)
5630
}
5731

58-
return nil
32+
return newChrootOS(baseDir)
5933
}
6034

61-
func (fs *OS) ReadDir(path string) ([]os.FileInfo, error) {
62-
l, err := ioutil.ReadDir(path)
63-
if err != nil {
64-
return nil, err
65-
}
66-
67-
var s = make([]os.FileInfo, len(l))
68-
for i, f := range l {
69-
s[i] = f
35+
// WithBoundOS returns the option of using a Bound filesystem OS.
36+
func WithBoundOS() Option {
37+
return func(o *options) {
38+
o.Type = BoundOSFS
7039
}
71-
72-
return s, nil
7340
}
7441

75-
func (fs *OS) Rename(from, to string) error {
76-
if err := fs.createDir(to); err != nil {
77-
return err
42+
// WithChrootOS returns the option of using a Chroot filesystem OS.
43+
func WithChrootOS() Option {
44+
return func(o *options) {
45+
o.Type = ChrootOSFS
7846
}
79-
80-
return rename(from, to)
81-
}
82-
83-
func (fs *OS) MkdirAll(path string, perm os.FileMode) error {
84-
return os.MkdirAll(path, defaultDirectoryMode)
8547
}
8648

87-
func (fs *OS) Open(filename string) (billy.File, error) {
88-
return fs.OpenFile(filename, os.O_RDONLY, 0)
49+
type options struct {
50+
Type
8951
}
9052

91-
func (fs *OS) Stat(filename string) (os.FileInfo, error) {
92-
return os.Stat(filename)
93-
}
53+
type Type int
9454

95-
func (fs *OS) Remove(filename string) error {
96-
return os.Remove(filename)
97-
}
55+
const (
56+
ChrootOSFS Type = iota
57+
BoundOSFS
58+
)
9859

99-
func (fs *OS) TempFile(dir, prefix string) (billy.File, error) {
100-
if err := fs.createDir(dir + string(os.PathSeparator)); err != nil {
60+
func readDir(dir string) ([]os.FileInfo, error) {
61+
entries, err := os.ReadDir(dir)
62+
if err != nil {
10163
return nil, err
10264
}
65+
infos := make([]fs.FileInfo, 0, len(entries))
66+
for _, entry := range entries {
67+
fi, err := entry.Info()
68+
if err != nil {
69+
return nil, err
70+
}
71+
infos = append(infos, fi)
72+
}
73+
return infos, nil
74+
}
10375

104-
f, err := ioutil.TempFile(dir, prefix)
76+
func tempFile(dir, prefix string) (billy.File, error) {
77+
f, err := os.CreateTemp(dir, prefix)
10578
if err != nil {
10679
return nil, err
10780
}
10881
return &file{File: f}, nil
10982
}
11083

111-
func (fs *OS) Join(elem ...string) string {
112-
return filepath.Join(elem...)
113-
}
114-
115-
func (fs *OS) RemoveAll(path string) error {
116-
return os.RemoveAll(filepath.Clean(path))
117-
}
118-
119-
func (fs *OS) Lstat(filename string) (os.FileInfo, error) {
120-
return os.Lstat(filepath.Clean(filename))
121-
}
122-
123-
func (fs *OS) Symlink(target, link string) error {
124-
if err := fs.createDir(link); err != nil {
125-
return err
84+
func openFile(fn string, flag int, perm os.FileMode, createDir func(string) error) (billy.File, error) {
85+
if flag&os.O_CREATE != 0 {
86+
if createDir == nil {
87+
return nil, fmt.Errorf("createDir func cannot be nil if file needs to be opened in create mode")
88+
}
89+
if err := createDir(fn); err != nil {
90+
return nil, err
91+
}
12692
}
12793

128-
return os.Symlink(target, link)
129-
}
130-
131-
func (fs *OS) Readlink(link string) (string, error) {
132-
return os.Readlink(link)
133-
}
134-
135-
// Capabilities implements the Capable interface.
136-
func (fs *OS) Capabilities() billy.Capability {
137-
return billy.DefaultCapabilities
94+
f, err := os.OpenFile(fn, flag, perm)
95+
if err != nil {
96+
return nil, err
97+
}
98+
return &file{File: f}, err
13899
}
139100

140101
// file is a wrapper for an os.File which adds support for file locking.

0 commit comments

Comments
 (0)