Browse Source

Merge pull request #64 from digineo/mlst

 Use MLST if supported
Julien Laffaye 9 years ago
parent
commit
a5c2cfe9ac
5 changed files with 57 additions and 15 deletions
  1. 7 7
      .travis.yml
  2. 18 0
      .travis/prepare.sh
  3. 9 0
      .travis/proftpd.conf
  4. 0 0
      .travis/vsftpd.conf
  5. 23 8
      ftp.go

+ 7 - 7
.travis.yml

@@ -1,14 +1,14 @@
 language: go
 language: go
+dist: trusty
+sudo: required
 go:
 go:
   - 1.7.3
   - 1.7.3
+env:
+  - FTP_SERVER=vsftpd
+  - FTP_SERVER=proftpd
 before_install:
 before_install:
-- sudo mkdir --mode 0777 -p /var/ftp/incoming
-- sudo apt-get update -qq
-- sudo apt-get install -qq vsftpd
-- sudo cp $TRAVIS_BUILD_DIR/.vsftpd.conf /etc/vsftpd.conf
-- sudo service vsftpd restart
+- sudo $TRAVIS_BUILD_DIR/.travis/prepare.sh "$FTP_SERVER"
 - sudo sysctl net.ipv6.conf.lo.disable_ipv6=0
 - sudo sysctl net.ipv6.conf.lo.disable_ipv6=0
-- go get github.com/axw/gocov/gocov
 - go get github.com/mattn/goveralls
 - go get github.com/mattn/goveralls
 script:
 script:
-- $GOPATH/bin/goveralls -service=travis-ci
+- goveralls -v

+ 18 - 0
.travis/prepare.sh

@@ -0,0 +1,18 @@
+#!/bin/sh -e
+
+case "$1" in
+  proftpd)
+    mkdir -p /etc/proftpd/conf.d/
+    cp $TRAVIS_BUILD_DIR/.travis/proftpd.conf /etc/proftpd/conf.d/
+    ;;
+  vsftpd)
+    cp $TRAVIS_BUILD_DIR/.travis/vsftpd.conf /etc/vsftpd.conf
+    ;;
+  *)
+    echo "unknown software: $1"
+    exit 1
+esac
+
+mkdir --mode 0777 -p /var/ftp/incoming
+
+apt-get install -qq "$1"

+ 9 - 0
.travis/proftpd.conf

@@ -0,0 +1,9 @@
+<Anonymous /var/ftp>
+  User        ftp
+  Group       nogroup
+  MaxClients  2
+  # We want clients to be able to login with "anonymous" as well as "ftp"
+  UserAlias   anonymous ftp
+
+  RequireValidShell  off
+</Anonymous>

+ 0 - 0
.vsftpd.conf → .travis/vsftpd.conf


+ 23 - 8
ftp.go

@@ -24,11 +24,12 @@ const (
 
 
 // ServerConn represents the connection to a remote FTP server.
 // ServerConn represents the connection to a remote FTP server.
 type ServerConn struct {
 type ServerConn struct {
-	conn        *textproto.Conn
-	host        string
-	timeout     time.Duration
-	features    map[string]string
-	disableEPSV bool
+	conn          *textproto.Conn
+	host          string
+	timeout       time.Duration
+	features      map[string]string
+	disableEPSV   bool
+	mlstSupported bool
 }
 }
 
 
 // Entry describes a file and is returned by List().
 // Entry describes a file and is returned by List().
@@ -100,6 +101,10 @@ func DialTimeout(addr string, timeout time.Duration) (*ServerConn, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
+	if _, mlstSupported := c.features["MLST"]; mlstSupported {
+		c.mlstSupported = true
+	}
+
 	return c, nil
 	return c, nil
 }
 }
 
 
@@ -337,7 +342,18 @@ 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.cmdDataConnFrom(0, "LIST %s", path)
+	var cmd string
+	var parseFunc func(string) (*Entry, error)
+
+	if c.mlstSupported {
+		cmd = "MLSD"
+		parseFunc = parseRFC3659ListLine
+	} else {
+		cmd = "LIST"
+		parseFunc = parseListLine
+	}
+
+	conn, err := c.cmdDataConnFrom(0, "%s %s", cmd, path)
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
@@ -347,8 +363,7 @@ func (c *ServerConn) List(path string) (entries []*Entry, err error) {
 
 
 	scanner := bufio.NewScanner(r)
 	scanner := bufio.NewScanner(r)
 	for scanner.Scan() {
 	for scanner.Scan() {
-		line := scanner.Text()
-		entry, err := parseListLine(line)
+		entry, err := parseFunc(scanner.Text())
 		if err == nil {
 		if err == nil {
 			entries = append(entries, entry)
 			entries = append(entries, entry)
 		}
 		}