ls: new zig API (PR incoming!).
This commit is contained in:
		
							parent
							
								
									d046fe6180
								
							
						
					
					
						commit
						15f1dab417
					
				
					 1 changed files with 9 additions and 128 deletions
				
			
		
							
								
								
									
										137
									
								
								src/ls.zig
									
										
									
									
									
								
							
							
						
						
									
										137
									
								
								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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue