v2 / vlib / os / os_stat_default.c.v
129 lines · 122 sloc · 3.24 KB · 37255767290c243b71f0e78d77c3bd5e875748e6
Raw
1module os
2
3// stat returns a platform-agnostic Stat struct, containing metadata about the given file/folder path.
4// It returns a POSIX error, if it can not do so.
5// Note: symlinks are followed, and the resulting Stat for their target will be returned.
6// If this is not desired, call lstat/1 instead.
7pub fn stat(path string) !Stat {
8 mut s := C.stat{}
9 unsafe {
10 res := C.stat(&char(path.str), &s)
11 if res != 0 {
12 return error_posix()
13 }
14 return Stat{
15 dev: s.st_dev
16 inode: s.st_ino
17 nlink: s.st_nlink
18 mode: s.st_mode
19 uid: s.st_uid
20 gid: s.st_gid
21 rdev: s.st_rdev
22 size: s.st_size
23 atime: s.st_atime
24 mtime: s.st_mtime
25 ctime: s.st_ctime
26 }
27 }
28}
29
30// lstat is similar to stat/1 for normal files/folders.
31// Unlike stat/1, however, it will return the stat info for a symlink, instead of its target.
32pub fn lstat(path string) !Stat {
33 mut s := C.stat{}
34 unsafe {
35 res := C.lstat(&char(path.str), &s)
36 if res != 0 {
37 return error_posix()
38 }
39 return Stat{
40 dev: s.st_dev
41 inode: s.st_ino
42 nlink: s.st_nlink
43 mode: s.st_mode
44 uid: s.st_uid
45 gid: s.st_gid
46 rdev: s.st_rdev
47 size: s.st_size
48 atime: s.st_atime
49 mtime: s.st_mtime
50 ctime: s.st_ctime
51 }
52 }
53}
54
55// get_filetype returns the FileType from the Stat struct.
56pub fn (st Stat) get_filetype() FileType {
57 match st.mode & u32(C.S_IFMT) {
58 u32(C.S_IFREG) {
59 return .regular
60 }
61 u32(C.S_IFDIR) {
62 return .directory
63 }
64 u32(C.S_IFCHR) {
65 return .character_device
66 }
67 u32(C.S_IFBLK) {
68 return .block_device
69 }
70 u32(C.S_IFIFO) {
71 return .fifo
72 }
73 u32(C.S_IFLNK) {
74 return .symbolic_link
75 }
76 u32(C.S_IFSOCK) {
77 return .socket
78 }
79 else {
80 return .unknown
81 }
82 }
83}
84
85// get_mode returns the file type and permissions (readable, writable, executable) in owner/group/others format.
86pub fn (st Stat) get_mode() FileMode {
87 return FileMode{
88 typ: st.get_filetype()
89 owner: FilePermission{
90 read: (st.mode & u32(C.S_IRUSR)) != 0
91 write: (st.mode & u32(C.S_IWUSR)) != 0
92 execute: (st.mode & u32(C.S_IXUSR)) != 0
93 }
94 group: FilePermission{
95 read: (st.mode & u32(C.S_IRGRP)) != 0
96 write: (st.mode & u32(C.S_IWGRP)) != 0
97 execute: (st.mode & u32(C.S_IXGRP)) != 0
98 }
99 others: FilePermission{
100 read: (st.mode & u32(C.S_IROTH)) != 0
101 write: (st.mode & u32(C.S_IWOTH)) != 0
102 execute: (st.mode & u32(C.S_IXOTH)) != 0
103 }
104 }
105}
106
107// is_dir returns a `bool` indicating whether the given `path` is a directory.
108pub fn is_dir(path string) bool {
109 attr := stat(path) or { return false }
110 return attr.get_filetype() == .directory
111}
112
113// is_link returns a boolean indicating whether `path` is a link.
114// Warning: `is_link()` is known to cause a TOCTOU vulnerability when used incorrectly
115// (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md).
116pub fn is_link(path string) bool {
117 attr := lstat(path) or { return false }
118 return attr.get_filetype() == .symbolic_link
119}
120
121// kind_of_existing_path identifies whether path is a file, directory, or link.
122fn kind_of_existing_path(path string) PathKind {
123 mut res := PathKind{}
124 attr := lstat(path) or { return res }
125 res.is_file = attr.get_filetype() == .regular
126 res.is_dir = attr.get_filetype() == .directory
127 res.is_link = attr.get_filetype() == .symbolic_link
128 return res
129}
130