Skip to content

Commit 7bfa5f2

Browse files
authored
Merge pull request #452 from pkg/patch/fix-filezilla
[bugfix] FileZilla parses the directory listing in longname
2 parents eaa697c + 66e738e commit 7bfa5f2

File tree

1 file changed

+19
-18
lines changed

1 file changed

+19
-18
lines changed

server_unix.go

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,35 @@ package sftp
66
import (
77
"fmt"
88
"os"
9-
"path"
109
"syscall"
1110
"time"
1211
)
1312

14-
func runLsStatt(dirent os.FileInfo, statt *syscall.Stat_t) string {
13+
// ls -l style output for a file, which is in the 'long output' section of a readdir response packet
14+
// this is a very simple (lazy) implementation, just enough to look almost like openssh in a few basic cases
15+
func runLs(dirname string, dirent os.FileInfo) string {
1516
// example from openssh sftp server:
1617
// crw-rw-rw- 1 root wheel 0 Jul 31 20:52 ttyvd
1718
// format:
1819
// {directory / char device / etc}{rwxrwxrwx} {number of links} owner group size month day [time (this year) | year (otherwise)] name
1920

2021
typeword := runLsTypeWord(dirent)
21-
numLinks := statt.Nlink
22-
uid := statt.Uid
23-
gid := statt.Gid
22+
23+
var numLinks uint64 = 1
24+
if dirent.IsDir() {
25+
numLinks = 0
26+
}
27+
28+
var uid, gid uint32
29+
30+
if statt, ok := dirent.Sys().(*syscall.Stat_t); ok {
31+
// The type of Nlink varies form int16 (aix-ppc64) to uint64 (linux-amd64),
32+
// we cast up to uint64 to make all OS/ARCH combos source compatible.
33+
numLinks = uint64(statt.Nlink)
34+
uid = statt.Uid
35+
gid = statt.Gid
36+
}
37+
2438
username := fmt.Sprintf("%d", uid)
2539
groupname := fmt.Sprintf("%d", gid)
2640
// TODO FIXME: uid -> username, gid -> groupname lookup for ls -l format output
@@ -39,16 +53,3 @@ func runLsStatt(dirent os.FileInfo, statt *syscall.Stat_t) string {
3953

4054
return fmt.Sprintf("%s %4d %-8s %-8s %8d %s %2d %5s %s", typeword, numLinks, username, groupname, dirent.Size(), monthStr, day, yearOrTime, dirent.Name())
4155
}
42-
43-
// ls -l style output for a file, which is in the 'long output' section of a readdir response packet
44-
// this is a very simple (lazy) implementation, just enough to look almost like openssh in a few basic cases
45-
func runLs(dirname string, dirent os.FileInfo) string {
46-
dsys := dirent.Sys()
47-
if dsys == nil {
48-
} else if statt, ok := dsys.(*syscall.Stat_t); !ok {
49-
} else {
50-
return runLsStatt(dirent, statt)
51-
}
52-
53-
return path.Join(dirname, dirent.Name())
54-
}

0 commit comments

Comments
 (0)