github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/util/fsutil/mode.go (about) 1 // Package fsutil implements filesystem utility functions. 2 package fsutil 3 4 import ( 5 "io/fs" 6 7 "github.com/ncruces/go-sqlite3" 8 "github.com/ncruces/go-sqlite3/internal/util" 9 ) 10 11 // ParseFileMode parses a file mode as returned by 12 // [fs.FileMode.String]. 13 func ParseFileMode(str string) (fs.FileMode, error) { 14 var mode fs.FileMode 15 err := util.ErrorString("invalid mode: " + str) 16 17 if len(str) < 10 { 18 return 0, err 19 } 20 21 for i, c := range []byte("dalTLDpSugct?") { 22 if str[0] == c { 23 if len(str) < 10 { 24 return 0, err 25 } 26 mode |= 1 << uint(32-1-i) 27 str = str[1:] 28 } 29 } 30 31 if mode == 0 { 32 if str[0] != '-' { 33 return 0, err 34 } 35 str = str[1:] 36 } 37 if len(str) != 9 { 38 return 0, err 39 } 40 41 for i, c := range []byte("rwxrwxrwx") { 42 if str[i] == c { 43 mode |= 1 << uint(9-1-i) 44 } 45 if str[i] != '-' { 46 return 0, err 47 } 48 } 49 50 return mode, nil 51 } 52 53 // FileModeFromUnix converts a POSIX mode_t to a file mode. 54 func FileModeFromUnix(mode fs.FileMode) fs.FileMode { 55 const ( 56 S_IFMT fs.FileMode = 0170000 57 S_IFIFO fs.FileMode = 0010000 58 S_IFCHR fs.FileMode = 0020000 59 S_IFDIR fs.FileMode = 0040000 60 S_IFBLK fs.FileMode = 0060000 61 S_IFREG fs.FileMode = 0100000 62 S_IFLNK fs.FileMode = 0120000 63 S_IFSOCK fs.FileMode = 0140000 64 ) 65 66 switch mode & S_IFMT { 67 case S_IFDIR: 68 mode |= fs.ModeDir 69 case S_IFLNK: 70 mode |= fs.ModeSymlink 71 case S_IFBLK: 72 mode |= fs.ModeDevice 73 case S_IFCHR: 74 mode |= fs.ModeCharDevice | fs.ModeDevice 75 case S_IFIFO: 76 mode |= fs.ModeNamedPipe 77 case S_IFSOCK: 78 mode |= fs.ModeSocket 79 case S_IFREG, 0: 80 // 81 default: 82 mode |= fs.ModeIrregular 83 } 84 85 return mode &^ S_IFMT 86 } 87 88 // FileModeFromValue calls [FileModeFromUnix] for numeric values, 89 // and [ParseFileMode] for textual values. 90 func FileModeFromValue(val sqlite3.Value) fs.FileMode { 91 if n := val.Int64(); n != 0 { 92 return FileModeFromUnix(fs.FileMode(n)) 93 } 94 mode, _ := ParseFileMode(val.Text()) 95 return mode 96 }