Skip to content

Commit 330f65d

Browse files
committed
std.posix: Add riscv32 support.
1 parent c3dda88 commit 330f65d

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

lib/std/posix.zig

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ else switch (native_os) {
4848
else => struct {},
4949
};
5050

51+
// riscv32-linux only has the statx syscall; no fstat or fstatat.
52+
const no_stat = !use_libc and native_os == .linux and builtin.cpu.arch == .riscv32;
53+
5154
pub const AF = system.AF;
5255
pub const AF_SUN = system.AF_SUN;
5356
pub const AI = system.AI;
@@ -102,7 +105,35 @@ pub const STDIN_FILENO = system.STDIN_FILENO;
102105
pub const STDOUT_FILENO = system.STDOUT_FILENO;
103106
pub const SYS = system.SYS;
104107
pub const Sigaction = system.Sigaction;
105-
pub const Stat = system.Stat;
108+
pub const Stat = if (no_stat) struct {
109+
// The system does not have a native stat structure. Make one up.
110+
111+
dev: dev_t,
112+
ino: ino_t,
113+
mode: mode_t,
114+
nlink: nlink_t,
115+
uid: uid_t,
116+
gid: gid_t,
117+
rdev: dev_t,
118+
size: off_t,
119+
blksize: blksize_t,
120+
blocks: blkcnt_t,
121+
atim: timespec,
122+
mtim: timespec,
123+
ctim: timespec,
124+
125+
pub fn atime(self: @This()) timespec {
126+
return self.atim;
127+
}
128+
129+
pub fn mtime(self: @This()) timespec {
130+
return self.mtim;
131+
}
132+
133+
pub fn ctime(self: @This()) timespec {
134+
return self.ctim;
135+
}
136+
} else system.Stat;
106137
pub const T = system.T;
107138
pub const TCP = system.TCP;
108139
pub const VDSO = system.VDSO;
@@ -4305,6 +4336,17 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
43054336
@compileError("fstat is not yet implemented on Windows");
43064337
}
43074338

4339+
if (no_stat) {
4340+
return fstatatZ(fd, "\x00", AT.EMPTY_PATH) catch |err| switch (err) {
4341+
error.FileNotFound,
4342+
error.NameTooLong,
4343+
error.InvalidUtf8,
4344+
error.SymLinkLoop,
4345+
=> unreachable,
4346+
else => |e| return e,
4347+
};
4348+
}
4349+
43084350
const fstat_sym = if (lfs64_abi) system.fstat64 else system.fstat;
43094351
var stat = mem.zeroes(Stat);
43104352
switch (errno(fstat_sym(fd, &stat))) {
@@ -4344,6 +4386,51 @@ pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat
43444386
}
43454387
}
43464388

4389+
// MKDEV in the kernel.
4390+
inline fn makedevLinux(major: u32, minor: u32) dev_t {
4391+
return (major << 20) | minor;
4392+
}
4393+
4394+
// Perform fstatat() by way of statx() for systems that only have the latter (e.g. linux-riscv32).
4395+
// More or less mirrors what glibc and musl do for platforms like this.
4396+
fn fstatatStatxZ(dirfd: fd_t, pathname: [*:0]const u8, stat_buf: *Stat, flags: u32) usize {
4397+
var statx = mem.zeroes(linux.Statx);
4398+
const rc = linux.statx(dirfd, pathname, flags | AT.NO_AUTOMOUNT, linux.STATX_BASIC_STATS, &statx);
4399+
const rcs: isize = @bitCast(rc);
4400+
4401+
if (rcs > -4096) return rc;
4402+
4403+
stat_buf.* = .{
4404+
// Convert device values to the older format.
4405+
.dev = makedevLinux(statx.dev_major, statx.dev_minor),
4406+
.rdev = makedevLinux(statx.rdev_major, statx.rdev_minor),
4407+
.ino = statx.ino,
4408+
.mode = statx.mode,
4409+
.nlink = statx.nlink,
4410+
.uid = statx.uid,
4411+
.gid = statx.gid,
4412+
.atim = .{
4413+
.sec = statx.atime.sec,
4414+
.nsec = statx.atime.nsec,
4415+
},
4416+
.mtim = .{
4417+
.sec = statx.mtime.sec,
4418+
.nsec = statx.mtime.nsec,
4419+
},
4420+
.ctim = .{
4421+
.sec = statx.ctime.sec,
4422+
.nsec = statx.ctime.nsec,
4423+
},
4424+
// Same size, but unsigned -> signed. Hard to imagine these overflowing in practice, and
4425+
// there is not much else we can do. This matches glibc and musl behavior.
4426+
.size = @as(i64, @intCast(statx.size)),
4427+
.blocks = @as(i64, @intCast(statx.blocks)),
4428+
.blksize = @as(i32, @intCast(statx.blksize)),
4429+
};
4430+
4431+
return rc;
4432+
}
4433+
43474434
/// Same as `fstatat` but `pathname` is null-terminated.
43484435
/// See also `fstatat`.
43494436
pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat {
@@ -4354,7 +4441,13 @@ pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!S
43544441
return Stat.fromFilestat(filestat);
43554442
}
43564443

4357-
const fstatat_sym = if (lfs64_abi) system.fstatat64 else system.fstatat;
4444+
const fstatat_sym = if (no_stat)
4445+
fstatatStatxZ
4446+
else if (lfs64_abi)
4447+
system.fstatat64
4448+
else
4449+
system.fstatat;
4450+
43584451
var stat = mem.zeroes(Stat);
43594452
switch (errno(fstatat_sym(dirfd, pathname, &stat, flags))) {
43604453
.SUCCESS => return stat,

0 commit comments

Comments
 (0)