Add application FS fuctionality
This commit is contained in:
parent
ab0d84140f
commit
2eb82d9035
169
fs.go
Normal file
169
fs.go
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
package nasin
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
import "os"
|
||||||
|
import "io/fs"
|
||||||
|
import "strings"
|
||||||
|
import "path/filepath"
|
||||||
|
|
||||||
|
// FS is an io.FS with extended capabilities that include writing to the
|
||||||
|
// underlying filesystem.
|
||||||
|
type FS interface {
|
||||||
|
fs.FS
|
||||||
|
fs.ReadDirFS
|
||||||
|
fs.ReadFileFS
|
||||||
|
|
||||||
|
// OpenFile is like os.OpenFile.
|
||||||
|
OpenFile (name string, flag int, perm os.FileMode) (FileWriter, error)
|
||||||
|
|
||||||
|
// Remove removes the named file or (empty) directory.
|
||||||
|
Remove (name string) error
|
||||||
|
|
||||||
|
// RemoveAll removes name and any children it contains.
|
||||||
|
RemoveAll (name string) error
|
||||||
|
|
||||||
|
// Rename renames (moves) oldname to newname.
|
||||||
|
Rename (oldname, newname string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileWriter is a writable version of fs.File.
|
||||||
|
type FileWriter interface {
|
||||||
|
fs.File
|
||||||
|
io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
type writeFs struct {
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
func pathErr (op, path string, err error) error {
|
||||||
|
return &fs.PathError {
|
||||||
|
Op: op,
|
||||||
|
Path: path,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this writeFs) subPath (name string) (string, error) {
|
||||||
|
if !fs.ValidPath(name) { return "", fs.ErrInvalid }
|
||||||
|
if strings.Contains(name, "/") { return "", fs.ErrInvalid }
|
||||||
|
return filepath.Join(this.path, name), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens the named file.
|
||||||
|
func (this writeFs) Open (name string) (fs.File, error) {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pathErr("open", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Open(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates or truncates the named file.
|
||||||
|
func (this writeFs) Create (name string) (FileWriter, error) {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pathErr("create", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Create(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenFile is the generalized open call; most users will use Open or Create
|
||||||
|
// instead.
|
||||||
|
func (this writeFs) OpenFile (
|
||||||
|
name string,
|
||||||
|
flag int,
|
||||||
|
perm os.FileMode,
|
||||||
|
) (
|
||||||
|
FileWriter,
|
||||||
|
error,
|
||||||
|
) {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pathErr("open", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.OpenFile(path, flag, perm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadDir reads the named directory and returns a list of directory entries
|
||||||
|
// sorted by filename.
|
||||||
|
func (this writeFs) ReadDir (name string) ([]fs.DirEntry, error) {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pathErr("readdir", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.ReadDir(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFile reads the named file and returns its contents.
|
||||||
|
// A successful call returns a nil error, not io.EOF.
|
||||||
|
// (Because ReadFile reads the whole file, the expected EOF
|
||||||
|
// from the final Read is not treated as an error to be reported.)
|
||||||
|
//
|
||||||
|
// The caller is permitted to modify the returned byte slice.
|
||||||
|
func (this writeFs) ReadFile (name string) ([]byte, error) {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pathErr("readfile", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.ReadFile(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteFile writes data to the named file, creating it if necessary.
|
||||||
|
func (this writeFs) WriteFile (name string, data []byte, perm os.FileMode) error {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return pathErr("writefile", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.WriteFile(path, data, perm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat returns a FileInfo describing the file.
|
||||||
|
func (this writeFs) Stat (name string) (fs.FileInfo, error) {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, pathErr("stat", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Stat(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the named file or (empty) directory.
|
||||||
|
func (this writeFs) Remove (name string) error {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return pathErr("remove", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Remove(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAll removes name and any children it contains.
|
||||||
|
func (this writeFs) RemoveAll (name string) error {
|
||||||
|
path, err := this.subPath(name)
|
||||||
|
if err != nil {
|
||||||
|
return pathErr("removeall", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.RemoveAll(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename renames (moves) oldname to newname.
|
||||||
|
func (this writeFs) Rename (oldname, newname string) error {
|
||||||
|
oldpath, err := this.subPath(oldname)
|
||||||
|
if err != nil {
|
||||||
|
return pathErr("rename", oldname, err)
|
||||||
|
}
|
||||||
|
newpath, err := this.subPath(newname)
|
||||||
|
if err != nil {
|
||||||
|
return pathErr("rename", newname, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Rename(oldpath, newpath)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user