github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/cli/lscolors/feature.go (about) 1 package lscolors 2 3 import ( 4 "os" 5 ) 6 7 type feature int 8 9 const ( 10 featureInvalid feature = iota 11 12 featureOrphanedSymlink 13 featureSymlink 14 15 featureMultiHardLink 16 17 featureNamedPipe 18 featureSocket 19 featureDoor 20 featureBlockDevice 21 featureCharDevice 22 23 featureWorldWritableStickyDirectory 24 featureWorldWritableDirectory 25 featureStickyDirectory 26 featureDirectory 27 28 featureCapability 29 30 featureSetuid 31 featureSetgid 32 featureExecutable 33 34 featureRegular 35 ) 36 37 // Weirdly, permission masks for group and other are missing on platforms other 38 // than linux, darwin and netbsd. So we replicate some of them here. 39 const ( 40 worldWritable = 02 // Writable by other 41 executable = 0111 // Executable 42 ) 43 44 func determineFeature(fname string, mh bool) (feature, error) { 45 stat, err := os.Lstat(fname) 46 47 if err != nil { 48 return featureInvalid, err 49 } 50 51 m := stat.Mode() 52 53 // Symlink and OrphanedSymlink has highest precedence 54 if is(m, os.ModeSymlink) { 55 _, err := os.Stat(fname) 56 if err != nil { 57 return featureOrphanedSymlink, nil 58 } 59 return featureSymlink, nil 60 } 61 62 // featureMultiHardLink 63 if mh && isMultiHardlink(stat) { 64 return featureMultiHardLink, nil 65 } 66 67 // type bits features 68 switch { 69 case is(m, os.ModeNamedPipe): 70 return featureNamedPipe, nil 71 case is(m, os.ModeSocket): // Never on Windows 72 return featureSocket, nil 73 case isDoor(stat): 74 return featureDoor, nil 75 case is(m, os.ModeCharDevice): 76 return featureCharDevice, nil 77 case is(m, os.ModeDevice): 78 // There is no dedicated os.Mode* flag for block device. On all 79 // supported Unix platforms, when os.ModeDevice is set but 80 // os.ModeCharDevice is not, the file is a block device (i.e. 81 // syscall.S_IFBLK is set). On Windows, this branch is unreachable. 82 // 83 // On Plan9, this in inaccurate. 84 return featureBlockDevice, nil 85 case is(m, os.ModeDir): 86 // Perm bits features for directory 87 perm := m.Perm() 88 switch { 89 case is(m, os.ModeSticky) && is(perm, worldWritable): 90 return featureWorldWritableStickyDirectory, nil 91 case is(perm, worldWritable): 92 return featureWorldWritableDirectory, nil 93 case is(m, os.ModeSticky): 94 return featureStickyDirectory, nil 95 default: 96 return featureDirectory, nil 97 } 98 } 99 100 // TODO(xiaq): Support featureCapacity 101 102 // Perm bits features for regular files 103 switch { 104 case is(m, os.ModeSetuid): 105 return featureSetuid, nil 106 case is(m, os.ModeSetgid): 107 return featureSetgid, nil 108 case m&executable != 0: 109 return featureExecutable, nil 110 } 111 112 // Check extension 113 return featureRegular, nil 114 } 115 116 func is(m, p os.FileMode) bool { 117 return m&p == p 118 }