linux-sysprog · beginner · ~20 min
Compute the right slice offset; bound-check the copy.
Copy the last few bytes of a buffer into an output buffer — the byte-level core of the tail command — while staying within the output's capacity.
Implement size_t tail_bytes(const char *buf, size_t n, char *out, size_t cap, size_t want) that copies the trailing portion of buf into out.
buf, n: the source buffer and its length.out, cap: the destination buffer and its capacity (including room for the NUL).want: how many trailing bytes are requested.Copies the last want bytes of buf (or all n bytes if want > n) into out, capped at cap - 1 bytes, then NUL-terminates out. Returns the number of bytes actually copied.
tail_bytes("abcdefghij", 10, out, 16, 4) -> 4, out = "ghij"
tail_bytes("abc", 3, out, 16, 100) -> 3, out = "abc" (want > n)
tail_bytes("xyz", 3, out, 2, 5) -> 1, out = "z" (capped to cap-1)
tail_bytes("ignored", 7, out, 16, 0) -> 0, out = ""
want == 0: copies nothing, out is the empty string.want > n: copies the whole buffer.cap == 1: only the NUL fits, returns 0.out. Beware unsigned underflow when computing the start offset.tail is fundamental to log viewing. The byte-mode kernel is just 'last N bytes' — and 'last N lines' is built on top of it.
Source buf of length n, destination out of capacity cap, and the requested trailing byte count want.
Copies the last want bytes (or all of buf if want > n), capped at cap-1, NUL-terminated; returns bytes copied.
want > n copies the whole buffer; want == 0 copies nothing. Always NUL-terminate. No allocations.
#include <stddef.h>
size_t tail_bytes(const char *buf, size_t n, char *out, size_t cap, size_t want) { /* TODO */ return 0; }
Computing start = n - want when want > n → underflow on size_t; not reserving the NUL byte in cap.
want == 0 → out is empty string. want > n → copy entire buf. cap == 1 → only NUL fits.
O(want).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.