Skip to content

Round10 fixes - #37

Merged
boyter merged 16 commits into
masterfrom
round10-fixes
Nov 2, 2026
Merged

boyter merged 16 commits into
masterfrom
round10-fixes

Conversation

@boyter

@boyter boyter commented Nov 2, 2026

Copy link
Copy Markdown
Owner

So many fixes..

boyter and others added 16 commits October 30, 2026 10:12
- Open SQLite databases at the path the operating system resolves, as
  filepath.Abs cleans .. against the shell's working directory, which wrote
  an empty output and could audit against a different database when the
  working directory was reached through a symlink
- Index SQLite records containing .. or .// rather than looking them up
  directly, which never matched them
- Keep spaces at the ends of the hashdeep invoked from directory
- Only remove a carriage return from hashdeep lines with windows line
  endings, so filenames ending in one can be audited
- Add round 10 checks to test-all.sh

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A path containing .. has everything up to its last .. resolved by the
  operating system when comparing paths, so after a symlink it names the
  directory actually read. Auditing ../d from a symlinked working directory,
  or a supplied path such as link/../d, could compare the files read against
  the records of a different directory and pass a modified tree
- Supplied paths are only cleaned when that names the same directory, and
  --absolute and -i resolve .. the same way
- A sum file listing a file more than once has every line checked as
  md5sum -c does, a different value of the same hash reporting it modified
- List an unreadable file whose SQLite record was paired as a move
- README: find -L, symlinked working directories, sum duplicates, SQLite index
- Add round 11 checks to test-all.sh

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ates through every directory

Resolving every .. through the operating system mixed physical and logical
paths from a symlinked working directory, reporting every file as moved, and a
.. the operating system cannot follow was cleaned into another path, so could
match a different file. Only the path up to the last .. of a supplied path is
resolved, so a symlink after it is walked as supplied.

Sum file lines naming the same file only through the sum file's directory are
now merged, so are all checked. SQLite audits report every spelling of an
unreadable file and list unreadable files in order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uments and records

A manifest whose invoked from directory was deleted or made unreadable reported
every file as moved, as .. through it was kept as written. A directory which no
longer exists cannot be a symlink, so .. after it is removed as text, while ..
after a dangling link or a file still never matches.

Paths supplied with .. now use the same rule as paths in audit files, so they
match hashdeep manifests made through symlinked directories. Sum file lines are
compared across every directory by the file they name, so conflicting lines are
found through symlinked and different directories, and directories are not
files. A missing SQLite record is only reported unreadable through its own path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h unsearchable directories

Merging sum lines naming the same file dropped a line's own path, so a scanned
symlink to a listed file was new, and let the kept line be checked against a
different file than the dropped line named. Every line is now kept, lines
naming the same real file are grouped for conflicts, and a line is only not
reported when another was checked against that same file.

A directory which cannot be searched may hold a symlink, so .. after it never
matches rather than being cleaned as text. A physical path inside the working
directory or a directory containing it is given through the working directory,
so lnk/../.. matches files found from a symlinked working directory. SQLite -v
finds unreadable spellings through the first directory which exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, check every hash of a sum file's lines for one file

Rewriting only the part of a path up to its last .. through the symlinked working
directory gave one file two keys, depending on whether it was reached by an
absolute physical path or by .. landing above it. Every compared path inside
where the working directory, or a directory containing it, really is, is now
compared through it, which also lets an absolute physical manifest pass when
audited from the symlink. SQLite lookups also try the physical spelling, with
as many placeholders as there are candidates.

Sum file lines naming the same file are all checked with every hash listed for
it, so a line with another algorithm is not hidden as a duplicate. SQLite -v
checks other spellings of an unreadable file through the directory its record
was found through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…spelling, keep conflicts through merges

Rewriting paths into a symlinked working directory was not canonical: with
nested symlinked ancestors a path written through one could get another key, an
unclean $PWD such as // applied it twice inside symlink loops, and cleaning the
joined path matched x/.. paths which can never be opened. Paths are now taken
through where every symlinked ancestor really is until nothing changes, then
through the deepest containing it, joined as text. When the working directory
was reached through a symlink every SQLite record is indexed, as a record can be
compared as another spelling.

A sum line's conflicting value is kept when its record is merged or grouped
with another spelling of the file, so the line is not hidden as a duplicate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lled SQLite records

A working directory reached through a symlink to / mapped /tmp/x to W/Rtmp/x,
which could match a SQLite record of that literal path. When the working
directory was reached through a symlink only records whose compared path differs
from their spelling are indexed, rather than every record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An audit file given as x/lnk/../m.hd added x as a directory relative records
are resolved against, as filepath.Dir cleaned the path as text, so a record
could match a different file in x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ame path with the same values

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r directory places its record is reported as moved

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ough, chosen by most files

Sum lines only stand in for a checked line when they name the checked file
through that directory, records dropped as duplicates are audited when they
name another file there, and SQLite duplicates are kept by row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fuse SQLite databases not keyed by path

A sum file listing every file by relative and absolute path, audited in
place from another directory, matched only absolute lines so no
directory was chosen, and its relative lines were judged through the
working directory and reported as missing.

A SQLite table without filepath as its primary key could list a path
twice with only one audited, and a rowid column hid the real rowid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…was chosen, and refuse generated rowid columns and inexact path keys

Grouping rows through every directory let a relative row naming a deleted
file through the directory hashit was invoked from be dropped as a
duplicate of an absolute row naming another file through the working
directory. Only sum files, which record no such directory, need that.

The schema check missed a generated rowid column, which pragma_table_info
does not list, and a filepath key with a collation such as nocase, which
let a renamed file pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ctly, or is missing on a row

A collation on the filepath column, with the key itself compared exactly,
let a rename differing in case or trailing space pass, and a numeric
filepath type let a file renamed from 1 to 01 or 1.0 pass, as lookups
compare using the column. A row without a path failed with a raw scan
error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pr-insights pr-insights Bot added M/size Normal or medium sized change VH/complexity Very high complexity labels Nov 2, 2026
@boyter
boyter merged commit 339d67e into master Nov 2, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

M/size Normal or medium sized change VH/complexity Very high complexity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant