file-handling · intermediate · ~12 min

Read a fixed-size record

Bounds-checked indexing into a fixed-record buffer.

Challenge

Read the Nth fixed-size record from a binary buffer with bounds checking — how databases, MFT entries, and packet logs index their records.

Task

Implement int read_record(const uint8_t *buf, size_t n, size_t recsize, int idx, unsigned char *out) that copies the idx-th recsize-byte record from buf into out.

Input

  • buf: a byte buffer holding back-to-back fixed-size records.
  • n: total number of valid bytes in buf.
  • recsize: size of each record in bytes.
  • idx: 0-based record index to read.
  • out: destination buffer, at least recsize bytes.

Output

Return 0 on success (the record is copied into out). Return -1 if buf/out is NULL, recsize == 0, idx < 0, or the record would run past n.

Example

buf = {0,1,2,3, 4,5,6,7, 8,9,10,11} (three 4-byte records)
read_record(buf, 12, 4, 0, out)   ->   0,  out = {0,1,2,3}
read_record(buf, 12, 4, 2, out)   ->   0,  out = {8,9,10,11}
read_record(buf, 12, 4, 3, out)   ->   -1  (past the end)

Edge cases

  • Last valid record vs. one past the end.
  • recsize == 0 or negative idx: -1.

Rules

  • The record starts at idx * recsize; verify start + recsize <= n before copying (guards against overrun and overflow).

Why this matters

Binary formats (databases, MFT, packet logs) are arrays of fixed-size records; reading record N is just bounds-checked indexing.

Input format

buf/n: record buffer and its byte length. recsize: record size. idx: 0-based index. out: destination.

Output format

0 on success (record copied to out); -1 on NULL / recsize==0 / idx<0 / out-of-range.

Constraints

Bounds-check idx*recsize + recsize <= n before copying.

Starter code

#include <stdint.h>
#include <stddef.h>
int read_record(const uint8_t *buf, size_t n, size_t recsize, int idx, unsigned char *out) {
    /* TODO */
    (void)buf; (void)n; (void)recsize; (void)idx; (void)out;
    return -1;
}

Common mistakes

Integer overflow on idx×recsize (guard with the bound check). Off-by-one letting the last record read past n.

Edge cases to handle

Last valid record. idx one past the end. recsize 0.

Complexity

O(recsize).

Background lessons

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