@@ -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 ARCH = system .ARCH ;
@@ -103,7 +106,35 @@ pub const STDIN_FILENO = system.STDIN_FILENO;
103106pub const STDOUT_FILENO = system .STDOUT_FILENO ;
104107pub const SYS = system .SYS ;
105108pub const Sigaction = system .Sigaction ;
106- pub const Stat = system .Stat ;
109+ pub const Stat = if (no_stat ) struct {
110+ // The system does not have a native stat structure. Make one up.
111+
112+ dev : dev_t ,
113+ ino : ino_t ,
114+ mode : mode_t ,
115+ nlink : nlink_t ,
116+ uid : uid_t ,
117+ gid : gid_t ,
118+ rdev : dev_t ,
119+ size : off_t ,
120+ blksize : blksize_t ,
121+ blocks : blkcnt_t ,
122+ atim : timespec ,
123+ mtim : timespec ,
124+ ctim : timespec ,
125+
126+ pub fn atime (self : @This ()) timespec {
127+ return self .atim ;
128+ }
129+
130+ pub fn mtime (self : @This ()) timespec {
131+ return self .mtim ;
132+ }
133+
134+ pub fn ctime (self : @This ()) timespec {
135+ return self .ctim ;
136+ }
137+ } else system .Stat ;
107138pub const T = system .T ;
108139pub const TCSA = system .TCSA ;
109140pub const TCP = system .TCP ;
@@ -4292,6 +4323,17 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
42924323 @compileError ("fstat is not yet implemented on Windows" );
42934324 }
42944325
4326+ if (no_stat ) {
4327+ return fstatatZ (fd , "\x00 " , AT .EMPTY_PATH ) catch | err | switch (err ) {
4328+ error .FileNotFound ,
4329+ error .NameTooLong ,
4330+ error .InvalidUtf8 ,
4331+ error .SymLinkLoop ,
4332+ = > unreachable ,
4333+ else = > | e | return e ,
4334+ };
4335+ }
4336+
42954337 const fstat_sym = if (lfs64_abi ) system .fstat64 else system .fstat ;
42964338 var stat = mem .zeroes (Stat );
42974339 switch (errno (fstat_sym (fd , & stat ))) {
@@ -4331,6 +4373,46 @@ pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat
43314373 }
43324374}
43334375
4376+ // MKDEV in the kernel.
4377+ inline fn makedevLinux (major : u32 , minor : u32 ) dev_t {
4378+ return (major << 20 ) | minor ;
4379+ }
4380+
4381+ fn fstatatStatxZ (dirfd : fd_t , pathname : [* :0 ]const u8 , stat_buf : * Stat , flags : u32 ) usize {
4382+ var statx = mem .zeroes (linux .Statx );
4383+ const rc = linux .statx (dirfd , pathname , flags | AT .NO_AUTOMOUNT , linux .STATX_BASIC_STATS , & statx );
4384+ const rcs : isize = @bitCast (rc );
4385+
4386+ if (rcs > -4096 ) return rc ;
4387+
4388+ stat_buf .* = .{
4389+ .dev = makedevLinux (statx .dev_major , statx .dev_minor ),
4390+ .rdev = makedevLinux (statx .rdev_major , statx .rdev_minor ),
4391+ .ino = statx .ino ,
4392+ .mode = statx .mode ,
4393+ .nlink = statx .nlink ,
4394+ .uid = statx .uid ,
4395+ .gid = statx .gid ,
4396+ .atim = .{
4397+ .tv_sec = statx .atime .tv_sec ,
4398+ .tv_nsec = statx .atime .tv_nsec ,
4399+ },
4400+ .mtim = .{
4401+ .tv_sec = statx .mtime .tv_sec ,
4402+ .tv_nsec = statx .mtime .tv_nsec ,
4403+ },
4404+ .ctim = .{
4405+ .tv_sec = statx .ctime .tv_sec ,
4406+ .tv_nsec = statx .ctime .tv_nsec ,
4407+ },
4408+ .size = @as (i64 , @intCast (statx .size )),
4409+ .blocks = @as (i64 , @intCast (statx .blocks )),
4410+ .blksize = @as (i32 , @intCast (statx .blksize )),
4411+ };
4412+
4413+ return rc ;
4414+ }
4415+
43344416/// Same as `fstatat` but `pathname` is null-terminated.
43354417/// See also `fstatat`.
43364418pub fn fstatatZ (dirfd : fd_t , pathname : [* :0 ]const u8 , flags : u32 ) FStatAtError ! Stat {
@@ -4341,7 +4423,13 @@ pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!S
43414423 return Stat .fromFilestat (filestat );
43424424 }
43434425
4344- const fstatat_sym = if (lfs64_abi ) system .fstatat64 else system .fstatat ;
4426+ const fstatat_sym = if (no_stat )
4427+ fstatatStatxZ
4428+ else if (lfs64_abi )
4429+ system .fstatat64
4430+ else
4431+ system .fstatat ;
4432+
43454433 var stat = mem .zeroes (Stat );
43464434 switch (errno (fstatat_sym (dirfd , pathname , & stat , flags ))) {
43474435 .SUCCESS = > return stat ,
0 commit comments