forked from toolshed/abra
		
	
		
			
				
	
	
		
			128 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| //go:build !js
 | |
| // +build !js
 | |
| 
 | |
| // Package osfs provides a billy filesystem for the OS.
 | |
| package osfs
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"io/fs"
 | |
| 	"os"
 | |
| 	"sync"
 | |
| 
 | |
| 	"github.com/go-git/go-billy/v5"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	defaultDirectoryMode = 0o755
 | |
| 	defaultCreateMode    = 0o666
 | |
| )
 | |
| 
 | |
| // Default Filesystem representing the root of the os filesystem.
 | |
| 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{
 | |
| 		deduplicatePath: true,
 | |
| 	}
 | |
| 	for _, opt := range opts {
 | |
| 		opt(o)
 | |
| 	}
 | |
| 
 | |
| 	if o.Type == BoundOSFS {
 | |
| 		return newBoundOS(baseDir, o.deduplicatePath)
 | |
| 	}
 | |
| 
 | |
| 	return newChrootOS(baseDir)
 | |
| }
 | |
| 
 | |
| // WithBoundOS returns the option of using a Bound filesystem OS.
 | |
| func WithBoundOS() Option {
 | |
| 	return func(o *options) {
 | |
| 		o.Type = BoundOSFS
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // WithChrootOS returns the option of using a Chroot filesystem OS.
 | |
| func WithChrootOS() Option {
 | |
| 	return func(o *options) {
 | |
| 		o.Type = ChrootOSFS
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // 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
 | |
| 
 | |
| const (
 | |
| 	ChrootOSFS Type = iota
 | |
| 	BoundOSFS
 | |
| )
 | |
| 
 | |
| func readDir(dir string) ([]os.FileInfo, error) {
 | |
| 	entries, err := os.ReadDir(dir)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	infos := make([]fs.FileInfo, 0, len(entries))
 | |
| 	for _, entry := range entries {
 | |
| 		fi, err := entry.Info()
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		infos = append(infos, fi)
 | |
| 	}
 | |
| 	return infos, nil
 | |
| }
 | |
| 
 | |
| func tempFile(dir, prefix string) (billy.File, error) {
 | |
| 	f, err := os.CreateTemp(dir, prefix)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &file{File: f}, nil
 | |
| }
 | |
| 
 | |
| func openFile(fn string, flag int, perm os.FileMode, createDir func(string) error) (billy.File, error) {
 | |
| 	if flag&os.O_CREATE != 0 {
 | |
| 		if createDir == nil {
 | |
| 			return nil, fmt.Errorf("createDir func cannot be nil if file needs to be opened in create mode")
 | |
| 		}
 | |
| 		if err := createDir(fn); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	f, err := os.OpenFile(fn, flag, perm)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &file{File: f}, err
 | |
| }
 | |
| 
 | |
| // file is a wrapper for an os.File which adds support for file locking.
 | |
| type file struct {
 | |
| 	*os.File
 | |
| 	m sync.Mutex
 | |
| }
 |