mirror of https://github.com/pkg/sftp.git
86 lines
2.1 KiB
Go
86 lines
2.1 KiB
Go
package sftp
|
|
|
|
import (
|
|
"io/fs"
|
|
"path"
|
|
)
|
|
|
|
type fsys struct {
|
|
dir string
|
|
cl *Client
|
|
}
|
|
|
|
// DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir.
|
|
//
|
|
// Note that cl.DirFS("/prefix") only guarantees that the Open calls it makes to the remote system will begin with "/prefix":
|
|
// cl.DirFS("/prefix").Open("file") is the same as cl.Open("/prefix/file").
|
|
// So, if /prefix/file is a symbolic link pointing outside the /prefix tree,
|
|
// then using DirFS does not stop the access any more than using cl.Open does.
|
|
// DirFS is therefore not a general substitute for a chroot-style security mechanism when the directory tree contains arbitrary content.
|
|
//
|
|
// The directory dir must not be "".
|
|
//
|
|
// The result implements io/fs.StatFS, io/fs.ReadFileFS, and io/fs.ReadDirFS.
|
|
func (cl *Client) DirFS(dir string) fs.FS {
|
|
return &fsys{
|
|
dir: path.Clean(dir),
|
|
cl: cl,
|
|
}
|
|
}
|
|
|
|
func (cl *fsys) join(name string) string {
|
|
return path.Join(cl.dir, name)
|
|
}
|
|
|
|
// Open implements fs.FS.
|
|
func (cl *fsys) Open(name string) (fs.File, error) {
|
|
if !fs.ValidPath(name) {
|
|
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrInvalid}
|
|
}
|
|
|
|
return cl.cl.Open(cl.join(name))
|
|
}
|
|
|
|
// ReadDir implements fs.ReadDirFS.
|
|
func (cl *fsys) ReadDir(name string) ([]fs.DirEntry, error) {
|
|
if !fs.ValidPath(name) {
|
|
return nil, &fs.PathError{Op: "readdir", Path: name, Err: fs.ErrInvalid}
|
|
}
|
|
|
|
return cl.cl.ReadDir(cl.join(name))
|
|
}
|
|
|
|
// ReadFile implements fs.ReadFileFS.
|
|
func (cl *fsys) ReadFile(name string) ([]byte, error) {
|
|
if !fs.ValidPath(name) {
|
|
return nil, &fs.PathError{Op: "readfile", Path: name, Err: fs.ErrInvalid}
|
|
}
|
|
|
|
return cl.cl.ReadFile(cl.join(name))
|
|
}
|
|
|
|
// Stat implements fs.StatFS.
|
|
func (cl *fsys) Stat(name string) (fs.FileInfo, error) {
|
|
if !fs.ValidPath(name) {
|
|
return nil, &fs.PathError{Op: "stat", Path: name, Err: fs.ErrInvalid}
|
|
}
|
|
|
|
return cl.cl.Stat(cl.join(name))
|
|
}
|
|
|
|
// Sub implements fs.SubFS.
|
|
func (cl *fsys) Sub(dir string) (fs.FS, error) {
|
|
if !fs.ValidPath(dir) {
|
|
return nil, &fs.PathError{Op: "sub", Path: dir, Err: fs.ErrInvalid}
|
|
}
|
|
|
|
if dir == "." {
|
|
return cl, nil
|
|
}
|
|
|
|
return &fsys{
|
|
dir: cl.join(dir),
|
|
cl: cl.cl,
|
|
}, nil
|
|
}
|