Skip to content

Commit

Permalink
Marshal extended data if file info supports it
Browse files Browse the repository at this point in the history
If the file information returned by ListAt supports the
FileInfoExtendedData interface, use it to retrieve extended data and
pass it back to the client. In similar fashion, we add the
FileInfoUidGid interface to allow for implementations to return uid and
gid data, even if the os lacks support in syscall.Stat_t.

Signed-off-by: Peter Verraedt <peter@verraedt.be>
  • Loading branch information
peterverraedt committed Jul 14, 2023
1 parent 971c283 commit 1fe811c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 0 deletions.
36 changes: 36 additions & 0 deletions attrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ func fileInfoFromStat(stat *FileStat, name string) os.FileInfo {
}
}

// FileInfoUidGid extends os.FileInfo and adds callbacks for Uid and Gid retrieval,
// as an alternative to *syscall.Stat_t objects on unix systems.
type FileInfoUidGid interface {
os.FileInfo
Uid() uint32
Gid() uint32
}

// FileInfoUidGid extends os.FileInfo and adds a callbacks for extended data retrieval.
type FileInfoExtendedData interface {
os.FileInfo
Extended() []StatExtended
}

func fileStatFromInfo(fi os.FileInfo) (uint32, *FileStat) {
mtime := fi.ModTime().Unix()
atime := mtime
Expand All @@ -86,5 +100,27 @@ func fileStatFromInfo(fi os.FileInfo) (uint32, *FileStat) {
// os specific file stat decoding
fileStatFromInfoOs(fi, &flags, fileStat)

// The call above will include the sshFileXferAttrUIDGID in case
// the os.FileInfo can be casted to *syscall.Stat_t on unix.
// If implementations of RequestServers Handlers want to implement
// setting uids and gids while running on non-unix systems or
// without using *syscall.Stat_t underneath on unix, we offer
// an alternative way to support this through the FileInfoUidGid
// interface.
// If fi implements FileInfoUidGid, retrieve Uid, Gid from it.
if fiExt, ok := fi.(FileInfoUidGid); ok {
flags |= sshFileXferAttrUIDGID
fileStat.UID = fiExt.Uid()
fileStat.GID = fiExt.Gid()
}

// if fi implements FileInfoExtendedData, retrieve extended data from it
if fiExt, ok := fi.(FileInfoExtendedData); ok {
fileStat.Extended = fiExt.Extended()
if len(fileStat.Extended) > 0 {
flags |= sshFileXferAttrExtended
}
}

return flags, fileStat
}
7 changes: 7 additions & 0 deletions ls_formatting.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ func runLs(idLookup NameLookupFileLister, dirent os.FileInfo) string {
uid = lsFormatID(sys.UID)
gid = lsFormatID(sys.GID)
default:
if fiExt, ok := dirent.(FileInfoUidGid); ok {
uid = lsFormatID(fiExt.Uid())
gid = lsFormatID(fiExt.Gid())

break
}

numLinks, uid, gid = lsLinksUIDGID(dirent)
}

Expand Down
9 changes: 9 additions & 0 deletions packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ func marshalFileInfo(b []byte, fi os.FileInfo) []byte {
b = marshalUint32(b, fileStat.Mtime)
}

if flags&sshFileXferAttrExtended != 0 {
b = marshalUint32(b, uint32(len(fileStat.Extended)))

for _, attr := range fileStat.Extended {
b = marshalString(b, attr.ExtType)
b = marshalString(b, attr.ExtData)
}
}

return b
}

Expand Down

0 comments on commit 1fe811c

Please sign in to comment.