forked from jshiffer/matterbridge
55 lines
1.6 KiB
Go
55 lines
1.6 KiB
Go
|
// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris
|
||
|
// +build cgo
|
||
|
|
||
|
package sftp
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"path"
|
||
|
"syscall"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
func runLsStatt(dirent os.FileInfo, statt *syscall.Stat_t) 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
|
||
|
username := fmt.Sprintf("%d", uid)
|
||
|
groupname := fmt.Sprintf("%d", gid)
|
||
|
// TODO FIXME: uid -> username, gid -> groupname lookup for ls -l format output
|
||
|
|
||
|
mtime := dirent.ModTime()
|
||
|
monthStr := mtime.Month().String()[0:3]
|
||
|
day := mtime.Day()
|
||
|
year := mtime.Year()
|
||
|
now := time.Now()
|
||
|
isOld := mtime.Before(now.Add(-time.Hour * 24 * 365 / 2))
|
||
|
|
||
|
yearOrTime := fmt.Sprintf("%02d:%02d", mtime.Hour(), mtime.Minute())
|
||
|
if isOld {
|
||
|
yearOrTime = fmt.Sprintf("%d", year)
|
||
|
}
|
||
|
|
||
|
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())
|
||
|
}
|