| author | |
| committer | |
| log | 2d3694ab42b73ba09124d5f1ddbfd9adaea79c47 |
| tree | 8c0adc21784e13f0c7a5ce9d88167b84c8c62b2c |
| parent | 1f79a9e4e300affd111b51ec172bbeff42ca755a |
| parent | 2e4482cd14d6af958c2e16d7db4d6cf73bd043b8 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/316845 files changed, 181 insertions(+), 175 deletions(-)
lib/std/Io.zig+3-3| ... | ... | @@ -160,9 +160,9 @@ pub const VTable = struct { |
| 160 | 160 | dirStat: *const fn (?*anyopaque, Dir) Dir.StatError!Dir.Stat, |
| 161 | 161 | dirStatFile: *const fn (?*anyopaque, Dir, []const u8, Dir.StatFileOptions) Dir.StatFileError!File.Stat, |
| 162 | 162 | dirAccess: *const fn (?*anyopaque, Dir, []const u8, Dir.AccessOptions) Dir.AccessError!void, |
| 163 | dirCreateFile: *const fn (?*anyopaque, Dir, []const u8, File.CreateFlags) File.OpenError!File, | |
| 163 | dirCreateFile: *const fn (?*anyopaque, Dir, []const u8, Dir.CreateFileOptions) File.OpenError!File, | |
| 164 | 164 | dirCreateFileAtomic: *const fn (?*anyopaque, Dir, []const u8, Dir.CreateFileAtomicOptions) Dir.CreateFileAtomicError!File.Atomic, |
| 165 | dirOpenFile: *const fn (?*anyopaque, Dir, []const u8, File.OpenFlags) File.OpenError!File, | |
| 165 | dirOpenFile: *const fn (?*anyopaque, Dir, []const u8, Dir.OpenFileOptions) File.OpenError!File, | |
| 166 | 166 | dirClose: *const fn (?*anyopaque, []const Dir) void, |
| 167 | 167 | dirRead: *const fn (?*anyopaque, *Dir.Reader, []Dir.Entry) Dir.Reader.Error!usize, |
| 168 | 168 | dirRealPath: *const fn (?*anyopaque, Dir, out_buffer: []u8) Dir.RealPathError!usize, |
| ... | ... | @@ -211,7 +211,7 @@ pub const VTable = struct { |
| 211 | 211 | fileMemoryMapRead: *const fn (?*anyopaque, *File.MemoryMap) File.ReadPositionalError!void, |
| 212 | 212 | fileMemoryMapWrite: *const fn (?*anyopaque, *File.MemoryMap) File.WritePositionalError!void, |
| 213 | 213 | |
| 214 | processExecutableOpen: *const fn (?*anyopaque, File.OpenFlags) std.process.OpenExecutableError!File, | |
| 214 | processExecutableOpen: *const fn (?*anyopaque, Dir.OpenFileOptions) std.process.OpenExecutableError!File, | |
| 215 | 215 | processExecutablePath: *const fn (?*anyopaque, buffer: []u8) std.process.ExecutablePathError!usize, |
| 216 | 216 | lockStderr: *const fn (?*anyopaque, ?Terminal.Mode) Cancelable!LockedStderr, |
| 217 | 217 | tryLockStderr: *const fn (?*anyopaque, ?Terminal.Mode) Cancelable!?LockedStderr, |
lib/std/Io/Dir.zig+122-7| ... | ... | @@ -495,6 +495,76 @@ pub fn closeMany(io: Io, dirs: []const Dir) void { |
| 495 | 495 | return io.vtable.dirClose(io.userdata, dirs); |
| 496 | 496 | } |
| 497 | 497 | |
| 498 | pub const OpenFileOptions = struct { | |
| 499 | mode: Mode = .read_only, | |
| 500 | /// Determines the behavior when opening a path that refers to a directory. | |
| 501 | /// | |
| 502 | /// If set to true, directories may be opened, but `error.IsDir` is still | |
| 503 | /// possible in certain scenarios, e.g. attempting to open a directory with | |
| 504 | /// write permissions. | |
| 505 | /// | |
| 506 | /// If set to false, `error.IsDir` will always be returned when opening a directory. | |
| 507 | /// | |
| 508 | /// When set to false: | |
| 509 | /// * On Windows, the behavior is implemented without any extra syscalls. | |
| 510 | /// * On other operating systems, the behavior is implemented with an additional | |
| 511 | /// `fstat` syscall. | |
| 512 | allow_directory: bool = true, | |
| 513 | /// Indicates intent for only some operations to be performed on this | |
| 514 | /// opened file: | |
| 515 | /// * `close` | |
| 516 | /// * `stat` | |
| 517 | /// On Linux and FreeBSD, this corresponds to `std.posix.O.PATH`. | |
| 518 | path_only: bool = false, | |
| 519 | /// Open the file with an advisory lock to coordinate with other processes | |
| 520 | /// accessing it at the same time. An exclusive lock will prevent other | |
| 521 | /// processes from acquiring a lock. A shared lock will prevent other | |
| 522 | /// processes from acquiring a exclusive lock, but does not prevent | |
| 523 | /// other process from getting their own shared locks. | |
| 524 | /// | |
| 525 | /// The lock is advisory, except on Linux in very specific circumstances[1]. | |
| 526 | /// This means that a process that does not respect the locking API can still get access | |
| 527 | /// to the file, despite the lock. | |
| 528 | /// | |
| 529 | /// On these operating systems, the lock is acquired atomically with | |
| 530 | /// opening the file: | |
| 531 | /// * Darwin | |
| 532 | /// * DragonFlyBSD | |
| 533 | /// * FreeBSD | |
| 534 | /// * Haiku | |
| 535 | /// * NetBSD | |
| 536 | /// * OpenBSD | |
| 537 | /// On these operating systems, the lock is acquired via a separate syscall | |
| 538 | /// after opening the file: | |
| 539 | /// * Linux | |
| 540 | /// * Windows | |
| 541 | /// | |
| 542 | /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt | |
| 543 | lock: File.Lock = .none, | |
| 544 | /// Sets whether or not to wait until the file is locked to return. If set to true, | |
| 545 | /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file | |
| 546 | /// is available to proceed. | |
| 547 | lock_nonblocking: bool = false, | |
| 548 | /// Set this to allow the opened file to automatically become the | |
| 549 | /// controlling TTY for the current process. | |
| 550 | allow_ctty: bool = false, | |
| 551 | follow_symlinks: bool = true, | |
| 552 | /// If supported by the operating system, attempted path resolution that | |
| 553 | /// would escape the directory instead returns `error.AccessDenied`. If | |
| 554 | /// unsupported, this option is ignored. | |
| 555 | resolve_beneath: bool = false, | |
| 556 | ||
| 557 | pub const Mode = enum { read_only, write_only, read_write }; | |
| 558 | ||
| 559 | pub fn isRead(self: OpenFileOptions) bool { | |
| 560 | return self.mode != .write_only; | |
| 561 | } | |
| 562 | ||
| 563 | pub fn isWrite(self: OpenFileOptions) bool { | |
| 564 | return self.mode != .read_only; | |
| 565 | } | |
| 566 | }; | |
| 567 | ||
| 498 | 568 | /// Opens a file for reading or writing, without attempting to create a new file. |
| 499 | 569 | /// |
| 500 | 570 | /// To create a new file, see `createFile`. |
| ... | ... | @@ -504,15 +574,60 @@ pub fn closeMany(io: Io, dirs: []const Dir) void { |
| 504 | 574 | /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). |
| 505 | 575 | /// On WASI, `sub_path` should be encoded as valid UTF-8. |
| 506 | 576 | /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. |
| 507 | pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { | |
| 508 | return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags); | |
| 577 | pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, options: OpenFileOptions) File.OpenError!File { | |
| 578 | return io.vtable.dirOpenFile(io.userdata, dir, sub_path, options); | |
| 509 | 579 | } |
| 510 | 580 | |
| 511 | pub fn openFileAbsolute(io: Io, absolute_path: []const u8, flags: File.OpenFlags) File.OpenError!File { | |
| 581 | pub fn openFileAbsolute(io: Io, absolute_path: []const u8, options: OpenFileOptions) File.OpenError!File { | |
| 512 | 582 | assert(path.isAbsolute(absolute_path)); |
| 513 | return openFile(.cwd(), io, absolute_path, flags); | |
| 583 | return openFile(.cwd(), io, absolute_path, options); | |
| 514 | 584 | } |
| 515 | 585 | |
| 586 | pub const CreateFileOptions = struct { | |
| 587 | /// Whether the file will be created with read access. | |
| 588 | read: bool = false, | |
| 589 | /// If the file already exists, and is a regular file, and the access | |
| 590 | /// mode allows writing, it will be truncated to length 0. | |
| 591 | truncate: bool = true, | |
| 592 | /// Ensures that this open call creates the file, otherwise causes | |
| 593 | /// `error.PathAlreadyExists` to be returned. | |
| 594 | exclusive: bool = false, | |
| 595 | /// Open the file with an advisory lock to coordinate with other processes | |
| 596 | /// accessing it at the same time. An exclusive lock will prevent other | |
| 597 | /// processes from acquiring a lock. A shared lock will prevent other | |
| 598 | /// processes from acquiring a exclusive lock, but does not prevent | |
| 599 | /// other process from getting their own shared locks. | |
| 600 | /// | |
| 601 | /// The lock is advisory, except on Linux in very specific circumstances[1]. | |
| 602 | /// This means that a process that does not respect the locking API can still get access | |
| 603 | /// to the file, despite the lock. | |
| 604 | /// | |
| 605 | /// On these operating systems, the lock is acquired atomically with | |
| 606 | /// opening the file: | |
| 607 | /// * Darwin | |
| 608 | /// * DragonFlyBSD | |
| 609 | /// * FreeBSD | |
| 610 | /// * Haiku | |
| 611 | /// * NetBSD | |
| 612 | /// * OpenBSD | |
| 613 | /// On these operating systems, the lock is acquired via a separate syscall | |
| 614 | /// after opening the file: | |
| 615 | /// * Linux | |
| 616 | /// * Windows | |
| 617 | /// | |
| 618 | /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt | |
| 619 | lock: File.Lock = .none, | |
| 620 | /// Sets whether or not to wait until the file is locked to return. If set to true, | |
| 621 | /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file | |
| 622 | /// is available to proceed. | |
| 623 | lock_nonblocking: bool = false, | |
| 624 | permissions: Permissions = .default_file, | |
| 625 | /// If supported by the operating system, attempted path resolution that | |
| 626 | /// would escape the directory instead returns `error.AccessDenied`. If | |
| 627 | /// unsupported, this option is ignored. | |
| 628 | resolve_beneath: bool = false, | |
| 629 | }; | |
| 630 | ||
| 516 | 631 | /// Creates, opens, or overwrites a file with write access. |
| 517 | 632 | /// |
| 518 | 633 | /// Allocates a resource to be dellocated with `File.close`. |
| ... | ... | @@ -520,11 +635,11 @@ pub fn openFileAbsolute(io: Io, absolute_path: []const u8, flags: File.OpenFlags |
| 520 | 635 | /// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). |
| 521 | 636 | /// On WASI, `sub_path` should be encoded as valid UTF-8. |
| 522 | 637 | /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. |
| 523 | pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { | |
| 638 | pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: CreateFileOptions) File.OpenError!File { | |
| 524 | 639 | return io.vtable.dirCreateFile(io.userdata, dir, sub_path, flags); |
| 525 | 640 | } |
| 526 | 641 | |
| 527 | pub fn createFileAbsolute(io: Io, absolute_path: []const u8, flags: File.CreateFlags) File.OpenError!File { | |
| 642 | pub fn createFileAbsolute(io: Io, absolute_path: []const u8, flags: CreateFileOptions) File.OpenError!File { | |
| 528 | 643 | return createFile(.cwd(), io, absolute_path, flags); |
| 529 | 644 | } |
| 530 | 645 | |
| ... | ... | @@ -534,7 +649,7 @@ pub const WriteFileOptions = struct { |
| 534 | 649 | /// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. |
| 535 | 650 | sub_path: []const u8, |
| 536 | 651 | data: []const u8, |
| 537 | flags: File.CreateFlags = .{}, | |
| 652 | flags: CreateFileOptions = .{}, | |
| 538 | 653 | }; |
| 539 | 654 | |
| 540 | 655 | pub const WriteFileError = File.Writer.Error || File.OpenError; |
lib/std/Io/File.zig+6-118| ... | ... | @@ -142,11 +142,8 @@ pub fn stat(file: File, io: Io) StatError!Stat { |
| 142 | 142 | return io.vtable.fileStat(io.userdata, file); |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | pub const OpenMode = enum { | |
| 146 | read_only, | |
| 147 | write_only, | |
| 148 | read_write, | |
| 149 | }; | |
| 145 | /// Deprecated, renamed to `Dir.OpenFileOptions.Mode`. | |
| 146 | pub const OpenMode = Dir.OpenFileOptions.Mode; | |
| 150 | 147 | |
| 151 | 148 | pub const Lock = enum { |
| 152 | 149 | none, |
| ... | ... | @@ -154,120 +151,11 @@ pub const Lock = enum { |
| 154 | 151 | exclusive, |
| 155 | 152 | }; |
| 156 | 153 | |
| 157 | pub const OpenFlags = struct { | |
| 158 | mode: OpenMode = .read_only, | |
| 159 | ||
| 160 | /// Determines the behavior when opening a path that refers to a directory. | |
| 161 | /// | |
| 162 | /// If set to true, directories may be opened, but `error.IsDir` is still | |
| 163 | /// possible in certain scenarios, e.g. attempting to open a directory with | |
| 164 | /// write permissions. | |
| 165 | /// | |
| 166 | /// If set to false, `error.IsDir` will always be returned when opening a directory. | |
| 167 | /// | |
| 168 | /// When set to false: | |
| 169 | /// * On Windows, the behavior is implemented without any extra syscalls. | |
| 170 | /// * On other operating systems, the behavior is implemented with an additional | |
| 171 | /// `fstat` syscall. | |
| 172 | allow_directory: bool = true, | |
| 173 | /// Indicates intent for only some operations to be performed on this | |
| 174 | /// opened file: | |
| 175 | /// * `close` | |
| 176 | /// * `stat` | |
| 177 | /// On Linux and FreeBSD, this corresponds to `std.posix.O.PATH`. | |
| 178 | path_only: bool = false, | |
| 179 | ||
| 180 | /// Open the file with an advisory lock to coordinate with other processes | |
| 181 | /// accessing it at the same time. An exclusive lock will prevent other | |
| 182 | /// processes from acquiring a lock. A shared lock will prevent other | |
| 183 | /// processes from acquiring a exclusive lock, but does not prevent | |
| 184 | /// other process from getting their own shared locks. | |
| 185 | /// | |
| 186 | /// The lock is advisory, except on Linux in very specific circumstances[1]. | |
| 187 | /// This means that a process that does not respect the locking API can still get access | |
| 188 | /// to the file, despite the lock. | |
| 189 | /// | |
| 190 | /// On these operating systems, the lock is acquired atomically with | |
| 191 | /// opening the file: | |
| 192 | /// * Darwin | |
| 193 | /// * DragonFlyBSD | |
| 194 | /// * FreeBSD | |
| 195 | /// * Haiku | |
| 196 | /// * NetBSD | |
| 197 | /// * OpenBSD | |
| 198 | /// On these operating systems, the lock is acquired via a separate syscall | |
| 199 | /// after opening the file: | |
| 200 | /// * Linux | |
| 201 | /// * Windows | |
| 202 | /// | |
| 203 | /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt | |
| 204 | lock: Lock = .none, | |
| 205 | ||
| 206 | /// Sets whether or not to wait until the file is locked to return. If set to true, | |
| 207 | /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file | |
| 208 | /// is available to proceed. | |
| 209 | lock_nonblocking: bool = false, | |
| 210 | ||
| 211 | /// Set this to allow the opened file to automatically become the | |
| 212 | /// controlling TTY for the current process. | |
| 213 | allow_ctty: bool = false, | |
| 214 | ||
| 215 | follow_symlinks: bool = true, | |
| 216 | ||
| 217 | pub fn isRead(self: OpenFlags) bool { | |
| 218 | return self.mode != .write_only; | |
| 219 | } | |
| 154 | /// Deprecated, renamed to `Dir.OpenFileOptions` | |
| 155 | pub const OpenFlags = Dir.OpenFileOptions; | |
| 220 | 156 | |
| 221 | pub fn isWrite(self: OpenFlags) bool { | |
| 222 | return self.mode != .read_only; | |
| 223 | } | |
| 224 | }; | |
| 225 | ||
| 226 | pub const CreateFlags = struct { | |
| 227 | /// Whether the file will be created with read access. | |
| 228 | read: bool = false, | |
| 229 | ||
| 230 | /// If the file already exists, and is a regular file, and the access | |
| 231 | /// mode allows writing, it will be truncated to length 0. | |
| 232 | truncate: bool = true, | |
| 233 | ||
| 234 | /// Ensures that this open call creates the file, otherwise causes | |
| 235 | /// `error.PathAlreadyExists` to be returned. | |
| 236 | exclusive: bool = false, | |
| 237 | ||
| 238 | /// Open the file with an advisory lock to coordinate with other processes | |
| 239 | /// accessing it at the same time. An exclusive lock will prevent other | |
| 240 | /// processes from acquiring a lock. A shared lock will prevent other | |
| 241 | /// processes from acquiring a exclusive lock, but does not prevent | |
| 242 | /// other process from getting their own shared locks. | |
| 243 | /// | |
| 244 | /// The lock is advisory, except on Linux in very specific circumstances[1]. | |
| 245 | /// This means that a process that does not respect the locking API can still get access | |
| 246 | /// to the file, despite the lock. | |
| 247 | /// | |
| 248 | /// On these operating systems, the lock is acquired atomically with | |
| 249 | /// opening the file: | |
| 250 | /// * Darwin | |
| 251 | /// * DragonFlyBSD | |
| 252 | /// * FreeBSD | |
| 253 | /// * Haiku | |
| 254 | /// * NetBSD | |
| 255 | /// * OpenBSD | |
| 256 | /// On these operating systems, the lock is acquired via a separate syscall | |
| 257 | /// after opening the file: | |
| 258 | /// * Linux | |
| 259 | /// * Windows | |
| 260 | /// | |
| 261 | /// [1]: https://www.kernel.org/doc/Documentation/filesystems/mandatory-locking.txt | |
| 262 | lock: Lock = .none, | |
| 263 | ||
| 264 | /// Sets whether or not to wait until the file is locked to return. If set to true, | |
| 265 | /// `error.WouldBlock` will be returned. Otherwise, the file will wait until the file | |
| 266 | /// is available to proceed. | |
| 267 | lock_nonblocking: bool = false, | |
| 268 | ||
| 269 | permissions: Permissions = .default_file, | |
| 270 | }; | |
| 157 | /// Deprecated, renamed to `Dir.CreateFileOptions`. | |
| 158 | pub const CreateFlags = Dir.CreateFileOptions; | |
| 271 | 159 | |
| 272 | 160 | pub const OpenError = error{ |
| 273 | 161 | PipeBusy, |
lib/std/Io/Threaded.zig+48-46| ... | ... | @@ -4217,7 +4217,7 @@ fn dirCreateFilePosix( |
| 4217 | 4217 | userdata: ?*anyopaque, |
| 4218 | 4218 | dir: Dir, |
| 4219 | 4219 | sub_path: []const u8, |
| 4220 | flags: File.CreateFlags, | |
| 4220 | options: Dir.CreateFileOptions, | |
| 4221 | 4221 | ) File.OpenError!File { |
| 4222 | 4222 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4223 | 4223 | _ = t; |
| ... | ... | @@ -4225,34 +4225,35 @@ fn dirCreateFilePosix( |
| 4225 | 4225 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 4226 | 4226 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| 4227 | 4227 | |
| 4228 | var os_flags: posix.O = .{ | |
| 4229 | .ACCMODE = if (flags.read) .RDWR else .WRONLY, | |
| 4228 | var flags: posix.O = .{ | |
| 4229 | .ACCMODE = if (options.read) .RDWR else .WRONLY, | |
| 4230 | 4230 | .CREAT = true, |
| 4231 | .TRUNC = flags.truncate, | |
| 4232 | .EXCL = flags.exclusive, | |
| 4231 | .TRUNC = options.truncate, | |
| 4232 | .EXCL = options.exclusive, | |
| 4233 | 4233 | }; |
| 4234 | if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; | |
| 4235 | if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; | |
| 4234 | if (@hasField(posix.O, "LARGEFILE")) flags.LARGEFILE = true; | |
| 4235 | if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; | |
| 4236 | if (@hasField(posix.O, "RESOLVE_BENEATH")) flags.RESOLVE_BENEATH = options.resolve_beneath; | |
| 4236 | 4237 | |
| 4237 | 4238 | // Use the O locking flags if the os supports them to acquire the lock |
| 4238 | 4239 | // atomically. Note that the NONBLOCK flag is removed after the openat() |
| 4239 | 4240 | // call is successful. |
| 4240 | if (have_flock_open_flags) switch (flags.lock) { | |
| 4241 | if (have_flock_open_flags) switch (options.lock) { | |
| 4241 | 4242 | .none => {}, |
| 4242 | 4243 | .shared => { |
| 4243 | os_flags.SHLOCK = true; | |
| 4244 | os_flags.NONBLOCK = flags.lock_nonblocking; | |
| 4244 | flags.SHLOCK = true; | |
| 4245 | flags.NONBLOCK = options.lock_nonblocking; | |
| 4245 | 4246 | }, |
| 4246 | 4247 | .exclusive => { |
| 4247 | os_flags.EXLOCK = true; | |
| 4248 | os_flags.NONBLOCK = flags.lock_nonblocking; | |
| 4248 | flags.EXLOCK = true; | |
| 4249 | flags.NONBLOCK = options.lock_nonblocking; | |
| 4249 | 4250 | }, |
| 4250 | 4251 | }; |
| 4251 | 4252 | |
| 4252 | 4253 | const fd: posix.fd_t = fd: { |
| 4253 | 4254 | const syscall: Syscall = try .start(); |
| 4254 | 4255 | while (true) { |
| 4255 | const rc = openat_sym(dir.handle, sub_path_posix, os_flags, flags.permissions.toMode()); | |
| 4256 | const rc = openat_sym(dir.handle, sub_path_posix, flags, options.permissions.toMode()); | |
| 4256 | 4257 | switch (posix.errno(rc)) { |
| 4257 | 4258 | .SUCCESS => { |
| 4258 | 4259 | syscall.finish(); |
| ... | ... | @@ -4298,9 +4299,9 @@ fn dirCreateFilePosix( |
| 4298 | 4299 | }; |
| 4299 | 4300 | errdefer closeFd(fd); |
| 4300 | 4301 | |
| 4301 | if (have_flock and !have_flock_open_flags and flags.lock != .none) { | |
| 4302 | const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; | |
| 4303 | const lock_flags = switch (flags.lock) { | |
| 4302 | if (have_flock and !have_flock_open_flags and options.lock != .none) { | |
| 4303 | const lock_nonblocking: i32 = if (options.lock_nonblocking) posix.LOCK.NB else 0; | |
| 4304 | const lock_flags = switch (options.lock) { | |
| 4304 | 4305 | .none => unreachable, |
| 4305 | 4306 | .shared => posix.LOCK.SH | lock_nonblocking, |
| 4306 | 4307 | .exclusive => posix.LOCK.EX | lock_nonblocking, |
| ... | ... | @@ -4332,7 +4333,7 @@ fn dirCreateFilePosix( |
| 4332 | 4333 | } |
| 4333 | 4334 | } |
| 4334 | 4335 | |
| 4335 | if (have_flock_open_flags and flags.lock_nonblocking) { | |
| 4336 | if (have_flock_open_flags and options.lock_nonblocking) { | |
| 4336 | 4337 | var fl_flags: usize = fl: { |
| 4337 | 4338 | const syscall: Syscall = try .start(); |
| 4338 | 4339 | while (true) { |
| ... | ... | @@ -4385,7 +4386,7 @@ fn dirCreateFileWindows( |
| 4385 | 4386 | userdata: ?*anyopaque, |
| 4386 | 4387 | dir: Dir, |
| 4387 | 4388 | sub_path: []const u8, |
| 4388 | flags: File.CreateFlags, | |
| 4389 | flags: Dir.CreateFileOptions, | |
| 4389 | 4390 | ) File.OpenError!File { |
| 4390 | 4391 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4391 | 4392 | _ = t; |
| ... | ... | @@ -4535,7 +4536,7 @@ fn dirCreateFileWasi( |
| 4535 | 4536 | userdata: ?*anyopaque, |
| 4536 | 4537 | dir: Dir, |
| 4537 | 4538 | sub_path: []const u8, |
| 4538 | flags: File.CreateFlags, | |
| 4539 | flags: Dir.CreateFileOptions, | |
| 4539 | 4540 | ) File.OpenError!File { |
| 4540 | 4541 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4541 | 4542 | _ = t; |
| ... | ... | @@ -4785,45 +4786,46 @@ fn dirOpenFilePosix( |
| 4785 | 4786 | userdata: ?*anyopaque, |
| 4786 | 4787 | dir: Dir, |
| 4787 | 4788 | sub_path: []const u8, |
| 4788 | flags: File.OpenFlags, | |
| 4789 | options: Dir.OpenFileOptions, | |
| 4789 | 4790 | ) File.OpenError!File { |
| 4790 | 4791 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4791 | 4792 | |
| 4792 | 4793 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 4793 | 4794 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| 4794 | 4795 | |
| 4795 | var os_flags: posix.O = switch (native_os) { | |
| 4796 | var flags: posix.O = switch (native_os) { | |
| 4796 | 4797 | .wasi => .{ |
| 4797 | .read = flags.mode != .write_only, | |
| 4798 | .write = flags.mode != .read_only, | |
| 4799 | .NOFOLLOW = !flags.follow_symlinks, | |
| 4798 | .read = options.mode != .write_only, | |
| 4799 | .write = options.mode != .read_only, | |
| 4800 | .NOFOLLOW = !options.follow_symlinks, | |
| 4800 | 4801 | }, |
| 4801 | 4802 | else => .{ |
| 4802 | .ACCMODE = switch (flags.mode) { | |
| 4803 | .ACCMODE = switch (options.mode) { | |
| 4803 | 4804 | .read_only => .RDONLY, |
| 4804 | 4805 | .write_only => .WRONLY, |
| 4805 | 4806 | .read_write => .RDWR, |
| 4806 | 4807 | }, |
| 4807 | .NOFOLLOW = !flags.follow_symlinks, | |
| 4808 | .NOFOLLOW = !options.follow_symlinks, | |
| 4808 | 4809 | }, |
| 4809 | 4810 | }; |
| 4810 | if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; | |
| 4811 | if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; | |
| 4812 | if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty; | |
| 4813 | if (@hasField(posix.O, "PATH") and flags.path_only) os_flags.PATH = true; | |
| 4811 | if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; | |
| 4812 | if (@hasField(posix.O, "LARGEFILE")) flags.LARGEFILE = true; | |
| 4813 | if (@hasField(posix.O, "NOCTTY")) flags.NOCTTY = !options.allow_ctty; | |
| 4814 | if (@hasField(posix.O, "PATH")) flags.PATH = options.path_only; | |
| 4815 | if (@hasField(posix.O, "RESOLVE_BENEATH")) flags.RESOLVE_BENEATH = options.resolve_beneath; | |
| 4814 | 4816 | |
| 4815 | // Use the O locking flags if the os supports them to acquire the lock | |
| 4817 | // Use the O locking options if the os supports them to acquire the lock | |
| 4816 | 4818 | // atomically. Note that the NONBLOCK flag is removed after the openat() |
| 4817 | 4819 | // call is successful. |
| 4818 | if (have_flock_open_flags) switch (flags.lock) { | |
| 4820 | if (have_flock_open_flags) switch (options.lock) { | |
| 4819 | 4821 | .none => {}, |
| 4820 | 4822 | .shared => { |
| 4821 | os_flags.SHLOCK = true; | |
| 4822 | os_flags.NONBLOCK = flags.lock_nonblocking; | |
| 4823 | flags.SHLOCK = true; | |
| 4824 | flags.NONBLOCK = options.lock_nonblocking; | |
| 4823 | 4825 | }, |
| 4824 | 4826 | .exclusive => { |
| 4825 | os_flags.EXLOCK = true; | |
| 4826 | os_flags.NONBLOCK = flags.lock_nonblocking; | |
| 4827 | flags.EXLOCK = true; | |
| 4828 | flags.NONBLOCK = options.lock_nonblocking; | |
| 4827 | 4829 | }, |
| 4828 | 4830 | }; |
| 4829 | 4831 | |
| ... | ... | @@ -4832,7 +4834,7 @@ fn dirOpenFilePosix( |
| 4832 | 4834 | const fd: posix.fd_t = fd: { |
| 4833 | 4835 | const syscall: Syscall = try .start(); |
| 4834 | 4836 | while (true) { |
| 4835 | const rc = openat_sym(dir.handle, sub_path_posix, os_flags, mode); | |
| 4837 | const rc = openat_sym(dir.handle, sub_path_posix, flags, mode); | |
| 4836 | 4838 | switch (posix.errno(rc)) { |
| 4837 | 4839 | .SUCCESS => { |
| 4838 | 4840 | syscall.finish(); |
| ... | ... | @@ -4878,7 +4880,7 @@ fn dirOpenFilePosix( |
| 4878 | 4880 | }; |
| 4879 | 4881 | errdefer closeFd(fd); |
| 4880 | 4882 | |
| 4881 | if (!flags.allow_directory) { | |
| 4883 | if (!options.allow_directory) { | |
| 4882 | 4884 | const is_dir = is_dir: { |
| 4883 | 4885 | const stat = fileStat(t, .{ |
| 4884 | 4886 | .handle = fd, |
| ... | ... | @@ -4893,9 +4895,9 @@ fn dirOpenFilePosix( |
| 4893 | 4895 | if (is_dir) return error.IsDir; |
| 4894 | 4896 | } |
| 4895 | 4897 | |
| 4896 | if (have_flock and !have_flock_open_flags and flags.lock != .none) { | |
| 4897 | const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; | |
| 4898 | const lock_flags = switch (flags.lock) { | |
| 4898 | if (have_flock and !have_flock_open_flags and options.lock != .none) { | |
| 4899 | const lock_nonblocking: i32 = if (options.lock_nonblocking) posix.LOCK.NB else 0; | |
| 4900 | const lock_flags = switch (options.lock) { | |
| 4899 | 4901 | .none => unreachable, |
| 4900 | 4902 | .shared => posix.LOCK.SH | lock_nonblocking, |
| 4901 | 4903 | .exclusive => posix.LOCK.EX | lock_nonblocking, |
| ... | ... | @@ -4926,7 +4928,7 @@ fn dirOpenFilePosix( |
| 4926 | 4928 | } |
| 4927 | 4929 | } |
| 4928 | 4930 | |
| 4929 | if (have_flock_open_flags and flags.lock_nonblocking) { | |
| 4931 | if (have_flock_open_flags and options.lock_nonblocking) { | |
| 4930 | 4932 | var fl_flags: usize = fl: { |
| 4931 | 4933 | const syscall: Syscall = try .start(); |
| 4932 | 4934 | while (true) { |
| ... | ... | @@ -4979,7 +4981,7 @@ fn dirOpenFileWindows( |
| 4979 | 4981 | userdata: ?*anyopaque, |
| 4980 | 4982 | dir: Dir, |
| 4981 | 4983 | sub_path: []const u8, |
| 4982 | flags: File.OpenFlags, | |
| 4984 | flags: Dir.OpenFileOptions, | |
| 4983 | 4985 | ) File.OpenError!File { |
| 4984 | 4986 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4985 | 4987 | _ = t; |
| ... | ... | @@ -4992,7 +4994,7 @@ fn dirOpenFileWindows( |
| 4992 | 4994 | pub fn dirOpenFileWtf16( |
| 4993 | 4995 | dir_handle: ?windows.HANDLE, |
| 4994 | 4996 | sub_path_w: []const u16, |
| 4995 | flags: File.OpenFlags, | |
| 4997 | flags: Dir.OpenFileOptions, | |
| 4996 | 4998 | ) File.OpenError!File { |
| 4997 | 4999 | const allow_directory = flags.allow_directory and !flags.isWrite(); |
| 4998 | 5000 | if (!allow_directory and std.mem.eql(u16, sub_path_w, &.{'.'})) return error.IsDir; |
| ... | ... | @@ -5129,7 +5131,7 @@ fn dirOpenFileWasi( |
| 5129 | 5131 | userdata: ?*anyopaque, |
| 5130 | 5132 | dir: Dir, |
| 5131 | 5133 | sub_path: []const u8, |
| 5132 | flags: File.OpenFlags, | |
| 5134 | flags: Dir.OpenFileOptions, | |
| 5133 | 5135 | ) File.OpenError!File { |
| 5134 | 5136 | if (builtin.link_libc) return dirOpenFilePosix(userdata, dir, sub_path, flags); |
| 5135 | 5137 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| ... | ... | @@ -10193,7 +10195,7 @@ fn posixSeekTo(fd: posix.fd_t, offset: u64) File.SeekError!void { |
| 10193 | 10195 | } |
| 10194 | 10196 | } |
| 10195 | 10197 | |
| 10196 | fn processExecutableOpen(userdata: ?*anyopaque, flags: File.OpenFlags) process.OpenExecutableError!File { | |
| 10198 | fn processExecutableOpen(userdata: ?*anyopaque, flags: Dir.OpenFileOptions) process.OpenExecutableError!File { | |
| 10197 | 10199 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 10198 | 10200 | switch (native_os) { |
| 10199 | 10201 | .wasi => return error.OperationUnsupported, |
lib/std/c.zig+2-1| ... | ... | @@ -8535,7 +8535,8 @@ pub const O = switch (native_os) { |
| 8535 | 8535 | CREAT: bool = false, |
| 8536 | 8536 | TRUNC: bool = false, |
| 8537 | 8537 | EXCL: bool = false, |
| 8538 | _12: u3 = 0, | |
| 8538 | RESOLVE_BENEATH: bool = false, | |
| 8539 | _13: u2 = 0, | |
| 8539 | 8540 | EVTONLY: bool = false, |
| 8540 | 8541 | _16: u1 = 0, |
| 8541 | 8542 | NOCTTY: bool = false, |