diff --git a/src/ls.zig b/src/ls.zig index 8a66424..3b119c8 100644 --- a/src/ls.zig +++ b/src/ls.zig @@ -46,118 +46,7 @@ const Options = struct { var options: Options = Options {}; -fn print_stats(fpath: []const u8, stats: std.fs.File.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 { +fn print_stats(fpath: []const u8, stats: os.system.Stat) !void { var buffer = [_]u8 {0} ** (std.fs.MAX_PATH_BYTES + 100); // var it: u16 = 0; 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(); // 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) { .File => try fmt.formatType('-', "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('\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()}); } - fn print_file (fpath: []const u8) !void { if (options.verbose == false) { 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}); } - const stats = statFile(dir, 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; + return try print_stats (entryname, try dir.fstatat(entryname)); } // Either print directory's content or file.