authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-13 23:56:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-13 23:56:32-07:00
log09074d7cd7ab76ebf87cb303825ce53834bcc532
treec2330896b9f461b58c7343704778db73a68ff640
parent01cc904fc7c10bd58a7eaf17e63126f9cc63922c

std.os: proper use of inline

Uses `inline` only to forward the comptime-ness of the flags parameter to function selection. Also fixes doc comments in std.c.versionCheck.

2 files changed, 23 insertions(+), 17 deletions(-)

lib/std/c.zig+4-4
...@@ -5,10 +5,10 @@ const page_size = std.mem.page_size;...@@ -5,10 +5,10 @@ const page_size = std.mem.page_size;
5const iovec = std.os.iovec;5const iovec = std.os.iovec;
6const iovec_const = std.os.iovec_const;6const iovec_const = std.os.iovec_const;
77
8/// If not linking libc, returns struct{pub const ok = false;}8/// If not linking libc, returns false.
9/// If linking musl libc, returns struct{pub const ok = true;}9/// If linking musl libc, returns true.
10/// If linking gnu libc (glibc), the `ok` value will be true if the target10/// If linking gnu libc (glibc), returns true if the target version is greater
11/// version is greater than or equal to `glibc_version`.11/// than or equal to `glibc_version`.
12/// If linking a libc other than these, returns `false`.12/// If linking a libc other than these, returns `false`.
13pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool {13pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool {
14 return comptime blk: {14 return comptime blk: {
lib/std/os.zig+19-13
...@@ -351,7 +351,6 @@ const FChmodAtError = FChmodError || error{...@@ -351,7 +351,6 @@ const FChmodAtError = FChmodError || error{
351 /// A component of `path` exceeded `NAME_MAX`, or the entire path exceeded351 /// A component of `path` exceeded `NAME_MAX`, or the entire path exceeded
352 /// `PATH_MAX`.352 /// `PATH_MAX`.
353 NameTooLong,353 NameTooLong,
354
355 /// `path` resolves to a symbolic link, and `AT.SYMLINK_NOFOLLOW` was set354 /// `path` resolves to a symbolic link, and `AT.SYMLINK_NOFOLLOW` was set
356 /// in `flags`. This error only occurs on Linux, where changing the mode of355 /// in `flags`. This error only occurs on Linux, where changing the mode of
357 /// a symbolic link has no meaning and can cause undefined behaviour on356 /// a symbolic link has no meaning and can cause undefined behaviour on
...@@ -359,23 +358,15 @@ const FChmodAtError = FChmodError || error{...@@ -359,23 +358,15 @@ const FChmodAtError = FChmodError || error{
359 ///358 ///
360 /// The procfs fallback was used but procfs was not mounted.359 /// The procfs fallback was used but procfs was not mounted.
361 OperationNotSupported,360 OperationNotSupported,
362
363 /// The procfs fallback was used but the process exceeded its open file361 /// The procfs fallback was used but the process exceeded its open file
364 /// limit.362 /// limit.
365 ProcessFdQuotaExceeded,363 ProcessFdQuotaExceeded,
366
367 /// The procfs fallback was used but the system exceeded it open file limit.364 /// The procfs fallback was used but the system exceeded it open file limit.
368 SystemFdQuotaExceeded,365 SystemFdQuotaExceeded,
369};366};
370367
371var has_fchmodat2_syscall = std.atomic.Value(bool).init(true);368var has_fchmodat2_syscall = std.atomic.Value(bool).init(true);
372369
373inline fn skipFchmodatFallback(flags: u32) bool {
374 return builtin.os.tag != .linux or
375 flags == 0 or
376 std.c.versionCheck(std.SemanticVersion{ .major = 2, .minor = 32, .patch = 0 }).ok;
377}
378
379/// Changes the `mode` of `path` relative to the directory referred to by370/// Changes the `mode` of `path` relative to the directory referred to by
380/// `dirfd`. The process must have the correct privileges in order to do this371/// `dirfd`. The process must have the correct privileges in order to do this
381/// successfully, or must have the effective user ID matching the owner of the372/// successfully, or must have the effective user ID matching the owner of the
...@@ -394,11 +385,23 @@ inline fn skipFchmodatFallback(flags: u32) bool {...@@ -394,11 +385,23 @@ inline fn skipFchmodatFallback(flags: u32) bool {
394pub inline fn fchmodat(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtError!void {385pub inline fn fchmodat(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtError!void {
395 if (!std.fs.has_executable_bit) @compileError("fchmodat unsupported by target OS");386 if (!std.fs.has_executable_bit) @compileError("fchmodat unsupported by target OS");
396387
397 const path_c = try toPosixPath(path);
398
399 // No special handling for linux is needed if we can use the libc fallback388 // No special handling for linux is needed if we can use the libc fallback
400 // or `flags` is empty. Glibc only added the fallback in 2.32.389 // or `flags` is empty. Glibc only added the fallback in 2.32.
401 while (skipFchmodatFallback(flags)) {390 const skip_fchmodat_fallback = builtin.os.tag != .linux or
391 std.c.versionCheck(.{ .major = 2, .minor = 32, .patch = 0 }) or
392 flags == 0;
393
394 // This function is marked inline so that when flags is comptime-known,
395 // skip_fchmodat_fallback will be comptime-known true.
396 if (skip_fchmodat_fallback)
397 return fchmodat1(dirfd, path, mode, flags);
398
399 return fchmodat2(dirfd, path, mode, flags);
400}
401
402fn fchmodat1(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtError!void {
403 const path_c = try toPosixPath(path);
404 while (true) {
402 const res = system.fchmodat(dirfd, &path_c, mode, flags);405 const res = system.fchmodat(dirfd, &path_c, mode, flags);
403 switch (system.getErrno(res)) {406 switch (system.getErrno(res)) {
404 .SUCCESS => return,407 .SUCCESS => return,
...@@ -421,8 +424,11 @@ pub inline fn fchmodat(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32)...@@ -421,8 +424,11 @@ pub inline fn fchmodat(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32)
421 else => |err| return unexpectedErrno(err),424 else => |err| return unexpectedErrno(err),
422 }425 }
423 }426 }
427}
424428
425 const use_fchmodat2 = (comptime builtin.os.isAtLeast(.linux, .{ .major = 6, .minor = 6, .patch = 0 }) orelse false) and429fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtError!void {
430 const path_c = try toPosixPath(path);
431 const use_fchmodat2 = (builtin.os.isAtLeast(.linux, .{ .major = 6, .minor = 6, .patch = 0 }) orelse false) and
426 has_fchmodat2_syscall.load(.Monotonic);432 has_fchmodat2_syscall.load(.Monotonic);
427 while (use_fchmodat2) {433 while (use_fchmodat2) {
428 // Later on this should be changed to `system.fchmodat2`434 // Later on this should be changed to `system.fchmodat2`