@ -100,18 +100,20 @@ func (fs *SftpServer) withTimeoutContext(fn func(ctx context.Context) error) err
// ==================== Command Dispatcher ====================
func ( fs * SftpServer ) dispatchCmd ( r * sftp . Request ) error {
glog . V ( 0 ) . Infof ( "Dispatch: %s %s" , r . Method , r . Filepath )
absPath := fs . toAbsolutePath ( r . Filepath )
glog . V ( 0 ) . Infof ( "Dispatch: %s %s (absolute: %s)" , r . Method , r . Filepath , absPath )
switch r . Method {
case "Remove" :
return fs . removeEntry ( r )
return fs . removeEntry ( absPath )
case "Rename" :
return fs . renameEntry ( r )
absTarget := fs . toAbsolutePath ( r . Target )
return fs . renameEntry ( absPath , absTarget )
case "Mkdir" :
return fs . makeDir ( r )
return fs . makeDir ( absPath )
case "Rmdir" :
return fs . removeDir ( r )
return fs . removeDir ( absPath )
case "Setstat" :
return fs . setFileStat ( r )
return fs . setFileStatWithRequest ( absPath , r )
default :
return fmt . Errorf ( "unsupported: %s" , r . Method )
}
@ -120,10 +122,11 @@ func (fs *SftpServer) dispatchCmd(r *sftp.Request) error {
// ==================== File Operations ====================
func ( fs * SftpServer ) readFile ( r * sftp . Request ) ( io . ReaderAt , error ) {
if err := fs . checkFilePermission ( r . Filepath , "read" ) ; err != nil {
absPath := fs . toAbsolutePath ( r . Filepath )
if err := fs . checkFilePermission ( absPath , "read" ) ; err != nil {
return nil , err
}
entry , err := fs . getEntry ( r . Filep ath)
entry , err := fs . getEntry ( absP ath)
if err != nil {
return nil , err
}
@ -131,7 +134,8 @@ func (fs *SftpServer) readFile(r *sftp.Request) (io.ReaderAt, error) {
}
func ( fs * SftpServer ) newFileWriter ( r * sftp . Request ) ( io . WriterAt , error ) {
dir , _ := util . FullPath ( r . Filepath ) . DirAndName ( )
absPath := fs . toAbsolutePath ( r . Filepath )
dir , _ := util . FullPath ( absPath ) . DirAndName ( )
if err := fs . checkFilePermission ( dir , "write" ) ; err != nil {
glog . Errorf ( "Permission denied for %s" , dir )
return nil , err
@ -145,6 +149,7 @@ func (fs *SftpServer) newFileWriter(r *sftp.Request) (io.WriterAt, error) {
return & SeaweedSftpFileWriter {
fs : * fs ,
req : r ,
absPath : absPath ,
tmpFile : tmpFile ,
permissions : 0644 ,
uid : fs . user . Uid ,
@ -153,16 +158,16 @@ func (fs *SftpServer) newFileWriter(r *sftp.Request) (io.WriterAt, error) {
} , nil
}
func ( fs * SftpServer ) removeEntry ( r * sftp . Request ) error {
return fs . deleteEntry ( r . Filep ath, false )
func ( fs * SftpServer ) removeEntry ( absPath string ) error {
return fs . deleteEntry ( absP ath, false )
}
func ( fs * SftpServer ) renameEntry ( r * sftp . Request ) error {
if err := fs . checkFilePermission ( r . Filep ath, "rename" ) ; err != nil {
func ( fs * SftpServer ) renameEntry ( absPath , absTarget string ) error {
if err := fs . checkFilePermission ( absP ath, "rename" ) ; err != nil {
return err
}
oldDir , oldName := util . FullPath ( r . Filep ath) . DirAndName ( )
newDir , newName := util . FullPath ( r . Target ) . DirAndName ( )
oldDir , oldName := util . FullPath ( absP ath) . DirAndName ( )
newDir , newName := util . FullPath ( abs Target) . DirAndName ( )
return fs . callWithClient ( false , func ( ctx context . Context , client filer_pb . SeaweedFilerClient ) error {
_ , err := client . AtomicRenameEntry ( ctx , & filer_pb . AtomicRenameEntryRequest {
OldDirectory : oldDir , OldName : oldName ,
@ -172,15 +177,15 @@ func (fs *SftpServer) renameEntry(r *sftp.Request) error {
} )
}
func ( fs * SftpServer ) setFileStat ( r * sftp . Request ) error {
if err := fs . checkFilePermission ( r . Filep ath, "write" ) ; err != nil {
func ( fs * SftpServer ) setFileStatWithRequest ( absPath string , r * sftp . Request ) error {
if err := fs . checkFilePermission ( absP ath, "write" ) ; err != nil {
return err
}
entry , err := fs . getEntry ( r . Filep ath)
entry , err := fs . getEntry ( absP ath)
if err != nil {
return err
}
dir , _ := util . FullPath ( r . Filep ath) . DirAndName ( )
dir , _ := util . FullPath ( absP ath) . DirAndName ( )
// apply attrs
if r . AttrFlags ( ) . Permissions {
entry . Attributes . FileMode = uint32 ( r . Attributes ( ) . FileMode ( ) )
@ -201,18 +206,19 @@ func (fs *SftpServer) setFileStat(r *sftp.Request) error {
// ==================== Directory Operations ====================
func ( fs * SftpServer ) listDir ( r * sftp . Request ) ( sftp . ListerAt , error ) {
if err := fs . checkFilePermission ( r . Filepath , "list" ) ; err != nil {
absPath := fs . toAbsolutePath ( r . Filepath )
if err := fs . checkFilePermission ( absPath , "list" ) ; err != nil {
return nil , err
}
if r . Method == "Stat" || r . Method == "Lstat" {
entry , err := fs . getEntry ( r . Filep ath)
entry , err := fs . getEntry ( absP ath)
if err != nil {
return nil , err
}
fi := & EnhancedFileInfo { FileInfo : FileInfoFromEntry ( entry ) , uid : entry . Attributes . Uid , gid : entry . Attributes . Gid }
return listerat ( [ ] os . FileInfo { fi } ) , nil
}
return fs . listAllPages ( r . Filep ath)
return fs . listAllPages ( absP ath)
}
func ( fs * SftpServer ) listAllPages ( dirPath string ) ( sftp . ListerAt , error ) {
@ -259,18 +265,18 @@ func (fs *SftpServer) fetchDirectoryPage(dirPath, start string) ([]os.FileInfo,
}
// makeDir creates a new directory with proper permissions.
func ( fs * SftpServer ) makeDir ( r * sftp . Request ) error {
func ( fs * SftpServer ) makeDir ( absPath string ) error {
if fs . user == nil {
return fmt . Errorf ( "cannot create directory: no user info" )
}
dir , name := util . FullPath ( r . Filep ath) . DirAndName ( )
if err := fs . checkFilePermission ( r . Filep ath, "mkdir" ) ; err != nil {
dir , name := util . FullPath ( absP ath) . DirAndName ( )
if err := fs . checkFilePermission ( absP ath, "mkdir" ) ; err != nil {
return err
}
// default mode and ownership
err := filer_pb . Mkdir ( context . Background ( ) , fs , string ( dir ) , name , func ( entry * filer_pb . Entry ) {
mode := uint32 ( 0755 | os . ModeDir )
if strings . HasPrefix ( r . Filep ath, fs . user . HomeDir ) {
if strings . HasPrefix ( absP ath, fs . user . HomeDir ) {
mode = uint32 ( 0700 | os . ModeDir )
}
entry . Attributes . FileMode = mode
@ -288,8 +294,8 @@ func (fs *SftpServer) makeDir(r *sftp.Request) error {
}
// removeDir deletes a directory.
func ( fs * SftpServer ) removeDir ( r * sftp . Request ) error {
return fs . deleteEntry ( r . Filep ath, false )
func ( fs * SftpServer ) removeDir ( absPath string ) error {
return fs . deleteEntry ( absP ath, false )
}
func ( fs * SftpServer ) putFile ( filepath string , reader io . Reader , user * user . User ) error {