The REST command must precede RETR/STOR

This commit is contained in:
Arnaud Ysmal 2013-12-04 23:30:50 +01:00
parent dc7badc748
commit c16ccba01d

44
ftp.go
View File

@ -236,13 +236,21 @@ func (c *ServerConn) cmd(expected int, format string, args ...interface{}) (int,
return code, line, err return code, line, err
} }
// cmdDataConn executes a command which require a FTP data connection. // cmdDataConnFrom executes a command which require a FTP data connection.
func (c *ServerConn) cmdDataConn(format string, args ...interface{}) (net.Conn, error) { // Issues a REST FTP command to specify the number of bytes to skip for the transfer.
func (c *ServerConn) cmdDataConnFrom(offset uint64, format string, args ...interface{}) (net.Conn, error) {
conn, err := c.openDataConn() conn, err := c.openDataConn()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if offset != 0 {
_, _, err := c.cmd(StatusRequestFilePending, "REST %d", offset)
if err != nil {
return nil, err
}
}
_, err = c.conn.Cmd(format, args...) _, err = c.conn.Cmd(format, args...)
if err != nil { if err != nil {
conn.Close() conn.Close()
@ -308,7 +316,7 @@ func parseListLine(line string) (*Entry, error) {
// NameList issues an NLST FTP command. // NameList issues an NLST FTP command.
func (c *ServerConn) NameList(path string) (entries []string, err error) { func (c *ServerConn) NameList(path string) (entries []string, err error) {
conn, err := c.cmdDataConn("NLST %s", path) conn, err := c.cmdDataConnFrom(0, "NLST %s", path)
if err != nil { if err != nil {
return return
} }
@ -328,7 +336,7 @@ func (c *ServerConn) NameList(path string) (entries []string, err error) {
// List issues a LIST FTP command. // List issues a LIST FTP command.
func (c *ServerConn) List(path string) (entries []*Entry, err error) { func (c *ServerConn) List(path string) (entries []*Entry, err error) {
conn, err := c.cmdDataConn("LIST %s", path) conn, err := c.cmdDataConnFrom(0, "LIST %s", path)
if err != nil { if err != nil {
return return
} }
@ -385,19 +393,20 @@ func (c *ServerConn) CurrentDir() (string, error) {
return msg[start+1 : end], nil return msg[start+1 : end], nil
} }
// Rest issues a REST FTP command to specify the number of bytes to skip for
// the next transfer.
func (c *ServerConn) Rest(offset uint64) error {
_, _, err := c.cmd(StatusRequestFilePending, "REST %d", offset)
return err
}
// Retr issues a RETR FTP command to fetch the specified file from the remote // Retr issues a RETR FTP command to fetch the specified file from the remote
// FTP server. // FTP server.
// //
// The returned ReadCloser must be closed to cleanup the FTP data connection. // The returned ReadCloser must be closed to cleanup the FTP data connection.
func (c *ServerConn) Retr(path string) (io.ReadCloser, error) { func (c *ServerConn) Retr(path string) (io.ReadCloser, error) {
conn, err := c.cmdDataConn("RETR %s", path) return c.RetrFrom(path, 0)
}
// Retr issues a RETR FTP command to fetch the specified file from the remote
// FTP server, the server will not send the offset first bytes of the file.
//
// The returned ReadCloser must be closed to cleanup the FTP data connection.
func (c *ServerConn) RetrFrom(path string, offset uint64) (io.ReadCloser, error) {
conn, err := c.cmdDataConnFrom(offset, "RETR %s", path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -411,7 +420,16 @@ func (c *ServerConn) Retr(path string) (io.ReadCloser, error) {
// //
// Hint: io.Pipe() can be used if an io.Writer is required. // Hint: io.Pipe() can be used if an io.Writer is required.
func (c *ServerConn) Stor(path string, r io.Reader) error { func (c *ServerConn) Stor(path string, r io.Reader) error {
conn, err := c.cmdDataConn("STOR %s", path) return c.StorFrom(path, r, 0)
}
// Stor issues a STOR FTP command to store a file to the remote FTP server.
// Stor creates the specified file with the content of the io.Reader, writing
// on the server will start at the given file offset.
//
// Hint: io.Pipe() can be used if an io.Writer is required.
func (c *ServerConn) StorFrom(path string, r io.Reader, offset uint64) error {
conn, err := c.cmdDataConnFrom(offset, "STOR %s", path)
if err != nil { if err != nil {
return err return err
} }