mirror of
https://code.blicky.net/yorhel/ncdu.git
synced 2026-11-03 21:49:42 -09:00
Zig 0.16: use statx(), not stat() on Linux
This commit is contained in:
parent
9103bae106
commit
e447acd83c
1 changed files with 91 additions and 35 deletions
126
src/scan.zig
126
src/scan.zig
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const main = @import("main.zig");
|
||||
const util = @import("util.zig");
|
||||
const model = @import("model.zig");
|
||||
|
|
@ -47,42 +48,97 @@ fn truncate(comptime T: type, comptime field: anytype, x: anytype) std.meta.fiel
|
|||
|
||||
|
||||
pub fn statAt(parent: std.Io.Dir, name: [:0]const u8, follow: bool, symlink: ?*bool) !sink.Stat {
|
||||
// std.posix.fstatatZ() in Zig 0.14 is not suitable due to https://github.com/ziglang/zig/issues/23463
|
||||
var stat: std.c.Stat = undefined;
|
||||
if (std.c.fstatat(parent.fd, name, &stat, if (follow) 0 else std.c.AT.SYMLINK_NOFOLLOW) != 0) {
|
||||
return switch (std.c._errno().*) {
|
||||
@intFromEnum(std.c.E.NOENT) => error.FileNotFound,
|
||||
@intFromEnum(std.c.E.NAMETOOLONG) => error.NameTooLong,
|
||||
@intFromEnum(std.c.E.NOMEM) => error.OutOfMemory,
|
||||
@intFromEnum(std.c.E.ACCES) => error.AccessDenied,
|
||||
else => error.Unexpected,
|
||||
};
|
||||
}
|
||||
if (symlink) |s| s.* = std.c.S.ISLNK(stat.mode);
|
||||
return sink.Stat{
|
||||
.etype =
|
||||
if (std.c.S.ISDIR(stat.mode)) .dir
|
||||
else if (stat.nlink > 1) .link
|
||||
else if (!std.c.S.ISREG(stat.mode)) .nonreg
|
||||
else .reg,
|
||||
.blocks = clamp(sink.Stat, .blocks, stat.blocks),
|
||||
.size = clamp(sink.Stat, .size, stat.size),
|
||||
.dev = truncate(sink.Stat, .dev, stat.dev),
|
||||
.ino = truncate(sink.Stat, .ino, stat.ino),
|
||||
.nlink = clamp(sink.Stat, .nlink, stat.nlink),
|
||||
.ext = .{
|
||||
.pack = .{
|
||||
.hasmtime = true,
|
||||
.hasuid = true,
|
||||
.hasgid = true,
|
||||
.hasmode = true,
|
||||
},
|
||||
.mtime = clamp(model.Ext, .mtime, stat.mtime().sec),
|
||||
.uid = truncate(model.Ext, .uid, stat.uid),
|
||||
.gid = truncate(model.Ext, .gid, stat.gid),
|
||||
.mode = truncate(model.Ext, .mode, stat.mode),
|
||||
switch (builtin.os.tag) {
|
||||
// stat() seems gone for Linux since Zig 0.16.
|
||||
// https://ziglang.org/download/0.16.0/release-notes.html#FileStat-Make-Access-Time-Optional
|
||||
.linux => {
|
||||
var stat: std.os.linux.Statx = undefined;
|
||||
return switch (std.os.linux.errno(std.os.linux.statx(
|
||||
parent.handle,
|
||||
name,
|
||||
std.os.linux.AT.EMPTY_PATH,
|
||||
std.os.linux.STATX{
|
||||
.TYPE = true,
|
||||
.BLOCKS = true,
|
||||
.SIZE = true,
|
||||
.INO = true,
|
||||
.NLINK = true,
|
||||
.UID = true,
|
||||
.GID = true,
|
||||
.MODE = true,
|
||||
.MTIME = true,
|
||||
},
|
||||
&stat,
|
||||
))) {
|
||||
.SUCCESS => sink.Stat{
|
||||
.etype =
|
||||
if (std.os.linux.S.ISDIR(stat.mode)) .dir
|
||||
else if (stat.nlink > 1) .link
|
||||
else if (!std.os.linux.S.ISREG(stat.mode)) .nonreg
|
||||
else .reg,
|
||||
.blocks = @truncate(stat.blocks),
|
||||
.size = stat.size,
|
||||
.dev = stat.dev_major,
|
||||
.ino = stat.ino,
|
||||
.nlink = @truncate(stat.nlink),
|
||||
.ext = .{
|
||||
.pack = .{
|
||||
.hasmtime = true,
|
||||
.hasuid = true,
|
||||
.hasgid = true,
|
||||
.hasmode = true,
|
||||
},
|
||||
.mtime = @intCast(stat.mtime.sec),
|
||||
.uid = stat.uid,
|
||||
.gid = stat.gid,
|
||||
.mode = stat.mode,
|
||||
},
|
||||
},
|
||||
.NOENT => error.FileNotFound,
|
||||
.NAMETOOLONG => error.NameTooLong,
|
||||
.NOMEM => error.OutOfMemory,
|
||||
.ACCES => error.AccessDenied,
|
||||
else => error.Unexpected,
|
||||
};
|
||||
},
|
||||
};
|
||||
else => {
|
||||
var stat: std.c.Stat = undefined;
|
||||
if (std.c.fstatat(parent.fd, name, &stat, if (follow) 0 else std.c.AT.SYMLINK_NOFOLLOW) != 0) {
|
||||
return switch (std.c._errno().*) {
|
||||
@intFromEnum(std.c.E.NOENT) => error.FileNotFound,
|
||||
@intFromEnum(std.c.E.NAMETOOLONG) => error.NameTooLong,
|
||||
@intFromEnum(std.c.E.NOMEM) => error.OutOfMemory,
|
||||
@intFromEnum(std.c.E.ACCES) => error.AccessDenied,
|
||||
else => error.Unexpected,
|
||||
};
|
||||
}
|
||||
if (symlink) |s| s.* = std.c.S.ISLNK(stat.mode);
|
||||
return sink.Stat{
|
||||
.etype =
|
||||
if (std.c.S.ISDIR(stat.mode)) .dir
|
||||
else if (stat.nlink > 1) .link
|
||||
else if (!std.c.S.ISREG(stat.mode)) .nonreg
|
||||
else .reg,
|
||||
.blocks = clamp(sink.Stat, .blocks, stat.blocks),
|
||||
.size = clamp(sink.Stat, .size, stat.size),
|
||||
.dev = truncate(sink.Stat, .dev, stat.dev),
|
||||
.ino = truncate(sink.Stat, .ino, stat.ino),
|
||||
.nlink = clamp(sink.Stat, .nlink, stat.nlink),
|
||||
.ext = .{
|
||||
.pack = .{
|
||||
.hasmtime = true,
|
||||
.hasuid = true,
|
||||
.hasgid = true,
|
||||
.hasmode = true,
|
||||
},
|
||||
.mtime = clamp(model.Ext, .mtime, stat.mtime().sec),
|
||||
.uid = truncate(model.Ext, .uid, stat.uid),
|
||||
.gid = truncate(model.Ext, .gid, stat.gid),
|
||||
.mode = truncate(model.Ext, .mode, stat.mode),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue