github.com/haraldrudell/parl@v0.4.176/pfs/fsmode.go (about)

     1  /*
     2  © 2020–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package pfs
     7  
     8  import (
     9  	"fmt"
    10  	"io/fs"
    11  	"strings"
    12  )
    13  
    14  type FileMode struct {
    15  	fs.FileMode
    16  }
    17  
    18  const (
    19  	// AllModeBits is all known github.com/fsnotify/fsevents.EventFlags
    20  	AllModeBits fs.FileMode = fs.ModeDir | fs.ModeAppend | fs.ModeExclusive |
    21  		fs.ModeTemporary | fs.ModeSymlink | fs.ModeDevice | fs.ModeNamedPipe |
    22  		fs.ModeSocket | fs.ModeSetuid | fs.ModeSetgid | fs.ModeCharDevice |
    23  		fs.ModeSticky | fs.ModeIrregular
    24  	fsp = "fs."
    25  )
    26  
    27  type modeBit struct {
    28  	fs.FileMode
    29  	name string
    30  	ch   string
    31  	desc string
    32  }
    33  
    34  var modeBitList = []modeBit{
    35  	{fs.ModeDir, "ModeDir", "d", "is a directory"},
    36  	{fs.ModeAppend, "ModeAppend", "a", "append-only"},
    37  	{fs.ModeExclusive, "ModeExclusive", "l", "exclusive use (lower case L)"},
    38  	{fs.ModeTemporary, "ModeTemporary", "T", "temporary file; Plan 9 only"},
    39  	{fs.ModeSymlink, "ModeSymlink", "L", "symbolic link"},
    40  	{fs.ModeDevice, "ModeDevice", "D", "device file"},
    41  	{fs.ModeNamedPipe, "ModeNamedPipe", "p", "named pipe (FIFO)"},
    42  	{fs.ModeSocket, "ModeSocket", "S", "Unix domain socket"},
    43  	{fs.ModeSetuid, "ModeSetuid", "u", "setuid"},
    44  	{fs.ModeSetgid, "ModeSetgid", "g", "setgid"},
    45  	{fs.ModeCharDevice, "ModeCharDevice", "c", "Unix character device, when ModeDevice is set"},
    46  	{fs.ModeSticky, "ModeSticky", "t", "sticky"},
    47  	{fs.ModeIrregular, "ModeIrregular", "?", "non-regular file; nothing else is known about this file"},
    48  }
    49  
    50  func GetModeBitValues() (s string) {
    51  	var s1 []string
    52  	for _, bit := range modeBitList {
    53  		s1 = append(s1, fmt.Sprintf("%s %s %s: %s",
    54  			FileMode{bit.FileMode}.Hex8(),
    55  			bit.name,
    56  			bit.ch, bit.desc))
    57  	}
    58  	return strings.Join(s1, "\n")
    59  }
    60  
    61  // Check returns hex string of unknown bits, empty string if no unknown bits
    62  func (fm FileMode) Check() (str string) {
    63  	unknownFlags := fm.FileMode & ^AllModeBits & ^fs.ModePerm
    64  	if unknownFlags == 0 {
    65  		return
    66  	}
    67  	return FileMode{unknownFlags}.Hex()
    68  }
    69  
    70  func (fm FileMode) Hex8() (s string) {
    71  	d := uint32(fm.FileMode)
    72  	return fmt.Sprintf("0x%08x", d)
    73  }
    74  
    75  func (fm FileMode) Hex() (s string) {
    76  	d := uint32(fm.FileMode)
    77  	return fmt.Sprintf("0x%x", d)
    78  }
    79  
    80  func (fm FileMode) Or() (s string) {
    81  	fsFileMode := fm.FileMode
    82  	if fsFileMode == 0 {
    83  		return "0"
    84  	}
    85  	var s1 []string
    86  	for _, bit := range modeBitList {
    87  		if fsFileMode&bit.FileMode != 0 {
    88  			s1 = append(s1, fsp+bit.name)
    89  		}
    90  	}
    91  	return strings.Join(s1, "|")
    92  }
    93  
    94  func (fm FileMode) Ch() (s string) {
    95  	fsFileMode := fm.FileMode
    96  	for _, bit := range modeBitList {
    97  		if fsFileMode&bit.FileMode != 0 {
    98  			s += bit.ch
    99  		}
   100  	}
   101  	return
   102  }
   103  
   104  func (fm FileMode) String() (s string) {
   105  	fsFileMode := fm.FileMode
   106  	if fsFileMode == 0 {
   107  		return "0"
   108  	}
   109  	s = fm.Hex() + fm.Or()
   110  	s2 := fm.Check()
   111  	if s2 != "" {
   112  		s += "-bad:" + s2
   113  	}
   114  	return
   115  }