cybersecurity · intermediate · ~15 min · safe pentest lab

Write a USTAR tar header for one file

Bit-exact rendering of a fixed-layout binary header with self-referential checksum.

Challenge

Render a 512-byte USTAR tar header for a single file, including the self-referential checksum — the format every .tar evidence bundle uses.

Task

Implement int write_ustar_header(const char *name, size_t size, uint8_t out[512]) that fills the 512-byte out buffer with a USTAR header:

Offset Length Field Format
0 100 name NUL-padded ASCII
100 8 mode "0000644\0"
124 12 size octal ASCII + NUL
148 8 checksum 6 octal digits + NUL + space
156 1 typeflag '0'
257 6 magic "ustar\0"
263 2 version "00"

All other bytes are zero. Checksum: sum all 512 header bytes as if the checksum field held 8 spaces, then write that sum at offset 148 as 6 octal digits + NUL + space.

Input

  • name: the file name (NUL-terminated; may be NULL).
  • size: the file's size in bytes.
  • out: a caller-provided 512-byte buffer to fill (may be NULL).

Output

Returns 0 on success. Returns -1 if name or out is NULL, if strlen(name) >= 100, or if size needs more than 11 octal digits (size > 0o77777777777).

Example

write_ustar_header("hello.txt", 12, out)
  ->   0;  out[0..] = "hello.txt", size field = "00000000014",
           magic "ustar" at 257, version "00" at 263, typeflag '0' at 156

Edge cases

  • name 100 bytes or longer: return -1.
  • size too large for 11 octal digits: return -1.
  • name/out NULL: return -1.

Rules

  • Write the checksum field as 8 spaces first, sum the whole header, then overwrite it with the real value. Size is octal, not decimal.

Why this matters

Engagement deliverables ship as .tar bundles. Reading a tar header by hand once means you can audit any archive a teammate hands you.

Input format

A file name (NUL-terminated, may be NULL), a size, and a caller-provided 512-byte out buffer (may be NULL).

Output format

0 on success; -1 if name/out is NULL, strlen(name) >= 100, or size needs >11 octal digits.

Constraints

USTAR format; size in octal; checksum summed with the field as 8 spaces.

Starter code

#include <stdint.h>
#include <stddef.h>
int write_ustar_header(const char *name, size_t size, uint8_t out[512]) {
    /* TODO */
    (void)name; (void)size; (void)out;
    return -1;
}

Common mistakes

Computing the checksum BEFORE the spaces are placed. Forgetting the NUL+space terminator on the checksum. Writing the size in decimal.

Edge cases to handle

Maximum 11-octal-digit size. Long name boundary at exactly 100 chars (must be < 100). NULL inputs.

Complexity

O(1) — fixed 512-byte buffer.

Background lessons

Up next

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