Merge pull request #452 from pkg/patch/fix-filezilla

[bugfix] FileZilla parses the directory listing in longname
diff --git a/server_unix.go b/server_unix.go
index abceca4..a7b7617 100644
--- a/server_unix.go
+++ b/server_unix.go
@@ -6,21 +6,35 @@
 import (
 	"fmt"
 	"os"
-	"path"
 	"syscall"
 	"time"
 )
 
-func runLsStatt(dirent os.FileInfo, statt *syscall.Stat_t) string {
+// ls -l style output for a file, which is in the 'long output' section of a readdir response packet
+// this is a very simple (lazy) implementation, just enough to look almost like openssh in a few basic cases
+func runLs(dirname string, dirent os.FileInfo) string {
 	// example from openssh sftp server:
 	// crw-rw-rw-    1 root     wheel           0 Jul 31 20:52 ttyvd
 	// format:
 	// {directory / char device / etc}{rwxrwxrwx}  {number of links} owner group size month day [time (this year) | year (otherwise)] name
 
 	typeword := runLsTypeWord(dirent)
-	numLinks := statt.Nlink
-	uid := statt.Uid
-	gid := statt.Gid
+
+	var numLinks uint64 = 1
+	if dirent.IsDir() {
+		numLinks = 0
+	}
+
+	var uid, gid uint32
+
+	if statt, ok := dirent.Sys().(*syscall.Stat_t); ok {
+		// The type of Nlink varies form int16 (aix-ppc64) to uint64 (linux-amd64),
+		// we cast up to uint64 to make all OS/ARCH combos source compatible.
+		numLinks = uint64(statt.Nlink)
+		uid = statt.Uid
+		gid = statt.Gid
+	}
+
 	username := fmt.Sprintf("%d", uid)
 	groupname := fmt.Sprintf("%d", gid)
 	// TODO FIXME: uid -> username, gid -> groupname lookup for ls -l format output
@@ -39,16 +53,3 @@
 
 	return fmt.Sprintf("%s %4d %-8s %-8s %8d %s %2d %5s %s", typeword, numLinks, username, groupname, dirent.Size(), monthStr, day, yearOrTime, dirent.Name())
 }
-
-// ls -l style output for a file, which is in the 'long output' section of a readdir response packet
-// this is a very simple (lazy) implementation, just enough to look almost like openssh in a few basic cases
-func runLs(dirname string, dirent os.FileInfo) string {
-	dsys := dirent.Sys()
-	if dsys == nil {
-	} else if statt, ok := dsys.(*syscall.Stat_t); !ok {
-	} else {
-		return runLsStatt(dirent, statt)
-	}
-
-	return path.Join(dirname, dirent.Name())
-}