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).
This commit is contained in:
Ryan Liptak 2020-06-26 15:49:31 -07:00
parent 0e3d74df8a
commit 14c3c47fb7

View File

@ -1112,6 +1112,16 @@ pub const Dir = struct {
pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void {
os.unlinkat(self.fd, sub_path, 0) catch |err| switch (err) {
error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
error.AccessDenied => |e| switch (builtin.os.tag) {
// non-Linux POSIX systems return EPERM when trying to delete a directory, so
// we need to handle that case specifically and translate the error
.macosx, .ios, .freebsd, .netbsd, .dragonfly => {
const fstat = os.fstatat(self.fd, sub_path, 0) catch return e;
const is_dir = fstat.mode & os.S_IFMT == os.S_IFDIR;
return if (is_dir) error.IsDir else e;
},
else => return e,
},
else => |e| return e,
};
}
@ -1122,6 +1132,16 @@ pub const Dir = struct {
pub fn deleteFileZ(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void {
os.unlinkatZ(self.fd, sub_path_c, 0) catch |err| switch (err) {
error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
error.AccessDenied => |e| switch (builtin.os.tag) {
// non-Linux POSIX systems return EPERM when trying to delete a directory, so
// we need to handle that case specifically and translate the error
.macosx, .ios, .freebsd, .netbsd, .dragonfly => {
const fstat = os.fstatatZ(self.fd, sub_path_c, 0) catch return e;
const is_dir = fstat.mode & os.S_IFMT == os.S_IFDIR;
return if (is_dir) error.IsDir else e;
},
else => return e,
},
else => |e| return e,
};
}