v/vlib/os/os_stat_default.c.v
2025-06-25 22:29:47 +03:00

133 lines
3.3 KiB
V

module os
// stat returns a platform-agnostic Stat struct comparable to what is
// available in other programming languages and fails with the POSIX
// error if the stat call fails. Symlinks are followed and the resulting
// Stat provided. (If this is not desired, use lstat().)
pub fn stat(path string) !Stat {
mut s := C.stat{}
unsafe {
res := C.stat(&char(path.str), &s)
if res != 0 {
return error_posix()
}
return Stat{
dev: s.st_dev
inode: s.st_ino
nlink: s.st_nlink
mode: s.st_mode
uid: s.st_uid
gid: s.st_gid
rdev: s.st_rdev
size: s.st_size
atime: s.st_atime
mtime: s.st_mtime
ctime: s.st_ctime
}
}
}
// lstat returns a platform-agnostic Stat struct comparable to what is
// available in other programming languages and fails with the POSIX
// error if the stat call fails. If a link is stat'd, the stat info
// for the link is provided.
pub fn lstat(path string) !Stat {
mut s := C.stat{}
unsafe {
res := C.lstat(&char(path.str), &s)
if res != 0 {
return error_posix()
}
return Stat{
dev: s.st_dev
inode: s.st_ino
nlink: s.st_nlink
mode: s.st_mode
uid: s.st_uid
gid: s.st_gid
rdev: s.st_rdev
size: s.st_size
atime: s.st_atime
mtime: s.st_mtime
ctime: s.st_ctime
}
}
}
// get_filetype returns the FileType from the Stat struct
pub fn (st Stat) get_filetype() FileType {
match st.mode & u32(C.S_IFMT) {
u32(C.S_IFREG) {
return .regular
}
u32(C.S_IFDIR) {
return .directory
}
u32(C.S_IFCHR) {
return .character_device
}
u32(C.S_IFBLK) {
return .block_device
}
u32(C.S_IFIFO) {
return .fifo
}
u32(C.S_IFLNK) {
return .symbolic_link
}
u32(C.S_IFSOCK) {
return .socket
}
else {
return .unknown
}
}
}
// get_mode returns the file type and permissions (readable, writable, executable)
// in owner/group/others format.
pub fn (st Stat) get_mode() FileMode {
return FileMode{
typ: st.get_filetype()
owner: FilePermission{
read: (st.mode & u32(C.S_IRUSR)) != 0
write: (st.mode & u32(C.S_IWUSR)) != 0
execute: (st.mode & u32(C.S_IXUSR)) != 0
}
group: FilePermission{
read: (st.mode & u32(C.S_IRGRP)) != 0
write: (st.mode & u32(C.S_IWGRP)) != 0
execute: (st.mode & u32(C.S_IXGRP)) != 0
}
others: FilePermission{
read: (st.mode & u32(C.S_IROTH)) != 0
write: (st.mode & u32(C.S_IWOTH)) != 0
execute: (st.mode & u32(C.S_IXOTH)) != 0
}
}
}
// is_dir returns a `bool` indicating whether the given `path` is a directory.
pub fn is_dir(path string) bool {
attr := stat(path) or { return false }
return attr.get_filetype() == .directory
}
// is_link returns a boolean indicating whether `path` is a link.
// Warning: `is_link()` is known to cause a TOCTOU vulnerability when used incorrectly
// (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md).
pub fn is_link(path string) bool {
attr := lstat(path) or { return false }
return attr.get_filetype() == .symbolic_link
}
// kind_of_existing_path identifies whether path is a file, directory, or link.
fn kind_of_existing_path(path string) PathKind {
mut res := PathKind{}
attr := lstat(path) or { return res }
res.is_file = attr.get_filetype() == .regular
res.is_dir = attr.get_filetype() == .directory
res.is_link = attr.get_filetype() == .symbolic_link
return res
}