| git.druid.rocks | index | druid520 | kaboom | src/ | user/ | cat.nsc |
src/user/cat.nsc
include "syscalls.nsh";
include "lib.nsh";
include "string.nsh";
include "stdio.nsh";
/* one arg -- kfs_resolve (by way of fd_open, kernel-side) handles a
* bare name, a relative path, or an absolute one, so "cat file",
* "cat doc/x" and "cat /doc/x" all work the same way. the whole file
* is read in one go by stdio.nsc's read_all, into a buffer sized to
* the real file (sys_fsize) -- no fixed cap. this used to be one
* 63488-byte sys_read (kfs's old max file size), which silently cut
* off anything bigger once kfs grew double indirection.
*
* the buffer is sys_alloc'd (inside read_all), not a global array
* or a stack local: kaboom's single shared 64kib stack (see boot.s)
* has no room for a big buffer sitting in any one frame, and a
* global array would exist in every cat process's own .bss whether
* or not it's ever run -- the whole point of building an arena
* allocator (see alloc.nsc) was to stop reaching for a fixed-size
* buffer for something that's really "give me some memory, once, at
* runtime". */
global i32
main(i32 argc, ptr argv)
{
ptr fname;
u64 fname_len;
i32 fd;
i64 n;
ptr buf;
if(argc < 2)
{
fputs(2, "usage: cat file\n");
return 1;
}
fname = argv_get(argv, 1);
fname_len = strlen(fname);
fd = sys_open(fname, fname_len);
if(fd < 0)
{
print_err(2, "cat", "file not found");
return 1;
}
buf = read_all(fd, &n);
sys_close(fd);
if(buf == (ptr)0)
{
print_err(2, "cat", "read failed");
return 1;
}
sys_write(1, buf, (u64)n);
return 0;
}