Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added client methods CreateDirectory() and RemoveDirectory() #4

Merged
merged 4 commits into from
May 25, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 99 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"path"
"sync"
"time"

"github.com/kr/fs"

Expand Down Expand Up @@ -224,6 +225,38 @@ func (c *Client) Lstat(p string) (os.FileInfo, error) {
}
}

// Chtimes changes the access and modification times of the named file.
func (c *Client) Chtimes(path string, atime time.Time, mtime time.Time) error {
type packet struct {
Type byte
Id uint32
Path string
Flags uint32
Atime uint32
Mtime uint32
}
c.mu.Lock()
defer c.mu.Unlock()
id := c.nextId()
typ, data, err := c.sendRequest(packet{
Type: ssh_FXP_SETSTAT,
Id: id,
Path: path,
Flags: ssh_FILEXFER_ATTR_ACMODTIME,
Atime: uint32(atime.Unix()),
Mtime: uint32(mtime.Unix()),
})
if err != nil {
return err
}
switch typ {
case ssh_FXP_STATUS:
return okOrErr(unmarshalStatus(id, data))
default:
return unimplementedPacketErr(typ)
}
}

// Open opens the named file for reading. If successful, methods on the
// returned file can be used for reading; the associated file descriptor
// has mode O_RDONLY.
Expand Down Expand Up @@ -378,9 +411,18 @@ func (c *Client) fstat(handle string) (*attr, error) {
// empty strings are ignored.
func (c *Client) Join(elem ...string) string { return path.Join(elem...) }

// Remove removes the named file or directory.
// Remove removes the specified file or directory. An error will be returned if no
// file or directory with the specified path exists, or if the specified directory
// is not empty.
func (c *Client) Remove(path string) error {
// TODO(dfc) can't handle directories, yet
err := c.removeFile(path)
if status, ok := err.(*StatusError); ok && (status.Code == ssh_FX_FAILURE) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for the parens, this isn't C

err = c.removeDirectory(path)
}
return err
}

func (c *Client) removeFile(path string) error {
type packet struct {
Type byte
Id uint32
Expand All @@ -405,6 +447,31 @@ func (c *Client) Remove(path string) error {
}
}

func (c *Client) removeDirectory(path string) error {
type packet struct {
Type byte
Id uint32
Path string
}
c.mu.Lock()
defer c.mu.Unlock()
id := c.nextId()
typ, data, err := c.sendRequest(packet{
Type: ssh_FXP_RMDIR,
Id: id,
Path: path,
})
if err != nil {
return err
}
switch typ {
case ssh_FXP_STATUS:
return okOrErr(unmarshalStatus(id, data))
default:
return unimplementedPacketErr(typ)
}
}

// Rename renames a file.
func (c *Client) Rename(oldname, newname string) error {
type packet struct {
Expand Down Expand Up @@ -475,6 +542,36 @@ func (c *Client) writeAt(handle string, offset uint64, buf []byte) (uint32, erro
}
}

// Creates the specified directory. An error will be returned if a file or
// directory with the specified path already exists, or if the directory's
// parent folder does not exist (the method cannot create complete paths).
func (c *Client) Mkdir(path string) error {
type packet struct {
Type byte
Id uint32
Path string
Flags uint32 // ignored
Size uint64 // ignored
}
c.mu.Lock()
defer c.mu.Unlock()
id := c.nextId()
typ, data, err := c.sendRequest(packet{
Type: ssh_FXP_MKDIR,
Id: id,
Path: path,
})
if err != nil {
return err
}
switch typ {
case ssh_FXP_STATUS:
return okOrErr(unmarshalStatus(id, data))
default:
return unimplementedPacketErr(typ)
}
}

// File represents a remote file.
type File struct {
c *Client
Expand Down
2 changes: 1 addition & 1 deletion packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func marshalUint32(b []byte, v uint32) []byte {
}

func marshalUint64(b []byte, v uint64) []byte {
return marshalUint32(marshalUint32(b, uint32(v>>24)), uint32(v))
return marshalUint32(marshalUint32(b, uint32(v>>32)), uint32(v))
}

func marshalString(b []byte, v string) []byte {
Expand Down