You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
zk/internal/adapter/fs/fs.go

137 lines
2.7 KiB
Go

package fs
import (
"os"
"path/filepath"
"strings"
"github.com/zk-org/zk/internal/util"
)
// FileStorage implements the port core.FileStorage.
type FileStorage struct {
// Current working directory.
workingDir string
logger util.Logger
}
// NewFileStorage creates a new instance of FileStorage using the given working
// directory as reference point for relative paths.
func NewFileStorage(workingDir string, logger util.Logger) (*FileStorage, error) {
if workingDir == "" {
var err error
workingDir, err = os.Getwd()
if err != nil {
return nil, err
}
}
return &FileStorage{workingDir, logger}, nil
}
func (fs *FileStorage) WorkingDir() string {
return fs.workingDir
}
func (fs *FileStorage) SetWorkingDir(path string) {
fs.workingDir = path
}
func (fs *FileStorage) Abs(path string) (string, error) {
var err error
if !filepath.IsAbs(path) {
path = filepath.Join(fs.workingDir, path)
path, err = filepath.Abs(path)
if err != nil {
return path, err
}
}
return path, nil
}
func (fs *FileStorage) Rel(path string) (string, error) {
return filepath.Rel(fs.workingDir, path)
}
func (fs *FileStorage) Canonical(path string) string {
path = filepath.Clean(path)
resolvedPath, err := filepath.EvalSymlinks(path)
if err != nil {
fs.logger.Err(err)
} else {
path = resolvedPath
}
return path
}
func (fs *FileStorage) FileExists(path string) (bool, error) {
fi, err := fs.fileInfo(path)
if err != nil {
return false, err
} else {
return fi != nil && (*fi).Mode().IsRegular(), nil
}
}
func (fs *FileStorage) DirExists(path string) (bool, error) {
fi, err := fs.fileInfo(path)
return !os.IsNotExist(err) && fi != nil && (*fi).Mode().IsDir(), nil
}
func (fs *FileStorage) fileInfo(path string) (*os.FileInfo, error) {
if fi, err := os.Stat(path); err == nil {
return &fi, nil
} else if os.IsNotExist(err) {
return nil, nil
} else {
return nil, err
}
}
func (fs *FileStorage) IsDescendantOf(dir string, path string) (bool, error) {
dir, err := fs.Abs(dir)
if err != nil {
return false, err
}
dir = fs.Canonical(dir)
path, err = fs.Abs(path)
if err != nil {
return false, err
}
path = fs.Canonical(path)
path, err = filepath.Rel(dir, path)
if err != nil {
return false, err
}
return !strings.HasPrefix(path, ".."), nil
}
func (fs *FileStorage) Read(path string) ([]byte, error) {
return os.ReadFile(path)
}
func (fs *FileStorage) Write(path string, content []byte) error {
dir := filepath.Dir(path)
if dir != "." && dir != ".." {
err := os.MkdirAll(dir, os.ModePerm)
if err != nil {
return err
}
}
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(content)
return err
}