mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-04 07:49:35 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			144 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build darwin dragonfly freebsd !android,linux netbsd openbsd solaris
 | 
						|
// +build cgo
 | 
						|
 | 
						|
package sftp
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"path"
 | 
						|
	"syscall"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
func runLsTypeWord(dirent os.FileInfo) string {
 | 
						|
	// find first character, the type char
 | 
						|
	// b     Block special file.
 | 
						|
	// c     Character special file.
 | 
						|
	// d     Directory.
 | 
						|
	// l     Symbolic link.
 | 
						|
	// s     Socket link.
 | 
						|
	// p     FIFO.
 | 
						|
	// -     Regular file.
 | 
						|
	tc := '-'
 | 
						|
	mode := dirent.Mode()
 | 
						|
	if (mode & os.ModeDir) != 0 {
 | 
						|
		tc = 'd'
 | 
						|
	} else if (mode & os.ModeDevice) != 0 {
 | 
						|
		tc = 'b'
 | 
						|
		if (mode & os.ModeCharDevice) != 0 {
 | 
						|
			tc = 'c'
 | 
						|
		}
 | 
						|
	} else if (mode & os.ModeSymlink) != 0 {
 | 
						|
		tc = 'l'
 | 
						|
	} else if (mode & os.ModeSocket) != 0 {
 | 
						|
		tc = 's'
 | 
						|
	} else if (mode & os.ModeNamedPipe) != 0 {
 | 
						|
		tc = 'p'
 | 
						|
	}
 | 
						|
 | 
						|
	// owner
 | 
						|
	orc := '-'
 | 
						|
	if (mode & 0400) != 0 {
 | 
						|
		orc = 'r'
 | 
						|
	}
 | 
						|
	owc := '-'
 | 
						|
	if (mode & 0200) != 0 {
 | 
						|
		owc = 'w'
 | 
						|
	}
 | 
						|
	oxc := '-'
 | 
						|
	ox := (mode & 0100) != 0
 | 
						|
	setuid := (mode & os.ModeSetuid) != 0
 | 
						|
	if ox && setuid {
 | 
						|
		oxc = 's'
 | 
						|
	} else if setuid {
 | 
						|
		oxc = 'S'
 | 
						|
	} else if ox {
 | 
						|
		oxc = 'x'
 | 
						|
	}
 | 
						|
 | 
						|
	// group
 | 
						|
	grc := '-'
 | 
						|
	if (mode & 040) != 0 {
 | 
						|
		grc = 'r'
 | 
						|
	}
 | 
						|
	gwc := '-'
 | 
						|
	if (mode & 020) != 0 {
 | 
						|
		gwc = 'w'
 | 
						|
	}
 | 
						|
	gxc := '-'
 | 
						|
	gx := (mode & 010) != 0
 | 
						|
	setgid := (mode & os.ModeSetgid) != 0
 | 
						|
	if gx && setgid {
 | 
						|
		gxc = 's'
 | 
						|
	} else if setgid {
 | 
						|
		gxc = 'S'
 | 
						|
	} else if gx {
 | 
						|
		gxc = 'x'
 | 
						|
	}
 | 
						|
 | 
						|
	// all / others
 | 
						|
	arc := '-'
 | 
						|
	if (mode & 04) != 0 {
 | 
						|
		arc = 'r'
 | 
						|
	}
 | 
						|
	awc := '-'
 | 
						|
	if (mode & 02) != 0 {
 | 
						|
		awc = 'w'
 | 
						|
	}
 | 
						|
	axc := '-'
 | 
						|
	ax := (mode & 01) != 0
 | 
						|
	sticky := (mode & os.ModeSticky) != 0
 | 
						|
	if ax && sticky {
 | 
						|
		axc = 't'
 | 
						|
	} else if sticky {
 | 
						|
		axc = 'T'
 | 
						|
	} else if ax {
 | 
						|
		axc = 'x'
 | 
						|
	}
 | 
						|
 | 
						|
	return fmt.Sprintf("%c%c%c%c%c%c%c%c%c%c", tc, orc, owc, oxc, grc, gwc, gxc, arc, awc, axc)
 | 
						|
}
 | 
						|
 | 
						|
func runLsStatt(dirname string, 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(dirname, dirent, statt)
 | 
						|
	}
 | 
						|
 | 
						|
	return path.Join(dirname, dirent.Name())
 | 
						|
}
 |