1 | // Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved. |
2 | // Use of this source code is governed by an MIT license |
3 | // that can be found in the LICENSE file. |
4 | module os |
5 | |
6 | pub enum FileType { |
7 | regular |
8 | directory |
9 | character_device |
10 | block_device |
11 | fifo |
12 | symbolic_link |
13 | socket |
14 | } |
15 | |
16 | struct FilePermission { |
17 | pub: |
18 | read bool |
19 | write bool |
20 | execute bool |
21 | } |
22 | |
23 | // bitmask returns a 3 bit sequence in the order RWE where |
24 | // the bit is set to 1 if the value is true or 0 otherwise. |
25 | pub fn (p FilePermission) bitmask() u32 { |
26 | mut mask := u32(0) |
27 | if p.read { |
28 | mask |= 4 |
29 | } |
30 | if p.write { |
31 | mask |= 2 |
32 | } |
33 | if p.execute { |
34 | mask |= 1 |
35 | } |
36 | return mask |
37 | } |
38 | |
39 | pub struct FileMode { |
40 | pub: |
41 | typ FileType |
42 | owner FilePermission |
43 | group FilePermission |
44 | others FilePermission |
45 | } |
46 | |
47 | // bitmask returns a 9 bit sequence in the order owner + group + others. |
48 | // This is a valid bitmask to use with `os.chmod`. |
49 | pub fn (m FileMode) bitmask() u32 { |
50 | return m.owner.bitmask() << 6 | m.group.bitmask() << 3 | m.others.bitmask() |
51 | } |
52 | |
53 | // inode returns the mode of the file/inode containing inode type and permission information |
54 | // it supports windows for regular files but it doesn't matter if you use owner, group or others when checking permissions on windows |
55 | pub fn inode(path string) FileMode { |
56 | mut attr := C.stat{} |
57 | unsafe { C.stat(&char(path.str), &attr) } |
58 | mut typ := FileType.regular |
59 | if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFDIR) { |
60 | typ = .directory |
61 | } |
62 | $if !windows { |
63 | if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFCHR) { |
64 | typ = .character_device |
65 | } else if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFBLK) { |
66 | typ = .block_device |
67 | } else if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFIFO) { |
68 | typ = .fifo |
69 | } else if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFLNK) { |
70 | typ = .symbolic_link |
71 | } else if attr.st_mode & u32(C.S_IFMT) == u32(C.S_IFSOCK) { |
72 | typ = .socket |
73 | } |
74 | } |
75 | $if windows { |
76 | return FileMode{ |
77 | typ: typ |
78 | owner: FilePermission{ |
79 | read: (attr.st_mode & u32(C.S_IREAD)) != 0 |
80 | write: (attr.st_mode & u32(C.S_IWRITE)) != 0 |
81 | execute: (attr.st_mode & u32(C.S_IEXEC)) != 0 |
82 | } |
83 | group: FilePermission{ |
84 | read: (attr.st_mode & u32(C.S_IREAD)) != 0 |
85 | write: (attr.st_mode & u32(C.S_IWRITE)) != 0 |
86 | execute: (attr.st_mode & u32(C.S_IEXEC)) != 0 |
87 | } |
88 | others: FilePermission{ |
89 | read: (attr.st_mode & u32(C.S_IREAD)) != 0 |
90 | write: (attr.st_mode & u32(C.S_IWRITE)) != 0 |
91 | execute: (attr.st_mode & u32(C.S_IEXEC)) != 0 |
92 | } |
93 | } |
94 | } $else { |
95 | return FileMode{ |
96 | typ: typ |
97 | owner: FilePermission{ |
98 | read: (attr.st_mode & u32(C.S_IRUSR)) != 0 |
99 | write: (attr.st_mode & u32(C.S_IWUSR)) != 0 |
100 | execute: (attr.st_mode & u32(C.S_IXUSR)) != 0 |
101 | } |
102 | group: FilePermission{ |
103 | read: (attr.st_mode & u32(C.S_IRGRP)) != 0 |
104 | write: (attr.st_mode & u32(C.S_IWGRP)) != 0 |
105 | execute: (attr.st_mode & u32(C.S_IXGRP)) != 0 |
106 | } |
107 | others: FilePermission{ |
108 | read: (attr.st_mode & u32(C.S_IROTH)) != 0 |
109 | write: (attr.st_mode & u32(C.S_IWOTH)) != 0 |
110 | execute: (attr.st_mode & u32(C.S_IXOTH)) != 0 |
111 | } |
112 | } |
113 | } |
114 | } |