@@ -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+
5154pub const AF = system .AF ;
5255pub const AF_SUN = system .AF_SUN ;
5356pub const AI = system .AI ;
@@ -102,7 +105,35 @@ pub const STDIN_FILENO = system.STDIN_FILENO;
102105pub const STDOUT_FILENO = system .STDOUT_FILENO ;
103106pub const SYS = system .SYS ;
104107pub 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 ;
106137pub const T = system .T ;
107138pub const TCP = system .TCP ;
108139pub 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`.
43494436pub 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