authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2020-06-26 15:49:31-07:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2020-06-26 16:00:43-07:00
log14c3c47fb7315e6199751082f9ef544972bb13e6
treeb8113e001c2dccc327264923c107467b64cbba9a
parent0e3d74df8a8c06bcc0b1e4bff205f4ab8e4c6c13

fs.deleteFile: Translate to error.IsDir when appropriate on POSIX systems

Linux deviates from POSIX and returns EISDIR while other POSIX systems return EPERM. To make all platforms consistent in their errors when calling deleteFile on a directory, we have to do a stat to translate EPERM (AccessDenied) to EISDIR (IsDir).

1 files changed, 20 insertions(+), 0 deletions(-)

lib/std/fs.zig+20
......@@ -1112,6 +1112,16 @@ pub const Dir = struct {
11121112 pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void {
11131113 os.unlinkat(self.fd, sub_path, 0) catch |err| switch (err) {
11141114 error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
1115 error.AccessDenied => |e| switch (builtin.os.tag) {
1116 // non-Linux POSIX systems return EPERM when trying to delete a directory, so
1117 // we need to handle that case specifically and translate the error
1118 .macosx, .ios, .freebsd, .netbsd, .dragonfly => {
1119 const fstat = os.fstatat(self.fd, sub_path, 0) catch return e;
1120 const is_dir = fstat.mode & os.S_IFMT == os.S_IFDIR;
1121 return if (is_dir) error.IsDir else e;
1122 },
1123 else => return e,
1124 },
11151125 else => |e| return e,
11161126 };
11171127 }
......@@ -1122,6 +1132,16 @@ pub const Dir = struct {
11221132 pub fn deleteFileZ(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void {
11231133 os.unlinkatZ(self.fd, sub_path_c, 0) catch |err| switch (err) {
11241134 error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
1135 error.AccessDenied => |e| switch (builtin.os.tag) {
1136 // non-Linux POSIX systems return EPERM when trying to delete a directory, so
1137 // we need to handle that case specifically and translate the error
1138 .macosx, .ios, .freebsd, .netbsd, .dragonfly => {
1139 const fstat = os.fstatatZ(self.fd, sub_path_c, 0) catch return e;
1140 const is_dir = fstat.mode & os.S_IFMT == os.S_IFDIR;
1141 return if (is_dir) error.IsDir else e;
1142 },
1143 else => return e,
1144 },
11251145 else => |e| return e,
11261146 };
11271147 }