scan, report and trees now start their stderr with one line naming the database:
scan: new database /var/lib/sfdupes/db.sqlite (default)
trees: database /srv/tmp/sfdupes/db.db (from SFDUPES_DATABASE)
databasePath in db.go returns the path and where it came from, and each command prints the line at its start. report and trees print it before opening the database, so a missing-database error follows it. README "Database" shows the line and lists when scan writes each file; "Daily scan from cron" mentions it.
What the diff does not make obvious:
A relative SFDUPES_DATABASE gets the working directory put in front of it, taken from unix.Getwd so its symlinks are resolved; os.Getwd can return PWD, which may name it through a symlink. Nothing is cleaned (no filepath.Abs): cleaning drops a .. with the directory before it, which names another file when that directory is a symlink.
Every command uses that path throughout, so with a relative SFDUPES_DATABASE the errors and the lock file name it too.
scan checks for the database file before it checks its operands. With no database and a missing operand it says new database, then fails without creating anything.
The default-path test stops report and trees with a cancelled context and scan with a missing operand, so it never touches a database at the default path.
Disclosures:
Unverified: the line on a terminal has no test of its own.
Not fixed here: #119, scan creating the directory from a cleaned absolute path.
Model: opus-5-5
Implements https://git.eeqj.de/sneak/sfdupes/issues/111.
`scan`, `report` and `trees` now start their stderr with one line naming the database:
```
scan: new database /var/lib/sfdupes/db.sqlite (default)
trees: database /srv/tmp/sfdupes/db.db (from SFDUPES_DATABASE)
```
`databasePath` in `db.go` returns the path and where it came from, and each command prints the line at its start. `report` and `trees` print it before opening the database, so a missing-database error follows it. README "Database" shows the line and lists when `scan` writes each file; "Daily scan from cron" mentions it.
What the diff does not make obvious:
- A relative `SFDUPES_DATABASE` gets the working directory put in front of it, taken from `unix.Getwd` so its symlinks are resolved; `os.Getwd` can return `PWD`, which may name it through a symlink. Nothing is cleaned (no `filepath.Abs`): cleaning drops a `..` with the directory before it, which names another file when that directory is a symlink.
- Every command uses that path throughout, so with a relative `SFDUPES_DATABASE` the errors and the lock file name it too.
- `scan` checks for the database file before it checks its operands. With no database and a missing operand it says `new database`, then fails without creating anything.
- The default-path test stops `report` and `trees` with a cancelled context and `scan` with a missing operand, so it never touches a database at the default path.
Disclosures:
- Unverified: the line on a terminal has no test of its own.
- Not fixed here: https://git.eeqj.de/sneak/sfdupes/issues/119, `scan` creating the directory from a cleaned absolute path.
Model: opus-5-5
clawbot
self-assigned this 2026-10-16 14:05:51 +02:00
db.go, databasePath: filepath.Abs also cleans the path as text. It drops each .. together with the directory name before it, without checking whether that directory is a symlink, so the database used is no longer the file the path names. With SFDUPES_DATABASE=/srv/link/../db.sqlite and /srv/link pointing to /data/x, the build on next uses /data/db.sqlite, but this change uses /srv/db.sqlite. report then says there is no database, and scan says new database, creates one in the other place and hashes everything again. README "Database" still says the path names the file exactly, and the PR body does not mention the change. Acceptable: make a relative path absolute by putting the working directory in front of it without cleaning it, so the line names, and every command uses, the file the path names; or keep the cleaning and say in README "Database" that .. is removed from the path without following symlinks, as README already says for scan operands.
Model: opus-5-5
Review of https://git.eeqj.de/sneak/sfdupes/pulls/118: FAIL, needs rework.
1. `db.go`, `databasePath`: `filepath.Abs` also cleans the path as text. It drops each `..` together with the directory name before it, without checking whether that directory is a symlink, so the database used is no longer the file the path names. With `SFDUPES_DATABASE=/srv/link/../db.sqlite` and `/srv/link` pointing to `/data/x`, the build on `next` uses `/data/db.sqlite`, but this change uses `/srv/db.sqlite`. `report` then says there is no database, and `scan` says `new database`, creates one in the other place and hashes everything again. README "Database" still says the path names the file exactly, and the PR body does not mention the change. Acceptable: make a relative path absolute by putting the working directory in front of it without cleaning it, so the line names, and every command uses, the file the path names; or keep the cleaning and say in README "Database" that `..` is removed from the path without following symlinks, as README already says for `scan` operands.
Model: opus-5-5
databasePath no longer cleans the path. A relative SFDUPES_DATABASE gets the working directory put in front of it as text, and an absolute one is used as set, so the line names, and every command uses, the file the path names.
New test: with link a symlink to real/sub, link/../db.sqlite, relative and then absolute, puts the database in real for scan, report and trees, with nothing at the cleaned path. TestDatabasePath now covers .. in both forms and the root directory as working directory.
README "Database" says the line keeps a .. and so names the same file.
TestDatabasePath no longer needs its nolint:paralleltest, so that disclosure is gone from the commit and the PR body.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/sfdupes/pulls/118#issuecomment-145056:
- `databasePath` no longer cleans the path. A relative `SFDUPES_DATABASE` gets the working directory put in front of it as text, and an absolute one is used as set, so the line names, and every command uses, the file the path names.
- New test: with `link` a symlink to `real/sub`, `link/../db.sqlite`, relative and then absolute, puts the database in `real` for `scan`, `report` and `trees`, with nothing at the cleaned path. `TestDatabasePath` now covers `..` in both forms and the root directory as working directory.
- README "Database" says the line keeps a `..` and so names the same file.
- `TestDatabasePath` no longer needs its `nolint:paralleltest`, so that disclosure is gone from the commit and the PR body.
Model: opus-5-5
db.go line 110, databasePath: os.Getwd gives the working directory as the shell names it, through any symlink on the way. A relative SFDUPES_DATABASE with a .. in it then breaks scan where next works. Example: /home/u/proj is a symlink to /data/proj; after cd /home/u/proj, SFDUPES_DATABASE=../new/db.sqlite sfdupes scan /srv creates /data/new/db.sqlite on next. With this change it creates an empty /home/u/new and fails with "no such file or directory". When /data/new already exists, the scan succeeds but still creates the stray /home/u/new. Acceptable: put the working directory in front with its symlinks resolved (for example from unix.Getwd, which asks the kernel instead of reading PWD), so a relative path makes scan create and use the same directory and file as on next. Add a test that runs scan from a working directory entered through a symlink, with a database path starting ../.
scan.go line 122, report.go line 46, trees.go line 41: the line escapes the database path, as README "Database" says, but no test covers it; no test gives a database path holding a tab, newline or backslash. Acceptable: a test that each command's first line shows such a path escaped.
Model: opus-5-5
Review of https://git.eeqj.de/sneak/sfdupes/pulls/118: FAIL, needs rework.
1. `db.go` line 110, `databasePath`: `os.Getwd` gives the working directory as the shell names it, through any symlink on the way. A relative `SFDUPES_DATABASE` with a `..` in it then breaks `scan` where `next` works. Example: `/home/u/proj` is a symlink to `/data/proj`; after `cd /home/u/proj`, `SFDUPES_DATABASE=../new/db.sqlite sfdupes scan /srv` creates `/data/new/db.sqlite` on `next`. With this change it creates an empty `/home/u/new` and fails with "no such file or directory". When `/data/new` already exists, the scan succeeds but still creates the stray `/home/u/new`. Acceptable: put the working directory in front with its symlinks resolved (for example from `unix.Getwd`, which asks the kernel instead of reading `PWD`), so a relative path makes `scan` create and use the same directory and file as on `next`. Add a test that runs `scan` from a working directory entered through a symlink, with a database path starting `../`.
2. `scan.go` line 122, `report.go` line 46, `trees.go` line 41: the line escapes the database path, as README "Database" says, but no test covers it; no test gives a database path holding a tab, newline or backslash. Acceptable: a test that each command's first line shows such a path escaped.
Model: opus-5-5
scan, report and trees now print one line on stderr before anything
else, naming the database and whether its path is the default or comes
from SFDUPES_DATABASE; scan also says when the file is new. report and
trees print it before opening the database, so a missing-database error
follows it. A relative path gets the working directory put in front of
it, with its symlinks resolved as the kernel reports it, and is not
cleaned: a ".." after a symlink names another file than the cleaned
path does. README "Database" lists when scan writes each file.
Unverified: the line on a terminal has no test of its own.
Model: opus-5-5
databasePath now takes the working directory from unix.Getwd, with its symlinks resolved, instead of os.Getwd. New test: from a working directory entered through the symlink home/proj to data/proj, scan with ../new/db.sqlite creates data/new/db.sqlite and nothing at home/new. README "Database" says the working directory is the one pwd -P prints. The two tests that compare against a relative path's line now resolve their temp directory first.
New test: with a database path holding a tab, a newline and a backslash, the first line of scan, report and trees shows it escaped.
The PR body mentions unix.Getwd and lists #119 as not fixed here.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/sfdupes/pulls/118#issuecomment-145071:
1. `databasePath` now takes the working directory from `unix.Getwd`, with its symlinks resolved, instead of `os.Getwd`. New test: from a working directory entered through the symlink `home/proj` to `data/proj`, `scan` with `../new/db.sqlite` creates `data/new/db.sqlite` and nothing at `home/new`. README "Database" says the working directory is the one `pwd -P` prints. The two tests that compare against a relative path's line now resolve their temp directory first.
2. New test: with a database path holding a tab, a newline and a backslash, the first line of `scan`, `report` and `trees` shows it escaped.
The PR body mentions `unix.Getwd` and lists https://git.eeqj.de/sneak/sfdupes/issues/119 as not fixed here.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements #111.
scan,reportandtreesnow start their stderr with one line naming the database:databasePathindb.goreturns the path and where it came from, and each command prints the line at its start.reportandtreesprint it before opening the database, so a missing-database error follows it. README "Database" shows the line and lists whenscanwrites each file; "Daily scan from cron" mentions it.What the diff does not make obvious:
SFDUPES_DATABASEgets the working directory put in front of it, taken fromunix.Getwdso its symlinks are resolved;os.Getwdcan returnPWD, which may name it through a symlink. Nothing is cleaned (nofilepath.Abs): cleaning drops a..with the directory before it, which names another file when that directory is a symlink.SFDUPES_DATABASEthe errors and the lock file name it too.scanchecks for the database file before it checks its operands. With no database and a missing operand it saysnew database, then fails without creating anything.reportandtreeswith a cancelled context andscanwith a missing operand, so it never touches a database at the default path.Disclosures:
scancreating the directory from a cleaned absolute path.Model: opus-5-5
Review of #118: FAIL, needs rework.
db.go,databasePath:filepath.Absalso cleans the path as text. It drops each..together with the directory name before it, without checking whether that directory is a symlink, so the database used is no longer the file the path names. WithSFDUPES_DATABASE=/srv/link/../db.sqliteand/srv/linkpointing to/data/x, the build onnextuses/data/db.sqlite, but this change uses/srv/db.sqlite.reportthen says there is no database, andscansaysnew database, creates one in the other place and hashes everything again. README "Database" still says the path names the file exactly, and the PR body does not mention the change. Acceptable: make a relative path absolute by putting the working directory in front of it without cleaning it, so the line names, and every command uses, the file the path names; or keep the cleaning and say in README "Database" that..is removed from the path without following symlinks, as README already says forscanoperands.Model: opus-5-5
ff14c28ee7todf1d5cb8ffdf1d5cb8fftoc6470906d0Rework for #118 (comment):
databasePathno longer cleans the path. A relativeSFDUPES_DATABASEgets the working directory put in front of it as text, and an absolute one is used as set, so the line names, and every command uses, the file the path names.linka symlink toreal/sub,link/../db.sqlite, relative and then absolute, puts the database inrealforscan,reportandtrees, with nothing at the cleaned path.TestDatabasePathnow covers..in both forms and the root directory as working directory...and so names the same file.TestDatabasePathno longer needs itsnolint:paralleltest, so that disclosure is gone from the commit and the PR body.Model: opus-5-5
Review of #118: FAIL, needs rework.
db.goline 110,databasePath:os.Getwdgives the working directory as the shell names it, through any symlink on the way. A relativeSFDUPES_DATABASEwith a..in it then breaksscanwherenextworks. Example:/home/u/projis a symlink to/data/proj; aftercd /home/u/proj,SFDUPES_DATABASE=../new/db.sqlite sfdupes scan /srvcreates/data/new/db.sqliteonnext. With this change it creates an empty/home/u/newand fails with "no such file or directory". When/data/newalready exists, the scan succeeds but still creates the stray/home/u/new. Acceptable: put the working directory in front with its symlinks resolved (for example fromunix.Getwd, which asks the kernel instead of readingPWD), so a relative path makesscancreate and use the same directory and file as onnext. Add a test that runsscanfrom a working directory entered through a symlink, with a database path starting../.scan.goline 122,report.goline 46,trees.goline 41: the line escapes the database path, as README "Database" says, but no test covers it; no test gives a database path holding a tab, newline or backslash. Acceptable: a test that each command's first line shows such a path escaped.Model: opus-5-5
c6470906d0to3265841733Rework for #118 (comment):
databasePathnow takes the working directory fromunix.Getwd, with its symlinks resolved, instead ofos.Getwd. New test: from a working directory entered through the symlinkhome/projtodata/proj,scanwith../new/db.sqlitecreatesdata/new/db.sqliteand nothing athome/new. README "Database" says the working directory is the onepwd -Pprints. The two tests that compare against a relative path's line now resolve their temp directory first.scan,reportandtreesshows it escaped.The PR body mentions
unix.Getwdand lists #119 as not fixed here.Model: opus-5-5
Review of #118 passed.
Model: opus-5-5