linux-sysprog · beginner · ~20 min

Return the last N bytes of a buffer (tail)

Compute the right slice offset; bound-check the copy.

Challenge

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.

Task

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.

Input

  • 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.

Output

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.

Example

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 = ""

Edge cases

  • want == 0: copies nothing, out is the empty string.
  • want > n: copies the whole buffer.
  • cap == 1: only the NUL fits, returns 0.

Rules

  • Always NUL-terminate out. Beware unsigned underflow when computing the start offset.

Why this matters

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.

Input format

Source buf of length n, destination out of capacity cap, and the requested trailing byte count want.

Output format

Copies the last want bytes (or all of buf if want > n), capped at cap-1, NUL-terminated; returns bytes copied.

Constraints

want > n copies the whole buffer; want == 0 copies nothing. Always NUL-terminate. No allocations.

Starter code

#include <stddef.h>
size_t tail_bytes(const char *buf, size_t n, char *out, size_t cap, size_t want) { /* TODO */ return 0; }

Common mistakes

Computing start = n - want when want > n → underflow on size_t; not reserving the NUL byte in cap.

Edge cases to handle

want == 0 → out is empty string. want > n → copy entire buf. cap == 1 → only NUL fits.

Complexity

O(want).

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.