mirror of
https://github.com/vlang/v.git
synced 2025-08-03 09:47:15 -04:00
130 lines
3.2 KiB
V
130 lines
3.2 KiB
V
module os
|
|
|
|
// stat returns a platform-agnostic Stat struct, containing metadata about the given file/folder path.
|
|
// It returns a POSIX error, if it can not do so.
|
|
// Note: symlinks are followed, and the resulting Stat for their target will be returned.
|
|
// If this is not desired, call lstat/1 instead.
|
|
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 is similar to stat/1 for normal files/folders.
|
|
// Unlike stat/1, however, it will return the stat info for a symlink, instead of its target.
|
|
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
|
|
}
|