mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Change to Permissions bit_set from relying on octal numbering for os2
This commit is contained in:
@@ -18,7 +18,7 @@ find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, al
|
||||
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
|
||||
path := concatenate({base_path, `\`, win32_wstring_to_utf8(cstring16(raw_data(d.cFileName[:])), temp_allocator) or_else ""}, allocator) or_return
|
||||
|
||||
handle := win32.HANDLE(_open_internal(path, {.Read}, 0o666) or_else 0)
|
||||
handle := win32.HANDLE(_open_internal(path, {.Read}, Permissions_Read_Write_All) or_else 0)
|
||||
defer win32.CloseHandle(handle)
|
||||
|
||||
fi.fullpath = path
|
||||
|
||||
+44
-5
@@ -90,17 +90,56 @@ O_SPARSE :: File_Flags{.Sparse}
|
||||
*/
|
||||
O_INHERITABLE :: File_Flags{.Inheritable}
|
||||
|
||||
Permissions :: distinct bit_set[Permission_Flag; u32]
|
||||
Permission_Flag :: enum u32 {
|
||||
Execute_Other = 0,
|
||||
Write_Other = 1,
|
||||
Read_Other = 2,
|
||||
|
||||
Execute_Group = 3,
|
||||
Write_Group = 4,
|
||||
Read_Group = 5,
|
||||
|
||||
Execute_User = 6,
|
||||
Write_User = 7,
|
||||
Read_User = 8,
|
||||
}
|
||||
|
||||
Permissions_Execute_All :: Permissions{.Execute_User, .Execute_Group, .Execute_Other}
|
||||
Permissions_Write_All :: Permissions{.Write_User, .Write_Group, .Write_Other}
|
||||
Permissions_Read_All :: Permissions{.Read_User, .Read_Group, .Read_Other}
|
||||
|
||||
Permissions_Read_Write_All :: Permissions_Read_All + Permissions_Write_All
|
||||
|
||||
Permissions_All :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All
|
||||
|
||||
Permissions_Default_File :: Permissions_Read_All + Permissions_Write_All
|
||||
Permissions_Default_Directory :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All
|
||||
Permissions_Default :: Permissions_Default_Directory
|
||||
|
||||
perm :: proc{
|
||||
perm_number,
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
perm_number :: proc "contextless" (perm: int) -> Permissions {
|
||||
return transmute(Permissions)u32(perm & 0o777)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
stdin: ^File = nil // OS-Specific
|
||||
stdout: ^File = nil // OS-Specific
|
||||
stderr: ^File = nil // OS-Specific
|
||||
|
||||
@(require_results)
|
||||
create :: proc(name: string) -> (^File, Error) {
|
||||
return open(name, {.Read, .Write, .Create}, 0o777)
|
||||
return open(name, {.Read, .Write, .Create}, Permissions_Default)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File, Error) {
|
||||
open :: proc(name: string, flags := File_Flags{.Read}, perm := Permissions_Default) -> (^File, Error) {
|
||||
return _open(name, flags, perm)
|
||||
}
|
||||
|
||||
@@ -237,7 +276,7 @@ change_directory :: proc(name: string) -> Error {
|
||||
|
||||
chmod :: change_mode
|
||||
|
||||
change_mode :: proc(name: string, mode: int) -> Error {
|
||||
change_mode :: proc(name: string, mode: Permissions) -> Error {
|
||||
return _chmod(name, mode)
|
||||
}
|
||||
|
||||
@@ -255,7 +294,7 @@ fchange_directory :: proc(f: ^File) -> Error {
|
||||
|
||||
fchmod :: fchange_mode
|
||||
|
||||
fchange_mode :: proc(f: ^File, mode: int) -> Error {
|
||||
fchange_mode :: proc(f: ^File, mode: Permissions) -> Error {
|
||||
return _fchmod(f, mode)
|
||||
}
|
||||
|
||||
@@ -331,7 +370,7 @@ _copy_file :: proc(dst_path, src_path: string) -> Error {
|
||||
return .Invalid_File
|
||||
}
|
||||
|
||||
dst := open(dst_path, {.Read, .Write, .Create, .Trunc}, info.mode & 0o777) or_return
|
||||
dst := open(dst_path, {.Read, .Write, .Create, .Trunc}, info.mode & Permissions_All) or_return
|
||||
defer close(dst)
|
||||
|
||||
_, err := io.copy(to_writer(dst), to_reader(src))
|
||||
|
||||
@@ -65,7 +65,7 @@ _standard_stream_init :: proc "contextless" () {
|
||||
stderr = new_std(&files[2], 2, "/proc/self/fd/2")
|
||||
}
|
||||
|
||||
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
|
||||
_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) {
|
||||
temp_allocator := TEMP_ALLOCATOR_GUARD({})
|
||||
name_cstr := clone_to_cstring(name, temp_allocator) or_return
|
||||
|
||||
@@ -88,7 +88,7 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
|
||||
if .Trunc in flags { sys_flags += {.TRUNC} }
|
||||
if .Inheritable in flags { sys_flags -= {.CLOEXEC} }
|
||||
|
||||
fd, errno := linux.open(name_cstr, sys_flags, transmute(linux.Mode)u32(perm))
|
||||
fd, errno := linux.open(name_cstr, sys_flags, transmute(linux.Mode)transmute(u32)perm)
|
||||
if errno != .NONE {
|
||||
return nil, _get_platform_error(errno)
|
||||
}
|
||||
@@ -132,7 +132,7 @@ _clone :: proc(f: ^File) -> (clone: ^File, err: Error) {
|
||||
|
||||
|
||||
@(require_results)
|
||||
_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) {
|
||||
_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm: Permissions) -> (f: ^File, err: Error) {
|
||||
assert(buffer_size > 0)
|
||||
f, err = _open(name, flags, perm)
|
||||
if f != nil && err == nil {
|
||||
@@ -369,15 +369,15 @@ _fchdir :: proc(f: ^File) -> Error {
|
||||
return _get_platform_error(linux.fchdir(impl.fd))
|
||||
}
|
||||
|
||||
_chmod :: proc(name: string, mode: int) -> Error {
|
||||
_chmod :: proc(name: string, mode: Permissions) -> Error {
|
||||
temp_allocator := TEMP_ALLOCATOR_GUARD({})
|
||||
name_cstr := clone_to_cstring(name, temp_allocator) or_return
|
||||
return _get_platform_error(linux.chmod(name_cstr, transmute(linux.Mode)(u32(mode))))
|
||||
return _get_platform_error(linux.chmod(name_cstr, transmute(linux.Mode)transmute(u32)mode))
|
||||
}
|
||||
|
||||
_fchmod :: proc(f: ^File, mode: int) -> Error {
|
||||
_fchmod :: proc(f: ^File, mode: Permissions) -> Error {
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)(u32(mode))))
|
||||
return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)transmute(u32)mode))
|
||||
}
|
||||
|
||||
// NOTE: will throw error without super user priviledges
|
||||
|
||||
@@ -46,7 +46,7 @@ init_std_files :: proc "contextless" () {
|
||||
stderr = new_std(&files[2], posix.STDERR_FILENO, "/dev/stderr")
|
||||
}
|
||||
|
||||
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
|
||||
_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) {
|
||||
if name == "" {
|
||||
err = .Invalid_Path
|
||||
return
|
||||
@@ -72,7 +72,7 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
|
||||
temp_allocator := TEMP_ALLOCATOR_GUARD({})
|
||||
cname := clone_to_cstring(name, temp_allocator) or_return
|
||||
|
||||
fd := posix.open(cname, sys_flags, transmute(posix.mode_t)posix._mode_t(perm))
|
||||
fd := posix.open(cname, sys_flags, transmute(posix.mode_t)posix._mode_t(transmute(u32)perm))
|
||||
if fd < 0 {
|
||||
err = _get_platform_error()
|
||||
return
|
||||
@@ -284,17 +284,17 @@ _fchdir :: proc(f: ^File) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_fchmod :: proc(f: ^File, mode: int) -> Error {
|
||||
if posix.fchmod(__fd(f), transmute(posix.mode_t)posix._mode_t(mode)) != .OK {
|
||||
_fchmod :: proc(f: ^File, mode: Permissions) -> Error {
|
||||
if posix.fchmod(__fd(f), transmute(posix.mode_t)posix._mode_t(transmute(u32)mode)) != .OK {
|
||||
return _get_platform_error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
_chmod :: proc(name: string, mode: int) -> (err: Error) {
|
||||
_chmod :: proc(name: string, mode: Permissions) -> (err: Error) {
|
||||
temp_allocator := TEMP_ALLOCATOR_GUARD({})
|
||||
cname := clone_to_cstring(name, temp_allocator) or_return
|
||||
if posix.chmod(cname, transmute(posix.mode_t)posix._mode_t(mode)) != .OK {
|
||||
if posix.chmod(cname, transmute(posix.mode_t)posix._mode_t(transmute(u32)mode)) != .OK {
|
||||
return _get_platform_error()
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -8,7 +8,7 @@ import "core:sys/posix"
|
||||
|
||||
_posix_absolute_path :: proc(fd: posix.FD, name: string, allocator: runtime.Allocator) -> (path: cstring, err: Error) {
|
||||
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
|
||||
cname := clone_to_cstring(name, temp_allocator)
|
||||
cname := clone_to_cstring(name, temp_allocator) or_return
|
||||
|
||||
buf: [posix.PATH_MAX]byte
|
||||
path = posix.realpath(cname, raw_data(buf[:]))
|
||||
|
||||
@@ -161,7 +161,7 @@ read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator, loc :
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
write_entire_file :: proc(name: string, data: []byte, perm: int = 0o644, truncate := true) -> Error {
|
||||
write_entire_file :: proc(name: string, data: []byte, perm := Permissions_Read_All + {.Write_User}, truncate := true) -> Error {
|
||||
flags := O_WRONLY|O_CREATE
|
||||
if truncate {
|
||||
flags |= O_TRUNC
|
||||
|
||||
@@ -51,8 +51,8 @@ init_std_files :: proc "contextless" () {
|
||||
}
|
||||
|
||||
@(init)
|
||||
init_preopens :: proc() {
|
||||
strip_prefixes :: proc(path: string) -> string {
|
||||
init_preopens :: proc "contextless" () {
|
||||
strip_prefixes :: proc "contextless" (path: string) -> string {
|
||||
path := path
|
||||
loop: for len(path) > 0 {
|
||||
switch {
|
||||
@@ -69,6 +69,8 @@ init_preopens :: proc() {
|
||||
return path
|
||||
}
|
||||
|
||||
context = runtime.default_context()
|
||||
|
||||
n: int
|
||||
n_loop: for fd := wasi.fd_t(3); ; fd += 1 {
|
||||
_, err := wasi.fd_prestat_get(fd)
|
||||
@@ -171,7 +173,7 @@ match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) {
|
||||
return match.fd, relative, true
|
||||
}
|
||||
|
||||
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
|
||||
_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) {
|
||||
dir_fd, relative, ok := match_preopen(name)
|
||||
if !ok {
|
||||
return nil, .Invalid_Path
|
||||
@@ -373,11 +375,11 @@ _fchdir :: proc(f: ^File) -> Error {
|
||||
return .Unsupported
|
||||
}
|
||||
|
||||
_fchmod :: proc(f: ^File, mode: int) -> Error {
|
||||
_fchmod :: proc(f: ^File, mode: Permissions) -> Error {
|
||||
return .Unsupported
|
||||
}
|
||||
|
||||
_chmod :: proc(name: string, mode: int) -> Error {
|
||||
_chmod :: proc(name: string, mode: Permissions) -> Error {
|
||||
return .Unsupported
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import win32 "core:sys/windows"
|
||||
|
||||
INVALID_HANDLE :: ~uintptr(0)
|
||||
|
||||
S_IWRITE :: 0o200
|
||||
_ERROR_BAD_NETPATH :: 53
|
||||
MAX_RW :: 1<<30
|
||||
|
||||
@@ -81,7 +80,7 @@ _handle :: proc "contextless" (f: ^File) -> win32.HANDLE {
|
||||
return win32.HANDLE(_fd(f))
|
||||
}
|
||||
|
||||
_open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: uintptr, err: Error) {
|
||||
_open_internal :: proc(name: string, flags: File_Flags, perm: Permissions) -> (handle: uintptr, err: Error) {
|
||||
if len(name) == 0 {
|
||||
err = .Not_Exist
|
||||
return
|
||||
@@ -122,7 +121,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
|
||||
}
|
||||
|
||||
attrs: u32 = win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS
|
||||
if perm & S_IWRITE == 0 {
|
||||
if .Write_User not_in perm {
|
||||
attrs = win32.FILE_ATTRIBUTE_READONLY
|
||||
if create_mode == win32.CREATE_ALWAYS {
|
||||
// NOTE(bill): Open has just asked to create a file in read-only mode.
|
||||
@@ -150,7 +149,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
|
||||
}
|
||||
|
||||
|
||||
_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
|
||||
_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) {
|
||||
flags := flags if flags != nil else {.Read}
|
||||
handle := _open_internal(name, flags, perm) or_return
|
||||
return _new_file(handle, name, file_allocator())
|
||||
@@ -193,7 +192,7 @@ _new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) -
|
||||
|
||||
|
||||
@(require_results)
|
||||
_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) {
|
||||
_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm: Permissions) -> (f: ^File, err: Error) {
|
||||
assert(buffer_size > 0)
|
||||
flags := flags if flags != nil else {.Read}
|
||||
handle := _open_internal(name, flags, perm) or_return
|
||||
@@ -744,7 +743,7 @@ _fchdir :: proc(f: ^File) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_fchmod :: proc(f: ^File, mode: int) -> Error {
|
||||
_fchmod :: proc(f: ^File, mode: Permissions) -> Error {
|
||||
if f == nil || f.impl == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -753,7 +752,7 @@ _fchmod :: proc(f: ^File, mode: int) -> Error {
|
||||
return _get_platform_error()
|
||||
}
|
||||
attrs := d.dwFileAttributes
|
||||
if mode & S_IWRITE != 0 {
|
||||
if .Write_User in mode {
|
||||
attrs &~= win32.FILE_ATTRIBUTE_READONLY
|
||||
} else {
|
||||
attrs |= win32.FILE_ATTRIBUTE_READONLY
|
||||
@@ -780,7 +779,7 @@ _chdir :: proc(name: string) -> Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
_chmod :: proc(name: string, mode: int) -> Error {
|
||||
_chmod :: proc(name: string, mode: Permissions) -> Error {
|
||||
f := open(name, {.Write}) or_return
|
||||
defer close(f)
|
||||
return _fchmod(f, mode)
|
||||
|
||||
@@ -34,7 +34,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error {
|
||||
return .Exist
|
||||
}
|
||||
|
||||
clean_path := clean_path(path, temp_allocator)
|
||||
clean_path := clean_path(path, temp_allocator) or_return
|
||||
return internal_mkdir_all(clean_path)
|
||||
|
||||
internal_mkdir_all :: proc(path: string) -> Error {
|
||||
@@ -114,3 +114,7 @@ _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err
|
||||
|
||||
return concatenate({"/", arg}, allocator)
|
||||
}
|
||||
|
||||
_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) {
|
||||
return "", .Unsupported
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ File_Info :: struct {
|
||||
|
||||
inode: u128, // might be zero if cannot be determined
|
||||
size: i64 `fmt:"M"`,
|
||||
mode: int `fmt:"o"`,
|
||||
mode: Permissions,
|
||||
type: File_Type,
|
||||
|
||||
creation_time: time.Time,
|
||||
|
||||
@@ -26,7 +26,7 @@ _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fi: File
|
||||
case linux.S_IFREG: type = .Regular
|
||||
case linux.S_IFSOCK: type = .Socket
|
||||
}
|
||||
mode := int(0o7777 & transmute(u32)s.mode)
|
||||
mode := transmute(Permissions)(0o7777 & transmute(u32)s.mode)
|
||||
|
||||
// TODO: As of Linux 4.11, the new statx syscall can retrieve creation_time
|
||||
fi = File_Info {
|
||||
|
||||
@@ -14,7 +14,7 @@ internal_stat :: proc(stat: posix.stat_t, fullpath: string) -> (fi: File_Info) {
|
||||
fi.inode = u128(stat.st_ino)
|
||||
fi.size = i64(stat.st_size)
|
||||
|
||||
fi.mode = int(transmute(posix._mode_t)(stat.st_mode - posix.S_IFMT))
|
||||
fi.mode = transmute(Permissions)u32(transmute(posix._mode_t)(stat.st_mode - posix.S_IFMT))
|
||||
|
||||
fi.type = .Undetermined
|
||||
switch {
|
||||
|
||||
@@ -211,11 +211,11 @@ _file_type_from_create_file :: proc(wname: win32.wstring, create_file_attributes
|
||||
return file_type(h)
|
||||
}
|
||||
|
||||
_file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (type: File_Type, mode: int) {
|
||||
_file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (type: File_Type, mode: Permissions) {
|
||||
if file_attributes & win32.FILE_ATTRIBUTE_READONLY != 0 {
|
||||
mode |= 0o444
|
||||
mode += Permissions_Write_All
|
||||
} else {
|
||||
mode |= 0o666
|
||||
mode += Permissions_Read_Write_All
|
||||
}
|
||||
|
||||
is_sym := false
|
||||
@@ -229,7 +229,7 @@ _file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: wi
|
||||
type = .Symlink
|
||||
} else if file_attributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||
type = .Directory
|
||||
mode |= 0o111
|
||||
mode += Permissions_Execute_All
|
||||
} else if h != nil {
|
||||
type = file_type(h)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ MAX_ATTEMPTS :: 1<<13 // Should be enough for everyone, right?
|
||||
|
||||
// Creates a new temperatory file in the directory `dir`.
|
||||
//
|
||||
// Opens the file for reading and writing, with 0o666 permissions, and returns the new `^File`.
|
||||
// Opens the file for reading and writing, with `Permissions_Read_Write_All` permissions, and returns the new `^File`.
|
||||
// The filename is generated by taking a pattern, and adding a randomized string to the end.
|
||||
// If the pattern includes an "*", the random string replaces the last "*".
|
||||
// If `dir` is an empty string, `temp_directory()` will be used.
|
||||
@@ -26,7 +26,7 @@ create_temp_file :: proc(dir, pattern: string) -> (f: ^File, err: Error) {
|
||||
attempts := 0
|
||||
for {
|
||||
name := concatenate_strings_from_buffer(name_buf[:], prefix, random_string(rand_buf[:]), suffix)
|
||||
f, err = open(name, {.Read, .Write, .Create, .Excl}, 0o666)
|
||||
f, err = open(name, {.Read, .Write, .Create, .Excl}, Permissions_Read_Write_All)
|
||||
if err == .Exist {
|
||||
close(f)
|
||||
attempts += 1
|
||||
|
||||
Reference in New Issue
Block a user