| ... | ... | @@ -7191,9 +7191,9 @@ fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize { |
| 7191 | 7191 | return n; |
| 7192 | 7192 | }, |
| 7193 | 7193 | .linux, .serenity, .illumos => { |
| 7194 | | var procfs_buf: ["/proc/self/path/-2147483648\x00".len]u8 = undefined; |
| 7194 | var proc_buf: [std.fmt.count("/proc/self/path/{d}\x00", .{std.math.minInt(posix.fd_t)})]u8 = undefined; |
| 7195 | 7195 | const template = if (native_os == .illumos) "/proc/self/path/{d}" else "/proc/self/fd/{d}"; |
| 7196 | | const proc_path = std.mem.printSentinel(&procfs_buf, template, .{fd}, 0) catch unreachable; |
| 7196 | const proc_path = std.mem.printSentinel(&proc_buf, template, .{fd}, 0) catch unreachable; |
| 7197 | 7197 | const syscall: Syscall = try .start(); |
| 7198 | 7198 | while (true) { |
| 7199 | 7199 | const rc = posix.system.readlink(proc_path, out_buffer.ptr, out_buffer.len); |
| ... | ... | @@ -7266,27 +7266,32 @@ fn fileHardLink( |
| 7266 | 7266 | new_sub_path: []const u8, |
| 7267 | 7267 | options: File.HardLinkOptions, |
| 7268 | 7268 | ) File.HardLinkError!void { |
| 7269 | | _ = userdata; |
| 7270 | | if (native_os != .linux) return error.OperationUnsupported; |
| 7269 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 7270 | _ = t; |
| 7271 | 7271 | |
| 7272 | 7272 | var new_path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 7273 | 7273 | const new_sub_path_posix = try pathToPosix(new_sub_path, &new_path_buffer); |
| 7274 | 7274 | |
| 7275 | | const flags: u32 = if (options.follow_symlinks) |
| 7276 | | posix.AT.SYMLINK_FOLLOW | posix.AT.EMPTY_PATH |
| 7277 | | else |
| 7278 | | posix.AT.EMPTY_PATH; |
| 7275 | switch (native_os) { |
| 7276 | else => return error.OperationUnsupported, |
| 7277 | .freebsd, .linux => { |
| 7278 | const flags: u32 = if (options.follow_symlinks) |
| 7279 | posix.AT.SYMLINK_FOLLOW | posix.AT.EMPTY_PATH |
| 7280 | else |
| 7281 | posix.AT.EMPTY_PATH; |
| 7279 | 7282 | |
| 7280 | | return linkat(file.handle, "", new_dir.handle, new_sub_path_posix, flags) catch |err| switch (err) { |
| 7281 | | error.FileNotFound => { |
| 7282 | | if (options.follow_symlinks) return error.FileNotFound; |
| 7283 | | var proc_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; |
| 7284 | | const proc_path = std.mem.printSentinel(&proc_buf, "/proc/self/fd/{d}", .{file.handle}, 0) catch |
| 7285 | | unreachable; |
| 7286 | | return linkat(posix.AT.FDCWD, proc_path, new_dir.handle, new_sub_path_posix, posix.AT.SYMLINK_FOLLOW); |
| 7283 | return linkat(file.handle, "", new_dir.handle, new_sub_path_posix, flags) catch |err| switch (err) { |
| 7284 | error.FileNotFound => {}, |
| 7285 | else => |e| return e, |
| 7286 | }; |
| 7287 | 7287 | }, |
| 7288 | | else => |e| return e, |
| 7289 | | }; |
| 7288 | .netbsd, .openbsd => {}, |
| 7289 | } |
| 7290 | |
| 7291 | if (options.follow_symlinks) return error.FileNotFound; |
| 7292 | var dev_buf: [std.fmt.count("/dev/fd/{d}\x00", .{std.math.minInt(posix.fd_t)})]u8 = undefined; |
| 7293 | const dev_path = std.mem.printSentinel(&dev_buf, "/dev/fd/{d}", .{file.handle}, 0) catch unreachable; |
| 7294 | return linkat(posix.AT.FDCWD, dev_path, new_dir.handle, new_sub_path_posix, posix.AT.SYMLINK_FOLLOW); |
| 7290 | 7295 | } |
| 7291 | 7296 | |
| 7292 | 7297 | fn linkat( |
| ... | ... | @@ -8732,12 +8737,12 @@ fn fchmodatFallback( |
| 8732 | 8737 | ) Dir.SetFilePermissionsError!void { |
| 8733 | 8738 | comptime assert(native_os == .linux); |
| 8734 | 8739 | |
| 8735 | | // Fallback to changing permissions using procfs: |
| 8740 | // Fallback to changing permissions using devfs: |
| 8736 | 8741 | // |
| 8737 | 8742 | // 1. Open `path` as a `PATH` descriptor. |
| 8738 | 8743 | // 2. Stat the fd and check if it isn't a symbolic link. |
| 8739 | | // 3. Generate the procfs reference to the fd via `/proc/self/fd/{fd}`. |
| 8740 | | // 4. Pass the procfs path to `chmod` with the `mode`. |
| 8744 | // 3. Generate the devfs reference to the fd via `/dev/fd/{fd}`. |
| 8745 | // 4. Pass the devfs path to `chmod` with the `mode`. |
| 8741 | 8746 | const path_fd: posix.fd_t = fd: { |
| 8742 | 8747 | const syscall: Syscall = try .start(); |
| 8743 | 8748 | while (true) { |
| ... | ... | @@ -8808,11 +8813,11 @@ fn fchmodatFallback( |
| 8808 | 8813 | if ((path_mode & posix.S.IFMT) == posix.S.IFLNK) |
| 8809 | 8814 | return error.OperationUnsupported; |
| 8810 | 8815 | |
| 8811 | | var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; |
| 8812 | | const proc_path = std.mem.printSentinel(&procfs_buf, "/proc/self/fd/{d}", .{path_fd}, 0) catch unreachable; |
| 8816 | var dev_buf: [std.fmt.count("/dev/fd/{d}\x00", .{std.math.minInt(posix.fd_t)})]u8 = undefined; |
| 8817 | const dev_path = std.mem.printSentinel(&dev_buf, "/dev/fd/{d}", .{path_fd}, 0) catch unreachable; |
| 8813 | 8818 | const syscall: Syscall = try .start(); |
| 8814 | 8819 | while (true) { |
| 8815 | | switch (posix.errno(posix.system.chmod(proc_path, mode))) { |
| 8820 | switch (posix.errno(posix.system.chmod(dev_path, mode))) { |
| 8816 | 8821 | .SUCCESS => return syscall.finish(), |
| 8817 | 8822 | .INTR => { |
| 8818 | 8823 | try syscall.checkCancel(); |
| ... | ... | @@ -8821,7 +8826,7 @@ fn fchmodatFallback( |
| 8821 | 8826 | else => |e| { |
| 8822 | 8827 | syscall.finish(); |
| 8823 | 8828 | switch (e) { |
| 8824 | | .NOENT => return error.OperationUnsupported, // procfs not mounted. |
| 8829 | .NOENT => return error.OperationUnsupported, // devfs not mounted. |
| 8825 | 8830 | .BADF => |err| return errnoBug(err), |
| 8826 | 8831 | .FAULT => |err| return errnoBug(err), |
| 8827 | 8832 | .INVAL => |err| return errnoBug(err), |
| ... | ... | @@ -17446,9 +17451,6 @@ pub fn posixExecveat( |
| 17446 | 17451 | ) process.ReplaceError { |
| 17447 | 17452 | try Thread.checkCancel(); |
| 17448 | 17453 | switch (err: { |
| 17449 | | if (path) |p| if (dir == posix.AT.FDCWD or Dir.path.isAbsoluteZ(p)) { |
| 17450 | | break :err posix.errno(posix.system.execve(p, argv, env_block.slice.ptr)); |
| 17451 | | }; |
| 17452 | 17454 | if (comptime native_os == .linux and (!builtin.link_libc or |
| 17453 | 17455 | (builtin.target.isGnuLibC() and builtin.target.os.version_range.linux.glibc.order( |
| 17454 | 17456 | .{ .major = 2, .minor = 34, .patch = 0 }, |
| ... | ... | @@ -17462,34 +17464,57 @@ pub fn posixExecveat( |
| 17462 | 17464 | .NOSYS => {}, |
| 17463 | 17465 | } |
| 17464 | 17466 | } |
| 17465 | | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 17466 | | var path_len = realPathPosix(dir, &path_buffer) catch |err| switch (err) { |
| 17467 | | else => |e| return e, |
| 17468 | | error.InputOutput, |
| 17469 | | error.FileTooBig, |
| 17470 | | error.NoSpaceLeft, |
| 17471 | | error.PathAlreadyExists, |
| 17472 | | error.SymLinkLoop, |
| 17473 | | error.NetworkNotFound, |
| 17474 | | error.PipeBusy, |
| 17475 | | error.AntivirusInterference, |
| 17476 | | => return error.FileNotFound, |
| 17477 | | error.DeviceBusy, |
| 17478 | | error.NoDevice, |
| 17479 | | error.UnrecognizedVolume, |
| 17480 | | => return error.FileSystem, |
| 17467 | if (path) |p| if (dir == posix.AT.FDCWD or Dir.path.isAbsoluteZ(p)) { |
| 17468 | break :err posix.errno(posix.system.execve(p, argv, env_block.slice.ptr)); |
| 17481 | 17469 | }; |
| 17482 | | if (path) |p| { |
| 17483 | | const path_slice = std.mem.span(p); |
| 17484 | | path_buffer[path_len] = Dir.path.sep; |
| 17485 | | path_len += 1; |
| 17486 | | @memcpy(path_buffer[path_len..][0..path_slice.len], path_slice); |
| 17487 | | path_len += path_slice.len; |
| 17488 | | } |
| 17489 | | path_buffer[path_len] = 0; |
| 17490 | | break :err posix.errno( |
| 17491 | | posix.system.execve(path_buffer[0..path_len :0], argv, env_block.slice.ptr), |
| 17492 | | ); |
| 17470 | const exe: posix.fd_t = if (path) |p| exe: { |
| 17471 | var flags: posix.O = .{}; |
| 17472 | if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; |
| 17473 | if (@hasField(posix.O, "LARGEFILE")) flags.LARGEFILE = true; |
| 17474 | if (@hasField(posix.O, "NOCTTY")) flags.NOCTTY = true; |
| 17475 | if (@hasField(posix.O, "PATH")) flags.PATH = true; |
| 17476 | if (@hasField(posix.O, "EXEC")) flags.EXEC = true; |
| 17477 | const rc = openat_sym(dir, p, flags, @as(posix.mode_t, 0)); |
| 17478 | while (true) switch (posix.errno(rc)) { |
| 17479 | .SUCCESS => break :exe @intCast(rc), |
| 17480 | .INTR, .AGAIN => {}, |
| 17481 | .FAULT => |err| return errnoBug(err), |
| 17482 | .INVAL => return error.BadPathName, |
| 17483 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| 17484 | .ACCES => return error.AccessDenied, |
| 17485 | .FBIG => return error.InvalidExe, |
| 17486 | .OVERFLOW => return error.InvalidExe, |
| 17487 | .ISDIR => return error.IsDir, |
| 17488 | .LOOP => return error.InvalidExe, |
| 17489 | .MFILE => return error.ProcessFdQuotaExceeded, |
| 17490 | .NAMETOOLONG => return error.NameTooLong, |
| 17491 | .NFILE => return error.SystemFdQuotaExceeded, |
| 17492 | .NODEV => return error.FileSystem, |
| 17493 | .NOENT => return error.FileNotFound, |
| 17494 | .SRCH => return error.FileNotFound, // Linux when opening procfs files. |
| 17495 | .NOMEM => return error.SystemResources, |
| 17496 | .NOTDIR => return error.NotDir, |
| 17497 | .PERM => return error.PermissionDenied, |
| 17498 | .BUSY => return error.FileSystem, |
| 17499 | .TXTBSY => return error.FileBusy, |
| 17500 | .NXIO => return error.FileSystem, |
| 17501 | .ILSEQ => return error.BadPathName, |
| 17502 | else => |err| return posix.unexpectedErrno(err), |
| 17503 | }; |
| 17504 | } else dir; |
| 17505 | defer closeFd(exe); |
| 17506 | if (builtin.link_libc and @TypeOf(posix.system.fexecve) != void) { |
| 17507 | break :err posix.errno(posix.system.fexecve(exe, argv, env_block.slice.ptr)); |
| 17508 | } |
| 17509 | switch (native_os) { |
| 17510 | else => return error.OperationUnsupported, |
| 17511 | .linux, .serenity, .illumos => { |
| 17512 | var proc_buf: [std.fmt.count("/proc/self/path/{d}\x00", .{std.math.minInt(posix.fd_t)})]u8 = undefined; |
| 17513 | const template = if (native_os == .illumos) "/proc/self/path/{d}" else "/proc/self/fd/{d}"; |
| 17514 | const proc_path = std.mem.printSentinel(&proc_buf, template, .{exe}, 0) catch unreachable; |
| 17515 | break :err posix.errno(posix.system.execve(proc_path, argv, env_block.slice.ptr)); |
| 17516 | }, |
| 17517 | } |
| 17493 | 17518 | }) { |
| 17494 | 17519 | .FAULT => |err| return errnoBug(err), // Bad pointer parameter. |
| 17495 | 17520 | .@"2BIG" => return error.SystemResources, |