From 9284a88df536a8e9d80846c718efeeda5e56b898 Mon Sep 17 00:00:00 2001 From: Julian Kornberger Date: Wed, 22 May 2019 12:26:03 +0200 Subject: [PATCH] Support line with ACL permissions (#146) closes #145 --- parse.go | 6 ++++-- parse_test.go | 58 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/parse.go b/parse.go index 508f6b5..181c020 100644 --- a/parse.go +++ b/parse.go @@ -73,8 +73,10 @@ func parseRFC3659ListLine(line string, now time.Time, loc *time.Location) (*Entr // the UNIX ls command. func parseLsListLine(line string, now time.Time, loc *time.Location) (*Entry, error) { - // Has the first field a length of 10 bytes? - if strings.IndexByte(line, ' ') != 10 { + // Has the first field a length of exactly 10 bytes + // - or 10 bytes with an additional '+' character for indicating ACLs? + // If not, return. + if i := strings.IndexByte(line, ' '); !(i == 10 || (i == 11 && line[10] == '+')) { return nil, errUnsupportedListLine } diff --git a/parse_test.go b/parse_test.go index 7980185..20a8c7e 100644 --- a/parse_test.go +++ b/parse_test.go @@ -1,6 +1,7 @@ package ftp import ( + "fmt" "strings" "testing" "time" @@ -68,6 +69,9 @@ var listTests = []line{ // Odd link count from hostedftp.com {"-r-------- 0 user group 65222236 Feb 24 00:39 RegularFile", "RegularFile", 65222236, EntryTypeFile, newTime(thisYear, time.February, 24, 0, 39)}, + + // Line with ACL persmissions + {"-rwxrw-r--+ 1 521 101 2080 May 21 10:53 data.csv", "data.csv", 2080, EntryTypeFile, newTime(thisYear, time.May, 21, 10, 53)}, } // Not supported, we expect a specific error message @@ -84,35 +88,41 @@ var listTestsFail = []unsupportedLine{ func TestParseValidListLine(t *testing.T) { for _, lt := range listTests { - entry, err := parseListLine(lt.line, now, time.UTC) - if err != nil { - t.Errorf("parseListLine(%v) returned err = %v", lt.line, err) - continue - } - if entry.Name != lt.name { - t.Errorf("parseListLine(%v).Name = '%v', want '%v'", lt.line, entry.Name, lt.name) - } - if entry.Type != lt.entryType { - t.Errorf("parseListLine(%v).EntryType = %v, want %v", lt.line, entry.Type, lt.entryType) - } - if entry.Size != lt.size { - t.Errorf("parseListLine(%v).Size = %v, want %v", lt.line, entry.Size, lt.size) - } - if !entry.Time.Equal(lt.time) { - t.Errorf("parseListLine(%v).Time = %v, want %v", lt.line, entry.Time, lt.time) - } + t.Run(fmt.Sprintf("parseListLine(%v)", lt.line), func(t *testing.T) { + + entry, err := parseListLine(lt.line, now, time.UTC) + if err != nil { + t.Errorf("returned err = %v", err) + return + } + if entry.Name != lt.name { + t.Errorf("Name = '%v', want '%v'", entry.Name, lt.name) + } + if entry.Type != lt.entryType { + t.Errorf("EntryType = %v, want %v", entry.Type, lt.entryType) + } + if entry.Size != lt.size { + t.Errorf("Size = %v, want %v", entry.Size, lt.size) + } + if !entry.Time.Equal(lt.time) { + t.Errorf("Time = %v, want %v", entry.Time, lt.time) + } + }) } } func TestParseUnsupportedListLine(t *testing.T) { for _, lt := range listTestsFail { - _, err := parseListLine(lt.line, now, time.UTC) - if err == nil { - t.Errorf("parseListLine(%v) expected to fail", lt.line) - } - if err != lt.err { - t.Errorf("parseListLine(%v) expected to fail with error: '%s'; was: '%s'", lt.line, lt.err.Error(), err.Error()) - } + t.Run(fmt.Sprintf("parseListLine(%v)", lt.line), func(t *testing.T) { + + _, err := parseListLine(lt.line, now, time.UTC) + if err == nil { + t.Error("expected to fail") + } + if err != lt.err { + t.Errorf("expected to fail with error: '%s'; was: '%s'", lt.err.Error(), err.Error()) + } + }) } }