summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/pkg/sftp/request.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pkg/sftp/request.go')
-rw-r--r--vendor/github.com/pkg/sftp/request.go353
1 files changed, 0 insertions, 353 deletions
diff --git a/vendor/github.com/pkg/sftp/request.go b/vendor/github.com/pkg/sftp/request.go
deleted file mode 100644
index d74d6fa3..00000000
--- a/vendor/github.com/pkg/sftp/request.go
+++ /dev/null
@@ -1,353 +0,0 @@
-package sftp
-
-import (
- "context"
- "io"
- "os"
- "path"
- "path/filepath"
- "sync"
- "syscall"
-
- "github.com/pkg/errors"
-)
-
-// MaxFilelist is the max number of files to return in a readdir batch.
-var MaxFilelist int64 = 100
-
-// Request contains the data and state for the incoming service request.
-type Request struct {
- // Get, Put, Setstat, Stat, Rename, Remove
- // Rmdir, Mkdir, List, Readlink, Symlink
- Method string
- Filepath string
- Flags uint32
- Attrs []byte // convert to sub-struct
- Target string // for renames and sym-links
- // reader/writer/readdir from handlers
- state state
- // context lasts duration of request
- ctx context.Context
- cancelCtx context.CancelFunc
-}
-
-type state struct {
- *sync.RWMutex
- writerAt io.WriterAt
- readerAt io.ReaderAt
- listerAt ListerAt
- lsoffset int64
-}
-
-// New Request initialized based on packet data
-func requestFromPacket(ctx context.Context, pkt hasPath) *Request {
- method := requestMethod(pkt)
- request := NewRequest(method, pkt.getPath())
- request.ctx, request.cancelCtx = context.WithCancel(ctx)
-
- switch p := pkt.(type) {
- case *sshFxpOpenPacket:
- request.Flags = p.Pflags
- case *sshFxpSetstatPacket:
- request.Flags = p.Flags
- request.Attrs = p.Attrs.([]byte)
- case *sshFxpRenamePacket:
- request.Target = cleanPath(p.Newpath)
- case *sshFxpSymlinkPacket:
- request.Target = cleanPath(p.Linkpath)
- }
- return request
-}
-
-// NewRequest creates a new Request object.
-func NewRequest(method, path string) *Request {
- return &Request{Method: method, Filepath: cleanPath(path),
- state: state{RWMutex: new(sync.RWMutex)}}
-}
-
-// shallow copy of existing request
-func (r *Request) copy() *Request {
- r.state.Lock()
- defer r.state.Unlock()
- r2 := new(Request)
- *r2 = *r
- return r2
-}
-
-// Context returns the request's context. To change the context,
-// use WithContext.
-//
-// The returned context is always non-nil; it defaults to the
-// background context.
-//
-// For incoming server requests, the context is canceled when the
-// request is complete or the client's connection closes.
-func (r *Request) Context() context.Context {
- if r.ctx != nil {
- return r.ctx
- }
- return context.Background()
-}
-
-// WithContext returns a copy of r with its context changed to ctx.
-// The provided ctx must be non-nil.
-func (r *Request) WithContext(ctx context.Context) *Request {
- if ctx == nil {
- panic("nil context")
- }
- r2 := r.copy()
- r2.ctx = ctx
- r2.cancelCtx = nil
- return r2
-}
-
-// Returns current offset for file list
-func (r *Request) lsNext() int64 {
- r.state.RLock()
- defer r.state.RUnlock()
- return r.state.lsoffset
-}
-
-// Increases next offset
-func (r *Request) lsInc(offset int64) {
- r.state.Lock()
- defer r.state.Unlock()
- r.state.lsoffset = r.state.lsoffset + offset
-}
-
-// manage file read/write state
-func (r *Request) setWriterState(wa io.WriterAt) {
- r.state.Lock()
- defer r.state.Unlock()
- r.state.writerAt = wa
-}
-func (r *Request) setReaderState(ra io.ReaderAt) {
- r.state.Lock()
- defer r.state.Unlock()
- r.state.readerAt = ra
-}
-func (r *Request) setListerState(la ListerAt) {
- r.state.Lock()
- defer r.state.Unlock()
- r.state.listerAt = la
-}
-
-func (r *Request) getWriter() io.WriterAt {
- r.state.RLock()
- defer r.state.RUnlock()
- return r.state.writerAt
-}
-
-func (r *Request) getReader() io.ReaderAt {
- r.state.RLock()
- defer r.state.RUnlock()
- return r.state.readerAt
-}
-
-func (r *Request) getLister() ListerAt {
- r.state.RLock()
- defer r.state.RUnlock()
- return r.state.listerAt
-}
-
-// Close reader/writer if possible
-func (r *Request) close() error {
- if r.cancelCtx != nil {
- r.cancelCtx()
- }
- rd := r.getReader()
- if c, ok := rd.(io.Closer); ok {
- return c.Close()
- }
- wt := r.getWriter()
- if c, ok := wt.(io.Closer); ok {
- return c.Close()
- }
- return nil
-}
-
-// called from worker to handle packet/request
-func (r *Request) call(handlers Handlers, pkt requestPacket) responsePacket {
- switch r.Method {
- case "Get":
- return fileget(handlers.FileGet, r, pkt)
- case "Put", "Open":
- return fileput(handlers.FilePut, r, pkt)
- case "Setstat", "Rename", "Rmdir", "Mkdir", "Symlink", "Remove":
- return filecmd(handlers.FileCmd, r, pkt)
- case "List", "Stat", "Readlink":
- return filelist(handlers.FileList, r, pkt)
- default:
- return statusFromError(pkt,
- errors.Errorf("unexpected method: %s", r.Method))
- }
-}
-
-// file data for additional read/write packets
-func packetData(p requestPacket) (data []byte, offset int64, length uint32) {
- switch p := p.(type) {
- case *sshFxpReadPacket:
- length = p.Len
- offset = int64(p.Offset)
- case *sshFxpWritePacket:
- data = p.Data
- length = p.Length
- offset = int64(p.Offset)
- }
- return
-}
-
-// wrap FileReader handler
-func fileget(h FileReader, r *Request, pkt requestPacket) responsePacket {
- var err error
- reader := r.getReader()
- if reader == nil {
- reader, err = h.Fileread(r)
- if err != nil {
- return statusFromError(pkt, err)
- }
- r.setReaderState(reader)
- }
-
- _, offset, length := packetData(pkt)
- data := make([]byte, clamp(length, maxTxPacket))
- n, err := reader.ReadAt(data, offset)
- // only return EOF erro if no data left to read
- if err != nil && (err != io.EOF || n == 0) {
- return statusFromError(pkt, err)
- }
- return &sshFxpDataPacket{
- ID: pkt.id(),
- Length: uint32(n),
- Data: data[:n],
- }
-}
-
-// wrap FileWriter handler
-func fileput(h FileWriter, r *Request, pkt requestPacket) responsePacket {
- var err error
- writer := r.getWriter()
- if writer == nil {
- writer, err = h.Filewrite(r)
- if err != nil {
- return statusFromError(pkt, err)
- }
- r.setWriterState(writer)
- }
-
- data, offset, _ := packetData(pkt)
- _, err = writer.WriteAt(data, offset)
- return statusFromError(pkt, err)
-}
-
-// wrap FileCmder handler
-func filecmd(h FileCmder, r *Request, pkt requestPacket) responsePacket {
- err := h.Filecmd(r)
- return statusFromError(pkt, err)
-}
-
-// wrap FileLister handler
-func filelist(h FileLister, r *Request, pkt requestPacket) responsePacket {
- var err error
- lister := r.getLister()
- if lister == nil {
- lister, err = h.Filelist(r)
- if err != nil {
- return statusFromError(pkt, err)
- }
- r.setListerState(lister)
- }
-
- offset := r.lsNext()
- finfo := make([]os.FileInfo, MaxFilelist)
- n, err := lister.ListAt(finfo, offset)
- r.lsInc(int64(n))
- // ignore EOF as we only return it when there are no results
- finfo = finfo[:n] // avoid need for nil tests below
-
- switch r.Method {
- case "List":
- if err != nil && err != io.EOF {
- return statusFromError(pkt, err)
- }
- if n == 0 {
- return statusFromError(pkt, io.EOF)
- }
- dirname := filepath.ToSlash(path.Base(r.Filepath))
- ret := &sshFxpNamePacket{ID: pkt.id()}
-
- for _, fi := range finfo {
- ret.NameAttrs = append(ret.NameAttrs, sshFxpNameAttr{
- Name: fi.Name(),
- LongName: runLs(dirname, fi),
- Attrs: []interface{}{fi},
- })
- }
- return ret
- case "Stat":
- if err != nil && err != io.EOF {
- return statusFromError(pkt, err)
- }
- if n == 0 {
- err = &os.PathError{Op: "stat", Path: r.Filepath,
- Err: syscall.ENOENT}
- return statusFromError(pkt, err)
- }
- return &sshFxpStatResponse{
- ID: pkt.id(),
- info: finfo[0],
- }
- case "Readlink":
- if err != nil && err != io.EOF {
- return statusFromError(pkt, err)
- }
- if n == 0 {
- err = &os.PathError{Op: "readlink", Path: r.Filepath,
- Err: syscall.ENOENT}
- return statusFromError(pkt, err)
- }
- filename := finfo[0].Name()
- return &sshFxpNamePacket{
- ID: pkt.id(),
- NameAttrs: []sshFxpNameAttr{{
- Name: filename,
- LongName: filename,
- Attrs: emptyFileStat,
- }},
- }
- default:
- err = errors.Errorf("unexpected method: %s", r.Method)
- return statusFromError(pkt, err)
- }
-}
-
-// init attributes of request object from packet data
-func requestMethod(p requestPacket) (method string) {
- switch p.(type) {
- case *sshFxpReadPacket:
- method = "Get"
- case *sshFxpWritePacket:
- method = "Put"
- case *sshFxpReaddirPacket:
- method = "List"
- case *sshFxpOpenPacket, *sshFxpOpendirPacket:
- method = "Open"
- case *sshFxpSetstatPacket, *sshFxpFsetstatPacket:
- method = "Setstat"
- case *sshFxpRenamePacket:
- method = "Rename"
- case *sshFxpSymlinkPacket:
- method = "Symlink"
- case *sshFxpRemovePacket:
- method = "Remove"
- case *sshFxpStatPacket, *sshFxpLstatPacket, *sshFxpFstatPacket:
- method = "Stat"
- case *sshFxpRmdirPacket:
- method = "Rmdir"
- case *sshFxpReadlinkPacket:
- method = "Readlink"
- case *sshFxpMkdirPacket:
- method = "Mkdir"
- }
- return method
-}