Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
os: add os.stat() and helpers (#20739)
- Loading branch information
Showing
6 changed files
with
242 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
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. If a link is stat'd, the stat info | ||
// for the link is provided. | ||
pub fn stat(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 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import os | ||
import rand | ||
import time | ||
|
||
fn test_stat() { | ||
start_time := time.utc() | ||
|
||
temp_dir := os.join_path(os.temp_dir(), rand.ulid()) | ||
os.mkdir(temp_dir)! | ||
defer { | ||
os.rmdir(temp_dir) or {} | ||
} | ||
|
||
test_file := os.join_path(temp_dir, rand.ulid()) | ||
test_content := rand.ulid() | ||
os.write_file(test_file, test_content)! | ||
defer { | ||
os.rm(test_file) or {} | ||
} | ||
|
||
end_time := time.utc() | ||
|
||
mut fstat := os.stat(test_file)! | ||
assert fstat.get_filetype() == .regular | ||
assert fstat.size == u64(test_content.len) | ||
assert fstat.ctime >= start_time.unix | ||
assert fstat.ctime <= end_time.unix | ||
assert fstat.mtime >= start_time.unix | ||
assert fstat.mtime <= end_time.unix | ||
|
||
$if !windows { | ||
os.chmod(test_file, 0o600)! | ||
fstat = os.stat(test_file)! | ||
|
||
mut fmode := fstat.get_mode() | ||
assert fmode.typ == .regular | ||
assert fmode.owner.read && fmode.owner.write && !fmode.owner.execute | ||
assert !fmode.group.read && !fmode.group.write && !fmode.group.execute | ||
assert !fmode.others.read && !fmode.others.write && !fmode.others.execute | ||
|
||
os.chmod(test_file, 0o421)! | ||
fstat = os.stat(test_file)! | ||
fmode = fstat.get_mode() | ||
assert fmode.owner.read && !fmode.owner.write && !fmode.owner.execute | ||
assert !fmode.group.read && fmode.group.write && !fmode.group.execute | ||
assert !fmode.others.read && !fmode.others.write && fmode.others.execute | ||
|
||
os.chmod(test_file, 0o600)! | ||
} | ||
|
||
// When using the Time struct, allow for up to 1 second difference due to nanoseconds | ||
// which are not captured in the timestamp | ||
dstat := os.stat(temp_dir)! | ||
assert dstat.get_filetype() == .directory | ||
assert fstat.dev == dstat.dev, 'File and directory should be created on same device' | ||
assert fstat.rdev == dstat.rdev, 'File and directory should have same device ID' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
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. If a link is stat'd, the stat info | ||
// for the link is provided. | ||
pub fn stat(path string) !Stat { | ||
mut s := C.__stat64{} | ||
unsafe { | ||
res := C._wstat64(path.to_wide(), &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_IFDIR) { | ||
return .directory | ||
} | ||
else { | ||
return .regular | ||
} | ||
} | ||
} | ||
|
||
// get_mode returns the file type and permissions (readable, writable, executable) | ||
// in owner/group/others format, however, they will all be the same for Windows | ||
pub fn (st Stat) get_mode() FileMode { | ||
return FileMode{ | ||
typ: st.get_filetype() | ||
owner: FilePermission{ | ||
read: (st.mode & u32(C.S_IREAD)) != 0 | ||
write: (st.mode & u32(C.S_IWRITE)) != 0 | ||
execute: (st.mode & u32(C.S_IEXEC)) != 0 | ||
} | ||
group: FilePermission{ | ||
read: (st.mode & u32(C.S_IREAD)) != 0 | ||
write: (st.mode & u32(C.S_IWRITE)) != 0 | ||
execute: (st.mode & u32(C.S_IEXEC)) != 0 | ||
} | ||
others: FilePermission{ | ||
read: (st.mode & u32(C.S_IREAD)) != 0 | ||
write: (st.mode & u32(C.S_IWRITE)) != 0 | ||
execute: (st.mode & u32(C.S_IEXEC)) != 0 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
module os | ||
|
||
pub struct C.__stat64 { | ||
st_dev u32 // 4 | ||
st_ino u16 // 2 | ||
st_mode u16 // 2 | ||
st_nlink u16 // 2 | ||
st_uid u16 // 2 | ||
st_gid u16 // 2 | ||
st_rdev u32 // 4 | ||
st_size u64 // 8 | ||
st_atime i64 // 8 | ||
st_mtime i64 // 8 | ||
st_ctime i64 // 8 | ||
} |