commit
a5c2cfe9ac
14
.travis.yml
14
.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 $TRAVIS_BUILD_DIR/.travis/prepare.sh "$FTP_SERVER"
|
||||||
- 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 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
.travis/prepare.sh
Executable file
18
.travis/prepare.sh
Executable file
@ -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
.travis/proftpd.conf
Normal file
9
.travis/proftpd.conf
Normal file
@ -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>
|
31
ftp.go
31
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
|
conn *textproto.Conn
|
||||||
host string
|
host string
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
features map[string]string
|
features map[string]string
|
||||||
disableEPSV bool
|
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 := parseFunc(scanner.Text())
|
||||||
entry, err := parseListLine(line)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
entries = append(entries, entry)
|
entries = append(entries, entry)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user