mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 16:45:27 +00:00
Add chmod
and chown
This commit is contained in:
parent
dfd604834b
commit
796687f156
@ -147,6 +147,8 @@ pub extern "c" fn dup(fd: c.fd_t) c_int;
|
||||
pub extern "c" fn dup2(old_fd: c.fd_t, new_fd: c.fd_t) c_int;
|
||||
pub extern "c" fn readlink(noalias path: [*:0]const u8, noalias buf: [*]u8, bufsize: usize) isize;
|
||||
pub extern "c" fn readlinkat(dirfd: c.fd_t, noalias path: [*:0]const u8, noalias buf: [*]u8, bufsize: usize) isize;
|
||||
pub extern "c" fn fchmod(fd: c.fd_t, mode: c.mode_t) c_int;
|
||||
pub extern "c" fn fchown(fd: c.fd_t, owner: c.uid_t, group: c.gid_t) c_int;
|
||||
|
||||
pub extern "c" fn rmdir(path: [*:0]const u8) c_int;
|
||||
pub extern "c" fn getenv(name: [*:0]const u8) ?[*:0]u8;
|
||||
|
@ -2178,6 +2178,37 @@ pub const Dir = struct {
|
||||
};
|
||||
return file.stat();
|
||||
}
|
||||
|
||||
pub const ChmodError = File.ChmodError;
|
||||
|
||||
/// Changes the mode of the directory.
|
||||
/// The process must have the correct privileges in order to do this
|
||||
/// successfully, or must have the effective user ID matching the owner
|
||||
/// of the directory. Additionally, the directory must have been opened
|
||||
/// with `OpenDirOptions{ .iterate = true }`.
|
||||
pub fn chmod(self: Dir, new_mode: File.Mode) ChmodError!void {
|
||||
const file: File = .{
|
||||
.handle = self.fd,
|
||||
.capable_io_mode = .blocking,
|
||||
};
|
||||
try file.chmod(new_mode);
|
||||
}
|
||||
|
||||
/// Changes the owner and group of the directory.
|
||||
/// The process must have the correct privileges in order to do this
|
||||
/// successfully. The group may be changed by the owner of the directory to
|
||||
/// any group of which the owner is a member. Additionally, the directory
|
||||
/// must have been opened with `OpenDirOptions{ .iterate = true }`. If the
|
||||
/// owner or group is specified as `null`, the ID is not changed.
|
||||
pub fn chown(self: Dir, owner: ?File.Uid, group: ?File.Gid) ChownError!void {
|
||||
const file: File = .{
|
||||
.handle = self.fd,
|
||||
.capable_io_mode = .blocking,
|
||||
};
|
||||
try file.chown(owner, group);
|
||||
}
|
||||
|
||||
pub const ChownError = File.ChownError;
|
||||
};
|
||||
|
||||
/// Returns a handle to the current working directory. It is not opened with iteration capability.
|
||||
|
@ -31,6 +31,8 @@ pub const File = struct {
|
||||
pub const Handle = os.fd_t;
|
||||
pub const Mode = os.mode_t;
|
||||
pub const INode = os.ino_t;
|
||||
pub const Uid = os.uid_t;
|
||||
pub const Gid = os.gid_t;
|
||||
|
||||
pub const Kind = enum {
|
||||
BlockDevice,
|
||||
@ -362,6 +364,27 @@ pub const File = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub const ChmodError = std.os.FChmodError;
|
||||
|
||||
/// Changes the mode of the file.
|
||||
/// The process must have the correct privileges in order to do this
|
||||
/// successfully, or must have the effective user ID matching the owner
|
||||
/// of the file.
|
||||
pub fn chmod(self: File, new_mode: Mode) ChmodError!void {
|
||||
try os.fchmod(self.handle, new_mode);
|
||||
}
|
||||
|
||||
pub const ChownError = std.os.FChownError;
|
||||
|
||||
/// Changes the owner and group of the file.
|
||||
/// The process must have the correct privileges in order to do this
|
||||
/// successfully. The group may be changed by the owner of the file to
|
||||
/// any group of which the owner is a member. If the owner or group is
|
||||
/// specified as `null`, the ID is not changed.
|
||||
pub fn chown(self: File, owner: ?Uid, group: ?Gid) ChownError!void {
|
||||
try os.fchown(self.handle, owner, group);
|
||||
}
|
||||
|
||||
pub const UpdateTimesError = os.FutimensError || windows.SetFileTimeError;
|
||||
|
||||
/// The underlying file system may have a different granularity than nanoseconds,
|
||||
|
@ -1022,3 +1022,43 @@ test ". and .. in absolute functions" {
|
||||
|
||||
try fs.deleteDirAbsolute(subdir_path);
|
||||
}
|
||||
|
||||
test "chmod" {
|
||||
if (builtin.os.tag == .windows or builtin.os.tag == .wasi)
|
||||
return error.SkipZigTest;
|
||||
|
||||
var tmp = tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
|
||||
const file = try tmp.dir.createFile("test_file", .{ .mode = 0o600 });
|
||||
defer file.close();
|
||||
try testing.expect((try file.stat()).mode & 0o7777 == 0o600);
|
||||
|
||||
try file.chmod(0o644);
|
||||
try testing.expect((try file.stat()).mode & 0o7777 == 0o644);
|
||||
|
||||
try tmp.dir.makeDir("test_dir");
|
||||
var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true });
|
||||
defer dir.close();
|
||||
|
||||
try dir.chmod(0o700);
|
||||
try testing.expect((try dir.stat()).mode & 0o7777 == 0o700);
|
||||
}
|
||||
|
||||
test "chown" {
|
||||
if (builtin.os.tag == .windows or builtin.os.tag == .wasi)
|
||||
return error.SkipZigTest;
|
||||
|
||||
var tmp = tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
|
||||
const file = try tmp.dir.createFile("test_file", .{});
|
||||
defer file.close();
|
||||
try file.chown(null, null);
|
||||
|
||||
try tmp.dir.makeDir("test_dir");
|
||||
|
||||
var dir = try tmp.dir.openDir("test_dir", .{ .iterate = true });
|
||||
defer dir.close();
|
||||
try dir.chown(null, null);
|
||||
}
|
||||
|
@ -255,6 +255,87 @@ pub fn close(fd: fd_t) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub const FChmodError = error{
|
||||
AccessDenied,
|
||||
InputOutput,
|
||||
SymLinkLoop,
|
||||
FileNotFound,
|
||||
SystemResources,
|
||||
ReadOnlyFileSystem,
|
||||
} || UnexpectedError;
|
||||
|
||||
/// Changes the mode of the file referred to by the file descriptor.
|
||||
/// The process must have the correct privileges in order to do this
|
||||
/// successfully, or must have the effective user ID matching the owner
|
||||
/// of the file.
|
||||
pub fn fchmod(fd: fd_t, mode: mode_t) FChmodError!void {
|
||||
if (builtin.os.tag == .windows or builtin.os.tag == .wasi)
|
||||
@compileError("Unsupported OS");
|
||||
|
||||
while (true) {
|
||||
const res = system.fchmod(fd, mode);
|
||||
|
||||
switch (system.getErrno(res)) {
|
||||
.SUCCESS => return,
|
||||
.INTR => continue,
|
||||
.BADF => unreachable, // Can be reached if the fd refers to a directory opened without `OpenDirOptions{ .iterate = true }`
|
||||
|
||||
.FAULT => unreachable,
|
||||
.INVAL => unreachable,
|
||||
.ACCES => return error.AccessDenied,
|
||||
.IO => return error.InputOutput,
|
||||
.LOOP => return error.SymLinkLoop,
|
||||
.NOENT => return error.FileNotFound,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.NOTDIR => return error.FileNotFound,
|
||||
.PERM => return error.AccessDenied,
|
||||
.ROFS => return error.ReadOnlyFileSystem,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const FChownError = error{
|
||||
AccessDenied,
|
||||
InputOutput,
|
||||
SymLinkLoop,
|
||||
FileNotFound,
|
||||
SystemResources,
|
||||
ReadOnlyFileSystem,
|
||||
} || UnexpectedError;
|
||||
|
||||
/// Changes the owner and group of the file referred to by the file descriptor.
|
||||
/// The process must have the correct privileges in order to do this
|
||||
/// successfully. The group may be changed by the owner of the directory to
|
||||
/// any group of which the owner is a member. If the owner or group is
|
||||
/// specified as `null`, the ID is not changed.
|
||||
pub fn fchown(fd: fd_t, owner: ?uid_t, group: ?gid_t) FChownError!void {
|
||||
if (builtin.os.tag == .windows or builtin.os.tag == .wasi)
|
||||
@compileError("Unsupported OS");
|
||||
|
||||
while (true) {
|
||||
const res = system.fchown(fd, owner orelse @as(u32, 0) -% 1, group orelse @as(u32, 0) -% 1);
|
||||
|
||||
switch (system.getErrno(res)) {
|
||||
.SUCCESS => return,
|
||||
.INTR => continue,
|
||||
.BADF => unreachable, // Can be reached if the fd refers to a directory opened without `OpenDirOptions{ .iterate = true }`
|
||||
|
||||
.FAULT => unreachable,
|
||||
.INVAL => unreachable,
|
||||
.ACCES => return error.AccessDenied,
|
||||
.IO => return error.InputOutput,
|
||||
.LOOP => return error.SymLinkLoop,
|
||||
.NOENT => return error.FileNotFound,
|
||||
.NOMEM => return error.SystemResources,
|
||||
.NOTDIR => return error.FileNotFound,
|
||||
.PERM => return error.AccessDenied,
|
||||
.ROFS => return error.ReadOnlyFileSystem,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const GetRandomError = OpenError;
|
||||
|
||||
/// Obtain a series of random bytes. These bytes can be used to seed user-space
|
||||
|
@ -733,6 +733,14 @@ pub fn close(fd: i32) usize {
|
||||
return syscall1(.close, @bitCast(usize, @as(isize, fd)));
|
||||
}
|
||||
|
||||
pub fn fchmod(fd: i32, mode: mode_t) usize {
|
||||
return syscall2(.fchmod, @bitCast(usize, @as(isize, fd)), mode);
|
||||
}
|
||||
|
||||
pub fn fchown(fd: i32, owner: uid_t, group: gid_t) usize {
|
||||
return syscall3(.fchown, @bitCast(usize, @as(isize, fd)), owner, group);
|
||||
}
|
||||
|
||||
/// Can only be called on 32 bit systems. For 64 bit see `lseek`.
|
||||
pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {
|
||||
// NOTE: The offset parameter splitting is independent from the target
|
||||
|
Loading…
Reference in New Issue
Block a user