ls: new zig API (PR incoming!).

master
Philippe Pittoli 2022-05-06 00:48:42 +02:00
parent d046fe6180
commit 15f1dab417
1 changed files with 9 additions and 128 deletions

View File

@ -46,118 +46,7 @@ const Options = struct {
var options: Options = Options {}; var options: Options = Options {};
fn print_stats(fpath: []const u8, stats: std.fs.File.Stat) void { fn print_stats(fpath: []const u8, stats: os.system.Stat) !void {
// lib.print("FS STATS: {}\n", .{stats});
// print kind (directory, file, pipe, etc.)
switch (stats.kind) {
.File => lib.print("-", .{}),
.Directory => lib.print("d", .{}),
.CharacterDevice => lib.print("c", .{}),
.BlockDevice => lib.print("b", .{}),
.NamedPipe => lib.print("p", .{}),
.SymLink => lib.print("s", .{}),
.UnixDomainSocket => lib.print("s", .{}),
else => {
if (builtin.os.tag == .solaris) switch (stats.kind) {
.Door => lib.print("D", .{}), // TODO: what to print here?
.EventPort => lib.print("e", .{}), // TODO: what to print here?
else => lib.print("?", .{}),
};
},
}
// print rights
const perms = PermissionsUnix.unixNew(stats.mode);
const classes = [_]PermissionsUnix.Class {
PermissionsUnix.Class.user,
PermissionsUnix.Class.group,
PermissionsUnix.Class.other
};
const rights = [_]PermissionsUnix.Permission {
PermissionsUnix.Permission.read,
PermissionsUnix.Permission.write,
PermissionsUnix.Permission.execute
};
for (classes) |c| {
for (rights) |r| {
if (perms.unixHas(c,r)) {
switch(r) {
.read => lib.print("r", .{}),
.write => lib.print("w", .{}),
.execute => lib.print("x", .{}),
}
}
else {
lib.print("-", .{});
}
}
}
// TODO: print user & group
// TODO: print size
// TODO: print date last write
// lib.print("{s}: {}\n", .{fpath, stats});
return lib.print(" {s}\n", .{fpath});
}
fn fs_kind_from_linux_stat (st: std.os.linux.Stat) Kind {
const kind: Kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) {
.BLOCK_DEVICE => Kind.BlockDevice,
.CHARACTER_DEVICE => Kind.CharacterDevice,
.DIRECTORY => Kind.Directory,
.SYMBOLIC_LINK => Kind.SymLink,
.REGULAR_FILE => Kind.File,
.SOCKET_STREAM, .SOCKET_DGRAM => Kind.UnixDomainSocket,
else => Kind.Unknown,
} else blk: {
const m = st.mode & os.S.IFMT;
switch (m) {
os.S.IFBLK => break :blk Kind.BlockDevice,
os.S.IFCHR => break :blk Kind.CharacterDevice,
os.S.IFDIR => break :blk Kind.Directory,
os.S.IFIFO => break :blk Kind.NamedPipe,
os.S.IFLNK => break :blk Kind.SymLink,
os.S.IFREG => break :blk Kind.File,
os.S.IFSOCK => break :blk Kind.UnixDomainSocket,
else => {},
}
if (builtin.os.tag == .solaris) switch (m) {
os.S.IFDOOR => break :blk Kind.Door,
os.S.IFPORT => break :blk Kind.EventPort,
else => {},
};
break :blk .Unknown;
};
return kind;
}
// mode = type (directory, file, symlink, etc.) + rights
pub fn linuxstat_to_fsstat(st: std.os.linux.Stat) std.fs.File.StatError!std.fs.File.Stat {
// lib.print("LINUX STATS: {}\n", .{st});
const atime = st.atime();
const mtime = st.mtime();
const ctime = st.ctime();
const kind = fs_kind_from_linux_stat (st);
const stats = std.fs.File.Stat{
.inode = st.ino,
.size = @bitCast(u64, st.size),
.mode = st.mode,
.kind = kind,
.atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
.mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
.ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
};
// lib.print("{}\n", .{stats});
return stats;
}
fn print_linux_stats (fpath: []const u8, stats: std.os.linux.Stat) !void {
var buffer = [_]u8 {0} ** (std.fs.MAX_PATH_BYTES + 100); var buffer = [_]u8 {0} ** (std.fs.MAX_PATH_BYTES + 100);
// var it: u16 = 0; // var it: u16 = 0;
var fbs = std.io.fixedBufferStream(&buffer); var fbs = std.io.fixedBufferStream(&buffer);
@ -168,7 +57,7 @@ fn print_linux_stats (fpath: []const u8, stats: std.os.linux.Stat) !void {
// fbs.reset(); // fbs.reset();
// print kind (directory, file, pipe, etc.) // print kind (directory, file, pipe, etc.)
const kind = fs_kind_from_linux_stat(stats); const kind = fs.File.Stat.system_stat_kind_to_fs_kind(stats);
switch (kind) { switch (kind) {
.File => try fmt.formatType('-', "c", fmtopts, writer, depth), .File => try fmt.formatType('-', "c", fmtopts, writer, depth),
.Directory => try fmt.formatType('d', "c", fmtopts, writer, depth), .Directory => try fmt.formatType('d', "c", fmtopts, writer, depth),
@ -229,10 +118,15 @@ fn print_linux_stats (fpath: []const u8, stats: std.os.linux.Stat) !void {
try fmt.formatType(fpath, "s", fmtopts, writer, depth); try fmt.formatType(fpath, "s", fmtopts, writer, depth);
try fmt.formatType('\n', "c", fmtopts, writer, depth); try fmt.formatType('\n', "c", fmtopts, writer, depth);
// TODO: print user & group
// TODO: print size
// TODO: print date last write
// lib.print("{s}: {}\n", .{fpath, stats});
return lib.print("{s}", .{fbs.getWritten()}); return lib.print("{s}", .{fbs.getWritten()});
} }
fn print_file (fpath: []const u8) !void { fn print_file (fpath: []const u8) !void {
if (options.verbose == false) { if (options.verbose == false) {
return lib.print("{s}\n", .{fpath}); return lib.print("{s}\n", .{fpath});
@ -271,20 +165,7 @@ fn print_file_in_dir (dir: fs.Dir, entryname: []const u8) !void {
return lib.print("{s}\n", .{entryname}); return lib.print("{s}\n", .{entryname});
} }
const stats = statFile(dir, entryname); return try print_stats (entryname, try dir.fstatat(entryname));
// return print_stats (entryname, try linuxstat_to_fsstat(stats));
return try print_linux_stats (entryname, stats);
}
// TODO: improve this to use the fstatat syscall instead of making 2 syscalls here.
pub fn statFile(self: fs.Dir, sub_path: []const u8) std.os.linux.Stat {
var stat: std.os.linux.Stat = undefined;
var t = [_:0]u8{0} ** std.fs.MAX_PATH_BYTES;
std.mem.copy (u8, t[0..], sub_path);
var p = t[0..sub_path.len+1:0]; // add a final \0 at the end of the string, and make the type checker happy
_ = std.os.linux.fstatat(self.fd, p, &stat, 0); // returns usize
return stat;
} }
// Either print directory's content or file. // Either print directory's content or file.