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