scan creates the database's folder in the wrong place when the path holds .. after a symlink #119

Open
opened 2026-10-16 14:45:15 +02:00 by clawbot · 0 comments
Collaborator

Found while reworking #118 for #111.

README "Database" says SFDUPES_DATABASE names the database file exactly. scan opens the file through that exact path, but it creates the missing parent folder from filepath.Dir(path) in lockScanDatabase and openScanDatabase (db.go). filepath.Dir cleans the path as text, dropping each .. together with the name before it without checking for a symlink. With SFDUPES_DATABASE=/srv/link/../new/db.sqlite, /srv/link pointing to /data/x and /data/new missing, scan creates /srv/new. The path itself leads to /data/new, so scan then fails to create the database there, leaving an empty /srv/new behind.

Definition of done

  • scan creates the folder the database path actually leads to: the path with its last element removed as plain text, never cleaned, so .. is followed through symlinks as the system follows it when opening the file.
  • Both places that create the folder use the same helper, in db.go beside databasePath.
  • Tests: the case above, a symlinked directory followed by .. and a missing folder. The database lands where the path leads, and nothing is created at the cleaned path. Plus a plain missing folder, as now.
  • TODO.md Completed Steps entry in the same commit; script/cibuild green on a fresh clone.

Notes for the implementer

  • Package main (the repo's only package); db.go only, plus its tests.
  • Small and plain.

Model: opus-5-5

Found while reworking https://git.eeqj.de/sneak/sfdupes/pulls/118 for https://git.eeqj.de/sneak/sfdupes/issues/111. README "Database" says `SFDUPES_DATABASE` names the database file exactly. `scan` opens the file through that exact path, but it creates the missing parent folder from `filepath.Dir(path)` in `lockScanDatabase` and `openScanDatabase` (`db.go`). `filepath.Dir` cleans the path as text, dropping each `..` together with the name before it without checking for a symlink. With `SFDUPES_DATABASE=/srv/link/../new/db.sqlite`, `/srv/link` pointing to `/data/x` and `/data/new` missing, `scan` creates `/srv/new`. The path itself leads to `/data/new`, so `scan` then fails to create the database there, leaving an empty `/srv/new` behind. ## Definition of done - `scan` creates the folder the database path actually leads to: the path with its last element removed as plain text, never cleaned, so `..` is followed through symlinks as the system follows it when opening the file. - Both places that create the folder use the same helper, in `db.go` beside `databasePath`. - Tests: the case above, a symlinked directory followed by `..` and a missing folder. The database lands where the path leads, and nothing is created at the cleaned path. Plus a plain missing folder, as now. - `TODO.md` Completed Steps entry in the same commit; `script/cibuild` green on a fresh clone. ## Notes for the implementer - Package `main` (the repo's only package); `db.go` only, plus its tests. - Small and plain. Model: opus-5-5
clawbot added this to the 1.0.0 milestone 2026-10-16 14:45:15 +02:00
Sign in to join this conversation.