Flash 65 lines
// cp — copy SRC to DST for /bin/cp.
//
// cp SRC DST
//
// Opens SRC read-only, creates DST (a fresh writable file via SYS_CREATE),
// and streams SRC's bytes into it in 512-byte chunks. DST must not already
// exist (create fails closed on a name collision — no clobber); SRC and DST
// are files, and DST's name must fit 8.3 (the create syscall rejects a longer
// one). Errors print a diagnostic to fd 2 and exit.
//
// The first consumer of SYS_CREATE: it is what exercises the create -> write
// -> persist path end to end (the acceptance loop copies a file, reboots, and
// reads it back). Same coreutil recipe as cat: flibc _start shim, flibc_mem,
// stack buffer only.
use flibc
link "flibc_start"
link "flibc_mem"
const BUF_LEN usize = 512
fn diag(msg []u8) {
_ = flibc.sys.write_fd(2, msg.ptr, msg.len)
}
export fn main(argc usize, argv argv) noreturn {
if argc < 3 {
diag("usage: cp SRC DST\n")
flibc.exit()
}
const src = argv[1] orelse flibc.exit()
const dst = argv[2] orelse flibc.exit()
const sfd = flibc.sys.open(src)
if sfd < 0 {
diag("cp: cannot open source\n")
flibc.exit()
}
const dfd = flibc.sys.create(dst)
if dfd < 0 {
diag("cp: cannot create destination\n")
_ = flibc.sys.close(sfd)
flibc.exit()
}
var buf [BUF_LEN]u8 = undefined
while true {
n := flibc.sys.read(sfd, &buf, buf.len)
if n <= 0 {
break
}
// FAT32 write() pushes the whole chunk in one call; a short write is
// therefore an error (ENOSPC / fault), not a partial that needs a
// retry loop.
if flibc.sys.write_fd(dfd, &buf, #intCast(n)) != n {
diag("cp: write error\n")
break
}
}
_ = flibc.sys.close(sfd)
_ = flibc.sys.close(dfd)
flibc.exit()
}