1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
# Brck -- a simple bit rot checker
Brck is a simple bit rot checker for legacy file systems.
It records and compares the modification times and cryptographic hash sums of regular files.
When a file's hash changed but it's modification time did not, then Brck reports the file as corrupted so you have a chance to restore the file from backup.
You do have backups, right? 😉
Brck's original source code is hosted on [git.skreutz.com](https://git.skreutz.com/brck.git/).
## Installation
Brck is available on [crates.io](https://crates.io/crates/brck).
You can install it using Rust's package manager [Cargo](https://doc.rust-lang.org/cargo/).
$ cargo install brck
Alternatively you can run (or install) the experimental Nix flake.
$ nix run git+https://git.skreutz.com/brck.git -- --help
## Usage
Without any options, Brck will record all regular files in current working directory recursively and write those records to a gzipped `.brck` file.
$ brck
When you run the same command again, Brck will compare the recorded files against the current file system and report any corrupted files.
$ brck
corrupted: ./test_file
Error: Found 1 denied difference
You can optionally deny all changes to existing files:
$ brck -d changed,removed,corrupted
Brck is quiet by default.
Increase the verbosity using `-v` or request a summary using `-s`.
Alternatively, enable the JSON output using `-J` and perform your own post-processing, e.g., using [jq](https://jqlang.github.io/jq/):
$ brck -vvJ | jq -sr 'group_by(.type)[] | [.[0].type, length] | @tsv' 2>/dev/null
added 4
corrupted 1
unchanged 1219
See the built-in help for all supported options:
$ brck --help
## Features
* Parallel sequential processing: Brck processes files in parallel, yet outputs and records files in-order
* One-pass: Brck reads your files only once
* Constant memory: Brck's memory footprint is independent of the number of processed files
* Relative paths: Brck records relative paths such that you can move the containing directory around
* Quiet by default: Without any options, Brck prints denied differences to standard output, and errors to standard error; nothing else
* Human readable or machine readable, newline-delimited JSON output, at your option
* Graceful shutdown on the first interrupt signal, forceful immediate shutdown on the second
* [Pledged](https://man.openbsd.org/pledge) and [unveiled](https://man.openbsd.org/unveil) on OpenBSD
## Limitations
* Brck doesn't follow symlinks.
* Brck doesn't track hardlinks. Performance will be suboptimal in the presence of large hardlinked files because Brck hashes each copy individually.
* Brck doesn't track reflinks. Modern copy-on-write file systems are out of scope because they should check file content integrity themselves, like OpenZFS and Btrfs do.
* Brck may leak file meta data because its `.brck` file may have different permissions than the listed files.
* Brck doesn't respect platform-specific temporary directories such as `TMPDIR` on UNIX. Instead, it creates its temporary files in the current working directory, next to the `.brck` file. This way, Brck can update the files atomically on POSIX-conform systems.
* Brck may fail to remove its temporary files, e.g., when the process gets killed.
## License
This work is dual-licensed under [MIT](LICENSE-MIT) or [Apache License, Version 2.0](LICENSE-APACHE-2.0).
## Contribution
Contributions are welcome! Please [contact](https://www.skreutz.com/contact/) me via email.
## See also
* Definition of *bit rot* in the [Jargon File](http://www.catb.org/jargon/html/B/bit-rot.html) ([archive](https://web.archive.org/web/20240312124910/http://www.catb.org/jargon/html/B/bit-rot.html))
* A similar Python program named [Bitrot](https://github.com/ambv/bitrot/)
* A similar Rust program named [Legdur](https://git.cyplo.dev/cyplo/legdur) ([crates.io](https://crates.io/crates/legdur))
* A blog post on [Things UNIX can do atomically](https://web.archive.org/web/20160304224616/http://rcrowley.org/2010/01/06/things-unix-can-do-atomically)
|