package sshfx

// FileMode represents a file’s mode and permission bits.
// The bits are defined according to POSIX standards,
// and may not apply to the OS being built for.
type FileMode uint32

// Permission flags, defined here to avoid potential inconsistencies in individual OS implementations.
const (
	ModePerm       FileMode = 0o0777 // S_IRWXU | S_IRWXG | S_IRWXO
	ModeUserRead   FileMode = 0o0400 // S_IRUSR
	ModeUserWrite  FileMode = 0o0200 // S_IWUSR
	ModeUserExec   FileMode = 0o0100 // S_IXUSR
	ModeGroupRead  FileMode = 0o0040 // S_IRGRP
	ModeGroupWrite FileMode = 0o0020 // S_IWGRP
	ModeGroupExec  FileMode = 0o0010 // S_IXGRP
	ModeOtherRead  FileMode = 0o0004 // S_IROTH
	ModeOtherWrite FileMode = 0o0002 // S_IWOTH
	ModeOtherExec  FileMode = 0o0001 // S_IXOTH

	ModeSetUID FileMode = 0o4000 // S_ISUID
	ModeSetGID FileMode = 0o2000 // S_ISGID
	ModeSticky FileMode = 0o1000 // S_ISVTX

	ModeType       FileMode = 0xF000 // S_IFMT
	ModeNamedPipe  FileMode = 0x1000 // S_IFIFO
	ModeCharDevice FileMode = 0x2000 // S_IFCHR
	ModeDir        FileMode = 0x4000 // S_IFDIR
	ModeDevice     FileMode = 0x6000 // S_IFBLK
	ModeRegular    FileMode = 0x8000 // S_IFREG
	ModeSymlink    FileMode = 0xA000 // S_IFLNK
	ModeSocket     FileMode = 0xC000 // S_IFSOCK
)

// IsDir reports whether m describes a directory.
// That is, it tests for m.Type() == ModeDir.
func ( FileMode) () bool {
	return ( & ModeType) == ModeDir
}

// IsRegular reports whether m describes a regular file.
// That is, it tests for m.Type() == ModeRegular
func ( FileMode) () bool {
	return ( & ModeType) == ModeRegular
}

// Perm returns the POSIX permission bits in m (m & ModePerm).
func ( FileMode) () FileMode {
	return ( & ModePerm)
}

// Type returns the type bits in m (m & ModeType).
func ( FileMode) () FileMode {
	return ( & ModeType)
}

// String returns a `-rwxrwxrwx` style string representing the `ls -l` POSIX permissions string.
func ( FileMode) () string {
	var  [10]byte

	switch .Type() {
	case ModeRegular:
		[0] = '-'
	case ModeDir:
		[0] = 'd'
	case ModeSymlink:
		[0] = 'l'
	case ModeDevice:
		[0] = 'b'
	case ModeCharDevice:
		[0] = 'c'
	case ModeNamedPipe:
		[0] = 'p'
	case ModeSocket:
		[0] = 's'
	default:
		[0] = '?'
	}

	const  = "rwxrwxrwx"
	for ,  := range  {
		if &(1<<uint(9-1-)) != 0 {
			[+1] = byte()
		} else {
			[+1] = '-'
		}
	}

	if &ModeSetUID != 0 {
		if [3] == 'x' {
			[3] = 's'
		} else {
			[3] = 'S'
		}
	}

	if &ModeSetGID != 0 {
		if [6] == 'x' {
			[6] = 's'
		} else {
			[6] = 'S'
		}
	}

	if &ModeSticky != 0 {
		if [9] == 'x' {
			[9] = 't'
		} else {
			[9] = 'T'
		}
	}

	return string([:])
}