authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2022-10-05 20:08:53-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2022-10-05 20:08:53-07:00
log1468eb12f339b09baa1155d33694272828f9617a
treec89462539144dfbc769fb0535920e6e85cd4573f
parent063c5f43e9ff6add28ecbbcd79316ede23af3ae8

std.fs.deleteTree: Unify how the initial sub_path is treated between deleteTree/deleteTreeMinStackSize


1 files changed, 63 insertions(+), 100 deletions(-)

lib/std/fs.zig+63-100
...@@ -2076,24 +2076,7 @@ pub const Dir = struct {...@@ -2076,24 +2076,7 @@ pub const Dir = struct {
2076 /// this function recursively removes its entries and then tries again.2076 /// this function recursively removes its entries and then tries again.
2077 /// This operation is not atomic on most file systems.2077 /// This operation is not atomic on most file systems.
2078 pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {2078 pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void {
2079 if (self.deleteFile(sub_path)) {2079 var initial_iterable_dir = (try self.deleteTreeOpenInitialSubpath(sub_path, .File)) orelse return;
2080 return;
2081 } else |err| switch (err) {
2082 error.FileNotFound => return,
2083 error.IsDir => {},
2084 error.AccessDenied,
2085 error.InvalidUtf8,
2086 error.SymLinkLoop,
2087 error.NameTooLong,
2088 error.SystemResources,
2089 error.ReadOnlyFileSystem,
2090 error.NotDir,
2091 error.FileSystem,
2092 error.FileBusy,
2093 error.BadPathName,
2094 error.Unexpected,
2095 => |e| return e,
2096 }
20972080
2098 const StackItem = struct {2081 const StackItem = struct {
2099 name: []const u8,2082 name: []const u8,
...@@ -2108,32 +2091,6 @@ pub const Dir = struct {...@@ -2108,32 +2091,6 @@ pub const Dir = struct {
2108 }2091 }
2109 }2092 }
21102093
2111 var initial_iterable_dir = self.openIterableDir(sub_path, .{ .no_follow = true }) catch |err| switch (err) {
2112 error.NotDir => {
2113 // Somehow the sub_path got changed into a file while we were trying to delete the tree.
2114 // This implies that the dir at the sub_path was deleted at some point so we consider this
2115 // as a successful delete and return.
2116 return;
2117 },
2118 error.FileNotFound => {
2119 // That's fine, we were trying to remove this directory anyway.
2120 return;
2121 },
2122 error.InvalidHandle,
2123 error.AccessDenied,
2124 error.SymLinkLoop,
2125 error.ProcessFdQuotaExceeded,
2126 error.NameTooLong,
2127 error.SystemFdQuotaExceeded,
2128 error.NoDevice,
2129 error.SystemResources,
2130 error.Unexpected,
2131 error.InvalidUtf8,
2132 error.BadPathName,
2133 error.DeviceBusy,
2134 => |e| return e,
2135 };
2136
2137 stack.appendAssumeCapacity(StackItem{2094 stack.appendAssumeCapacity(StackItem{
2138 .name = sub_path,2095 .name = sub_path,
2139 .parent_dir = self,2096 .parent_dir = self,
...@@ -2309,62 +2266,7 @@ pub const Dir = struct {...@@ -2309,62 +2266,7 @@ pub const Dir = struct {
23092266
2310 fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint: File.Kind) DeleteTreeError!void {2267 fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint: File.Kind) DeleteTreeError!void {
2311 start_over: while (true) {2268 start_over: while (true) {
2312 var iterable_dir = iterable_dir: {2269 var iterable_dir = (try self.deleteTreeOpenInitialSubpath(sub_path, kind_hint)) orelse return;
2313 var treat_as_dir = kind_hint == .Directory;
2314
2315 handle_entry: while (true) {
2316 if (treat_as_dir) {
2317 break :iterable_dir self.openIterableDir(sub_path, .{ .no_follow = true }) catch |err| switch (err) {
2318 error.NotDir => {
2319 treat_as_dir = false;
2320 continue :handle_entry;
2321 },
2322 error.FileNotFound => {
2323 // That's fine, we were trying to remove this directory anyway.
2324 return;
2325 },
2326
2327 error.InvalidHandle,
2328 error.AccessDenied,
2329 error.SymLinkLoop,
2330 error.ProcessFdQuotaExceeded,
2331 error.NameTooLong,
2332 error.SystemFdQuotaExceeded,
2333 error.NoDevice,
2334 error.SystemResources,
2335 error.Unexpected,
2336 error.InvalidUtf8,
2337 error.BadPathName,
2338 error.DeviceBusy,
2339 => |e| return e,
2340 };
2341 } else {
2342 if (self.deleteFile(sub_path)) {
2343 return;
2344 } else |err| switch (err) {
2345 error.FileNotFound => return,
2346
2347 error.IsDir => {
2348 treat_as_dir = true;
2349 continue :handle_entry;
2350 },
2351
2352 error.AccessDenied,
2353 error.InvalidUtf8,
2354 error.SymLinkLoop,
2355 error.NameTooLong,
2356 error.SystemResources,
2357 error.ReadOnlyFileSystem,
2358 error.NotDir,
2359 error.FileSystem,
2360 error.FileBusy,
2361 error.BadPathName,
2362 error.Unexpected,
2363 => |e| return e,
2364 }
2365 }
2366 }
2367 };
2368 var cleanup_dir_parent: ?IterableDir = null;2270 var cleanup_dir_parent: ?IterableDir = null;
2369 defer if (cleanup_dir_parent) |*d| d.close();2271 defer if (cleanup_dir_parent) |*d| d.close();
23702272
...@@ -2470,6 +2372,67 @@ pub const Dir = struct {...@@ -2470,6 +2372,67 @@ pub const Dir = struct {
2470 }2372 }
2471 }2373 }
24722374
2375 /// On successful delete, returns null.
2376 fn deleteTreeOpenInitialSubpath(self: Dir, sub_path: []const u8, kind_hint: File.Kind) !?IterableDir {
2377 return iterable_dir: {
2378 // Treat as a file by default
2379 var treat_as_dir = kind_hint == .Directory;
2380
2381 handle_entry: while (true) {
2382 if (treat_as_dir) {
2383 break :iterable_dir self.openIterableDir(sub_path, .{ .no_follow = true }) catch |err| switch (err) {
2384 error.NotDir => {
2385 treat_as_dir = false;
2386 continue :handle_entry;
2387 },
2388 error.FileNotFound => {
2389 // That's fine, we were trying to remove this directory anyway.
2390 return null;
2391 },
2392
2393 error.InvalidHandle,
2394 error.AccessDenied,
2395 error.SymLinkLoop,
2396 error.ProcessFdQuotaExceeded,
2397 error.NameTooLong,
2398 error.SystemFdQuotaExceeded,
2399 error.NoDevice,
2400 error.SystemResources,
2401 error.Unexpected,
2402 error.InvalidUtf8,
2403 error.BadPathName,
2404 error.DeviceBusy,
2405 => |e| return e,
2406 };
2407 } else {
2408 if (self.deleteFile(sub_path)) {
2409 return null;
2410 } else |err| switch (err) {
2411 error.FileNotFound => return null,
2412
2413 error.IsDir => {
2414 treat_as_dir = true;
2415 continue :handle_entry;
2416 },
2417
2418 error.AccessDenied,
2419 error.InvalidUtf8,
2420 error.SymLinkLoop,
2421 error.NameTooLong,
2422 error.SystemResources,
2423 error.ReadOnlyFileSystem,
2424 error.NotDir,
2425 error.FileSystem,
2426 error.FileBusy,
2427 error.BadPathName,
2428 error.Unexpected,
2429 => |e| return e,
2430 }
2431 }
2432 }
2433 };
2434 }
2435
2473 /// Writes content to the file system, creating a new file if it does not exist, truncating2436 /// Writes content to the file system, creating a new file if it does not exist, truncating
2474 /// if it already exists.2437 /// if it already exists.
2475 pub fn writeFile(self: Dir, sub_path: []const u8, data: []const u8) !void {2438 pub fn writeFile(self: Dir, sub_path: []const u8, data: []const u8) !void {