You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							110 lines
						
					
					
						
							2.3 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							110 lines
						
					
					
						
							2.3 KiB
						
					
					
				
								// sftp_helpers.go
							 | 
						|
								package sftpd
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"io"
							 | 
						|
									"os"
							 | 
						|
									"sync"
							 | 
						|
									"time"
							 | 
						|
								
							 | 
						|
									"github.com/pkg/sftp"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								// FileInfo implements os.FileInfo.
							 | 
						|
								type FileInfo struct {
							 | 
						|
									name    string
							 | 
						|
									size    int64
							 | 
						|
									mode    os.FileMode
							 | 
						|
									modTime time.Time
							 | 
						|
									isDir   bool
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (fi *FileInfo) Name() string       { return fi.name }
							 | 
						|
								func (fi *FileInfo) Size() int64        { return fi.size }
							 | 
						|
								func (fi *FileInfo) Mode() os.FileMode  { return fi.mode }
							 | 
						|
								func (fi *FileInfo) ModTime() time.Time { return fi.modTime }
							 | 
						|
								func (fi *FileInfo) IsDir() bool        { return fi.isDir }
							 | 
						|
								func (fi *FileInfo) Sys() interface{}   { return nil }
							 | 
						|
								
							 | 
						|
								// bufferReader wraps a byte slice to io.ReaderAt.
							 | 
						|
								type bufferReader struct {
							 | 
						|
									b []byte
							 | 
						|
									i int64
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func NewBufferReader(b []byte) *bufferReader { return &bufferReader{b: b} }
							 | 
						|
								
							 | 
						|
								func (r *bufferReader) Read(p []byte) (int, error) {
							 | 
						|
									if r.i >= int64(len(r.b)) {
							 | 
						|
										return 0, io.EOF
							 | 
						|
									}
							 | 
						|
									n := copy(p, r.b[r.i:])
							 | 
						|
									r.i += int64(n)
							 | 
						|
									return n, nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (r *bufferReader) ReadAt(p []byte, off int64) (int, error) {
							 | 
						|
									if off >= int64(len(r.b)) {
							 | 
						|
										return 0, io.EOF
							 | 
						|
									}
							 | 
						|
									n := copy(p, r.b[off:])
							 | 
						|
									if n < len(p) {
							 | 
						|
										return n, io.EOF
							 | 
						|
									}
							 | 
						|
									return n, nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// listerat implements sftp.ListerAt.
							 | 
						|
								type listerat []os.FileInfo
							 | 
						|
								
							 | 
						|
								func (l listerat) ListAt(ls []os.FileInfo, offset int64) (int, error) {
							 | 
						|
									if offset >= int64(len(l)) {
							 | 
						|
										return 0, io.EOF
							 | 
						|
									}
							 | 
						|
									n := copy(ls, l[offset:])
							 | 
						|
									if n < len(ls) {
							 | 
						|
										return n, io.EOF
							 | 
						|
									}
							 | 
						|
									return n, nil
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// SeaweedSftpFileWriter buffers writes and flushes on Close.
							 | 
						|
								type SeaweedSftpFileWriter struct {
							 | 
						|
									fs          SftpServer
							 | 
						|
									req         *sftp.Request
							 | 
						|
									mu          sync.Mutex
							 | 
						|
									tmpFile     *os.File
							 | 
						|
									permissions os.FileMode
							 | 
						|
									uid         uint32
							 | 
						|
									gid         uint32
							 | 
						|
									offset      int64
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (w *SeaweedSftpFileWriter) Write(p []byte) (int, error) {
							 | 
						|
									w.mu.Lock()
							 | 
						|
									defer w.mu.Unlock()
							 | 
						|
									n, err := w.tmpFile.WriteAt(p, w.offset)
							 | 
						|
									w.offset += int64(n)
							 | 
						|
									return n, err
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (w *SeaweedSftpFileWriter) WriteAt(p []byte, off int64) (int, error) {
							 | 
						|
									w.mu.Lock()
							 | 
						|
									defer w.mu.Unlock()
							 | 
						|
									return w.tmpFile.WriteAt(p, off)
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func (w *SeaweedSftpFileWriter) Close() error {
							 | 
						|
									w.mu.Lock()
							 | 
						|
									defer w.mu.Unlock()
							 | 
						|
								
							 | 
						|
									defer os.Remove(w.tmpFile.Name()) // Clean up temp file
							 | 
						|
									defer w.tmpFile.Close()
							 | 
						|
								
							 | 
						|
									if _, err := w.tmpFile.Seek(0, io.SeekStart); err != nil {
							 | 
						|
										return err
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									// Stream the file instead of loading it
							 | 
						|
									return w.fs.putFile(w.req.Filepath, w.tmpFile, w.fs.user)
							 | 
						|
								}
							 |