1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
//! Code taken from 0.15.2 and `std.fs.file`. See README.md for license and
//! details.
const std = @import("std");
pub const PipeError = error{
SystemFdQuotaExceeded,
ProcessFdQuotaExceeded,
} || std.posix.UnexpectedError;
pub fn close(fd: std.posix.fd_t) void {
switch (std.posix.errno(std.posix.system.close(fd))) {
.BADF => unreachable, // Always a race condition
else => {}, // Includes EINTR, see std.posix source in 0.15.2
}
}
pub fn pipe() PipeError![2]std.posix.fd_t {
var fds: [2]std.posix.fd_t = undefined;
switch (std.posix.errno(std.posix.system.pipe(&fds))) {
.SUCCESS => return fds,
.INVAL => unreachable, // Invalid parameters to pipe()
.FAULT => unreachable, // Invalid fds pointer
.NFILE => return error.SystemFdQuotaExceeded,
.MFILE => return error.ProcessFdQuotaExceeded,
else => |err| return std.posix.unexpectedErrno(err),
}
}
pub fn pipe2(flags: std.posix.O) PipeError![2]std.posix.fd_t {
if (@TypeOf(std.posix.system.pipe2) != void) {
var fds: [2]std.posix.fd_t = undefined;
switch (std.posix.errno(std.posix.system.pipe2(&fds, flags))) {
.SUCCESS => return fds,
.INVAL => unreachable, // Invalid flags
.FAULT => unreachable, // Invalid fds pointer
.NFILE => return error.SystemFdQuotaExceeded,
.MFILE => return error.ProcessFdQuotaExceeded,
else => |err| return std.posix.unexpectedErrno(err),
}
}
const fds: [2]std.posix.fd_t = try pipe();
errdefer {
close(fds[0]);
close(fds[1]);
}
// https://github.com/ziglang/zig/issues/18882
if (@as(u32, @bitCast(flags)) == 0)
return fds;
// CLOEXEC is special, it's a file descriptor flag and must be set using
// F.SETFD.
if (flags.CLOEXEC) {
for (fds) |fd| {
switch (std.posix.errno(std.posix.system.fcntl(fd, std.posix.F.SETFD, @as(u32, std.posix.FD_CLOEXEC)))) {
.SUCCESS => {},
.INVAL => unreachable, // Invalid flags
.BADF => unreachable, // Always a race condition
else => |err| return std.posix.unexpectedErrno(err),
}
}
}
const new_flags: u32 = f: {
var new_flags = flags;
new_flags.CLOEXEC = false;
break :f @bitCast(new_flags);
};
// Set every other flag affecting the file status using F.SETFL.
if (new_flags != 0) {
for (fds) |fd| {
switch (std.posix.errno(std.posix.system.fcntl(fd, std.posix.F.SETFL, new_flags))) {
.SUCCESS => {},
.INVAL => unreachable, // Invalid flags
.BADF => unreachable, // Always a race condition
else => |err| return std.posix.unexpectedErrno(err),
}
}
}
return fds;
}
|