mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
std.Io.Dir: add resolve_beneath flag and implement for freebsd,macos
This commit is contained in:
+12
-4
@@ -549,6 +549,10 @@ pub const OpenFileOptions = struct {
|
||||
/// controlling TTY for the current process.
|
||||
allow_ctty: bool = false,
|
||||
follow_symlinks: bool = true,
|
||||
/// If supported by the operating system, attempted path resolution that
|
||||
/// would escape the directory instead returns `error.AccessDenied`. If
|
||||
/// unsupported, this option is ignored.
|
||||
resolve_beneath: bool = false,
|
||||
|
||||
pub const Mode = enum { read_only, write_only, read_write };
|
||||
|
||||
@@ -570,13 +574,13 @@ pub const OpenFileOptions = struct {
|
||||
/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
|
||||
/// On WASI, `sub_path` should be encoded as valid UTF-8.
|
||||
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
|
||||
pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: OpenFileOptions) File.OpenError!File {
|
||||
return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags);
|
||||
pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, options: OpenFileOptions) File.OpenError!File {
|
||||
return io.vtable.dirOpenFile(io.userdata, dir, sub_path, options);
|
||||
}
|
||||
|
||||
pub fn openFileAbsolute(io: Io, absolute_path: []const u8, flags: OpenFileOptions) File.OpenError!File {
|
||||
pub fn openFileAbsolute(io: Io, absolute_path: []const u8, options: OpenFileOptions) File.OpenError!File {
|
||||
assert(path.isAbsolute(absolute_path));
|
||||
return openFile(.cwd(), io, absolute_path, flags);
|
||||
return openFile(.cwd(), io, absolute_path, options);
|
||||
}
|
||||
|
||||
pub const CreateFileOptions = struct {
|
||||
@@ -618,6 +622,10 @@ pub const CreateFileOptions = struct {
|
||||
/// is available to proceed.
|
||||
lock_nonblocking: bool = false,
|
||||
permissions: Permissions = .default_file,
|
||||
/// If supported by the operating system, attempted path resolution that
|
||||
/// would escape the directory instead returns `error.AccessDenied`. If
|
||||
/// unsupported, this option is ignored.
|
||||
resolve_beneath: bool = false,
|
||||
};
|
||||
|
||||
/// Creates, opens, or overwrites a file with write access.
|
||||
|
||||
+42
-40
@@ -4217,7 +4217,7 @@ fn dirCreateFilePosix(
|
||||
userdata: ?*anyopaque,
|
||||
dir: Dir,
|
||||
sub_path: []const u8,
|
||||
flags: Dir.CreateFileOptions,
|
||||
options: Dir.CreateFileOptions,
|
||||
) File.OpenError!File {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
_ = t;
|
||||
@@ -4225,34 +4225,35 @@ fn dirCreateFilePosix(
|
||||
var path_buffer: [posix.PATH_MAX]u8 = undefined;
|
||||
const sub_path_posix = try pathToPosix(sub_path, &path_buffer);
|
||||
|
||||
var os_flags: posix.O = .{
|
||||
.ACCMODE = if (flags.read) .RDWR else .WRONLY,
|
||||
var flags: posix.O = .{
|
||||
.ACCMODE = if (options.read) .RDWR else .WRONLY,
|
||||
.CREAT = true,
|
||||
.TRUNC = flags.truncate,
|
||||
.EXCL = flags.exclusive,
|
||||
.TRUNC = options.truncate,
|
||||
.EXCL = options.exclusive,
|
||||
};
|
||||
if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true;
|
||||
if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true;
|
||||
if (@hasField(posix.O, "LARGEFILE")) flags.LARGEFILE = true;
|
||||
if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true;
|
||||
if (@hasField(posix.O, "RESOLVE_BENEATH")) flags.RESOLVE_BENEATH = options.resolve_beneath;
|
||||
|
||||
// Use the O locking flags if the os supports them to acquire the lock
|
||||
// atomically. Note that the NONBLOCK flag is removed after the openat()
|
||||
// call is successful.
|
||||
if (have_flock_open_flags) switch (flags.lock) {
|
||||
if (have_flock_open_flags) switch (options.lock) {
|
||||
.none => {},
|
||||
.shared => {
|
||||
os_flags.SHLOCK = true;
|
||||
os_flags.NONBLOCK = flags.lock_nonblocking;
|
||||
flags.SHLOCK = true;
|
||||
flags.NONBLOCK = options.lock_nonblocking;
|
||||
},
|
||||
.exclusive => {
|
||||
os_flags.EXLOCK = true;
|
||||
os_flags.NONBLOCK = flags.lock_nonblocking;
|
||||
flags.EXLOCK = true;
|
||||
flags.NONBLOCK = options.lock_nonblocking;
|
||||
},
|
||||
};
|
||||
|
||||
const fd: posix.fd_t = fd: {
|
||||
const syscall: Syscall = try .start();
|
||||
while (true) {
|
||||
const rc = openat_sym(dir.handle, sub_path_posix, os_flags, flags.permissions.toMode());
|
||||
const rc = openat_sym(dir.handle, sub_path_posix, flags, options.permissions.toMode());
|
||||
switch (posix.errno(rc)) {
|
||||
.SUCCESS => {
|
||||
syscall.finish();
|
||||
@@ -4298,9 +4299,9 @@ fn dirCreateFilePosix(
|
||||
};
|
||||
errdefer closeFd(fd);
|
||||
|
||||
if (have_flock and !have_flock_open_flags and flags.lock != .none) {
|
||||
const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0;
|
||||
const lock_flags = switch (flags.lock) {
|
||||
if (have_flock and !have_flock_open_flags and options.lock != .none) {
|
||||
const lock_nonblocking: i32 = if (options.lock_nonblocking) posix.LOCK.NB else 0;
|
||||
const lock_flags = switch (options.lock) {
|
||||
.none => unreachable,
|
||||
.shared => posix.LOCK.SH | lock_nonblocking,
|
||||
.exclusive => posix.LOCK.EX | lock_nonblocking,
|
||||
@@ -4332,7 +4333,7 @@ fn dirCreateFilePosix(
|
||||
}
|
||||
}
|
||||
|
||||
if (have_flock_open_flags and flags.lock_nonblocking) {
|
||||
if (have_flock_open_flags and options.lock_nonblocking) {
|
||||
var fl_flags: usize = fl: {
|
||||
const syscall: Syscall = try .start();
|
||||
while (true) {
|
||||
@@ -4785,45 +4786,46 @@ fn dirOpenFilePosix(
|
||||
userdata: ?*anyopaque,
|
||||
dir: Dir,
|
||||
sub_path: []const u8,
|
||||
flags: Dir.OpenFileOptions,
|
||||
options: Dir.OpenFileOptions,
|
||||
) File.OpenError!File {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
|
||||
var path_buffer: [posix.PATH_MAX]u8 = undefined;
|
||||
const sub_path_posix = try pathToPosix(sub_path, &path_buffer);
|
||||
|
||||
var os_flags: posix.O = switch (native_os) {
|
||||
var flags: posix.O = switch (native_os) {
|
||||
.wasi => .{
|
||||
.read = flags.mode != .write_only,
|
||||
.write = flags.mode != .read_only,
|
||||
.NOFOLLOW = !flags.follow_symlinks,
|
||||
.read = options.mode != .write_only,
|
||||
.write = options.mode != .read_only,
|
||||
.NOFOLLOW = !options.follow_symlinks,
|
||||
},
|
||||
else => .{
|
||||
.ACCMODE = switch (flags.mode) {
|
||||
.ACCMODE = switch (options.mode) {
|
||||
.read_only => .RDONLY,
|
||||
.write_only => .WRONLY,
|
||||
.read_write => .RDWR,
|
||||
},
|
||||
.NOFOLLOW = !flags.follow_symlinks,
|
||||
.NOFOLLOW = !options.follow_symlinks,
|
||||
},
|
||||
};
|
||||
if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true;
|
||||
if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true;
|
||||
if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty;
|
||||
if (@hasField(posix.O, "PATH") and flags.path_only) os_flags.PATH = true;
|
||||
if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true;
|
||||
if (@hasField(posix.O, "LARGEFILE")) flags.LARGEFILE = true;
|
||||
if (@hasField(posix.O, "NOCTTY")) flags.NOCTTY = !options.allow_ctty;
|
||||
if (@hasField(posix.O, "PATH")) flags.PATH = options.path_only;
|
||||
if (@hasField(posix.O, "RESOLVE_BENEATH")) flags.RESOLVE_BENEATH = options.resolve_beneath;
|
||||
|
||||
// Use the O locking flags if the os supports them to acquire the lock
|
||||
// Use the O locking options if the os supports them to acquire the lock
|
||||
// atomically. Note that the NONBLOCK flag is removed after the openat()
|
||||
// call is successful.
|
||||
if (have_flock_open_flags) switch (flags.lock) {
|
||||
if (have_flock_open_flags) switch (options.lock) {
|
||||
.none => {},
|
||||
.shared => {
|
||||
os_flags.SHLOCK = true;
|
||||
os_flags.NONBLOCK = flags.lock_nonblocking;
|
||||
flags.SHLOCK = true;
|
||||
flags.NONBLOCK = options.lock_nonblocking;
|
||||
},
|
||||
.exclusive => {
|
||||
os_flags.EXLOCK = true;
|
||||
os_flags.NONBLOCK = flags.lock_nonblocking;
|
||||
flags.EXLOCK = true;
|
||||
flags.NONBLOCK = options.lock_nonblocking;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4832,7 +4834,7 @@ fn dirOpenFilePosix(
|
||||
const fd: posix.fd_t = fd: {
|
||||
const syscall: Syscall = try .start();
|
||||
while (true) {
|
||||
const rc = openat_sym(dir.handle, sub_path_posix, os_flags, mode);
|
||||
const rc = openat_sym(dir.handle, sub_path_posix, flags, mode);
|
||||
switch (posix.errno(rc)) {
|
||||
.SUCCESS => {
|
||||
syscall.finish();
|
||||
@@ -4878,7 +4880,7 @@ fn dirOpenFilePosix(
|
||||
};
|
||||
errdefer closeFd(fd);
|
||||
|
||||
if (!flags.allow_directory) {
|
||||
if (!options.allow_directory) {
|
||||
const is_dir = is_dir: {
|
||||
const stat = fileStat(t, .{
|
||||
.handle = fd,
|
||||
@@ -4893,9 +4895,9 @@ fn dirOpenFilePosix(
|
||||
if (is_dir) return error.IsDir;
|
||||
}
|
||||
|
||||
if (have_flock and !have_flock_open_flags and flags.lock != .none) {
|
||||
const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0;
|
||||
const lock_flags = switch (flags.lock) {
|
||||
if (have_flock and !have_flock_open_flags and options.lock != .none) {
|
||||
const lock_nonblocking: i32 = if (options.lock_nonblocking) posix.LOCK.NB else 0;
|
||||
const lock_flags = switch (options.lock) {
|
||||
.none => unreachable,
|
||||
.shared => posix.LOCK.SH | lock_nonblocking,
|
||||
.exclusive => posix.LOCK.EX | lock_nonblocking,
|
||||
@@ -4926,7 +4928,7 @@ fn dirOpenFilePosix(
|
||||
}
|
||||
}
|
||||
|
||||
if (have_flock_open_flags and flags.lock_nonblocking) {
|
||||
if (have_flock_open_flags and options.lock_nonblocking) {
|
||||
var fl_flags: usize = fl: {
|
||||
const syscall: Syscall = try .start();
|
||||
while (true) {
|
||||
|
||||
+2
-1
@@ -8535,7 +8535,8 @@ pub const O = switch (native_os) {
|
||||
CREAT: bool = false,
|
||||
TRUNC: bool = false,
|
||||
EXCL: bool = false,
|
||||
_12: u3 = 0,
|
||||
RESOLVE_BENEATH: bool = false,
|
||||
_13: u2 = 0,
|
||||
EVTONLY: bool = false,
|
||||
_16: u1 = 0,
|
||||
NOCTTY: bool = false,
|
||||
|
||||
Reference in New Issue
Block a user