github.com/urjitbhatia/afero@v1.1.0/sftpfs/sftp.go (about) 1 // Copyright © 2015 Jerry Jacobs <jerry.jacobs@xor-gate.org>. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package sftpfs 15 16 import ( 17 "os" 18 "time" 19 20 "github.com/pkg/sftp" 21 "github.com/spf13/afero" 22 ) 23 24 // Fs is a afero.Fs implementation that uses functions provided by the sftp package. 25 // 26 // For details in any method, check the documentation of the sftp package 27 // (github.com/pkg/sftp). 28 type Fs struct { 29 client *sftp.Client 30 } 31 32 func New(client *sftp.Client) afero.Fs { 33 return &Fs{client: client} 34 } 35 36 func (s Fs) Name() string { return "sftpfs" } 37 38 func (s Fs) Create(name string) (afero.File, error) { 39 return FileCreate(s.client, name) 40 } 41 42 func (s Fs) Mkdir(name string, perm os.FileMode) error { 43 err := s.client.Mkdir(name) 44 if err != nil { 45 return err 46 } 47 return s.client.Chmod(name, perm) 48 } 49 50 func (s Fs) MkdirAll(path string, perm os.FileMode) error { 51 // Fast path: if we can tell whether path is a directory or file, stop with success or error. 52 dir, err := s.Stat(path) 53 if err == nil { 54 if dir.IsDir() { 55 return nil 56 } 57 return err 58 } 59 60 // Slow path: make sure parent exists and then call Mkdir for path. 61 i := len(path) 62 for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator. 63 i-- 64 } 65 66 j := i 67 for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element. 68 j-- 69 } 70 71 if j > 1 { 72 // Create parent 73 err = s.MkdirAll(path[0:j-1], perm) 74 if err != nil { 75 return err 76 } 77 } 78 79 // Parent now exists; invoke Mkdir and use its result. 80 err = s.Mkdir(path, perm) 81 if err != nil { 82 // Handle arguments like "foo/." by 83 // double-checking that directory doesn't exist. 84 dir, err1 := s.Lstat(path) 85 if err1 == nil && dir.IsDir() { 86 return nil 87 } 88 return err 89 } 90 return nil 91 } 92 93 func (s Fs) Open(name string) (afero.File, error) { 94 return FileOpen(s.client, name) 95 } 96 97 func (s Fs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) { 98 return nil, nil 99 } 100 101 func (s Fs) Remove(name string) error { 102 return s.client.Remove(name) 103 } 104 105 func (s Fs) RemoveAll(path string) error { 106 // TODO have a look at os.RemoveAll 107 // https://github.com/golang/go/blob/master/src/os/path.go#L66 108 return nil 109 } 110 111 func (s Fs) Rename(oldname, newname string) error { 112 return s.client.Rename(oldname, newname) 113 } 114 115 func (s Fs) Stat(name string) (os.FileInfo, error) { 116 return s.client.Stat(name) 117 } 118 119 func (s Fs) Lstat(p string) (os.FileInfo, error) { 120 return s.client.Lstat(p) 121 } 122 123 func (s Fs) Chmod(name string, mode os.FileMode) error { 124 return s.client.Chmod(name, mode) 125 } 126 127 func (s Fs) Chtimes(name string, atime time.Time, mtime time.Time) error { 128 return s.client.Chtimes(name, atime, mtime) 129 }