Browse Source

Use `SHFileOperationW` for `remove_all` on Windows

gingerBill 1 year ago
parent
commit
65fec9134e
3 changed files with 32 additions and 60 deletions
  1. 12 0
      core/os/os2/file_util.odin
  2. 2 1
      core/os/os2/file_windows.odin
  3. 18 59
      core/os/os2/path_windows.odin

+ 12 - 0
core/os/os2/file_util.odin

@@ -8,6 +8,18 @@ write_string :: proc(f: ^File, s: string) -> (n: int, err: Error) {
 	return write(f, transmute([]byte)s)
 }
 
+write_strings :: proc(f: ^File, strings: ..string) -> (n: int, err: Error) {
+	for s in strings {
+		m: int
+		m, err = write_string(f, s)
+		n += m
+		if err != nil {
+			return
+		}
+	}
+	return
+}
+
 write_byte :: proc(f: ^File, b: byte) -> (n: int, err: Error) {
 	return write(f, []byte{b})
 }

+ 2 - 1
core/os/os2/file_windows.odin

@@ -109,11 +109,12 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
 				case 0:
 					return uintptr(h), nil
 				case:
-					return 0, Platform_Error(e)
+					return 0, _get_platform_error()
 				}
 			}
 		}
 	}
+
 	h := win32.CreateFileW(path, access, share_mode, &sa, create_mode, attrs, nil)
 	if h == win32.INVALID_HANDLE {
 		return 0, _get_platform_error()

+ 18 - 59
core/os/os2/path_windows.odin

@@ -75,72 +75,31 @@ _remove_all :: proc(path: string) -> Error {
 		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
+	dir := win32_utf8_to_wstring(path, temp_allocator()) or_return
+
+	empty: [1]u16
+
+	file_op := win32.SHFILEOPSTRUCTW {
+		nil,
+		win32.FO_DELETE,
+		dir,
+		&empty[0],
+		win32.FOF_NOCONFIRMATION | win32.FOF_NOERRORUI | win32.FOF_SILENT,
+		false,
+		nil,
+		&empty[0],
+	}
+	res := win32.SHFileOperationW(&file_op)
+	if res != 0 {
+		return _get_platform_error()
 	}
-	return err
+	return nil
 }
 
 @private cwd_lock: win32.SRWLOCK // zero is initialized