v2 / vlib / os / os_stat_windows.c.v
109 lines · 102 sloc · 2.92 KB · 37255767290c243b71f0e78d77c3bd5e875748e6
Raw
1module os
2
3// stat returns metadata for the given file/folder.
4// It will return a POSIX error message, if it can not do so.
5// C._wstat64() can be used on 32- and 64-bit Windows per
6// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions?view=msvc-170
7pub fn stat(path string) !Stat {
8 mut s := C.__stat64{}
9 unsafe {
10 res := C._wstat64(path.to_wide(), &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 the same as stat() for Windows.
31@[inline]
32pub fn lstat(path string) !Stat {
33 return stat(path)
34}
35
36// get_filetype returns the FileType from the Stat struct.
37pub fn (st Stat) get_filetype() FileType {
38 match st.mode & u32(C.S_IFMT) {
39 u32(C.S_IFDIR) {
40 return .directory
41 }
42 else {
43 return .regular
44 }
45 }
46}
47
48// get_mode returns the file type and permissions (readable, writable, executable) in owner/group/others format.
49// Note: they will all be the same for Windows.
50pub fn (st Stat) get_mode() FileMode {
51 return FileMode{
52 typ: st.get_filetype()
53 owner: FilePermission{
54 read: (st.mode & u32(C.S_IREAD)) != 0
55 write: (st.mode & u32(C.S_IWRITE)) != 0
56 execute: (st.mode & u32(C.S_IEXEC)) != 0
57 }
58 group: FilePermission{
59 read: (st.mode & u32(C.S_IREAD)) != 0
60 write: (st.mode & u32(C.S_IWRITE)) != 0
61 execute: (st.mode & u32(C.S_IEXEC)) != 0
62 }
63 others: FilePermission{
64 read: (st.mode & u32(C.S_IREAD)) != 0
65 write: (st.mode & u32(C.S_IWRITE)) != 0
66 execute: (st.mode & u32(C.S_IEXEC)) != 0
67 }
68 }
69}
70
71// is_dir returns a `bool` indicating whether the given `path` is a directory.
72pub fn is_dir(path string) bool {
73 w_path := path.replace('/', '\\')
74 attr := C.GetFileAttributesW(w_path.to_wide())
75 if attr == u32(C.INVALID_FILE_ATTRIBUTES) {
76 return false
77 }
78 if int(attr) & C.FILE_ATTRIBUTE_DIRECTORY != 0 {
79 return true
80 }
81 return false
82}
83
84// is_link returns a boolean indicating whether `path` is a link.
85// Warning: `is_link()` is known to cause a TOCTOU vulnerability when used incorrectly
86// (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md)
87pub fn is_link(path string) bool {
88 path_ := path.replace('/', '\\')
89 attr := C.GetFileAttributesW(path_.to_wide())
90 return int(attr) != int(C.INVALID_FILE_ATTRIBUTES) && (attr & 0x400) != 0
91}
92
93// kind_of_existing_path identifies whether path is a file, directory, or link.
94fn kind_of_existing_path(path string) PathKind {
95 mut res := PathKind{}
96 attr := C.GetFileAttributesW(path.to_wide())
97 if attr != u32(C.INVALID_FILE_ATTRIBUTES) {
98 if (int(attr) & C.FILE_ATTRIBUTE_NORMAL) != 0 {
99 res.is_file = true
100 }
101 if (int(attr) & C.FILE_ATTRIBUTE_DIRECTORY) != 0 {
102 res.is_dir = true
103 }
104 if (int(attr) & 0x400) != 0 {
105 res.is_link = true
106 }
107 }
108 return res
109}
110