123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- //+private
- package os2
- import "core:time"
- import "base:runtime"
- import "core:strings"
- import "core:sys/unix"
- import "core:path/filepath"
- // File type
- S_IFMT :: 0o170000 // Type of file mask
- S_IFIFO :: 0o010000 // Named pipe (fifo)
- S_IFCHR :: 0o020000 // Character special
- S_IFDIR :: 0o040000 // Directory
- S_IFBLK :: 0o060000 // Block special
- S_IFREG :: 0o100000 // Regular
- S_IFLNK :: 0o120000 // Symbolic link
- S_IFSOCK :: 0o140000 // Socket
- // File mode
- // Read, write, execute/search by owner
- S_IRWXU :: 0o0700 // RWX mask for owner
- S_IRUSR :: 0o0400 // R for owner
- S_IWUSR :: 0o0200 // W for owner
- S_IXUSR :: 0o0100 // X for owner
- // Read, write, execute/search by group
- S_IRWXG :: 0o0070 // RWX mask for group
- S_IRGRP :: 0o0040 // R for group
- S_IWGRP :: 0o0020 // W for group
- S_IXGRP :: 0o0010 // X for group
- // Read, write, execute/search by others
- S_IRWXO :: 0o0007 // RWX mask for other
- S_IROTH :: 0o0004 // R for other
- S_IWOTH :: 0o0002 // W for other
- S_IXOTH :: 0o0001 // X for other
- S_ISUID :: 0o4000 // Set user id on execution
- S_ISGID :: 0o2000 // Set group id on execution
- S_ISVTX :: 0o1000 // Directory restrcted delete
- S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK }
- S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG }
- S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR }
- S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR }
- S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK }
- S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO }
- S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK }
- F_OK :: 0 // Test for file existance
- X_OK :: 1 // Test for execute permission
- W_OK :: 2 // Test for write permission
- R_OK :: 4 // Test for read permission
- @private
- Unix_File_Time :: struct {
- seconds: i64,
- nanoseconds: i64,
- }
- @private
- _Stat :: struct {
- device_id: u64, // ID of device containing file
- serial: u64, // File serial number
- nlink: u64, // Number of hard links
- mode: u32, // Mode of the file
- uid: u32, // User ID of the file's owner
- gid: u32, // Group ID of the file's group
- _padding: i32, // 32 bits of padding
- rdev: u64, // Device ID, if device
- size: i64, // Size of the file, in bytes
- block_size: i64, // Optimal bllocksize for I/O
- blocks: i64, // Number of 512-byte blocks allocated
- last_access: Unix_File_Time, // Time of last access
- modified: Unix_File_Time, // Time of last modification
- status_change: Unix_File_Time, // Time of last status change
- _reserve1,
- _reserve2,
- _reserve3: i64,
- }
- _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
- return _fstat_internal(f.impl.fd, allocator)
- }
- _fstat_internal :: proc(fd: int, allocator: runtime.Allocator) -> (File_Info, Error) {
- s: _Stat
- result := unix.sys_fstat(fd, &s)
- if result < 0 {
- return {}, _get_platform_error(result)
- }
- // TODO: As of Linux 4.11, the new statx syscall can retrieve creation_time
- fi := File_Info {
- fullpath = _get_full_path(fd, allocator),
- name = "",
- size = s.size,
- mode = 0,
- is_directory = S_ISDIR(s.mode),
- modification_time = time.Time {s.modified.seconds},
- access_time = time.Time {s.last_access.seconds},
- creation_time = time.Time{0}, // regular stat does not provide this
- }
- fi.name = filepath.base(fi.fullpath)
- return fi, nil
- }
- // NOTE: _stat and _lstat are using _fstat to avoid a race condition when populating fullpath
- _stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
- name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
- fd := unix.sys_open(name_cstr, _O_RDONLY)
- if fd < 0 {
- return {}, _get_platform_error(fd)
- }
- defer unix.sys_close(fd)
- return _fstat_internal(fd, allocator)
- }
- _lstat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
- name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
- fd := unix.sys_open(name_cstr, _O_RDONLY | _O_PATH | _O_NOFOLLOW)
- if fd < 0 {
- return {}, _get_platform_error(fd)
- }
- defer unix.sys_close(fd)
- return _fstat_internal(fd, allocator)
- }
- _same_file :: proc(fi1, fi2: File_Info) -> bool {
- return fi1.fullpath == fi2.fullpath
- }
- _stat_internal :: proc(name: string) -> (s: _Stat, res: int) {
- name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
- res = unix.sys_stat(name_cstr, &s)
- return
- }
|