All checks were successful
check / check (push) Successful in 35s
Fix every golangci-lint finding under the repo's standard .golangci.yml (from ~192 down to 0 under the pinned v2.10.1) without changing program behavior: - gochecknoglobals: replace the verbose/quiet/exclude* package globals with an options struct threaded through the command implementations. - err113: introduce package-level sentinel errors and wrap them with %w. - errcheck: check or explicitly discard every previously unchecked error (bar.Add/Finish, deferred Close, verbose writes). - forbidigo: route verbose output through os.Stdout instead of fmt.Print*. - noinlineerr / wsl_v5 / nlreturn / gofmt: split inline error checks and normalize whitespace. - complexity (cyclop/gocognit/nestif): extract small behavior-preserving helpers (runOverPaths, countAndBar, walkSkip, clearOne, checkOne, missingChecksum, reportCheck). - mnd/lll/nonamedreturns/revive/modernize/nilnil: named constants, wrapped lines, unnamed returns, doc comments, SplitSeq, non-(nil,nil) returns. - paralleltest/thelper: mark tests parallel (now race-safe with no shared globals) and add t.Helper(); probe the real xattr key so the guard is accurate. Also make the tests actually runnable in CI rather than skipping: - move the xattr keys into the user.* namespace (user.berlin.sneak.app.*), which Linux requires for regular-file xattrs; macOS treats the whole string as an opaque name, so behavior is unchanged there. - run the Docker builder's checks as an unprivileged user so the permission tests are meaningful (root bypasses file mode bits).
115 lines
3.3 KiB
Markdown
115 lines
3.3 KiB
Markdown
[**attrsum**](https://git.eeqj.de/sneak/attrsum/) is a **Go
|
||
1.22** command-line utility that **adds, updates, verifies, and clears per-file
|
||
file content checksums stored in extended attributes (xattrs) on macOS (APFS) and
|
||
Linux**, released under the [WTFPL v2](http://www.wtfpl.net/).
|
||
|
||
Original release 2025-05-08.
|
||
|
||
Current version 1.0 (2025-05-08).
|
||
|
||
---
|
||
|
||
## Getting Started — Quick Build
|
||
|
||
```bash
|
||
# prerequisites: Go 1.22+
|
||
git clone https://git.eeqj.de/sneak/attrsum.git
|
||
cd attrsum
|
||
go build -o attrsum .
|
||
```
|
||
|
||
### Install
|
||
|
||
```bash
|
||
go install git.eeqj.de/sneak/attrsum@latest # into GOPATH/bin or $(go env GOBIN)
|
||
```
|
||
|
||
Semantic Versioning 2.0.0 is used for tags.
|
||
|
||
---
|
||
|
||
## Usage
|
||
|
||
```bash
|
||
# add checksum & timestamp xattrs to every regular file under one or more paths
|
||
attrsum sum add DIR1 DIR2 file.txt
|
||
|
||
# update checksum only when file mtime is newer than stored sumtime
|
||
attrsum sum update DIR1 DIR2
|
||
|
||
# verify checksums, stop on first error
|
||
attrsum check DIR1 DIR2
|
||
|
||
# verify every file, reporting each result, keep going after errors
|
||
attrsum -v check --continue DIR1 DIR2
|
||
|
||
# remove checksum & timestamp xattrs
|
||
attrsum clear DIR1 DIR2
|
||
|
||
# read paths from stdin (use - as argument)
|
||
find /data -name "*.jpg" | attrsum sum add -
|
||
|
||
# quiet mode (suppress progress bar and summary)
|
||
attrsum -q sum add DIR
|
||
```
|
||
|
||
| xattr key | meaning |
|
||
|---------------------------------------------|--------------------------------|
|
||
| `user.berlin.sneak.app.attrsum.checksum` | base-58 multihash (sha2-256) |
|
||
| `user.berlin.sneak.app.attrsum.sumtime` | RFC 3339 timestamp of checksum |
|
||
|
||
Flags:
|
||
|
||
* `-v, --verbose` — per-file log output
|
||
* `-q, --quiet` — suppress all output except errors (no progress bar or summary)
|
||
* `--exclude PATTERN` — skip paths matching rsync/Doublestar glob
|
||
* `--exclude-dotfiles` — skip any path component that starts with `.`
|
||
|
||
All commands display a progress bar with ETA and print a summary report to stderr on completion (unless `--quiet` is specified).
|
||
|
||
`attrsum` **never follows symlinks** and skips non-regular files (sockets, devices, …).
|
||
|
||
---
|
||
|
||
## Why?
|
||
|
||
Apple APFS and Linux ext3/ext4 **store no per-file content checksums**, so
|
||
silent data corruption can pass unnoticed. `attrsum` keeps a portable checksum **inside each file’s xattrs**, providing integrity
|
||
verification that travels with the file itself—no external database
|
||
required. Now you can trust a USB stick didn't eat your data.
|
||
|
||
---
|
||
|
||
## TODO
|
||
|
||
Future improvements under consideration:
|
||
|
||
- **Dry-run mode (`--dry-run`, `-n`)** — show what would be done without making changes
|
||
- **JSON output (`--json`)** — machine-readable output for scripting and integration
|
||
- **Parallel processing (`-j N`)** — use multiple goroutines for faster checksumming on large trees
|
||
- **Exit code documentation** — formalize and document exit codes for scripting
|
||
|
||
---
|
||
|
||
## Contributing
|
||
|
||
* Author & maintainer: **sneak** – <sneak@sneak.berlin>
|
||
* Issues / PRs: <https://git.eeqj.de/sneak/attrsum/>
|
||
* Code must pass `go vet`, `go test ./...`, and `go fmt`.
|
||
* No CLA; contributions are under WTFPL v2.
|
||
|
||
---
|
||
|
||
## Community & Support
|
||
|
||
Bug tracker and wiki are in the Gitea repo linked above.
|
||
|
||
No formal Code of Conduct; be excellent to each other.
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
*Everything is permitted.*
|
||
See [WTFPL v2](http://www.wtfpl.net/txt/copying/).
|