github.com/applejag/afero@v1.1.1/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  }