@@ -3,11 +3,21 @@ package ftp
33import (
44 "errors"
55 "fmt"
6+ "os"
67 "strconv"
78 "strings"
89 "time"
910)
1011
12+ var permMap = []struct {
13+ char byte
14+ bit os.FileMode
15+ }{
16+ {'r' , 0400 }, {'w' , 0200 }, {'x' , 0100 }, // owner
17+ {'r' , 0040 }, {'w' , 0020 }, {'x' , 0010 }, // group
18+ {'r' , 0004 }, {'w' , 0002 }, {'x' , 0001 }, // others
19+ }
20+
1121var errUnsupportedListLine = errors .New ("unsupported LIST line" )
1222var errUnsupportedListDate = errors .New ("unsupported LIST date" )
1323var errUnknownListEntryType = errors .New ("unknown entry type" )
@@ -59,6 +69,12 @@ func parseNextRFC3659ListLine(line string, loc *time.Location, e *Entry) (*Entry
5969 value := field [i + 1 :]
6070
6171 switch key {
72+ case "unix.mode" :
73+ if parsedFileMode , err := strconv .ParseInt (value , 8 , 64 ); err != nil {
74+ return nil , err
75+ } else {
76+ e .FileMode = os .FileMode (parsedFileMode )
77+ }
6278 case "modify" :
6379 var err error
6480 e .Time , err = time .ParseInLocation ("20060102150405" , value , loc )
@@ -99,6 +115,16 @@ func parseLsListLine(line string, now time.Time, loc *time.Location) (*Entry, er
99115 return nil , errUnsupportedListLine
100116 }
101117
118+ fileMode := os .FileMode (0 )
119+ if len (fields [0 ]) == 10 {
120+ for i , pm := range permMap {
121+ c := fields [0 ][i + 1 ]
122+ if c == pm .char || (pm .char == 'x' && c == 's' ) {
123+ fileMode |= pm .bit
124+ }
125+ }
126+ }
127+
102128 if fields [1 ] == "folder" && fields [2 ] == "0" {
103129 e := & Entry {
104130 Type : EntryTypeFolder ,
@@ -135,7 +161,8 @@ func parseLsListLine(line string, now time.Time, loc *time.Location) (*Entry, er
135161 }
136162
137163 e := & Entry {
138- Name : scanner .Remaining (),
164+ FileMode : fileMode ,
165+ Name : scanner .Remaining (),
139166 }
140167 switch fields [0 ][0 ] {
141168 case '-' :
0 commit comments