Mock out os2.remove_all for Windows

This commit is contained in:
gingerBill
2024-07-23 17:05:41 +01:00
parent 8037ace873
commit a28392852a
3 changed files with 103 additions and 12 deletions
+2 -2
View File
@@ -31,11 +31,11 @@ getwd :: get_working_directory
@(require_results)
get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
return _getwd(allocator)
return _get_working_directory(allocator)
}
setwd :: set_working_directory
set_working_directory :: proc(dir: string) -> (err: Error) {
return _setwd(dir)
return _set_working_directory(dir)
}
+2 -2
View File
@@ -163,7 +163,7 @@ _remove_all :: proc(path: string) -> Error {
return _get_platform_error(linux.rmdir(path_cstr))
}
_getwd :: proc(allocator: runtime.Allocator) -> (string, Error) {
_get_working_directory :: proc(allocator: runtime.Allocator) -> (string, Error) {
// NOTE(tetra): I would use PATH_MAX here, but I was not able to find
// an authoritative value for it across all systems.
// The largest value I could find was 4096, so might as well use the page size.
@@ -183,7 +183,7 @@ _getwd :: proc(allocator: runtime.Allocator) -> (string, Error) {
unreachable()
}
_setwd :: proc(dir: string) -> Error {
_set_working_directory :: proc(dir: string) -> Error {
dir_cstr := temp_cstring(dir) or_return
return _get_platform_error(linux.chdir(dir_cstr))
}
+99 -8
View File
@@ -71,18 +71,109 @@ _mkdir_all :: proc(path: string, perm: int) -> Error {
}
_remove_all :: proc(path: string) -> Error {
// TODO(bill): _remove_all for windows
return nil
if path == "" {
return nil
}
err := remove(path)
if err == nil || err == .Not_Exist {
return nil
}
TEMP_ALLOCATOR_GUARD()
dir, serr := stat_do_not_follow_links(path, temp_allocator())
if serr != nil {
if serr == .Not_Exist || serr == .Invalid_Dir {
return nil
}
return serr
}
if dir.type != .Directory {
return err
}
err = nil
remove_contents: {
f: ^File
f, err = open(path)
if err != nil {
if err == .Not_Exist {
return nil
}
return err
}
files, read_err := read_all_directory(f, temp_allocator())
for file in files {
err1 := remove_all(file.fullpath)
if err == nil {
err = err1
}
}
close(f)
if read_err == .EOF {
break remove_contents
}
if err == nil {
err = read_err
}
if len(files) == 0 {
break remove_contents
}
}
err1 := remove(path)
if err1 == nil || err1 == .Not_Exist {
return nil
}
if ODIN_OS == .Windows && err1 == .Permission_Denied {
if fi, err2 := stat(path, temp_allocator()); err2 == nil {
if err2 = chmod(path, 0o200|fi.mode); err2 == nil {
err1 = remove(path)
}
}
}
if err == nil {
err = err1
}
return err
}
_getwd :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
// TODO(bill)
return "", nil
@private cwd_lock: win32.SRWLOCK // zero is initialized
_get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
win32.AcquireSRWLockExclusive(&cwd_lock)
TEMP_ALLOCATOR_GUARD()
sz_utf16 := win32.GetCurrentDirectoryW(0, nil)
dir_buf_wstr := make([]u16, sz_utf16, temp_allocator()) or_return
sz_utf16 = win32.GetCurrentDirectoryW(win32.DWORD(len(dir_buf_wstr)), raw_data(dir_buf_wstr))
assert(int(sz_utf16)+1 == len(dir_buf_wstr)) // the second time, it _excludes_ the NUL.
win32.ReleaseSRWLockExclusive(&cwd_lock)
return win32_utf16_to_utf8(dir_buf_wstr, allocator)
}
_setwd :: proc(dir: string) -> (err: Error) {
// TODO(bill)
return nil
_set_working_directory :: proc(dir: string) -> (err: Error) {
TEMP_ALLOCATOR_GUARD()
wstr := win32_utf8_to_wstring(dir, temp_allocator()) or_return
win32.AcquireSRWLockExclusive(&cwd_lock)
if !win32.SetCurrentDirectoryW(wstr) {
err = _get_platform_error()
}
win32.ReleaseSRWLockExclusive(&cwd_lock)
return
}
can_use_long_paths: bool