authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2023-07-08 09:17:28-04:00
committergravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2023-08-02 17:39:52-04:00
logb9aa1dcaf1a905682ee4da6b9c37626ed2a552a6
treedc32e96fd947205d49c7e303b01738266303a2c2
parent6293a646e33d2cfe064d4475f42f7d77a3831cf4

plan 9: filesystem support


3 files changed, 74 insertions(+), 24 deletions(-)

lib/std/fs.zig+6-4
......@@ -39,7 +39,7 @@ pub const Watch = @import("fs/watch.zig").Watch;
3939/// fit into a UTF-8 encoded array of this length.
4040/// The byte count includes room for a null sentinel byte.
4141pub const MAX_PATH_BYTES = switch (builtin.os.tag) {
42 .linux, .macos, .ios, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .solaris => os.PATH_MAX,
42 .linux, .macos, .ios, .freebsd, .openbsd, .netbsd, .dragonfly, .haiku, .solaris, .plan9 => os.PATH_MAX,
4343 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
4444 // If it would require 4 UTF-8 bytes, then there would be a surrogate
4545 // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
......@@ -1160,7 +1160,9 @@ pub const Dir = struct {
11601160 return self.openFileW(path_w.span(), flags);
11611161 }
11621162
1163 var os_flags: u32 = os.O.CLOEXEC;
1163 var os_flags: u32 = 0;
1164 if (@hasDecl(os.O, "CLOEXEC")) os_flags = os.O.CLOEXEC;
1165
11641166 // Use the O locking flags if the os supports them to acquire the lock
11651167 // atomically.
11661168 const has_flock_open_flags = @hasDecl(os.O, "EXLOCK");
......@@ -1180,7 +1182,7 @@ pub const Dir = struct {
11801182 if (@hasDecl(os.O, "LARGEFILE")) {
11811183 os_flags |= os.O.LARGEFILE;
11821184 }
1183 if (!flags.allow_ctty) {
1185 if (@hasDecl(os.O, "NOCTTY") and !flags.allow_ctty) {
11841186 os_flags |= os.O.NOCTTY;
11851187 }
11861188 os_flags |= switch (flags.mode) {
......@@ -1196,7 +1198,7 @@ pub const Dir = struct {
11961198
11971199 // WASI doesn't have os.flock so we intetinally check OS prior to the inner if block
11981200 // since it is not compiltime-known and we need to avoid undefined symbol in Wasm.
1199 if (builtin.target.os.tag != .wasi) {
1201 if (@hasDecl(os.system, "LOCK") and builtin.target.os.tag != .wasi) {
12001202 if (!has_flock_open_flags and flags.lock != .none) {
12011203 // TODO: integrate async I/O
12021204 const lock_nonblocking = if (flags.lock_nonblocking) os.LOCK.NB else @as(i32, 0);
lib/std/os/plan9.zig+60-20
......@@ -1,6 +1,12 @@
11const std = @import("../std.zig");
22const builtin = @import("builtin");
33
4pub const fd_t = i32;
5
6pub const STDIN_FILENO = 0;
7pub const STDOUT_FILENO = 1;
8pub const STDERR_FILENO = 2;
9pub const PATH_MAX = 1023;
410pub const syscall_bits = switch (builtin.cpu.arch) {
511 .x86_64 => @import("plan9/x86_64.zig"),
612 else => @compileError("more plan9 syscall implementations (needs more inline asm in stage2"),
......@@ -57,7 +63,8 @@ pub const SIG = struct {
5763};
5864pub const sigset_t = c_long;
5965pub const empty_sigset = 0;
60pub const siginfo_t = c_long; // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we incude it here to be compatible.
66pub const siginfo_t = c_long;
67// TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we incude it here to be compatible.
6168pub const Sigaction = extern struct {
6269 pub const handler_fn = *const fn (c_int) callconv(.C) void;
6370 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
......@@ -69,6 +76,9 @@ pub const Sigaction = extern struct {
6976 mask: sigset_t,
7077 flags: c_int,
7178};
79pub const AT = struct {
80 pub const FDCWD = -100; // we just make up a constant; FDCWD and openat don't actually exist in plan9
81};
7282// TODO implement sigaction
7383// right now it is just a shim to allow using start.zig code
7484pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize {
......@@ -132,20 +142,47 @@ pub const SYS = enum(usize) {
132142 _NSEC = 53,
133143};
134144
135pub fn pwrite(fd: usize, buf: [*]const u8, count: usize, offset: usize) usize {
136 return syscall_bits.syscall4(.PWRITE, fd, @intFromPtr(buf), count, offset);
145pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
146 return syscall_bits.syscall3(._WRITE, @bitCast(@as(isize, fd)), @intFromPtr(buf), count);
147}
148pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
149 return syscall_bits.syscall4(.PWRITE, @bitCast(@as(isize, fd)), @intFromPtr(buf), count, offset);
137150}
138151
139pub fn pread(fd: usize, buf: [*]const u8, count: usize, offset: usize) usize {
140 return syscall_bits.syscall4(.PREAD, fd, @intFromPtr(buf), count, offset);
152pub fn read(fd: i32, buf: [*]const u8, count: usize) usize {
153 return syscall_bits.syscall3(._READ, @bitCast(@as(isize, fd)), @intFromPtr(buf), count);
154}
155pub fn pread(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
156 return syscall_bits.syscall4(.PREAD, @bitCast(@as(isize, fd)), @intFromPtr(buf), count, offset);
157}
158
159pub fn open(path: [*:0]const u8, omode: mode_t) usize {
160 return syscall_bits.syscall2(.OPEN, @intFromPtr(path), @bitCast(@as(isize, omode)));
161}
162
163pub fn openat(dirfd: i32, path: [*:0]const u8, _: u32, omode: mode_t) usize {
164 if (dirfd == AT.FDCWD) { // openat(AT_FDCWD, ...) == open(...)
165 return open(path, omode);
166 }
167 var dir_path_buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
168 var total_path_buf: [std.fs.MAX_PATH_BYTES + 1]u8 = undefined;
169 const rc = fd2path(dirfd, &dir_path_buf, std.fs.MAX_PATH_BYTES);
170 if (rc != 0) return rc;
171 var fba = std.heap.FixedBufferAllocator.init(&total_path_buf);
172 var alloc = fba.allocator();
173 const dir_path = std.mem.span(@as([*:0]u8, @ptrCast(&dir_path_buf)));
174 const total_path = std.fs.path.join(alloc, &.{ dir_path, std.mem.span(path) }) catch unreachable; // the allocation shouldn't fail because it should not exceed MAX_PATH_BYTES
175 fba.reset();
176 const total_path_z = alloc.dupeZ(u8, total_path) catch unreachable; // should not exceed MAX_PATH_BYTES + 1
177 return open(total_path_z.ptr, omode);
141178}
142179
143pub fn open(path: [*:0]const u8, omode: OpenMode) usize {
144 return syscall_bits.syscall2(.OPEN, @intFromPtr(path), @intFromEnum(omode));
180pub fn fd2path(fd: i32, buf: [*]u8, nbuf: usize) usize {
181 return syscall_bits.syscall3(.FD2PATH, @bitCast(@as(isize, fd)), @intFromPtr(buf), nbuf);
145182}
146183
147pub fn create(path: [*:0]const u8, omode: OpenMode, perms: usize) usize {
148 return syscall_bits.syscall3(.CREATE, @intFromPtr(path), @intFromEnum(omode), perms);
184pub fn create(path: [*:0]const u8, omode: mode_t, perms: usize) usize {
185 return syscall_bits.syscall3(.CREATE, @intFromPtr(path), @bitCast(@as(isize, omode)), perms);
149186}
150187
151188pub fn exit(status: u8) noreturn {
......@@ -163,16 +200,19 @@ pub fn exits(status: ?[*:0]const u8) noreturn {
163200 unreachable;
164201}
165202
166pub fn close(fd: usize) usize {
167 return syscall_bits.syscall1(.CLOSE, fd);
203pub fn close(fd: i32) usize {
204 return syscall_bits.syscall1(.CLOSE, @bitCast(@as(isize, fd)));
168205}
169pub const OpenMode = enum(usize) {
170 OREAD = 0, //* open for read
171 OWRITE = 1, //* write
172 ORDWR = 2, //* read and write
173 OEXEC = 3, //* execute, == read but check execute permission
174 OTRUNC = 16, //* or'ed in (except for exec), truncate file first
175 OCEXEC = 32, //* or'ed in (per file descriptor), close on exec
176 ORCLOSE = 64, //* or'ed in, remove on close
177 OEXCL = 0x1000, //* or'ed in, exclusive create
206pub const mode_t = i32;
207pub const O = struct {
208 pub const READ = 0; // open for read
209 pub const RDONLY = 0;
210 pub const WRITE = 1; // write
211 pub const WRONLY = 1;
212 pub const RDWR = 2; // read and write
213 pub const EXEC = 3; // execute, == read but check execute permission
214 pub const TRUNC = 16; // or'ed in (except for exec), truncate file first
215 pub const CEXEC = 32; // or'ed in (per file descriptor), close on exec
216 pub const RCLOSE = 64; // or'ed in, remove on close
217 pub const EXCL = 0x1000; // or'ed in, exclusive create
178218};
lib/std/os/plan9/errno.zig+8
......@@ -73,4 +73,12 @@ pub const E = enum(u16) {
7373 // These added in 1003.1b-1993
7474 CANCELED = 61,
7575 INPROGRESS = 62,
76
77 // We just add these to be compatible with std.os, which uses them,
78 // They should never get used.
79 DQUOT,
80 CONNRESET,
81 OVERFLOW,
82 LOOP,
83 TXTBSY,
7684};