| git.druid.rocks | index | druid520 | kaboom | src/ | user/ | ls.nsc |
src/user/ls.nsc
include "syscalls.nsh";
include "lib.nsh";
include "string.nsh";
include "stdio.nsh";
void
print_names(ptr names, i32 count)
{
i32 i;
ptr entry;
i = 0;
while(i < count)
{
/* puts, not a hand-rolled 24-byte-capped length scan -- safe
* because every kfs dirent name is guaranteed null-terminated
* within its 24-byte field (kfs_name_matches on the kernel
* side refuses any name over 23 bytes in the first place), so
* puts's own byte-at-a-time scan for the terminator never
* reads into the next entry. */
entry = names + (u64)i * (u64)24;
puts(entry);
putchar((u8)10);
i = i + 1;
}
}
/* with no argument, lists the cwd (the only thing this ever did
* before). with one, "ls name" or "ls /a/b" -- resolves the argument
* as a real path (kfs_resolve, by way of sys_stat/sys_listdir_path,
* handles both a bare relative name and a real multi-component or
* absolute path) and either lists it (a directory) or just prints
* its own name back (a file, matching real ls's own behavior on a
* file argument). "ls doc" (a subdirectory of cwd) previously did
* nothing useful at all -- this argument handling never existed. */
global i32
main(i32 argc, ptr argv)
{
i8 names[1536]; /* 64 entries * 24 bytes -- directories can chain
* past 15 entries/block now (see kfs.nsc's
* kfs_dir_next_block), so 16 stopped being a
* real ceiling the moment /bin itself grew past
* it. 64 is comfortably past anything real yet. */
i32 count;
ptr path;
u64 path_len;
i64 kind;
if(argc < 2)
{
count = sys_listdir(&names[0], 64);
if(count < 0)
{
print_err(2, "ls", "listing failed");
return 1;
}
print_names(&names[0], count);
stdio_flush();
return 0;
}
path = argv_get(argv, 1);
path_len = strlen(path);
kind = sys_stat(path, path_len);
if(kind == (i64)1) /* a file: print its own name, like real ls */
{
puts(path);
putchar((u8)10);
stdio_flush();
return 0;
}
if(kind == (i64)2) /* a directory: list it */
{
count = sys_listdir_path(path, path_len, &names[0], 64);
if(count < 0)
{
print_err(2, "ls", "listing failed");
return 1;
}
print_names(&names[0], count);
stdio_flush();
return 0;
}
print_err(2, "ls", "not found");
return 1;
}