| ... | @@ -206,7 +206,7 @@ pub fn updateFile( | ... | @@ -206,7 +206,7 @@ pub fn updateFile( |
| 206 | } | 206 | } |
| 207 | | 207 | |
| 208 | if (std.fs.path.dirname(dest_path)) |dirname| { | 208 | if (std.fs.path.dirname(dest_path)) |dirname| { |
| 209 | try dest_dir.makePath(io, dirname); | 209 | try dest_dir.makePathMode(io, dirname, default_mode); |
| 210 | } | 210 | } |
| 211 | | 211 | |
| 212 | var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available. | 212 | var buffer: [1000]u8 = undefined; // Used only when direct fd-to-fd is not available. |
| ... | @@ -287,13 +287,17 @@ pub fn makeDir(dir: Dir, io: Io, sub_path: []const u8) MakeError!void { | ... | @@ -287,13 +287,17 @@ pub fn makeDir(dir: Dir, io: Io, sub_path: []const u8) MakeError!void { |
| 287 | | 287 | |
| 288 | pub const MakePathError = MakeError || StatPathError; | 288 | pub const MakePathError = MakeError || StatPathError; |
| 289 | | 289 | |
| 290 | /// Calls makeDir iteratively to make an entire path, creating any parent | 290 | /// Same as `makePathMode` but passes `default_mode`. |
| 291 | /// directories that do not exist. | 291 | pub fn makePath(dir: Dir, io: Io, sub_path: []const u8) MakePathError!void { |
| | 292 | _ = try io.vtable.dirMakePath(io.userdata, dir, sub_path, default_mode); |
| | 293 | } |
| | 294 | |
| | 295 | /// Creates parent directories as necessary to ensure `sub_path` exists as a directory. |
| 292 | /// | 296 | /// |
| 293 | /// Returns success if the path already exists and is a directory. | 297 | /// Returns success if the path already exists and is a directory. |
| 294 | /// | 298 | /// |
| 295 | /// This function is not atomic, and if it returns an error, the file system | 299 | /// This function may not be atomic. If it returns an error, the file system |
| 296 | /// may have been modified regardless. | 300 | /// may have been modified. |
| 297 | /// | 301 | /// |
| 298 | /// Fails on an empty path with `error.BadPathName` as that is not a path that | 302 | /// Fails on an empty path with `error.BadPathName` as that is not a path that |
| 299 | /// can be created. | 303 | /// can be created. |
| ... | @@ -309,8 +313,8 @@ pub const MakePathError = MakeError || StatPathError; | ... | @@ -309,8 +313,8 @@ pub const MakePathError = MakeError || StatPathError; |
| 309 | /// - On other platforms, `..` are not resolved before the path is passed to `mkdirat`, | 313 | /// - On other platforms, `..` are not resolved before the path is passed to `mkdirat`, |
| 310 | /// meaning a `sub_path` like "first/../second" will create both a `./first` | 314 | /// meaning a `sub_path` like "first/../second" will create both a `./first` |
| 311 | /// and a `./second` directory. | 315 | /// and a `./second` directory. |
| 312 | pub fn makePath(dir: Dir, io: Io, sub_path: []const u8) MakePathError!void { | 316 | pub fn makePathMode(dir: Dir, io: Io, sub_path: []const u8, mode: Mode) MakePathError!void { |
| 313 | _ = try makePathStatus(dir, io, sub_path); | 317 | _ = try io.vtable.dirMakePath(io.userdata, dir, sub_path, mode); |
| 314 | } | 318 | } |
| 315 | | 319 | |
| 316 | pub const MakePathStatus = enum { existed, created }; | 320 | pub const MakePathStatus = enum { existed, created }; |
| ... | @@ -318,34 +322,7 @@ pub const MakePathStatus = enum { existed, created }; | ... | @@ -318,34 +322,7 @@ pub const MakePathStatus = enum { existed, created }; |
| 318 | /// Same as `makePath` except returns whether the path already existed or was | 322 | /// Same as `makePath` except returns whether the path already existed or was |
| 319 | /// successfully created. | 323 | /// successfully created. |
| 320 | pub fn makePathStatus(dir: Dir, io: Io, sub_path: []const u8) MakePathError!MakePathStatus { | 324 | pub fn makePathStatus(dir: Dir, io: Io, sub_path: []const u8) MakePathError!MakePathStatus { |
| 321 | var it = std.fs.path.componentIterator(sub_path); | 325 | return io.vtable.dirMakePath(io.userdata, dir, sub_path, default_mode); |
| 322 | var status: MakePathStatus = .existed; | | |
| 323 | var component = it.last() orelse return error.BadPathName; | | |
| 324 | while (true) { | | |
| 325 | if (makeDir(dir, io, component.path)) { | | |
| 326 | status = .created; | | |
| 327 | } else |err| switch (err) { | | |
| 328 | error.PathAlreadyExists => { | | |
| 329 | // stat the file and return an error if it's not a directory | | |
| 330 | // this is important because otherwise a dangling symlink | | |
| 331 | // could cause an infinite loop | | |
| 332 | check_dir: { | | |
| 333 | // workaround for windows, see https://github.com/ziglang/zig/issues/16738 | | |
| 334 | const fstat = statPath(dir, io, component.path, .{}) catch |stat_err| switch (stat_err) { | | |
| 335 | error.IsDir => break :check_dir, | | |
| 336 | else => |e| return e, | | |
| 337 | }; | | |
| 338 | if (fstat.kind != .directory) return error.NotDir; | | |
| 339 | } | | |
| 340 | }, | | |
| 341 | error.FileNotFound => |e| { | | |
| 342 | component = it.previous() orelse return e; | | |
| 343 | continue; | | |
| 344 | }, | | |
| 345 | else => |e| return e, | | |
| 346 | } | | |
| 347 | component = it.next() orelse return status; | | |
| 348 | } | | |
| 349 | } | 326 | } |
| 350 | | 327 | |
| 351 | pub const MakeOpenPathError = MakeError || OpenError || StatPathError; | 328 | pub const MakeOpenPathError = MakeError || OpenError || StatPathError; |