linux-sysprog · intermediate · ~20 min

Join two path components safely

snprintf-based safe concatenation with the per-segment slash rule.

Challenge

Implement int path_join(char *out, size_t cap, const char *a, const char *b).

The function concatenates two path components into out, inserting a single / between them if needed (no double slashes, no missing separators).

  • If b starts with /, treat it as absolute — out is just a copy of b (capped).
  • If a is empty, out is just a copy of b.
  • If b is empty, out is just a copy of a.
  • Otherwise, out is a + '/' + b, with at most one / between them.

Return:

  • 0 on success.
  • -1 if out is too small.

Examples

path_join(out, 32, "/etc", "passwd")          -> 0, out = "/etc/passwd"
path_join(out, 32, "/etc/", "passwd")         -> 0, out = "/etc/passwd"   // no double slash
path_join(out, 32, "/etc", "/passwd")         -> 0, out = "/passwd"      // b absolute
path_join(out, 32, "", "passwd")              -> 0, out = "passwd"
path_join(out, 5,  "/etc", "passwd")          -> -1                       // too small

Why this matters

Every CLI tool that constructs dir/file does some version of this. Doing it without snprintf overflows or double slashes is the kind of small care that distinguishes solid C from sloppy.

Input format

Two path components + output buffer.

Output format

0/-1 + populated out.

Constraints

Use snprintf for the safe build; reject on cap overflow.

Starter code

#include <stddef.h>
int path_join(char *out, size_t cap, const char *a, const char *b) { /* TODO */ return -1; }

Common mistakes

Always inserting / (creates // when a already ends with /). Forgetting the absolute-b rule. Failing to detect snprintf truncation.

Edge cases to handle

Both empty; a ending in /; b starting with /; tiny cap.

Complexity

O(strlen(a) + strlen(b)).

Background lessons

Up next

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