Compare commits

...

13 Commits

Author SHA1 Message Date
geos_one
db9aca72df bump 2025-08-12 21:37:36 +02:00
Mo Zhou
153663d8b6 Import Debian changes 12.4-1
snapraid (12.4-1) unstable; urgency=medium
.
  * New upstream version 12.4
.
snapraid (12.3-1) unstable; urgency=medium
.
  * New upstream version 12.3
.
snapraid (12.2-1) unstable; urgency=medium
.
  * New upstream version 12.2
.
snapraid (12.1-1) unstable; urgency=medium
.
  * New upstream version 12.1
.
snapraid (12.0-1) unstable; urgency=medium
.
  [ Debian Janitor ]
  * Trim trailing whitespace.
  * Set upstream metadata fields: Repository, Repository-Browse.
.
  [ Mo Zhou ]
  * New upstream version 12.0 (Closes: #995324)
2025-08-12 21:36:56 +02:00
geos_one
345149210e Import Upstream version 12.4 2025-08-12 21:36:56 +02:00
Mario Fetka
73b05cde71 Merge tag 'upstream/12.2'
Upstream version 12.2
2023-07-01 12:07:26 +02:00
Mario Fetka
1aa8d4d499 Imported Upstream version 12.2 2023-07-01 12:07:26 +02:00
Mario Fetka
2285cff2a6 Roleback 2021-10-03 10:07:58 +02:00
Mario Fetka
a311749e46 Merge tag 'upstream/11.6'
Upstream version 11.6
2021-10-03 10:04:54 +02:00
Mario Fetka
d767689d60 Bump 2020-09-11 13:43:22 +02:00
Mario Fetka
1dd99167db Merge tag 'upstream/11.5'
Upstream version 11.5
2020-09-11 13:42:24 +02:00
Mario Fetka
859826a091 Bump 2019-01-07 14:42:44 +01:00
Mario Fetka
36b5ac9c36 Merge tag 'upstream/11.3'
Upstream version 11.3
2019-01-07 14:41:49 +01:00
Mario Fetka
cfd0df25f8 Bump 2019-01-07 14:09:54 +01:00
Maxim Tikhonov
2e8fba7836 Imported Debian patch 11.2-0tikhonov1~xenial 2019-01-07 14:06:17 +01:00
68 changed files with 2168 additions and 16212 deletions

52
.circleci/config.yml Normal file
View File

@ -0,0 +1,52 @@
# Build configuration for https://circleci.com/
version: 2.1
orbs:
win: circleci/windows@2.2.0
workflows:
main:
jobs:
- build_ubuntu
- build_docker
jobs:
build_docker:
docker:
- image: circleci/buildpack-deps:stable
steps:
- checkout
- run: autoreconf -i && ./configure --enable-warning-as-error && make all dist
build_ubuntu:
machine:
image: ubuntu-2004:202101-01
steps:
- checkout
- run: autoreconf -i && ./configure --enable-warning-as-error && make all dist
build_win:
executor:
name: win/default
steps:
- run:
name: Installing MSYS2
shell: powershell.exe
command: 'choco install msys2'
- run:
name: Installing tools
shell: powershell.exe
command: 'C:\tools\msys64\usr\bin\bash.exe -l -c "pacman --needed --noconfirm -S autoreconf automake mingw-w64-x86_64-toolchain"'
- checkout
- run:
name: Autoreconf
shell: C:\\tools\\msys64\\usr\\bin\\bash.exe -l
command: 'cd /c/Users/circleci/project && autoreconf -i'
- run:
name: Configure
shell: C:\\tools\\msys64\\usr\\bin\\bash.exe -l
command: 'cd /c/Users/circleci/project && ./configure --enable-warning-as-error'
- run:
name: Make
shell: C:\\tools\\msys64\\usr\\bin\\bash.exe -l
command: 'cd /c/Users/circleci/project && make'

17
.drone.yml Normal file
View File

@ -0,0 +1,17 @@
# Build configuration for https://www.tea-ci.org
build:
image: teaci/msys$$arch
shell: mingw$$arch
pull: true
commands:
- autoreconf -i
- ./configure --enable-warning-as-error
- make
- make check
matrix:
arch:
- 64
- 32

43
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Build
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build-mac:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: brew install automake
- run: autoreconf -i
- run: ./configure --enable-warning-as-error
- run: make all
- run: make distcheck
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: autoreconf -i
- run: ./configure --enable-warning-as-error
- run: make all
- run: make distcheck
build-win:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v2
- uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: mingw-w64-x86_64-gcc autoconf automake make
- run: autoreconf -i
- run: ./configure --enable-warning-as-error
- run: make all
- run: make distcheck

71
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '20 6 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

69
.gitignore vendored Normal file
View File

@ -0,0 +1,69 @@
# archives
*.zip
*.tar.gz
*.tgz
# backups
*~
# logs
*.log
stream*.bin
# upload
makepush.sh
makemount.sh
makeumount.sh
# autotools
Makefile
Makefile.in
compile
aclocal.m4
autom4te.cache/
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
install-sh
missing
stamp-h1
.dirstamp
# objects
snapraid
mktest
mkstream
*.exe
*.o
*.gcda
*.gcno
*.gcov
# projects
*.dst
*.epr
*.geany
# AFL
makeafl.sh
afl/
afl_corpus/
# specific
cov/
contrib/
paper/
kernel/
obj/
bench/
support/
archive/
www/
wiki/
beta/
ftp/

View File

@ -1 +0,0 @@
11.6

151
CHECKSUMS Normal file
View File

@ -0,0 +1,151 @@
sha256
761eaf08937139a89d79d1ffbad42508f270d3aa603eac50475f7449ae278dcf snapraid-1.2.tar.gz
10e64f2629eb469a32eabc84e1f9a59593cbbf61282ead964b622af1ec0c4681 snapraid-1.2-windows-x64.zip
27da3c54fe408ab53c6e2b4b398ae46328a2dbc701b785a55bf76ffed6046eb2 snapraid-1.2-windows-x86.zip
2e6aaa660a5a74665044ead40959006632dcd1ee1e21091e6260f5b845304f96 snapraid-1.3.tar.gz
0d0cefeabf8230b66414a8731ceb52a0adaaedb5be0fa11d07a6be44e9f2fb6d snapraid-1.3-windows-x64.zip
4358802fb022ba5e2f8d1323ce963155adccea99069abd5f901eadf1411b6366 snapraid-1.3-windows-x86.zip
157b0ca7cfa9cba43cf995b4c32b0b206e299f5ffff58062069bb6ec41c77c0d snapraid-1.4.tar.gz
5b210dd4667369799fd02757e8efc4d733c704cfe72319d297d4ab969b80c962 snapraid-1.4-windows-x64.zip
77047e1fa1bfcb12db7d5c3167e7dbbbb1718909f1003fd185cdf219cd952427 snapraid-1.4-windows-x86.zip
f460bf9aee4b02b6c08f19b0caa2928b075c73ca4cfc41c7f426f015f67cffbc snapraid-1.5.tar.gz
d19262bdf9e572fa80285887886a8fbe9a7b9bd4159496f112d383bf9b4db797 snapraid-1.5-windows-x64.zip
28816c0cde4cf8ce8e91a585eb9aab5552344a331237b6a2afd50396685814fd snapraid-1.5-windows-x86.zip
e0684d036cfd6b9fcdf23792c057fec4f4531d25aab7c677ff35e7a8be07b098 snapraid-1.6.tar.gz
9c13f99d67aafe43f5c540d97d0f6b40289856f547b8f33ee8aee27b270a7fae snapraid-1.6-windows-x64.zip
ae94db99a06068e17134ce69009492c4bfd8f6e54ea1848df105bb89f9f7ba28 snapraid-1.6-windows-x86.zip
1cf7a8f58533d6bc717ff6d396114ec4ed61eb66ff2756370e4cc730ee4edc4d snapraid-1.7.tar.gz
0cb49c676f3f9fd1f0fc938513b6dcaaf15390b64098e17cff5066667e4d01d5 snapraid-1.7-windows-x64.zip
44bc6b947ba845a89ecf812b82e751dca2dd4a6143ff06391c3b8b285a7ed3a2 snapraid-1.7-windows-x86.zip
da1c09f0139e683c03942c2b9489c2d9b989c59d147f7c28258c8e58c3938037 snapraid-1.8.tar.gz
fca7352fece5d7243af45ba8c5a07e08cc0e24d226468a619b9d86a3767e7099 snapraid-1.8-windows-x64.zip
35520cab33b3b3f9efc4ba4d7a968a7d7d49637b5e256921e0091424f5dd60ee snapraid-1.8-windows-x86.zip
504c3fe288b66c84bc65173979e7cede06370ca2a5f02ef3ca200c2fc8b09ea9 snapraid-1.9.tar.gz
ddba596451a05c61b20ce1e82c8039ba3c13be67b7469f2c75c6b0b7b4b18356 snapraid-1.9-windows-x64.zip
5a0dd3cdc0edf69cd03d926b594e41f5ca7e07564ef1cb3d6ac417c76f16b77b snapraid-1.9-windows-x86.zip
5e4eee49748faf966ebcc1cb3b9127ad7047542baf8952c6e0a9cbb32dac4d88 snapraid-1.10.tar.gz
7812a37f8767beb9542def762b2e131caafffc1b1b21f1d9422030e93e367f12 snapraid-1.10-windows-x64.zip
b899784498050c5d41752464bd31cec7de9e77ec865f55e2192fea75f52787d5 snapraid-1.10-windows-x86.zip
c349c4c25e3cb794d908dc75422ca9b04b44162c295b41d4ea55081af1a3451f snapraid-1.11.tar.gz
47e8f09f3d012d0a34d71e6ece7b9171c82af27766cca709fc9bbd104328cc7d snapraid-1.11-windows-x64.zip
8a8b0562192732022ae1732f5ae48e5f8745e217f73683123b2822e316918204 snapraid-1.11-windows-x86.zip
bd89ef0ddc3909c50fecc30da1d5d70342b92952b5d3ae0a2e31a66c8755dc8a snapraid-1.12.tar.gz
290c5ac8667ca7ada12a0d550e06c9fbc5f4e29abb5af0ef105eba38fb274c5d snapraid-1.12-windows-x64.zip
8cbc4e447f2152c3e76025cdbad03c54e7c85e004bb535f9dc7dde9b86605fe8 snapraid-1.12-windows-x86.zip
7c824abf6cacd8b847467916a1b4c28f48161e4b9f9b6c2f607c4de473a663c9 snapraid-1.13.tar.gz
22f6e9bf1dff5df4abff29b7cf364dc029959991dc158257f2a283721581abf4 snapraid-1.13-windows-x64.zip
9801b1a0331c461ce70c7824e2624dd2866358d61d923ff854253f340985947e snapraid-1.13-windows-x86.zip
68a48c961fcc15ffcfb86e4c5ea2371d562252e61f58fe87a529f479e81fb2bb snapraid-2.0.tar.gz
a2e1fb0610c8bfc57d73da1dbd276c238a032bf9b4c73a41977fcc57e773fff4 snapraid-2.0-windows-x64.zip
0fc3bee4d107bcd5e55a1c5bb81015558d9791d66a44f9ae2e3723906c3199df snapraid-2.0-windows-x86.zip
788377f579486c2b16548563a3d25f385594ae4276f1328c8f82cd0d5e0af9b6 snapraid-2.1.tar.gz
6e32fc0603136c4d3ad60fc1f04e6c919b7e7159267750ebf0dd8ad20ee6b442 snapraid-2.1-windows-x64.zip
d2813aec37f96506bcf98f2b5196204f065786731a5874f495f18f58fe87064b snapraid-2.1-windows-x86.zip
faf9545f0a66865e754ad587731483becf895a954c22e023501a2f28af44682a snapraid-2.2.tar.gz
2ea4b610c8d99f3766f6d2c89be5eafd1e16a17454d9df02d982fa184b517744 snapraid-2.2-windows-x64.zip
e2dac0663546f06ac3e679a93ba5de9e7de91563e09c1396fd367c5b16e011be snapraid-2.2-windows-x86.zip
68e610d67087c02715289934472c5fa3d7aa77c8085298ba54f02f26f7d396ad snapraid-3.0.tar.gz
ca7943f270a940554ddbd8c09698228120da2bac5b6d78486a34f5b301e24f47 snapraid-3.0-windows-x64.zip
c6a47d8bf544e69d9b301fe525d193c8faa8ef056c78f8a0649637d2e99b93c6 snapraid-3.0-windows-x86.zip
b5b22350c221e145c3347426f186f188f5d64616d03f196b35d75db564e78f7f snapraid-3.1.tar.gz
6d275cf3d579a5050e936879db85acbcb34b6522b36d5bc81b2f3764ca011c87 snapraid-3.1-windows-x64.zip
66f5967e559368193aef7b13a1c641694ca62f64e4b5749a7e2709aac6dc5759 snapraid-3.1-windows-x86.zip
99617ef379c4e46cc4366f2b3baced653f786ef08a40d74dca23a11a9240b096 snapraid-3.2.tar.gz
94d121d8cc0b9ab7ef1648e42edbfe1cfc602231c86a086d21984177da566f77 snapraid-3.2-windows-x64.zip
1d1ed69d3eab8247a7444e603ba09a56ec77979d3865489b2d8a7fc5db65848f snapraid-3.2-windows-x86.zip
c5a6e77613fab5cecb1aa55750f2045934d9374ba70471b6d35296c34509e5a9 snapraid-4.0.tar.gz
a59c911fef0d4d3e95d5521c6a180b40c455870be3ee9dbb5991b05b2cdd2f05 snapraid-4.0-windows-x64.zip
97ec4ae7b6ec6cd05e0c2ae835def526d12c35fa3546d27bd93978d978cd62aa snapraid-4.0-windows-x86.zip
7f5a37be7b8b78056d6602cef8ef702fe4f0d0b6ac3fa4bcefeb70743425b6fe snapraid-4.2.tar.gz
bf7861274639f2e9e5819ec3a89eed911cd79a212824fe3a6b64e45c0d1e2cc4 snapraid-4.2-windows-x64.zip
c7d9330be1936d7d7b07c51668fc8d3f88ce270e9e74945288d75eda2405a377 snapraid-4.2-windows-x86.zip
09f1ebfb5c45680c50651e94287d59e58260c46aee922d8864fb06fd591740e8 snapraid-4.3.tar.gz
ba1008452ff679c1e144206c73a81e4cb2689006c9ce37b60ceab45ef4c99dda snapraid-4.3-windows-x64.zip
23b21e162d5d18a4f68c8635e1f111fddb91d380514d8ddab9040b18a49d9994 snapraid-4.3-windows-x86.zip
aa22ea2e01a8db45ba43a3139d763cb2d12548de96f957a1ea1b5f80f04a4d83 snapraid-4.4.tar.gz
ca68dd88741290a6ee6494a9186b58766cab2b838f4a55ab23921b524b15ee82 snapraid-4.4-windows-x64.zip
3d9cccc2080d1435e7e747c7eeeffc85e0b68ad45b390c236de321b8aca44d46 snapraid-4.4-windows-x86.zip
ba43b0534197c6064b7a171321762be2ac2c848d4849c578007cc65aa963bed5 snapraid-5.1.tar.gz
54a31c5c979b9c3ad481cd918a48e220f11ce04de0a8ec6f41a957af7ba259fc snapraid-5.1-windows-x64.zip
6758966b3a120bf5b97f21748f649b2f147800b10377a0ee69d922be318ee399 snapraid-5.1-windows-x86.zip
eab07c21201eceb4204f8039f021ff0032515719aa5e640c330da45dd8b8e7a3 snapraid-5.2.tar.gz
554cc7be40fff0a0f249522bda957dfba229066e81102624b979213666b1aaae snapraid-5.2-windows-x64.zip
44f909157ba89d769af59e971c71b15bd38dfd62359b2e2c7eeb8cef0f9dc081 snapraid-5.2-windows-x86.zip
81e00fced6bb040d49aa6e3dc6fda97f22bf677d00f6c0c490e312c23222b421 snapraid-5.3.tar.gz
2627b2491b4d432a311cca1c924f4b40cef7a64c930b7e5eca55b3b9a8a62e61 snapraid-5.3-windows-x64.zip
d1019dc29922d4787c3fd9d4222dfc3b84a6a2e0c6b2db298340747238d8fb46 snapraid-5.3-windows-x86.zip
d836200058b98f189e576ad5619d4ffcd867e5dc8d2a4b775bff07d4f201c938 snapraid-6.0.tar.gz
06f2e56bc30c89e4a1561ec32cf72b240765456505f17da539af4b4338a6b12c snapraid-6.0-windows-x64.zip
6ae0a3fa973a28c64489bc28d7a7f4b354d3fc6703bcb83ef661cf76e994b34d snapraid-6.0-windows-x86.zip
1709c09b0e0699ce38452be7340c279c561b91433a6810600386bb9d8c0491e3 snapraid-6.1.tar.gz
40d995a88a23d799a32eba15f64c983a012771c527208cec2ad98787a45ef4c3 snapraid-6.1-windows-x64.zip
f8e09b3300717d1f9ee9b69bb132038642839c19a15a1f47810f3de10ad559eb snapraid-6.1-windows-x86.zip
b182328227ed9b87b01037f7d005d38a6e3cfb0f675e919978c696dcc6246787 snapraid-6.2.tar.gz
72ccfbf6548b83bd6f229d4862763a4e4cf6001c94d9ee84bf7b2a379a9a7743 snapraid-6.2-windows-x64.zip
55f1bc131f9148ed2b52e0e252c7155e50f5b4383fe82cd74ec2edace2ddc9c6 snapraid-6.2-windows-x86.zip
1f1961385b865bff5282bd16aff76f372f3ed19b685ef7a3b27d907a499385d2 snapraid-6.3.tar.gz
bb55d74d6b3cb08b21f70fded8b706ec1e790222cb265524cb2dc5499ec73391 snapraid-6.3-windows-x64.zip
3e4fa161ea26b8472dbbbfb4e61b34aca904ff9621f5afafbc83280d334a89b2 snapraid-6.3-windows-x86.zip
7cad74422d45c8a05435a03d3228a2d621a962fb866caedde0497f180bd9f60d snapraid-6.4.tar.gz
59471b49733c36acfbdeb16b28fbee063c4582abab2c9168abc7abc75610f9fc snapraid-6.4-windows-x64.zip
abe80b7c019980da2af5e07e0ea8b1ac1e1cdb2eb663483c07dab6ad6bd15985 snapraid-6.4-windows-x86.zip
554684520204d45f8b7cee9abb0269dd2bdba272cb0130c3b26062bea551a791 snapraid-7.0.tar.gz
a617b435f97cd746b4076d00cde68f947cca21adaca6ce603fec4676827b7ae9 snapraid-7.0-windows-x64.zip
301af727522912184f6d4a8290757950fed4577da625d9951809ff69f50b6e4f snapraid-7.0-windows-x86.zip
dd9005b6d7ea701e4aa0f854a0e34dabe68d7765b75f12fc6b3e1fda4d5c2cef snapraid-7.1.tar.gz
0d3a9625a6156ffe9b9eb4703aa2fc63141c51b83c69e98fbecce5430b1980e4 snapraid-7.1-windows-x64.zip
e0afdb753ae6a3bb3484a1bfe1cf01b9178010a8c11604e4bbc44b2f83884842 snapraid-7.1-windows-x86.zip
a912628dd003b3d70f2736629d48eeb738e7d27cba74014001dcc46fce3bc3be snapraid-8.0.tar.gz
9c2158fb9e2c08570f6a03f5cea7ab68d2a424adb1f42bb6b3d970ba9dc8a15d snapraid-8.0-windows-x64.zip
3c2c4357450564010d80bbd2cb1d5583281885b32cf659a0cf3dadce4766e167 snapraid-8.0-windows-x86.zip
6bf89a1319ac3403958cd2c98a9c6102728c0070cfa1aedd90c4561d93c54e5d snapraid-8.1.tar.gz
83ad064d5c3938fdacb989983c6b0fafa0932c236dc4baa93512f3c97fa019bc snapraid-8.1-windows-x64.zip
25e5cffade3667348a242f44fb23719328d578010d79bb28a5cab662fc75916b snapraid-8.1-windows-x86.zip
dff5f4e9a41865313ddd60b6379d5c0b308880d33f197934f98313e8241c6274 snapraid-9.0.tar.gz
624c3aa6cb0bdb7c90566545ca831721ea5e543c843418a00ff4de753af07953 snapraid-9.0-windows-x64.zip
6ace6dafacd902bdf058e42c7d39591e327aef1bb19a94b05496f0f14aca8e1e snapraid-9.0-windows-x86.zip
397fdd7709e941e372b37025457794f8b0ce63a5a8455703ad17770cbccd3823 snapraid-9.1.tar.gz
4c56b2c5d556a3685239e444cb58ce84c398e86a173be34ff7cfa3a2b31a5b34 snapraid-9.1-windows-x64.zip
515ca2078cdcb58b59afc005770a06648d8f17adb27afa5751ca6f68de2c05c6 snapraid-9.1-windows-x86.zip
77de90645a5debd177995d7897d58277b7c778632f0d9852740f5670f3321176 snapraid-9.2.tar.gz
483d96dc8937f6df48b7f454f8ec8f7ee51b5e973fa8f004e59048d60525d2fb snapraid-9.2-windows-x64.zip
99c950ff31c73cc55a1b83e4dfdbb6e1717420af54721f8bbe813fbbba484e04 snapraid-9.2-windows-x86.zip
61c4f3ce8bd5ebb1178fe76ab5933e90c4cead6dba31669f11e262d258c2b2ba snapraid-9.3.tar.gz
178e743b6246265f936e63ab47fe2a942bf414992cd752478854b81bdf264913 snapraid-9.3-windows-x64.zip
2cb888833cdddc82431822f818de0cfd046ceda5a7aa17bf9c410b6147ed7e20 snapraid-9.3-windows-x86.zip
f7dcf19480256fc2c1db9ab976aa12f786e76da6044cc397f0451524e8031ad6 snapraid-10.0.tar.gz
a3b4b2563f44f17072bb20963d61aae53d9f0e6b9446509fee76bbfa9b51fd23 snapraid-10.0-windows-x64.zip
95a1859163beb8c8d02208b27ecf5298068972498c7e2b99b488693ad5f8f133 snapraid-10.0-windows-x86.zip
30a72b8853ea750128c96784b73bb55f7faa4b16367b2e03f40c1f78515c5771 snapraid-11.0.tar.gz
af6f24adb81008e7ccdb7a8f2c46d1187542bd290294563de90acf5d817d772d snapraid-11.0-windows-x64.zip
fedc7591c8de0ce2775482e6b18033cdaca62078a0a16d45421d5fb5dd5615d6 snapraid-11.0-windows-x86.zip
b9acafeb6cece61fd426f08362b596ba89eea0564231955b82156fd09c0e6884 snapraid-11.1.tar.gz
6468d1a55a9a8043eae3c7c292c908c0fbd1974af3f175df23d39dd4748d9bf9 snapraid-11.1-windows-x64.zip
e70929b44ed88701b542abbccadc57dd89469f58cf7d6ca0bf80ce706d854553 snapraid-11.1-windows-x86.zip
735cdeb7656ac48cbb0b4a89a203dd566505071e465d5effbcc56bcb8fd3a0d7 snapraid-11.2.tar.gz
025faabb6390b6af600034523e5988e14160015b835541d8427475ca7fa52057 snapraid-11.2-windows-x64.zip
de16e2083054f34e1206b552bd05c64218c0dffcf787d716c6639f8728457d20 snapraid-11.2-windows-x86.zip
d35ad92157936db3411e2cf7325665fc59e2d159204f9424895cfa9f33122af1 snapraid-11.3.tar.gz
b764a3341783d4694242412e0fca7c112e44e84a4a89a7c27b0f74a836a84baf snapraid-11.3-windows-x64.zip
f8e51bee80ae0223f402afe68f5192f1036434bab816c42333bf2e5f9fbc82a2 snapraid-11.3-windows-x86.zip
1de47b8277c7dd9c339396efdd2b12a865ff82fdf6ab47cb945f2e21717451c9 snapraid-11.4.tar.gz
0734ca7a521ba7c05eea6898f481ca812d2a2d78da4545f7990cd27e6381dc75 snapraid-11.4-windows-x64.zip
061075df60b584ade5c76551ca54d76726441421576a544cdfd621acb23d55e1 snapraid-11.4-windows-x86.zip
1f5267261bdbcf4d48b9359ce67184df11905590739140f740327fb73bcecafa snapraid-11.5.tar.gz
e18f6b825a25b71947c2c41a315440a3d394de348afca80e2ab13a525bbb8a2b snapraid-11.5-windows-x64.zip
a66753201e55c115699df78f89dd562c1b71e876aba5be35fcaf507bfe1e9e52 snapraid-11.5-windows-x86.zip
f030a3830449a78d10af41320da0be21c60f88dc8d328ebd056e0eb7596161cf snapraid-11.6.tar.gz
8a3b8fd240285b5abf62c3ce222a5c674b475a83b3c48a40e457d34bfbcd1744 snapraid-11.6-windows-x64.zip
e8e9140423552cbccbe9a162100a830cd7d2e29bae0893cca9f5bd1943393508 snapraid-11.6-windows-x86.zip
f07652261e9821a5adfbfa8dad3350aae3e7c285f42a6bd7d96a854e5bc56dda snapraid-12.0.tar.gz
a9cd1e30042b09ecc42b508955a1c1144b446a0399c83ecfb78b5455d528938c snapraid-12.0-windows-x64.zip
a037d16bb9d226da2c88df00e410f9e637f1acb6153ac078c9a3805e721282a6 snapraid-12.0-windows-x86.zip
49337d9bafa96c2beac0125463bd22622be2fc00f3b4dee7e4b0e864d2a49661 snapraid-12.1.tar.gz
23196a373b4c7a327a207f019ea833f888977f6e48743b0060706f67fbb1c13e snapraid-12.1-windows-x64.zip
488e3b57323fd55c1bccc14a051d4048a1a7b7b5d6440ece30b5161bda9f5498 snapraid-12.1-windows-x86.zip
9d30993aef7fd390369dcaf422ac35f3990e8c91f0fb26151f5b84ccb73d3e01 snapraid-12.2.tar.gz
1f08ee889b4e0d221267ad011cfbd6f3ebdf94a8809ba2b2d79dbb0751a7c06a snapraid-12.2-windows-x64.zip
daaccc71a2b2cf3d16d021d0c1f7db20e49fbaebea5cda6c301bf41bce8df073 snapraid-12.2-windows-x86.zip
1f27aba6e5db3929474da9c472fc4a3bc51d4a83aa5385af6b09afc9f68d6d44 snapraid-12.3.tar.gz
ffdd430f5f1ad8fba5bd0707bd860b0d3dca55cb8aeca633804638d64b5f0550 snapraid-12.3-windows-x64.zip
579d24cc607d0668e6f17c905eb75e409086a58f466c6fae2943c8e2fc8de039 snapraid-12.3-windows-x86.zip

25
HISTORY
View File

@ -1,6 +1,31 @@
SnapRAID HISTORY
================
12.4 2025/01
============
* Avoid a warning about function pointer conversion. No functional changes.
12.3 2024/01
============
* Fix potential integer overflow when computing the completion percentage.
No effect on the functionality.
* Documentation improvements.
12.2 2022/08
============
* Fix build issue with GLIBC 2.36
12.1 2022/01
============
* Reduce stack usage to work in environments with limited stack size, like
MUSL.
* Increase the default disk cache from 8 MiB to 16 MiB.
12.0 2021/12
============
* Parallel disk scanning. It's always enabled but it doesn't cover the -m
option that still process disks sequentially.
11.6 2021/10
============
* The 'fix' and 'check' command with the -e option now process the whole

16
INSTALL
View File

@ -7,25 +7,27 @@ code from http://www.snapraid.it and unpack it with:
tar xf snapraid-*.tar.gz
cd snapraid-*
To configure and build run:
To configure and build, run:
./configure
make
To check for correctness of the application run:
To run the correctness tests for the application:
make check
If it terminates with "Success", you can install the application and
the documentation running as root:
If this terminates with "Success", you can install the application and
the documentation by running:
sudo make install
To start using SnapRAID you have to change the example configuration
file snapraid.conf.example to fit your needs and copy it in /etc/snapraid.conf
(The snapraid application itself does not require root privileges.)
To start using SnapRAID, change the example configuration
file snapraid.conf.example to fit your needs and copy it to /etc/snapraid.conf
To get more help, see the "Getting Started" section in the snapraid manpage
typing:
by typing:
man snapraid

View File

@ -286,7 +286,7 @@ endif
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check
#### CONTROLLED ####
$(MSG) Filesystem allocation test
head -c 8192 /dev/zero > bench/disk1/TEST
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/TEST
# Copy the file to trigger the copy optimization check
cp -a bench/disk1/TEST bench/disk2/TEST
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync
@ -301,24 +301,24 @@ endif
# Now sync will complete with -E
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E sync
$(MSG) Filesystem fragmentation test
head -c 8192 /dev/zero > bench/disk1/TEST1
head -c 8192 /dev/zero > bench/disk1/TEST2
head -c 8192 /dev/zero > bench/disk1/TEST3
head -c 8192 /dev/zero > bench/disk1/TEST4
head -c 8192 /dev/zero > bench/disk1/TEST5
head -c 8192 /dev/zero > bench/disk1/TEST6
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/TEST1
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/TEST2
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/TEST3
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/TEST4
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/TEST5
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/TEST6
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync
# Now delete some files, and create a bigger one to fill the holes
rm bench/disk1/TEST1
rm bench/disk1/TEST3
rm bench/disk1/TEST5
head -c 65536 /dev/zero > bench/disk1/TESTX
dd bs=1 count=65536 if=/dev/zero of=bench/disk1/TESTX
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync -l ">&1"
rm -r bench/disk1/TEST*
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E sync
# Now enforce copy detection of a file without parity
# Create a file in a high number disk
head -c 8192 /dev/urandom > bench/disk6/STEP1
dd bs=1 count=8192 if=/dev/urandom of=bench/disk6/STEP1
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync
# Create two new copies. The one in disk1 will copy
# the hash from the one in disk6, and the one in disk2
@ -328,16 +328,16 @@ endif
cp -a bench/disk6/STEP1 bench/disk2/STEP1
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync
# Now create, duplicate, move and partial sync
head -c 8192 /dev/zero > bench/disk1/INVA1
head -c 8192 /dev/zero > bench/disk1/INVA2
head -c 8192 /dev/zero > bench/disk1/INVA3
head -c 8192 /dev/zero > bench/disk1/MOVE1
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/INVA1
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/INVA2
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/INVA3
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/MOVE1
cp -a bench/disk1/MOVE1 bench/disk1/MOVE2
cp -a bench/disk1/MOVE1 bench/disk1/MOVE3
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync
mv bench/disk1/MOVE2 bench/disk2/MOVE2
mv bench/disk1/MOVE3 bench/disk3/MOVE3
head -c 8192 /dev/zero > bench/disk4/MOVE4
dd bs=1 count=8192 if=/dev/zero of=bench/disk4/MOVE4
cp -a bench/disk1/INVA1 bench/disk1/EXTRA1
cp -a bench/disk1/INVA2 bench/disk1/EXTRA2
cp -a bench/disk1/INVA3 bench/disk1/EXTRA3
@ -770,7 +770,7 @@ endif
$(MSG) This triggers the recovering with q using p to check the validity, but failing for new blocks being filled with zero
cp -pR bench/disk1/a bench/disk1/a_copy
# Ensure that there is at least one zero filled file
head -c 8192 /dev/zero > bench/disk1/a_copy/ZERO_FILLED
dd bs=1 count=8192 if=/dev/zero of=bench/disk1/a_copy/ZERO_FILLED
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -B 1 --test-kill-after-sync -c $(CONF) sync
rm -r bench/disk1/a_copy
$(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR2) fix -l test-fail-earlysyncadd.log

File diff suppressed because it is too large Load Diff

44
README
View File

@ -1,33 +1,29 @@
SnapRAID
========
SnapRAID is a backup program for disk arrays. It stores parity
information of your data and it recovers from up to six disk
failures.
SnapRAID is a backup program designed for disk arrays, storing
parity information for data recovery in the event of up to six
disk failures.
SnapRAID is mainly targeted for a home media center, where you
have a lot of big files that rarely change.
Primarily intended for home media centers with large,
infrequently changing files, SnapRAID offers several features:
Beside the ability to recover from disk failures, the other
features of SnapRAID are:
* You can use disk already filled with files, without the need to
reformat them. You will access them like now.
* All your data is hashed to ensure data integrity and to avoid
* You can utilize disks already filled with files without the
need to reformat them, accessing them as usual.
* All your data is hashed to ensure data integrity and prevent
silent corruption.
* If the failed disks are too many to allow a recovery,
you lose the data only on the failed disks.
All the data in the other disks is safe.
* If you accidentally delete some files in a disk, you can
recover them.
* The disks can have different sizes.
* When the number of failed disks exceeds the parity count,
data loss is confined to the affected disks; data on
other disks remains accessible.
* If you accidentally delete files on a disk, recovery is
possible.
* Disks can have different sizes.
* You can add disks at any time.
* It doesn't lock-in your data. You can stop using SnapRAID at any
time without the need to reformat or move data.
* To access a file, only a single disk needs to spin, saving power and
producing less noise.
* SnapRAID doesn't lock in your data; you can stop using it
anytime without reformatting or moving data.
* To access a file, only a single disk needs to spin, saving
power and reducing noise.
The official site of SnapRAID is:
http://www.snapraid.it/
For more information, please visit the official SnapRAID site:
:http://www.snapraid.it/

12
TODO
View File

@ -5,6 +5,18 @@ This is the list of TODO items for SnapRAID.
- Next
* Add an option to ignore a specific Smart attribute. This solves PullRequest #17 an #21
* Support BTRFS subvolumes. Keep track of the subvolumeid, along with the inode, and use it when searching/comparing inodes.
The value 0 can be used for the root volume, like a normal filesystem.
See: https://github.com/kdave/btrfs-progs/tree/master/libbtrfsutil
* A "dependents" output option to [--test-fmt file|disk|path|dependents] for LIST.
Example, snapraid LIST --test-fmt dependents >FileList_with_dependents.txt
The goal is a filelist that, for every file, includes full paths to the dependent files
on other data disks needed to repair that file (in addition to the parity data).
I created a thread about it here: https://sourceforge.net/p/snapraid/discussion/1677233/thread/6e872fdae0/
- Minor
* Add a new -u, --filter-updated command that filters files

838
aclocal.m4 vendored
View File

@ -1,838 +0,0 @@
# generated automatically by aclocal 1.15 -*- Autoconf -*-
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
[m4_warning([this file was generated for autoconf 2.69.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# Copyright (C) 2002-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.15'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.15], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# _AM_AUTOCONF_VERSION(VERSION)
# -----------------------------
# aclocal traces this macro to find the Autoconf version.
# This is a private macro too. Using m4_define simplifies
# the logic in aclocal, which can simply ignore this definition.
m4_define([_AM_AUTOCONF_VERSION], [])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.15])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
# therefore $ac_aux_dir as well) can be either absolute or relative,
# depending on how configure is run. This is pretty annoying, since
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
# source directory, any form will work fine, but in subdirectories a
# relative path needs to be adjusted first.
#
# $ac_aux_dir/missing
# fails when called from a subdirectory if $ac_aux_dir is relative
# $top_srcdir/$ac_aux_dir/missing
# fails if $ac_aux_dir is absolute,
# fails when called from a subdirectory in a VPATH build with
# a relative $ac_aux_dir
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
# harmless because $srcdir is '.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
# and then we would define $MISSING as
# MISSING="\${SHELL} $am_aux_dir/missing"
# This will work as long as MISSING is not called from configure, because
# unfortunately $(top_srcdir) has no meaning in configure.
# However there are other variables, like CC, which are often used in
# configure, and could therefore not use this "fixed" $ac_aux_dir.
#
# Another solution, used here, is to always expand $ac_aux_dir to an
# absolute PATH. The drawback is that using absolute paths prevent a
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
# Expand $ac_aux_dir to an absolute path.
am_aux_dir=`cd "$ac_aux_dir" && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[AC_PREREQ([2.52])dnl
m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
m4_define([_AM_COND_VALUE_$1], [$2])dnl
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi
AC_CONFIG_COMMANDS_PRE(
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
AC_MSG_ERROR([[conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.]])
fi])])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
m4_define([AC_PROG_CC],
m4_defn([AC_PROG_CC])
[_AM_PROG_CC_C_O
])
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
# AM_INIT_AUTOMAKE([OPTIONS])
# -----------------------------------------------
# The call with PACKAGE and VERSION arguments is the old style
# call (pre autoconf-2.50), which is being phased out. PACKAGE
# and VERSION should now be passed to AC_INIT and removed from
# the call to AM_INIT_AUTOMAKE.
# We support both call styles for the transition. After
# the next Automake release, Autoconf can make the AC_INIT
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.65])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
AC_REQUIRE([AC_PROG_INSTALL])dnl
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
fi
# test whether we have cygpath
if test -z "$CYGPATH_W"; then
if (cygpath --version) >/dev/null 2>/dev/null; then
CYGPATH_W='cygpath -w'
else
CYGPATH_W=echo
fi
fi
AC_SUBST([CYGPATH_W])
# Define the identity of the package.
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
[AC_DIAGNOSE([obsolete],
[$0: two- and three-arguments forms are deprecated.])
m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
[ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
_AM_IF_OPTION([no-define],,
[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
# Some tools Automake needs.
AC_REQUIRE([AM_SANITY_CHECK])dnl
AC_REQUIRE([AC_ARG_PROGRAM])dnl
AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
AM_MISSING_PROG([AUTOCONF], [autoconf])
AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
AM_MISSING_PROG([AUTOHEADER], [autoheader])
AM_MISSING_PROG([MAKEINFO], [makeinfo])
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
# For better backward compatibility. To be removed once Automake 1.9.x
# dies out for good. For more background, see:
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
# We need awk for the "check" target (and possibly the TAP driver). The
# system "awk" is bad on some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
[_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
[_AM_DEPENDENCIES([CC])],
[m4_define([AC_PROG_CC],
m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES([CXX])],
[m4_define([AC_PROG_CXX],
m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES([OBJC])],
[m4_define([AC_PROG_OBJC],
m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[_AM_DEPENDENCIES([OBJCXX])],
[m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
])
AC_REQUIRE([AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
# POSIX will say in a future version that running "rm -f" with no argument
# is OK; and we want to be able to make that assumption in our Makefile
# recipes. So use an aggressive probe to check that the usage we want is
# actually supported "in the wild" to an acceptable degree.
# See automake bug#10828.
# To make any issue more visible, cause the running configure to be aborted
# by default if the 'rm' program in use doesn't match our expectations; the
# user can still override this though.
if rm -f && rm -fr && rm -rf; then : OK; else
cat >&2 <<'END'
Oops!
Your 'rm' program seems unable to run without file operands specified
on the command line, even when the '-f' option is present. This is contrary
to the behaviour of most rm programs out there, and not conforming with
the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
Please tell bug-automake@gnu.org about your system, including the value
of your $PATH and any error possibly output before this message. This
can help us improve future automake versions.
END
if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
echo 'Configuration will proceed anyway, since you have set the' >&2
echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
echo >&2
else
cat >&2 <<'END'
Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <http://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
to "yes", and re-run configure.
END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi
fi
dnl The trailing newline in this macro's definition is deliberate, for
dnl backward compatibility and to allow trailing 'dnl'-style comments
dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
])
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
dnl mangled by Autoconf and run in a shell conditional statement.
m4_define([_AC_COMPILER_EXEEXT],
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp files are numbered to have different names.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[# Compute $1's index in $config_headers.
_am_arg=$1
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
if test x"${install_sh+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
*)
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
[rm -rf .tst 2>/dev/null
mkdir .tst 2>/dev/null
if test -d .tst; then
am__leading_dot=.
else
am__leading_dot=_
fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
[AC_REQUIRE([AM_MISSING_HAS_RUN])
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
# AM_MISSING_HAS_RUN
# ------------------
# Define MISSING if not defined so far and test if it is modern enough.
# If it is, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
am_missing_run="$MISSING "
else
am_missing_run=
AC_MSG_WARN(['missing' script is too old or missing])
fi
])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
# --------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
# _AM_SET_OPTIONS(OPTIONS)
# ------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
# -------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_PROG_CC_C_O
# ---------------
# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
# to automatically call this.
AC_DEFUN([_AM_PROG_CC_C_O],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([compile])dnl
AC_LANG_PUSH([C])dnl
AC_CACHE_CHECK(
[whether $CC understands -c and -o together],
[am_cv_prog_cc_c_o],
[AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
# Make sure it works both with $CC and with simple cc.
# Following AC_PROG_CC_C_O, we do the test twice because some
# compilers refuse to overwrite an existing .o file with -o,
# though they will create one.
am_cv_prog_cc_c_o=yes
for am_i in 1 2; do
if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
&& test -f conftest2.$ac_objext; then
: OK
else
am_cv_prog_cc_c_o=no
break
fi
done
rm -f core conftest*
unset am_i])
if test "$am_cv_prog_cc_c_o" != yes; then
# Losing compiler, so override with the script.
# FIXME: It is wrong to rewrite CC.
# But if we don't then we get into trouble of one sort or another.
# A longer-term fix would be to have automake use am__CC in this case,
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
CC="$am_aux_dir/compile $CC"
fi
AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_RUN_LOG(COMMAND)
# -------------------
# Run COMMAND, save the exit status in ac_status, and log it.
# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
AC_DEFUN([AM_RUN_LOG],
[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
(exit $ac_status); }])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
'
case `pwd` in
*[[\\\"\#\$\&\'\`$am_lf]]*)
AC_MSG_ERROR([unsafe absolute working directory name]);;
esac
case $srcdir in
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
esac
# Do 'set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
am_has_slept=no
for am_try in 1 2; do
echo "timestamp, slept: $am_has_slept" > conftest.file
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$[*]" = "X"; then
# -L didn't work.
set X `ls -t "$srcdir/configure" conftest.file`
fi
if test "$[*]" != "X $srcdir/configure conftest.file" \
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
if test "$[2]" = conftest.file || test $am_try -eq 2; then
break
fi
# Just in case.
sleep 1
am_has_slept=yes
done
test "$[2]" = conftest.file
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
AC_MSG_RESULT([yes])
# If we didn't sleep, we still need to ensure time stamps of config.status and
# generated files are strictly newer.
am_sleep_pid=
if grep 'slept: no' conftest.file >/dev/null 2>&1; then
( sleep 1 ) &
am_sleep_pid=$!
fi
AC_CONFIG_COMMANDS_PRE(
[AC_MSG_CHECKING([that generated files are newer than configure])
if test -n "$am_sleep_pid"; then
# Hide warnings about reused PIDs.
wait $am_sleep_pid 2>/dev/null
fi
AC_MSG_RESULT([done])])
rm -f conftest.file
])
# Copyright (C) 2009-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_SILENT_RULES([DEFAULT])
# --------------------------
# Enable less verbose build rules; with the default set to DEFAULT
# ("yes" being less verbose, "no" or empty being verbose).
AC_DEFUN([AM_SILENT_RULES],
[AC_ARG_ENABLE([silent-rules], [dnl
AS_HELP_STRING(
[--enable-silent-rules],
[less verbose build output (undo: "make V=1")])
AS_HELP_STRING(
[--disable-silent-rules],
[verbose build output (undo: "make V=0")])dnl
])
case $enable_silent_rules in @%:@ (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
esac
dnl
dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
dnl do not support nested variable expansions.
dnl See automake bug#9928 and bug#10237.
am_make=${MAKE-make}
AC_CACHE_CHECK([whether $am_make supports nested variables],
[am_cv_make_support_nested_variables],
[if AS_ECHO([['TRUE=$(BAR$(V))
BAR0=false
BAR1=true
V=1
am__doit:
@$(TRUE)
.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
am_cv_make_support_nested_variables=yes
else
am_cv_make_support_nested_variables=no
fi])
if test $am_cv_make_support_nested_variables = yes; then
dnl Using '$V' instead of '$(V)' breaks IRIX make.
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
AC_SUBST([AM_V])dnl
AM_SUBST_NOTMAKE([AM_V])dnl
AC_SUBST([AM_DEFAULT_V])dnl
AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
AM_BACKSLASH='\'
AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_STRIP
# ---------------------
# One issue with vendor 'install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
# is unlikely to handle the host's binaries.
# Fortunately install-sh will honor a STRIPPROG variable, so we
# always use install-sh in "make install-strip", and initialize
# STRIPPROG with the value of the STRIP variable (set by the user).
AC_DEFUN([AM_PROG_INSTALL_STRIP],
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
# Installed binaries are usually stripped using 'strip' when the user
# run "make install-strip". However 'strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the 'STRIP' environment variable to overrule this program.
dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
if test "$cross_compiling" != no; then
AC_CHECK_TOOL([STRIP], [strip], :)
fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
# --------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2014 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
# FORMAT should be one of 'v7', 'ustar', or 'pax'.
#
# Substitute a variable $(am__tar) that is a command
# writing to stdout a FORMAT-tarball containing the directory
# $tardir.
# tardir=directory && $(am__tar) > result.tar
#
# Substitute a variable $(am__untar) that extract such
# a tarball read from stdin.
# $(am__untar) < result.tar
#
AC_DEFUN([_AM_PROG_TAR],
[# Always define AMTAR for backward compatibility. Yes, it's still used
# in the wild :-( We should find a proper way to deprecate it ...
AC_SUBST([AMTAR], ['$${TAR-tar}'])
# We'll loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
m4_if([$1], [v7],
[am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
[m4_case([$1],
[ustar],
[# The POSIX 1988 'ustar' format is defined with fixed-size fields.
# There is notably a 21 bits limit for the UID and the GID. In fact,
# the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
# and bug#13588).
am_max_uid=2097151 # 2^21 - 1
am_max_gid=$am_max_uid
# The $UID and $GID variables are not portable, so we need to resort
# to the POSIX-mandated id(1) utility. Errors in the 'id' calls
# below are definitely unexpected, so allow the users to see them
# (that is, avoid stderr redirection).
am_uid=`id -u || echo unknown`
am_gid=`id -g || echo unknown`
AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
if test $am_uid -le $am_max_uid; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
_am_tools=none
fi
AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
if test $am_gid -le $am_max_gid; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
_am_tools=none
fi],
[pax],
[],
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Go ahead even if we have the value already cached. We do so because we
# need to set the values for the 'am__tar' and 'am__untar' variables.
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
for _am_tool in $_am_tools; do
case $_am_tool in
gnutar)
for _am_tar in tar gnutar gtar; do
AM_RUN_LOG([$_am_tar --version]) && break
done
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
am__untar="$_am_tar -xf -"
;;
plaintar)
# Must skip GNU tar: if it does not support --format= it doesn't create
# ustar tarball either.
(tar --version) >/dev/null 2>&1 && continue
am__tar='tar chf - "$$tardir"'
am__tar_='tar chf - "$tardir"'
am__untar='tar xf -'
;;
pax)
am__tar='pax -L -x $1 -w "$$tardir"'
am__tar_='pax -L -x $1 -w "$tardir"'
am__untar='pax -r'
;;
cpio)
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
am__untar='cpio -i -H $1 -d'
;;
none)
am__tar=false
am__tar_=false
am__untar=false
;;
esac
# If the value was cached, stop now. We just wanted to have am__tar
# and am__untar set.
test -n "${am_cv_prog_tar_$1}" && break
# tar/untar a dummy directory, and stop if the command works.
rm -rf conftest.dir
mkdir conftest.dir
echo GrepMe > conftest.dir/file
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
rm -rf conftest.dir
if test -s conftest.tar; then
AM_RUN_LOG([$am__untar <conftest.tar])
AM_RUN_LOG([cat conftest.dir/file])
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
fi
done
rm -rf conftest.dir
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([acinclude.m4])

View File

@ -1896,7 +1896,7 @@ bail:
if (error && !fix)
log_fatal("WARNING! There are errors!\n");
if (unrecoverable_error)
log_fatal("DANGER! There are unrecoverable errors!\n");
log_fatal("DANGER! Unrecoverable errors detected!\n");
log_tag("summary:error:%u\n", error);
if (fix)
@ -1974,7 +1974,7 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
if (blockstart > blockmax) {
/* LCOV_EXCL_START */
log_fatal("Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
log_fatal("Error in the specified starting block %u. It's larger than the parity size %u.\n", blockstart, blockmax);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}

View File

@ -403,7 +403,7 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (blockstart > blockmax) {
/* LCOV_EXCL_START */
log_fatal("Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
log_fatal("Error in the specified starting block %u. It's larger than the parity size %u.\n", blockstart, blockmax);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}

View File

@ -435,21 +435,21 @@ void file_copy(struct snapraid_file* src_file, struct snapraid_file* dst_file)
if (src_file->size != dst_file->size) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in copy file with different size\n");
log_fatal("Internal inconsistency: Copy file with different size\n");
os_abort();
/* LCOV_EXCL_STOP */
}
if (src_file->mtime_sec != dst_file->mtime_sec) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in copy file with different mtime_sec\n");
log_fatal("Internal inconsistency: Copy file with different mtime_sec\n");
os_abort();
/* LCOV_EXCL_STOP */
}
if (src_file->mtime_nsec != dst_file->mtime_nsec) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in copy file with different mtime_nsec\n");
log_fatal("Internal inconsistency: Copy file with different mtime_nsec\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -499,7 +499,7 @@ int file_block_is_last(struct snapraid_file* file, block_off_t file_pos)
if (file_pos >= file->blockmax) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in file block position\n");
log_fatal("Internal inconsistency: File block position over the max\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -620,13 +620,13 @@ struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_fil
if (count == 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when allocating empty extent for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
log_fatal("Internal inconsistency: Allocating empty extent for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
os_abort();
/* LCOV_EXCL_STOP */
}
if (file_pos + count > file->blockmax) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when allocating overflowing extent for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax);
log_fatal("Internal inconsistency: Allocating overflowing extent for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -938,7 +938,7 @@ static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj)
if (obj->count == 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in parity count zero for file '%s' at '%u'\n",
log_fatal("Internal inconsistency: Parity count zero for file '%s' at '%u'\n",
obj->file->sub, obj->parity_pos);
++arg->result;
return;
@ -952,7 +952,7 @@ static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj)
/* check the order */
if (prev->parity_pos >= obj->parity_pos) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
log_fatal("Internal inconsistency: Parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count);
++arg->result;
return;
@ -962,7 +962,7 @@ static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj)
/* check that the extents don't overlap */
if (prev->parity_pos + prev->count > obj->parity_pos) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency for parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
log_fatal("Internal inconsistency: Parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n",
prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count);
++arg->result;
return;
@ -988,7 +988,7 @@ static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
if (obj->count == 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in file count zero for file '%s' at '%u'\n",
log_fatal("Internal inconsistency: File count zero for file '%s' at '%u'\n",
obj->file->sub, obj->file_pos);
++arg->result;
return;
@ -1004,7 +1004,7 @@ static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
/* check that the extent doesn't overflow the file */
if (prev->file_pos + prev->count > prev->file->blockmax) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in delete end for file '%s' at '%u:%u' overflowing size '%u'\n",
log_fatal("Internal inconsistency: Delete end for file '%s' at '%u:%u' overflowing size '%u'\n",
prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax);
++arg->result;
return;
@ -1014,7 +1014,7 @@ static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
/* check that the extent ends the file */
if (prev->file_pos + prev->count != prev->file->blockmax) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in file end for file '%s' at '%u:%u' instead of size '%u'\n",
log_fatal("Internal inconsistency: File end for file '%s' at '%u:%u' instead of size '%u'\n",
prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax);
++arg->result;
return;
@ -1027,7 +1027,7 @@ static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
/* check that the extent doesn't overflow the file */
if (obj->file_pos + obj->count > obj->file->blockmax) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in delete start for file '%s' at '%u:%u' overflowing size '%u'\n",
log_fatal("Internal inconsistency: Delete start for file '%s' at '%u:%u' overflowing size '%u'\n",
obj->file->sub, obj->file_pos, obj->count, obj->file->blockmax);
++arg->result;
return;
@ -1037,7 +1037,7 @@ static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
/* check that the extent starts the file */
if (obj->file_pos != 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in file start for file '%s' at '%u:%u'\n",
log_fatal("Internal inconsistency: File start for file '%s' at '%u:%u'\n",
obj->file->sub, obj->file_pos, obj->count);
++arg->result;
return;
@ -1048,7 +1048,7 @@ static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
/* check the order */
if (prev->file_pos >= obj->file_pos) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in file order for file '%s' at '%u:%u' and at '%u:%u'\n",
log_fatal("Internal inconsistency: File order for file '%s' at '%u:%u' and at '%u:%u'\n",
prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
++arg->result;
return;
@ -1059,7 +1059,7 @@ static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
/* check that the extents don't overlap */
if (prev->file_pos + prev->count > obj->file_pos) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in delete sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
log_fatal("Internal inconsistency: Delete sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
++arg->result;
return;
@ -1069,7 +1069,7 @@ static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj)
/* check that the extents are sequential */
if (prev->file_pos + prev->count != obj->file_pos) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in file sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
log_fatal("Internal inconsistency: File sequence for file '%s' at '%u:%u' and at '%u:%u'\n",
prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count);
++arg->result;
return;
@ -1267,7 +1267,7 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap
/* ensure that we are extending the extent at the end */
if (file_pos != extent->file_pos + extent->count) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name);
log_fatal("Internal inconsistency: Allocating file '%s' at position '%u/%u' in the middle of extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1289,7 +1289,7 @@ void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snap
if (parity_extent != extent || file_extent != extent) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name);
log_fatal("Internal inconsistency: Allocating file '%s' at position '%u/%u' for existing extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1313,7 +1313,7 @@ void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos)
extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos);
if (!extent) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing extent in disk '%s'\n", parity_pos, disk->name);
log_fatal("Internal inconsistency: Deallocating parity position '%u' for not existing extent in disk '%s'\n", parity_pos, disk->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1368,7 +1368,7 @@ void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos)
if (parity_extent != second_extent || file_extent != second_extent) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when deallocating parity position '%u' for splitting extent '%u:%u' in disk '%s'\n", parity_pos, second_extent->file_pos, second_extent->count, disk->name);
log_fatal("Internal inconsistency: Deallocating parity position '%u' for splitting extent '%u:%u' in disk '%s'\n", parity_pos, second_extent->file_pos, second_extent->count, disk->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1383,7 +1383,7 @@ struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t
{
if (file_pos >= file->blockmax) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
log_fatal("Internal inconsistency: Dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax);
os_abort();
/* LCOV_EXCL_STOP */
}

View File

@ -369,6 +369,13 @@ struct snapraid_disk {
*/
thread_mutex_t fs_mutex;
int fs_mutex_enabled; /*< If the lock has to be used. */
/**
* Mutex for protecting the scan process.
*
* It's used during the scan process to protect the stampset to identity copy of files
*/
thread_mutex_t stamp_mutex;
#endif
/**
@ -1041,7 +1048,7 @@ static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk,
ret = fs_par2file_find(disk, parity_pos, file_pos);
if (ret == 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when deresolving parity to file at position '%u' in disk '%s'\n", parity_pos, disk->name);
log_fatal("Internal inconsistency: Deresolving parity to file at position '%u' in disk '%s'\n", parity_pos, disk->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1065,7 +1072,7 @@ static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct sna
ret = fs_file2par_find(disk, file, file_pos);
if (ret == POS_NULL) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name);
log_fatal("Internal inconsistency: Resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1089,7 +1096,7 @@ static inline struct snapraid_block* fs_par2block_get(struct snapraid_disk* disk
ret = fs_par2block_find(disk, parity_pos);
if (ret == BLOCK_NULL) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency when deresolving parity to block at position '%u' in disk '%s'\n", parity_pos, disk->name);
log_fatal("Internal inconsistency: Deresolving parity to block at position '%u' in disk '%s'\n", parity_pos, disk->name);
os_abort();
/* LCOV_EXCL_STOP */
}

View File

@ -879,9 +879,9 @@ void io_init(struct snapraid_io* io, struct snapraid_state* state,
#if HAVE_THREAD
if (io_cache == 0) {
/* default is 8 MiB of cache */
/* default is 16 MiB of cache */
/* this seems to be a good tradeoff between speed and memory usage */
io->io_max = 8 * 1024 * 1024 / state->block_size;
io->io_max = 16 * 1024 * 1024 / state->block_size;
if (io->io_max < IO_MIN)
io->io_max = IO_MIN;
if (io->io_max > IO_MAX)

View File

@ -35,8 +35,8 @@
* 4 - 452 MB/s, CPU 54%, speed 118%
* 8 - 487 MB/s, CPU 60%, speed 128%
* 16 - 505 MB/s, CPU 63%, speed 132%
* 32 - 520 MB/s, CPU 64%, speed 136%
* 64 - 524 MB/s, CPU 65%, speed 137%
* 32 - 520 MB/s, CPU 64%, speed 136% [SnapRAID <= 12.0]
* 64 - 524 MB/s, CPU 65%, speed 137% [SnapRAID > 12.0]
* 128 - 525 MB/s, CPU 66%, speed 138%
*/
#define IO_MIN 3 /* required by writers, readers can work also with 2 */

View File

@ -31,14 +31,26 @@ int exit_sync_needed = 2;
/* Add missing Windows declaration */
/* For SetThreadExecutionState */
#ifndef WIN32_ES_SYSTEM_REQUIRED
#define WIN32_ES_SYSTEM_REQUIRED 0x00000001L
#endif
#ifndef WIN32_ES_DISPLAY_REQUIRED
#define WIN32_ES_DISPLAY_REQUIRED 0x00000002L
#endif
#ifndef WIN32_ES_USER_PRESENT
#define WIN32_ES_USER_PRESENT 0x00000004L
#endif
#ifndef WIN32_ES_AWAYMODE_REQUIRED
#define WIN32_ES_AWAYMODE_REQUIRED 0x00000040L
#endif
#ifndef WIN32_ES_CONTINUOUS
#define WIN32_ES_CONTINUOUS 0x80000000L
#endif
/* File Index */
#ifndef FILE_INVALID_FILE_ID
#define FILE_INVALID_FILE_ID ((ULONGLONG)-1LL)
#endif
/**
* Direct access to RtlGenRandom().
@ -475,7 +487,7 @@ static void windows_attr2stat(DWORD FileAttributes, DWORD ReparseTag, struct win
*/
static int windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ATTRIBUTE_TAG_INFO* tag, struct windows_stat* st)
{
uint64_t mtime;
int64_t mtime;
windows_attr2stat(info->dwFileAttributes, tag->ReparseTag, st);
@ -518,7 +530,7 @@ static int windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_
* "that includes 128-bit file identifiers. If GetFileInformationByHandle returns"
* "FILE_INVALID_FILE_ID, the identifier may only be described in 128 bit form."
*/
if (st->st_ino == FILE_INVALID_FILE_ID) {
if (st->st_ino == (uint64_t)FILE_INVALID_FILE_ID) {
log_fatal("Invalid inode number! Is this ReFS?\n");
errno = EINVAL;
return -1;
@ -532,7 +544,7 @@ static int windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_
*/
static int windows_stream2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ID_BOTH_DIR_INFO* stream, struct windows_stat* st)
{
uint64_t mtime;
int64_t mtime;
/* The FILE_ID_BOTH_DIR_INFO doesn't have the ReparseTag information */
/* we could use instead FILE_ID_EXTD_DIR_INFO, but it's available only */
@ -563,7 +575,7 @@ static int windows_stream2stat(const BY_HANDLE_FILE_INFORMATION* info, const FIL
st->st_sync = 0;
/* in ReFS the IDs are 128 bit, and the 64 bit interface may fail */
if (st->st_ino == FILE_INVALID_FILE_ID) {
if (st->st_ino == (uint64_t)FILE_INVALID_FILE_ID) {
log_fatal("Invalid inode number! Is this ReFS?\n");
errno = EINVAL;
return -1;
@ -577,7 +589,7 @@ static int windows_stream2stat(const BY_HANDLE_FILE_INFORMATION* info, const FIL
*/
static void windows_finddata2stat(const WIN32_FIND_DATAW* info, struct windows_stat* st)
{
uint64_t mtime;
int64_t mtime;
windows_attr2stat(info->dwFileAttributes, info->dwReserved0, st);
@ -789,7 +801,7 @@ static BOOL GetFilePhysicalOffset(HANDLE h, uint64_t* physical)
BOOL ret;
DWORD n;
/* in Wine FSCTL_GET_RETRIVIAL_POINTERS is not supported */
/* in Wine FSCTL_GET_RETRIEVAL_POINTERS is not supported */
if (is_wine) {
*physical = FILEPHY_UNREPORTED_OFFSET;
return TRUE;
@ -1039,7 +1051,7 @@ int windows_futimens(int fd, struct windows_timespec tv[2])
{
HANDLE h;
FILETIME ft;
uint64_t mtime;
int64_t mtime;
if (fd == -1) {
errno = EBADF;
@ -1061,7 +1073,7 @@ int windows_futimens(int fd, struct windows_timespec tv[2])
mtime = tv[0].tv_sec;
mtime *= 10000000;
mtime += tv[0].tv_nsec / 100;
mtime += 116444736000000000;
mtime += 116444736000000000LL;
ft.dwHighDateTime = mtime >> 32;
ft.dwLowDateTime = mtime;
@ -1079,7 +1091,7 @@ int windows_utimensat(int fd, const char* file, struct windows_timespec tv[2], i
wchar_t conv_buf[CONV_MAX];
HANDLE h;
FILETIME ft;
uint64_t mtime;
int64_t mtime;
DWORD wflags;
/*
@ -1119,7 +1131,7 @@ int windows_utimensat(int fd, const char* file, struct windows_timespec tv[2], i
mtime = tv[0].tv_sec;
mtime *= 10000000;
mtime += tv[0].tv_nsec / 100;
mtime += 116444736000000000;
mtime += 116444736000000000LL;
ft.dwHighDateTime = mtime >> 32;
ft.dwLowDateTime = mtime;
@ -1556,7 +1568,7 @@ int windows_link(const char* existing, const char* file)
}
/**
* In Windows 10 allow creation of symblink by not privileged user.
* In Windows 10 allow creation of symlink by not privileged user.
*
* See: Symlinks in Windows 10!
* https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/#cQG7cx48oGH86lkI.97

View File

@ -152,8 +152,8 @@ void parity_overflow(struct snapraid_state* state, data_off_t size)
}
if (found) {
log_fatal("\nYour data requires more parity than the available space.\n");
log_fatal("Please move the files 'outofparity' to another data disk.\n");
log_fatal("\nInsufficient parity space. Data requires more parity than available.\n");
log_fatal("Move the 'outofparity' files to a larger disk.\n");
}
}

View File

@ -362,7 +362,7 @@ int devuuid(uint64_t device, char* uuid, size_t size);
#define FILEPHY_REAL_OFFSET 3
/**
* Get the physcal address of the specified file.
* Get the physical address of the specified file.
* This is expected to be just a hint and not necessarily correct or unique.
* Return 0 on success.
*/

View File

@ -25,6 +25,17 @@
struct snapraid_scan {
struct snapraid_state* state; /**< State used. */
struct snapraid_disk* disk; /**< Disk used. */
thread_id_t thread; /**< Thread used for scanning the disk */
int is_diff; /**< If it's a diff command or a scanning */
int need_write; /**< If a state write is required */
#if HAVE_THREAD
/**
* Mutex for protecting the disk stampset table
*/
thread_mutex_t mutex;
#endif
/**
* Counters of changes.
@ -45,16 +56,69 @@ struct snapraid_scan {
tommy_node node;
};
static struct snapraid_scan* scan_alloc(struct snapraid_state* state, struct snapraid_disk* disk, int is_diff)
{
struct snapraid_scan* scan;
scan = malloc_nofail(sizeof(struct snapraid_scan));
scan->state = state;
scan->disk = disk;
scan->count_equal = 0;
scan->count_move = 0;
scan->count_copy = 0;
scan->count_restore = 0;
scan->count_change = 0;
scan->count_remove = 0;
scan->count_insert = 0;
tommy_list_init(&scan->file_insert_list);
tommy_list_init(&scan->link_insert_list);
tommy_list_init(&scan->dir_insert_list);
scan->is_diff = is_diff;
scan->need_write = 0;
#if HAVE_THREAD
thread_mutex_init(&disk->stamp_mutex);
#endif
return scan;
}
static void scan_free(struct snapraid_scan* scan)
{
#if HAVE_THREAD
thread_mutex_destroy(&scan->disk->stamp_mutex);
#endif
free(scan);
}
static void stamp_lock(struct snapraid_disk* disk)
{
#if HAVE_THREAD
thread_mutex_lock(&disk->stamp_mutex);
#else
(void)disk;
#endif
}
static void stamp_unlock(struct snapraid_disk* disk)
{
#if HAVE_THREAD
thread_mutex_unlock(&disk->stamp_mutex);
#else
(void)disk;
#endif
}
/**
* Remove the specified link from the data set.
*/
static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* slink)
{
struct snapraid_state* state = scan->state;
struct snapraid_disk* disk = scan->disk;
/* state changed */
state->need_write = 1;
scan->need_write = 1;
/* remove the file from the link containers */
tommy_hashdyn_remove_existing(&disk->linkset, &slink->nodeset);
@ -69,11 +133,10 @@ static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* s
*/
static void scan_link_insert(struct snapraid_scan* scan, struct snapraid_link* slink)
{
struct snapraid_state* state = scan->state;
struct snapraid_disk* disk = scan->disk;
/* state changed */
state->need_write = 1;
scan->need_write = 1;
/* insert the link in the link containers */
tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub));
@ -116,13 +179,13 @@ static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub,
/* it's an update */
/* we have to save the linkto/type */
state->need_write = 1;
scan->need_write = 1;
++scan->count_change;
log_tag("scan:update:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));
if (is_diff) {
printf("update %s\n", fmt_term(disk, slink->sub, esc_buffer));
msg_info("update %s\n", fmt_term(disk, slink->sub, esc_buffer));
}
/* update it */
@ -139,7 +202,7 @@ static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub,
log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
if (is_diff) {
printf("add %s\n", fmt_term(disk, sub, esc_buffer));
msg_info("add %s\n", fmt_term(disk, sub, esc_buffer));
}
/* and continue to insert it */
@ -166,7 +229,7 @@ static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file*
block_off_t parity_pos;
/* state changed */
state->need_write = 1;
scan->need_write = 1;
/* allocate the blocks of the file */
parity_pos = disk->first_free_block;
@ -267,7 +330,7 @@ static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_fil
tommy_list_remove_existing(&disk->filelist, &file->nodelist);
/* state changed */
state->need_write = 1;
scan->need_write = 1;
/* here we are supposed to adjust the ::first_free_block position */
/* with the parity position we are deleting */
@ -563,8 +626,11 @@ static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* f
/* insert the file in the containers */
if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
stamp_lock(disk);
tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec));
stamp_unlock(disk);
/* delayed allocation of the parity */
scan_file_delayed_allocate(scan, file);
@ -583,7 +649,10 @@ static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* f
if (!file_flag_has(file, FILE_IS_WITHOUT_INODE))
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset);
stamp_lock(disk);
tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset);
stamp_unlock(disk);
/* deallocate the file from the parity */
scan_file_deallocate(scan, file);
@ -706,7 +775,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
file->mtime_nsec = STAT_NSEC(st);
/* we have to save the new mtime */
state->need_write = 1;
scan->need_write = 1;
}
if (strcmp(file->sub, sub) != 0) {
@ -715,7 +784,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
log_tag("scan:move:%s:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer), esc_tag(sub, esc_buffer_alt));
if (is_diff) {
printf("move %s -> %s\n", fmt_term(disk, file->sub, esc_buffer), fmt_term(disk, sub, esc_buffer_alt));
msg_info("move %s -> %s\n", fmt_term(disk, file->sub, esc_buffer), fmt_term(disk, sub, esc_buffer_alt));
}
/* remove from the name set */
@ -728,7 +797,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub));
/* we have to save the new name */
state->need_write = 1;
scan->need_write = 1;
} else {
/* otherwise it's equal */
++scan->count_equal;
@ -864,7 +933,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
file->mtime_nsec = STAT_NSEC(st);
/* we have to save the new mtime */
state->need_write = 1;
scan->need_write = 1;
}
/* if when processing the disk we used the past inodes values */
@ -878,7 +947,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
if (is_diff) {
printf("restore %s\n", fmt_term(disk, sub, esc_buffer));
msg_info("restore %s\n", fmt_term(disk, sub, esc_buffer));
}
/* remove from the inode set */
@ -891,7 +960,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode));
/* we have to save the new inode */
state->need_write = 1;
scan->need_write = 1;
} else {
/* otherwise it's the case of not persistent inode, where doesn't */
/* matter if the inode is different or equal, because they have no */
@ -976,12 +1045,14 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
struct snapraid_disk* other_disk = i->data;
struct snapraid_file* other_file;
stamp_lock(other_disk);
/* if the nanosecond part of the time stamp is valid, search */
/* for name and stamp, otherwise for path and stamp */
if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID)
other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash);
else
other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash);
stamp_unlock(other_disk);
/* if found, and it's a fully hashed file */
if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) {
@ -993,7 +1064,7 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc_tag(other_file->sub, esc_buffer), disk->name, esc_tag(file->sub, esc_buffer_alt));
if (is_diff) {
printf("copy %s -> %s\n", fmt_term(other_disk, other_file->sub, esc_buffer), fmt_term(disk, file->sub, esc_buffer_alt));
msg_info("copy %s -> %s\n", fmt_term(other_disk, other_file->sub, esc_buffer), fmt_term(disk, file->sub, esc_buffer_alt));
}
/* mark it as reported */
@ -1017,14 +1088,14 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
);
if (is_diff) {
printf("update %s\n", fmt_term(disk, sub, esc_buffer));
msg_info("update %s\n", fmt_term(disk, sub, esc_buffer));
}
} else {
++scan->count_insert;
log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer));
if (is_diff) {
printf("add %s\n", fmt_term(disk, sub, esc_buffer));
msg_info("add %s\n", fmt_term(disk, sub, esc_buffer));
}
}
}
@ -1038,11 +1109,10 @@ static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub,
*/
static void scan_emptydir_remove(struct snapraid_scan* scan, struct snapraid_dir* dir)
{
struct snapraid_state* state = scan->state;
struct snapraid_disk* disk = scan->disk;
/* state changed */
state->need_write = 1;
scan->need_write = 1;
/* remove the file from the dir containers */
tommy_hashdyn_remove_existing(&disk->dirset, &dir->nodeset);
@ -1057,11 +1127,10 @@ static void scan_emptydir_remove(struct snapraid_scan* scan, struct snapraid_dir
*/
static void scan_emptydir_insert(struct snapraid_scan* scan, struct snapraid_dir* dir)
{
struct snapraid_state* state = scan->state;
struct snapraid_disk* disk = scan->disk;
/* state changed */
state->need_write = 1;
scan->need_write = 1;
/* insert the dir in the dir containers */
tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub));
@ -1172,7 +1241,7 @@ struct stat* dstat(const char* file, struct stat* st)
* Process a directory.
* Return != 0 if at least one file or link is processed.
*/
static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub)
static int scan_sub(struct snapraid_scan* scan, int level, int is_diff, char* path_next, char* sub_next, char* tmp)
{
struct snapraid_state* state = scan->state;
struct snapraid_disk* disk = scan->disk;
@ -1180,25 +1249,28 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
DIR* d;
tommy_list list;
tommy_node* node;
size_t path_len;
size_t sub_len;
path_len = strlen(path_next);
sub_len = strlen(sub_next);
tommy_list_init(&list);
d = opendir(dir);
d = opendir(path_next);
if (!d) {
/* LCOV_EXCL_START */
log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno));
log_fatal("Error opening directory '%s'. %s.\n", path_next, strerror(errno));
if (level == 0)
log_fatal("If this is the disk mount point, remember to create it manually\n");
else
log_fatal("If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub);
log_fatal("If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub_next);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* read the full directory */
while (1) {
char path_next[PATH_MAX];
char sub_next[PATH_MAX];
struct dirent_sorted* entry;
const char* name;
struct dirent* dd;
@ -1215,8 +1287,11 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
dd = readdir(d);
if (dd == 0 && errno != 0) {
/* LCOV_EXCL_START */
log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno));
log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub);
/* restore removing additions */
path_next[path_len] = 0;
sub_next[sub_len] = 0;
log_fatal("Error reading directory '%s'. %s.\n", path_next, strerror(errno));
log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub_next);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1229,8 +1304,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
continue;
pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
pathcatl(path_next, path_len, PATH_MAX, name);
/* check for not supported file names */
if (name[0] == 0) {
@ -1276,7 +1350,9 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
if (closedir(d) != 0) {
/* LCOV_EXCL_START */
log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno));
/* restore removing additions */
path_next[path_len] = 0;
log_fatal("Error closing directory '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1299,9 +1375,6 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
/* process the sorted dir entries */
node = list;
while (node != 0) {
char path_next[PATH_MAX];
char sub_next[PATH_MAX];
char out[PATH_MAX];
struct snapraid_filter* reason = 0;
struct dirent_sorted* dd = node->data;
const char* name = dd->d_name;
@ -1311,8 +1384,8 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
struct stat st_buf;
#endif
pathprint(path_next, sizeof(path_next), "%s%s", dir, name);
pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name);
pathcatl(path_next, path_len, PATH_MAX, name);
pathcatl(sub_next, sub_len, PATH_MAX, name);
/* start with an unknown type */
type = -1;
@ -1383,14 +1456,13 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET);
processed = 1;
} else {
msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
}
} else if (type == 1) { /* LNK */
if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
char subnew[PATH_MAX];
int ret;
ret = readlink(path_next, subnew, sizeof(subnew));
ret = readlink(path_next, tmp, PATH_MAX);
if (ret >= PATH_MAX) {
/* LCOV_EXCL_START */
log_fatal("Error in readlink file '%s'. Symlink too long.\n", path_next);
@ -1407,13 +1479,13 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
log_fatal("WARNING! Empty symbolic link '%s'.\n", path_next);
/* readlink doesn't put the final 0 */
subnew[ret] = 0;
tmp[ret] = 0;
/* process as a symbolic link */
scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK);
scan_link(scan, is_diff, sub_next, tmp, FILE_IS_SYMLINK);
processed = 1;
} else {
msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
}
} else if (type == 2) { /* DIR */
if (filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) {
@ -1429,13 +1501,12 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
} else
#endif
{
char sub_dir[PATH_MAX];
/* recurse */
pathslash(path_next, sizeof(path_next));
pathcpy(sub_dir, sizeof(sub_dir), sub_next);
pathslash(sub_dir, sizeof(sub_dir));
if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) {
pathslash(path_next, PATH_MAX);
pathslash(sub_next, PATH_MAX);
if (scan_sub(scan, level + 1, is_diff, path_next, sub_next, tmp) == 0) {
/* restore removing additions */
pathcatl(sub_next, sub_len, PATH_MAX, name);
/* scan the directory as empty dir */
scan_emptydir(scan, sub_next);
}
@ -1443,7 +1514,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
processed = 1;
}
} else {
msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
}
} else {
if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) {
@ -1453,7 +1524,7 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next);
} else {
msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out)));
msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, tmp, PATH_MAX));
}
}
@ -1467,6 +1538,80 @@ static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const ch
return processed;
}
/**
* Process a directory.
* Return != 0 if at least one file or link is processed.
*/
static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub)
{
/* working buffers used by scan_sub() */
char path_next[PATH_MAX];
char sub_next[PATH_MAX];
char tmp[PATH_MAX];
pathcpy(path_next, sizeof(path_next), dir);
pathcpy(sub_next, sizeof(sub_next), sub);
return scan_sub(scan, level, is_diff, path_next, sub_next, tmp);
}
static void* scan_disk(void* arg)
{
struct snapraid_scan* scan = arg;
struct snapraid_disk* disk = scan->disk;
int ret;
int has_persistent_inodes;
int has_syncronized_hardlinks;
uint64_t start;
/* check if the disk supports persistent inodes */
ret = fsinfo(disk->dir, &has_persistent_inodes, &has_syncronized_hardlinks, 0, 0);
if (ret < 0) {
/* LCOV_EXCL_START */
log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (!has_persistent_inodes) {
disk->has_volatile_inodes = 1;
}
if (!has_syncronized_hardlinks) {
disk->has_volatile_hardlinks = 1;
}
/* if inodes or UUID are not persistent/changed/unsupported */
if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) {
/* remove all the inodes from the inode collection */
/* if they are not persistent, all of them could be changed now */
/* and we don't want to find false matching ones */
/* see scan_file() for more details */
tommy_node* node = disk->filelist;
while (node) {
struct snapraid_file* file = node->data;
node = node->next;
/* remove from the inode set */
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
/* clear the inode */
file->inode = 0;
/* mark as missing inode */
file_flag_set(file, FILE_IS_WITHOUT_INODE);
}
}
start = tick_ms();
scan_dir(scan, 0, scan->is_diff, disk->dir, "");
if (!scan->is_diff)
msg_progress("Scanned %s in %" PRIu64 " seconds\n", disk->name, (tick_ms() - start) / 1000);
return 0;
}
static int state_diffscan(struct snapraid_state* state, int is_diff)
{
tommy_node* i;
@ -1482,76 +1627,44 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
if (is_diff)
msg_progress("Comparing...\n");
else
msg_progress("Scanning...\n");
/* first scan all the directory and find new and deleted files */
/* allocate all the scan data */
for (i = state->disklist; i != 0; i = i->next) {
struct snapraid_disk* disk = i->data;
struct snapraid_scan* scan;
tommy_node* node;
int ret;
int has_persistent_inodes;
int has_syncronized_hardlinks;
scan = malloc_nofail(sizeof(struct snapraid_scan));
scan->state = state;
scan->disk = disk;
scan->count_equal = 0;
scan->count_move = 0;
scan->count_copy = 0;
scan->count_restore = 0;
scan->count_change = 0;
scan->count_remove = 0;
scan->count_insert = 0;
tommy_list_init(&scan->file_insert_list);
tommy_list_init(&scan->link_insert_list);
tommy_list_init(&scan->dir_insert_list);
scan = scan_alloc(state, disk, is_diff);
tommy_list_insert_tail(&scanlist, &scan->node, scan);
if (!is_diff)
msg_progress("Scanning disk %s...\n", disk->name);
/* check if the disk supports persistent inodes */
ret = fsinfo(disk->dir, &has_persistent_inodes, &has_syncronized_hardlinks, 0, 0);
if (ret < 0) {
/* LCOV_EXCL_START */
log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (!has_persistent_inodes) {
disk->has_volatile_inodes = 1;
}
if (!has_syncronized_hardlinks) {
disk->has_volatile_hardlinks = 1;
}
/* if inodes or UUID are not persistent/changed/unsupported */
if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) {
/* remove all the inodes from the inode collection */
/* if they are not persistent, all of them could be changed now */
/* and we don't want to find false matching ones */
/* see scan_file() for more details */
node = disk->filelist;
while (node) {
struct snapraid_file* file = node->data;
node = node->next;
/* remove from the inode set */
tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset);
/* clear the inode */
file->inode = 0;
/* mark as missing inode */
file_flag_set(file, FILE_IS_WITHOUT_INODE);
}
}
scan_dir(scan, 0, is_diff, disk->dir, "");
}
/* first scan all the directory and find new and deleted files */
for (i = scanlist; i != 0; i = i->next) {
struct snapraid_scan* scan = i->data;
#if HAVE_THREAD
if (state->opt.skip_multi_scan)
scan_disk(scan);
else
thread_create(&scan->thread, scan_disk, scan);
#else
scan_disk(scan);
#endif
}
#if HAVE_THREAD
/* wait for all threads to terminate */
for (i = scanlist; i != 0; i = i->next) {
struct snapraid_scan* scan = i->data;
void* retval;
/* wait for thread termination */
if (!state->opt.skip_multi_scan)
thread_join(scan->thread, &retval);
}
#endif
/* we split the search in two phases because to detect files */
/* moved from one disk to another we have to start deletion */
/* only when all disks have all the new files found */
@ -1561,7 +1674,6 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
struct snapraid_scan* scan = i->data;
struct snapraid_disk* disk = scan->disk;
tommy_node* node;
unsigned phy_count;
unsigned phy_dup;
uint64_t phy_last;
struct snapraid_file* phy_file_last;
@ -1580,7 +1692,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer));
if (is_diff) {
printf("remove %s\n", fmt_term(disk, file->sub, esc_buffer));
msg_info("remove %s\n", fmt_term(disk, file->sub, esc_buffer));
}
scan_file_remove(scan, file);
@ -1601,7 +1713,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer));
if (is_diff) {
printf("remove %s\n", fmt_term(disk, slink->sub, esc_buffer));
msg_info("remove %s\n", fmt_term(disk, slink->sub, esc_buffer));
}
scan_link_remove(scan, slink);
@ -1644,7 +1756,6 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
/* to reuse the just freed space */
/* also check if the physical offset reported are fakes or not */
node = scan->file_insert_list;
phy_count = 0;
phy_dup = 0;
phy_last = FILEPHY_UNREAD_OFFSET;
phy_file_last = 0;
@ -1660,13 +1771,12 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
/* if verbose, print the list of duplicates real offsets */
/* other cases are for offsets not supported, so we don't need to report them file by file */
if (phy_last >= FILEPHY_REAL_OFFSET) {
log_fatal("WARNING! Files '%s%s' and '%s%s' have the same physical offset %" PRId64 ".\n", disk->dir, phy_file_last->sub, disk->dir, file->sub, phy_last);
log_fatal("WARNING! Files '%s%s' and '%s%s' share the same physical offset %" PRId64 ".\n", disk->dir, phy_file_last->sub, disk->dir, file->sub, phy_last);
}
++phy_dup;
}
phy_file_last = file;
phy_last = file->physical;
++phy_count;
}
/* next node */
@ -1707,6 +1817,14 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
}
}
/* propagate the state change (after all the scan operations are called) */
for (i = scanlist; i != 0; i = i->next) {
struct snapraid_scan* scan = i->data;
if (scan->need_write) {
state->need_write = 1;
}
}
/* check for disks where all the previously existing files where removed */
if (!state->opt.force_empty) {
int all_missing = 0;
@ -1738,13 +1856,13 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
}
}
if (done) {
log_fatal("\nare now missing or rewritten!\n");
log_fatal("\nare now missing or have been rewritten!\n");
if (all_rewritten) {
log_fatal("This could happen when restoring a disk with a backup\n");
log_fatal("This could occur when restoring a disk from a backup\n");
log_fatal("program that is not setting correctly the timestamps.\n");
}
if (all_missing) {
log_fatal("This could happen when some disks are not mounted\n");
log_fatal("This could occur when some disks are not mounted\n");
log_fatal("in the expected directory.\n");
}
if (!is_diff) {
@ -1770,7 +1888,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
}
}
if (done) {
log_fatal(". Files order won't be optimal.\n");
log_fatal(". The order of files won't be optimal.\n");
}
}
@ -1789,7 +1907,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
}
}
if (done) {
log_fatal(". Not using inodes to detect move operations.\n");
log_fatal(". Inodes are not used to detect move operations.\n");
}
/* check for disks with changed UUID */
@ -1811,7 +1929,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
}
}
if (done) {
log_fatal(". Not using inodes to detect move operations.\n");
log_fatal(". Inodes are not used to detect move operations.\n");
}
/* check for disks with unsupported UUID */
@ -1896,7 +2014,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
}
log_flush();
tommy_list_foreach(&scanlist, (tommy_foreach_func*)free);
tommy_list_foreach(&scanlist, (tommy_foreach_func*)scan_free);
/* check the file-system on all disks */
state_fscheck(state, "after scan");

View File

@ -671,7 +671,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
if (io_error || silent_error) {
log_fatal("Use 'snapraid status' to list the bad blocks.\n");
log_fatal("Use 'snapraid -e fix' to recover them.\n");
log_fatal("Use 'snapraid -p bad scrub' to recheck after fixing.\n");
log_fatal("Use 'snapraid -p bad scrub' to recheck after fixing to clear the bad state.\n");
}
log_tag("summary:error_file:%u\n", error);

View File

@ -38,7 +38,7 @@ void usage(void)
{
version();
printf("Usage: " PACKAGE " status|diff|sync|scrub|list|dup|up|down|smart|pool|check|fix [options]\n");
printf("Usage: " PACKAGE " status|diff|sync|scrub|list|dup|up|down|touch|smart|pool|check|fix [options]\n");
printf("\n");
printf("Commands:\n");
printf(" status Print the status of the array\n");
@ -49,6 +49,7 @@ void usage(void)
printf(" dup Find duplicate files\n");
printf(" up Spin-up the array\n");
printf(" down Spin-down the array\n");
printf(" touch Add non-zero ns timestamps to files\n");
printf(" smart SMART attributes of the array\n");
printf(" pool Create or update the virtual view of the array\n");
printf(" check Check the array\n");
@ -307,6 +308,7 @@ void config(char* conf, size_t conf_size, const char* argv0)
#define OPT_TEST_SKIP_CONTENT_WRITE 302
#define OPT_TEST_SKIP_SPACE_HOLDER 303
#define OPT_TEST_FORMAT 304
#define OPT_TEST_SKIP_MULTI_SCAN 305
#if HAVE_GETOPT_LONG
struct option long_options[] = {
@ -475,6 +477,9 @@ struct option long_options[] = {
/* Set the output format */
{ "test-fmt", 1, 0, OPT_TEST_FORMAT },
/* Skip thread in disk scan */
{ "test-skip-multi-scan", 0, 0, OPT_TEST_SKIP_MULTI_SCAN },
{ 0, 0, 0, 0 }
};
#endif
@ -929,6 +934,9 @@ int main(int argc, char* argv[])
/* LCOV_EXCL_STOP */
}
break;
case OPT_TEST_SKIP_MULTI_SCAN :
opt.skip_multi_scan = 1;
break;
default :
/* LCOV_EXCL_START */
log_fatal("Unknown option '%c'\n", (char)c);
@ -1076,28 +1084,28 @@ int main(int argc, char* argv[])
if (opt.force_full && opt.force_nocopy) {
/* LCOV_EXCL_START */
log_fatal("You cannot use the -F, --force-full and -N, --force-nocopy options at the same time\n");
log_fatal("You cannot use the -F, --force-full and -N, --force-nocopy options simultaneously\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (opt.force_realloc && opt.force_nocopy) {
/* LCOV_EXCL_START */
log_fatal("You cannot use the -R, --force-realloc and -N, --force-nocopy options at the same time\n");
log_fatal("You cannot use the -R, --force-realloc and -N, --force-nocopy options simultaneously\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (opt.force_realloc && opt.force_full) {
/* LCOV_EXCL_START */
log_fatal("You cannot use the -R, --force-realloc and -F, --force-full options at the same time\n");
log_fatal("You cannot use the -R, --force-realloc and -F, --force-full options simultaneously\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (opt.prehash && opt.force_nocopy) {
/* LCOV_EXCL_START */
log_fatal("You cannot use the -h, --pre-hash and -N, --force-nocopy options at the same time\n");
log_fatal("You cannot use the -h, --pre-hash and -N, --force-nocopy options simultaneously\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1141,7 +1149,7 @@ int main(int argc, char* argv[])
/* because we don't keep the information on what disk is the error */
if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) {
/* LCOV_EXCL_START */
log_fatal("You cannot use -e, --filter-error and -d, --filter-disk at the same time\n");
log_fatal("You cannot use -e, --filter-error and -d, --filter-disk simultaneously\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1153,7 +1161,7 @@ int main(int argc, char* argv[])
default :
if (import_timestamp != 0 || import_content != 0) {
/* LCOV_EXCL_START */
log_fatal("You cannot import with the '%s' command\n", command);
log_fatal("Import not allowed with the '%s' command\n", command);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1279,9 +1287,9 @@ int main(int argc, char* argv[])
if (lock == -1) {
/* LCOV_EXCL_START */
if (errno != EWOULDBLOCK) {
log_fatal("Error creating the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
log_fatal("Failed to create the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
} else {
log_fatal("The lock file '%s' is already locked!\n", state.lockfile);
log_fatal("The lock file '%s' is already in use!\n", state.lockfile);
log_fatal("SnapRAID is already in use!\n");
}
exit(EXIT_FAILURE);
@ -1347,7 +1355,7 @@ int main(int argc, char* argv[])
ret = system(run); /* ignore error */
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error in running command '%s'.\n", run);
log_fatal("Error executing command '%s'.\n", run);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1370,7 +1378,7 @@ int main(int argc, char* argv[])
if ((state.need_write || state.opt.force_content_write))
state_write(&state);
} else {
log_fatal("WARNING! Skipped state write for --test-kill-after-sync option.\n");
log_fatal("WARNING! Skipped writing state due to --test-kill-after-sync option.\n");
}
/* abort if required */
@ -1519,7 +1527,7 @@ int main(int argc, char* argv[])
if (!opt.skip_lock && state.lockfile[0]) {
if (lock_unlock(lock) == -1) {
/* LCOV_EXCL_START */
log_fatal("Error closing the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
log_fatal("Failed to close the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}

View File

@ -37,10 +37,6 @@
* writing to disk, but you'll need to access multiple times the same data,
* being potentially slower.
*
* For upcoming SnapRAID version it's planned to add a mutex protection
* at the file-system structure, slowing down multiple data access,
* so we disable it.
*
* Multi thread for verify is instead always generally faster,
* so we enable it if possible.
*/
@ -215,7 +211,7 @@ static void state_config_check(struct snapraid_state* state, const char* path, t
if (state->raid_mode == RAID_MODE_VANDERMONDE) {
if (state->level > 3) {
/* LCOV_EXCL_START */
log_fatal("If you use the z-parity you cannot have more than 3 parities.\n");
log_fatal("Using z-parity limits you to a maximum of 3 parities.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STIO */
}
@ -224,7 +220,7 @@ static void state_config_check(struct snapraid_state* state, const char* path, t
for (l = 0; l < state->level; ++l) {
if (state->parity[l].split_mac == 0) {
/* LCOV_EXCL_START */
log_fatal("No '%s' specification in '%s'\n", lev_config_name(l), path);
log_fatal("Missing '%s' specification in '%s'\n", lev_config_name(l), path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -232,7 +228,7 @@ static void state_config_check(struct snapraid_state* state, const char* path, t
if (tommy_list_empty(&state->contentlist)) {
/* LCOV_EXCL_START */
log_fatal("No 'content' specification in '%s'\n", path);
log_fatal("Missing 'content' specification in '%s'\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -859,7 +855,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
pathimport(device, sizeof(device), buffer);
slash = strrchr(device, '/');
if (slash)
*slash = 0;
*(slash + 1) = 0;
else
pathcpy(device, sizeof(device), ".");
if (stat(device, &st) == 0) {
@ -996,14 +992,14 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
ret = sgettok(f, buffer, sizeof(buffer));
if (ret < 0) {
/* LCOV_EXCL_START */
log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line);
log_fatal("Invalid 'smartctl' name in '%s' at line %u\n", path, line);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (!*buffer) {
/* LCOV_EXCL_START */
log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line);
log_fatal("Empty 'smartctl' name in '%s' at line %u\n", path, line);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1013,21 +1009,21 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
ret = sgetlasttok(f, custom, sizeof(custom));
if (ret < 0) {
/* LCOV_EXCL_START */
log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
log_fatal("Invalid 'smartctl' option in '%s' at line %u\n", path, line);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (!*custom) {
/* LCOV_EXCL_START */
log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line);
log_fatal("Empty 'smartctl' option in '%s' at line %u\n", path, line);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (validate_smartctl(custom) != 0) {
/* LCOV_EXCL_START */
log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line);
log_fatal("Invalid 'smartctl' option in '%s' at line %u\n", path, line);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1036,7 +1032,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
if (lev_config_scan(buffer, &level, 0) == 0) {
if (state->parity[level].smartctl[0] != 0) {
/* LCOV_EXCL_START */
log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line);
log_fatal("Duplicate parity 'smartctl' '%s' at line %u\n", buffer, line);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1054,7 +1050,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
}
if (!disk) {
/* LCOV_EXCL_START */
log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line);
log_fatal("Missing disk 'smartctl' '%s' at line %u\n", buffer, line);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1091,7 +1087,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
if (!filter) {
/* LCOV_EXCL_START */
log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line);
log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
log_fatal("Filters with relative paths are not supported. Ensure to add an initial slash\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1118,7 +1114,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
if (!filter) {
/* LCOV_EXCL_START */
log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line);
log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
log_fatal("Filters with relative paths are not supported. Ensure to add an initial slash\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1222,7 +1218,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
/* by default use a random hash seed */
if (randomize(state->hashseed, HASH_MAX) != 0) {
/* LCOV_EXCL_START */
log_fatal("Failed to get random values.\n");
log_fatal("Failed to retrieve random values.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1412,7 +1408,7 @@ static void state_map(struct snapraid_state* state)
disk = find_disk_by_name(state, map->name);
if (disk == 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
log_fatal("Internal inconsistency: Mapping not found for '%s'\n", map->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1481,11 +1477,11 @@ static void state_map(struct snapraid_state* state)
if (!state->opt.force_uuid && uuid_mismatch > state->level) {
/* LCOV_EXCL_START */
log_fatal("Too many disks have UUID changed from the latest 'sync'.\n");
log_fatal("If this happens because you really replaced them,\n");
log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command);
log_fatal("Instead, it's possible that you messed up the disk mount points,\n");
log_fatal("and you have to restore the mount points at the state of the latest sync.\n");
log_fatal("Too many disks have changed UUIDs since the last 'sync'.\n");
log_fatal("If this happened because you actually replaced them,\n");
log_fatal("you can still '%s', using 'snapraid --force-uuid %s'.\n", state->command, state->command);
log_fatal("Alternatively, you may have misconfigured the disk mount points,\n");
log_fatal("and you need to restore the mount points to the state of the latest sync.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1502,7 +1498,7 @@ static void state_map(struct snapraid_state* state)
/* ensure to don't go over the limit of the RAID engine */
if (diskcount > RAID_DATA_MAX) {
/* LCOV_EXCL_START */
log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX);
log_fatal("Too many data disks. Maximum allowed is %u.\n", RAID_DATA_MAX);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1514,15 +1510,15 @@ static void state_map(struct snapraid_state* state)
if (!state->opt.no_warnings) {
/* intentionally use log_fatal() instead of log_error() to give more visibility at the warning */
if (diskcount >= 36 && state->level < 6) {
log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount);
log_fatal("WARNING! For %u disks, it's recommended to use six parity levels.\n", diskcount);
} else if (diskcount >= 29 && state->level < 5) {
log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount);
log_fatal("WARNING! For %u disks, it's recommended to use five parity levels.\n", diskcount);
} else if (diskcount >= 22 && state->level < 4) {
log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount);
log_fatal("WARNING! For %u disks, it's recommended to use four parity levels.\n", diskcount);
} else if (diskcount >= 15 && state->level < 3) {
log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount);
log_fatal("WARNING! For %u disks, it's recommended to use three parity levels.\n", diskcount);
} else if (diskcount >= 5 && state->level < 2) {
log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount);
log_fatal("WARNING! For %u disks, it's recommended to use two parity levels.\n", diskcount);
}
}
}
@ -1543,7 +1539,7 @@ void state_refresh(struct snapraid_state* state)
disk = find_disk_by_name(state, map->name);
if (disk == 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency for mapping '%s'\n", map->name);
log_fatal("Internal inconsistency: Mapping not found for '%s'\n", map->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1551,7 +1547,7 @@ void state_refresh(struct snapraid_state* state)
ret = fsinfo(disk->dir, 0, 0, &total_space, &free_space);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno));
log_fatal("Error accessing disk '%s' to retrieve file-system info. %s.\n", disk->dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1579,7 +1575,7 @@ void state_refresh(struct snapraid_state* state)
ret = fsinfo(state->parity[l].split_map[s].path, 0, 0, &total_space, &free_space);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error accessing file '%s' to get file-system info. %s.\n", state->parity[l].split_map[s].path, strerror(errno));
log_fatal("Error accessing file '%s' to retrieve file-system info. %s.\n", state->parity[l].split_map[s].path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1609,13 +1605,13 @@ static void state_content_check(struct snapraid_state* state, const char* path)
struct snapraid_map* other = j->data;
if (strcmp(map->name, other->name) == 0) {
/* LCOV_EXCL_START */
log_fatal("Colliding 'map' disk specification in '%s'\n", path);
log_fatal("Conflicting 'map' disk specification in '%s'\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (map->position == other->position) {
/* LCOV_EXCL_START */
log_fatal("Colliding 'map' index specification in '%s'\n", path);
log_fatal("Conflicting 'map' index specification in '%s'\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1714,7 +1710,7 @@ static void decoding_error(const char* path, STREAM* f)
if (seof(f)) {
/* LCOV_EXCL_START */
log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f));
log_fatal("This content file is truncated. Use an alternate copy.\n");
log_fatal("This content file is truncated. Please use an alternate copy.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1726,11 +1722,11 @@ static void decoding_error(const char* path, STREAM* f)
/* LCOV_EXCL_STOP */
}
log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f));
log_fatal("Error decoding '%s' at offset %" PRIi64 "\n", path, stell(f));
if (sdeplete(f, buf) != 0) {
/* LCOV_EXCL_START */
log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f));
log_fatal("Failed to flush content file '%s' at offset %" PRIi64 "\n", path, stell(f));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1745,11 +1741,11 @@ static void decoding_error(const char* path, STREAM* f)
crc_stored = crc32c(crc_stored, buf, 4);
if (crc_computed != crc_stored) {
log_fatal("Mismatching CRC in '%s'\n", path);
log_fatal("This content file is damaged! Use an alternate copy.\n");
log_fatal("CRC mismatch in '%s'\n", path);
log_fatal("This content file is damaged! Please use an alternate copy.\n");
exit(EXIT_FAILURE);
} else {
log_fatal("The file CRC is correct!\n");
log_fatal("The CRC of the file is correct!\n");
}
}
@ -1835,7 +1831,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (ret < 0 || mapping >= mapping_max) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in mapping index!\n");
log_fatal("Internal inconsistency: File mapping index out of range\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1852,7 +1848,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (state->block_size == 0) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency due zero blocksize!\n");
log_fatal("Internal inconsistency: Zero blocksize\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1861,7 +1857,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (v_size / state->block_size > blockmax) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in file size too big!\n");
log_fatal("Internal inconsistency: File size too big!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1906,7 +1902,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (!*sub) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency for null file!\n");
log_fatal("Internal inconsistency: Null file!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1948,7 +1944,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (v_idx + v_count > file->blockmax) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in block number!\n");
log_fatal("Internal inconsistency: Block number out of range\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -1956,7 +1952,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (v_pos + v_count > blockmax) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count);
log_fatal("Internal inconsistency: Block size %u/%u!\n", blockmax, v_pos + v_count);
os_abort();
/* LCOV_EXCL_START */
}
@ -2080,7 +2076,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (v_pos + v_count > blockmax) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count);
log_fatal("Internal inconsistency: Info size %u/%u!\n", blockmax, v_pos + v_count);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2112,7 +2108,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (rehash && state->prevhash == HASH_UNDEFINED) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency for missing previous checksum!\n");
log_fatal("Internal inconsistency: Missing previous checksum!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2131,7 +2127,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (!info) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency for missing info!\n");
log_fatal("Internal inconsistency: Missing info!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2155,7 +2151,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (ret < 0 || mapping >= mapping_max) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in mapping index!\n");
log_fatal("Internal inconsistency: Hole mapping index out of range\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2178,7 +2174,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (v_pos + v_count > blockmax) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count);
log_fatal("Internal inconsistency: Hole size %u/%u!\n", blockmax, v_pos + v_count);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2255,7 +2251,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (ret < 0 || mapping >= mapping_max) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in mapping index!\n");
log_fatal("Internal inconsistency: Symlink mapping index out of range\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2272,7 +2268,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (!*sub) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency for null symlink!\n");
log_fatal("Internal inconsistency: Null symlink!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2306,7 +2302,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (ret < 0 || mapping >= mapping_max) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in mapping index!\n");
log_fatal("Internal inconsistency: Hardlink mapping index out of range!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2323,7 +2319,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (!*sub) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency for null hardlink!\n");
log_fatal("Internal inconsistency: Null hardlink!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2339,7 +2335,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (!*linkto) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency for empty hardlink '%s'!\n", sub);
log_fatal("Internal inconsistency: Empty hardlink '%s'!\n", sub);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2364,7 +2360,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (ret < 0 || mapping >= mapping_max) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency in mapping index!\n");
log_fatal("Internal inconsistency: Dir mapping index ouf of range!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2381,7 +2377,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (!*sub) {
/* LCOV_EXCL_START */
decoding_error(path, f);
log_fatal("Internal inconsistency for null dir!\n");
log_fatal("Internal inconsistency: Null dir!\n");
os_abort();
/* LCOV_EXCL_STOP */
}
@ -2823,8 +2819,8 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (crc_stored != crc_computed) {
/* LCOV_EXCL_START */
/* here don't call decoding_error() because it's too late to get the crc */
log_fatal("Mismatching CRC in '%s'\n", path);
log_fatal("This content file is damaged! Use an alternate copy.\n");
log_fatal("CRC mismatch in '%s'\n", path);
log_fatal("The content file is damaged! Please use an alternate copy.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -2850,7 +2846,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
if (!crc_checked) {
/* LCOV_EXCL_START */
log_fatal("Finished reading '%s' without finding the CRC\n", path);
log_fatal("Reached the end of '%s' without finding the expected CRC\n", path);
log_fatal("This content file is truncated or damaged! Use an alternate copy.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
@ -2862,7 +2858,7 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
/* check that the stored parity size matches the loaded state */
if (blockmax != parity_allocated_size(state)) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f));
log_fatal("Internal inconsistency: Parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f));
if (state->opt.skip_content_check) {
log_fatal("Overriding.\n");
blockmax = parity_allocated_size(state);
@ -3013,7 +3009,7 @@ static void* state_write_thread(void* arg)
disk = find_disk_by_name(state, map->name);
if (!disk) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
log_fatal("Internal inconsistency: Unmapped disk '%s'\n", map->name);
return context;
/* LCOV_EXCL_STOP */
}
@ -3134,7 +3130,7 @@ static void* state_write_thread(void* arg)
break;
default :
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state);
log_fatal("Internal inconsistency: State for block %u state %u\n", v_pos, v_state);
return context;
/* LCOV_EXCL_STOP */
}
@ -3344,8 +3340,8 @@ static void* state_write_thread(void* arg)
/* with the one of the data written to the stream */
if (crc != scrc_stream(f)) {
/* LCOV_EXCL_START */
log_fatal("CRC mismatch writing the content stream.\n");
log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n");
log_fatal("CRC mismatch while writing the content stream.\n");
log_fatal("DANGER! Your RAM memory is faulty! DO NOT PROCEED UNTIL FIXED!\n");
log_fatal("Try running a memory test like http://www.memtest86.com/\n");
return context;
/* LCOV_EXCL_STOP */
@ -3439,7 +3435,7 @@ static void state_write_content(struct snapraid_state* state, uint32_t* out_crc)
disk = find_disk_by_name(state, map->name);
if (!disk) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name);
log_fatal("Internal inconsistency: Unmapped disk '%s'\n", map->name);
os_abort();
/* LCOV_EXCL_STOP */
}
@ -3728,7 +3724,7 @@ void state_read(struct snapraid_state* state)
/* otherwise continue */
if (node->next) {
log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path);
log_fatal("WARNING! Content file '%s' not found, attempting with another copy...\n", path);
/* ensure to rewrite all the content files */
state->need_write = 1;
@ -3866,7 +3862,7 @@ static void* state_verify_thread(void* arg)
if (sdeplete(f, buf) != 0) {
/* LCOV_EXCL_START */
log_fatal("Error flushing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
log_fatal("Failed to flush content file '%s'. %s.\n", serrorfile(f), strerror(errno));
return context;
/* LCOV_EXCL_STOP */
}
@ -3904,6 +3900,8 @@ static void state_verify_content(struct snapraid_state* state, uint32_t crc)
tommy_node* i;
int fail;
msg_progress("Verifying...\n");
/* start all reading threads */
i = tommy_list_head(&state->contentlist);
while (i) {
@ -3912,8 +3910,6 @@ static void state_verify_content(struct snapraid_state* state, uint32_t crc)
char tmp[PATH_MAX];
STREAM* f;
msg_progress("Verifying %s...\n", content->content);
pathprint(tmp, sizeof(tmp), "%s.tmp", content->content);
f = sopen_read(tmp);
if (f == 0) {
@ -4249,7 +4245,7 @@ void state_progress_end(struct snapraid_state* state, block_off_t countpos, bloc
elapsed = now - state->progress_whole_start - state->progress_wasted;
msg_bar("%u%% completed, %u MB accessed", countpos * 100 / countmax, countsize_MB);
msg_bar("%u%% completed, %u MB accessed", muldiv(countpos, 100, countmax), countsize_MB);
msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60));
@ -4409,7 +4405,7 @@ static void state_progress_graph(struct snapraid_state* state, struct snapraid_i
struct snapraid_disk* disk = i->data;
v = disk->progress_tick[current] - ref(disk->progress_tick, oldest);
printr(disk->name, pad);
printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
printf("%3u%% | ", muldiv(v, 100, tick_total));
printc('*', v * bar / tick_total);
printf("\n");
@ -4420,32 +4416,32 @@ static void state_progress_graph(struct snapraid_state* state, struct snapraid_i
for (l = 0; l < state->level; ++l) {
v = state->parity[l].progress_tick[current] - ref(state->parity[l].progress_tick, oldest);
printr(lev_config_name(l), pad);
printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
printf("%3u%% | ", muldiv(v, 100, tick_total));
printc('*', v * bar / tick_total);
printf("\n");
}
v = state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest);
printr("raid", pad);
printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
printf("%3u%% | ", muldiv(v, 100, tick_total));
printc('*', v * bar / tick_total);
printf("\n");
v = state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest);
printr("hash", pad);
printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
printf("%3u%% | ", muldiv(v, 100, tick_total));
printc('*', v * bar / tick_total);
printf("\n");
v = state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest);
printr("sched", pad);
printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
printf("%3u%% | ", muldiv(v, 100, tick_total));
printc('*', v * bar / tick_total);
printf("\n");
v = state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest);
printr("misc", pad);
printf("%3" PRIu64 "%% | ", v * 100 / tick_total);
printf("%3u%% | ", muldiv(v, 100, tick_total));
printc('*', v * bar / tick_total);
printf("\n");
@ -4503,7 +4499,7 @@ int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_o
/* completion percentage */
if (countmax)
out_perc = countpos * 100 / countmax;
out_perc = muldiv(countpos, 100, countmax);
/* if we have at least 5 measures */
if (state->progress_tick >= 5
@ -4569,11 +4565,11 @@ int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_o
/* estimate the cpu usage percentage */
if (delta_tick_total != 0)
out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total);
out_cpu = muldiv(delta_tick_cpu, 100, delta_tick_total);
/* estimate the remaining time in minutes */
if (delta_pos != 0)
out_eta = (countmax - countpos) * delta_time / (60 * delta_pos);
out_eta = muldiv(countmax - countpos, delta_time, 60 * delta_pos);
if (state->opt.force_stats) {
os_clear();
@ -4738,7 +4734,7 @@ void state_fscheck(struct snapraid_state* state, const char* ope)
if (fs_check(disk) != 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in file-system for disk '%s' %s\n", disk->name, ope);
log_fatal("Internal inconsistency: File-system check for disk '%s' %s\n", disk->name, ope);
os_abort();
/* LCOV_EXCL_STOP */
}

View File

@ -119,6 +119,7 @@ struct snapraid_option {
int auto_conf; /**< Allow to run without configuration file. */
int force_stats; /**< Force stats print during process. */
uint64_t parity_limit_size; /**< Test limit for parity files. */
int skip_multi_scan; /**< Don't use threads in scan. */
};
struct snapraid_state {

View File

@ -39,14 +39,6 @@ unsigned day_ago(time_t ref, time_t now)
#define GRAPH_COLUMN 70
#define GRAPH_ROW 15
static unsigned perc(uint64_t part, uint64_t total)
{
if (!total)
return 0;
return (unsigned)(part * 100 / total);
}
/**
* Bit used to mark unscrubbed time info.
*/
@ -239,7 +231,7 @@ int state_status(struct snapraid_state* state)
printf(" - ");
} else {
printf("%8" PRIu64, (disk_block_max - disk_block_count) * (uint64_t)state->block_size / GIGA);
printf(" %3u%%", perc(disk_block_count, disk_block_max));
printf(" %3u%%", muldiv(disk_block_count, 100, disk_block_max));
}
printf(" %s\n", disk->name);
@ -266,7 +258,7 @@ int state_status(struct snapraid_state* state)
printf("%8.1f", (double)all_wasted / GIGA);
printf("%8" PRIu64, file_size / GIGA);
printf("%8" PRIu64, file_block_free * state->block_size / GIGA);
printf(" %3u%%", perc(file_block_count, file_block_count + file_block_free));
printf(" %3u%%", muldiv(file_block_count, 100, file_block_count + file_block_free));
printf("\n");
/* warn about invalid data free info */
@ -468,26 +460,26 @@ int state_status(struct snapraid_state* state)
if (unsynced_blocks) {
printf("WARNING! The array is NOT fully synced.\n");
printf("You have a sync in progress at %u%%.\n", (blockmax - unsynced_blocks) * 100 / blockmax);
printf("You have a sync in progress at %u%%.\n", muldiv(blockmax - unsynced_blocks, 100, blockmax));
} else {
printf("No sync is in progress.\n");
}
if (unscrubbed_blocks) {
printf("The %u%% of the array is not scrubbed.\n", (unscrubbed_blocks * 100 + blockmax - 1) / blockmax);
printf("%u%% of the array is not scrubbed.\n", muldiv_upper(unscrubbed_blocks, 100, blockmax));
} else {
printf("The full array was scrubbed at least one time.\n");
}
if (file_zerosubsecond) {
printf("You have %u files with zero sub-second timestamp.\n", file_zerosubsecond);
printf("Run the 'touch' command to set it to a not zero value.\n");
printf("You have %u files with a zero sub-second timestamp.\n", file_zerosubsecond);
printf("Run 'snapraid touch' to set their sub-second timestamps to a non-zero value.\n");
} else {
printf("No file has a zero sub-second timestamp.\n");
}
if (rehash) {
printf("You have a rehash in progress at %u%%.\n", (count - rehash) * 100 / count);
printf("You have a rehash in progress at %u%%.\n", muldiv(count - rehash, 100, count));
} else {
if (state->besthash != state->hash) {
printf("No rehash is in progress, but for optimal performance one is recommended.\n");

View File

@ -426,7 +426,7 @@ const char* esc_tag(const char* str, char* buffer)
bail:
/* LCOV_EXCL_START */
log_fatal("Escape for log too long\n");
log_fatal("Escape for log is too long\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -587,7 +587,7 @@ const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer
bail:
/* LCOV_EXCL_START */
log_fatal("Escape for shell too long\n");
log_fatal("Escape for shell is too long\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -663,6 +663,20 @@ void pathcat(char* dst, size_t size, const char* src)
memcpy(dst + dst_len, src, src_len + 1);
}
void pathcatl(char* dst, size_t dst_len, size_t size, const char* src)
{
size_t src_len = strlen(src);
if (dst_len + src_len + 1 > size) {
/* LCOV_EXCL_START */
log_fatal("Path too long '%s%s'\n", dst, src);
os_abort();
/* LCOV_EXCL_STOP */
}
memcpy(dst + dst_len, src, src_len + 1);
}
void pathcatc(char* dst, size_t size, char c)
{
size_t dst_len = strlen(dst);

View File

@ -265,6 +265,12 @@ void pathcpy(char* dst, size_t size, const char* src);
*/
void pathcat(char* dst, size_t size, const char* src);
/**
* Concatenate a path limiting the size knowing the length.
* Abort if too long.
*/
void pathcatl(char* dst, size_t dst_len, size_t size, const char* src);
/**
* Concatenate a path limiting the size.
* Abort if too long.

View File

@ -1456,7 +1456,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (blockstart > blockmax) {
/* LCOV_EXCL_START */
log_fatal("Error in the starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
log_fatal("Error in the starting block %u. It is larger than the parity size %u.\n", blockstart, blockmax);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1485,7 +1485,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
/* if the file is too small */
if (parityblocks < used_paritymax) {
log_fatal("WARNING! The %s parity has data only %u blocks instead of %u.\n", lev_name(l), parityblocks, used_paritymax);
log_fatal("WARNING! The %s parity has only %u blocks instead of %u.\n", lev_name(l), parityblocks, used_paritymax);
}
/* keep the smallest parity number of blocks */

View File

@ -58,7 +58,7 @@ void state_touch(struct snapraid_state* state)
/* get a random nanosecond value */
if (randomize(&nano, sizeof(nano)) != 0) {
/* LCOV_EXCL_START */
log_fatal("Failed to get random values.\n");
log_fatal("Failed to retrieve random values.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}

View File

@ -474,7 +474,7 @@ static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size)
#endif
/**
* Get the UUID using liblkid.
* Get the UUID using libblkid.
* It uses a cache to work without root permission, resulting in UUID
* not necessarily recent.
* We could call blkid_probe_all() to refresh the UUID, but it would

View File

@ -672,3 +672,22 @@ int lock_unlock(int f)
}
#endif
/****************************************************************************/
/* muldiv */
unsigned muldiv(uint64_t v, uint64_t mul, uint64_t div)
{
if (!div)
return 0;
return (uint32_t)(v * mul / div);
}
unsigned muldiv_upper(uint64_t v, uint64_t mul, uint64_t div)
{
if (!div)
return 0;
return (uint32_t)((v * mul + div - 1) / div);
}

View File

@ -251,5 +251,10 @@ static inline int bit_vect_test(bit_vect_t* bit_vect, size_t off)
return (bit_vect[off / BIT_VECT_SIZE] & mask) != 0;
}
#endif
/****************************************************************************/
/* muldiv */
unsigned muldiv(uint64_t v, uint64_t mul, uint64_t div);
unsigned muldiv_upper(uint64_t v, uint64_t mul, uint64_t div);
#endif

347
compile
View File

@ -1,347 +0,0 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

1421
config.guess vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,420 +0,0 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to 1 if you have the `access' function. */
#undef HAVE_ACCESS
/* Define to 1 if inline assembly should be used. */
#undef HAVE_ASSEMBLY
/* Define to 1 if avx2 is supported by the assembler. */
#undef HAVE_AVX2
/* Define to 1 if you have the `backtrace' function. */
#undef HAVE_BACKTRACE
/* Define to 1 if you have the `backtrace_symbols' function. */
#undef HAVE_BACKTRACE_SYMBOLS
/* Define to 1 if you have the <blkid/blkid.h> header file. */
#undef HAVE_BLKID_BLKID_H
/* Define to 1 if you have the `blkid_devno_to_devname' function. */
#undef HAVE_BLKID_DEVNO_TO_DEVNAME
/* Define to 1 if you have the `blkid_get_tag_value' function. */
#undef HAVE_BLKID_GET_TAG_VALUE
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#undef HAVE_DIRENT_H
/* Define to 1 if you have the <execinfo.h> header file. */
#undef HAVE_EXECINFO_H
/* Define to 1 if you have the `fallocate' function. */
#undef HAVE_FALLOCATE
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `ferror_unlocked' function. */
#undef HAVE_FERROR_UNLOCKED
/* Define to 1 if you have the `flock' function. */
#undef HAVE_FLOCK
/* Define to 1 if you have the `fnmatch' function. */
#undef HAVE_FNMATCH
/* Define to 1 if you have the <fnmatch.h> header file. */
#undef HAVE_FNMATCH_H
/* Define to 1 if you have the `fstatat' function. */
#undef HAVE_FSTATAT
/* Define to 1 if you have the `fsync' function. */
#undef HAVE_FSYNC
/* Define to 1 if you have the `ftruncate' function. */
#undef HAVE_FTRUNCATE
/* Define to 1 if you have the `futimens' function. */
#undef HAVE_FUTIMENS
/* Define to 1 if you have the `futimes' function. */
#undef HAVE_FUTIMES
/* Define to 1 if you have the `futimesat' function. */
#undef HAVE_FUTIMESAT
/* Define to 1 if you have the `getc_unlocked' function. */
#undef HAVE_GETC_UNLOCKED
/* Define to 1 if you have the `getopt' function. */
#undef HAVE_GETOPT
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the `getopt_long' function. */
#undef HAVE_GETOPT_LONG
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <io.h> header file. */
#undef HAVE_IO_H
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <linux/fiemap.h> header file. */
#undef HAVE_LINUX_FIEMAP_H
/* Define to 1 if you have the <linux/fs.h> header file. */
#undef HAVE_LINUX_FS_H
/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define to 1 if you have the `lutimes' function. */
#undef HAVE_LUTIMES
/* Define to 1 if you have the `mach_absolute_time' function. */
#undef HAVE_MACH_ABSOLUTE_TIME
/* Define to 1 if you have the <mach/mach_time.h> header file. */
#undef HAVE_MACH_MACH_TIME_H
/* Define to 1 if you have the <math.h> header file. */
#undef HAVE_MATH_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define to 1 if you have the `mkdir' function. */
#undef HAVE_MKDIR
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
/* Define to 1 if you have the `posix_fadvise' function. */
#undef HAVE_POSIX_FADVISE
/* Define to 1 if you have the `pthread_create' function. */
#undef HAVE_PTHREAD_CREATE
/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if sse2 is supported by the assembler. */
#undef HAVE_SSE2
/* Define to 1 if sse4.2 is supported by the assembler. */
#undef HAVE_SSE42
/* Define to 1 if ssse3 is supported by the assembler. */
#undef HAVE_SSSE3
/* Define to 1 if you have the `statfs' function. */
#undef HAVE_STATFS
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strrchr' function. */
#undef HAVE_STRRCHR
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
/* Define to 1 if `d_ino' is a member of `struct dirent'. */
#undef HAVE_STRUCT_DIRENT_D_INO
/* Define to 1 if `d_type' is a member of `struct dirent'. */
#undef HAVE_STRUCT_DIRENT_D_TYPE
/* Define to 1 if `f_fstypename' is a member of `struct statfs'. */
#undef HAVE_STRUCT_STATFS_F_FSTYPENAME
/* Define to 1 if `f_type' is a member of `struct statfs'. */
#undef HAVE_STRUCT_STATFS_F_TYPE
/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
/* Define to 1 if `st_nlink' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_NLINK
/* Define to 1 if you have the `sync_file_range' function. */
#undef HAVE_SYNC_FILE_RANGE
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_DIR_H
/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define to 1 if you have the <sys/mkdev.h> header file. */
#undef HAVE_SYS_MKDEV_H
/* Define to 1 if you have the <sys/mount.h> header file. */
#undef HAVE_SYS_MOUNT_H
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_NDIR_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/statfs.h> header file. */
#undef HAVE_SYS_STATFS_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
#undef HAVE_SYS_SYSMACROS_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/vfs.h> header file. */
#undef HAVE_SYS_VFS_H
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `utimensat' function. */
#undef HAVE_UTIMENSAT
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to 1 if assertions should be disabled. */
#undef NDEBUG
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Version number of package */
#undef VERSION
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT32_T
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT64_T
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT8_T
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to the type of a signed integer type of width exactly 8 bits if such
a type exists and the standard includes do not define it. */
#undef int8_t
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
/* Define to the equivalent of the C99 'restrict' keyword, or to
nothing if this is not supported. Do not define if restrict is
supported directly. */
#undef restrict
/* Work around a bug in Sun C++: it does not support _Restrict or
__restrict__, even though the corresponding Sun C compiler ends up with
"#define restrict _Restrict" or "#define restrict __restrict__" in the
previous line. Perhaps some future version of Sun C++ will work with
restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
#if defined __SUNPRO_CC && !defined __RESTRICT
# define _Restrict
# define __restrict__
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef uint32_t
/* Define to the type of an unsigned integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#undef uint64_t
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
#undef uint8_t
/* Define to empty if the keyword `volatile' does not work. Warning: valid
code using `volatile' can become incorrect without. Disable with care. */
#undef volatile

1807
config.sub vendored

File diff suppressed because it is too large Load Diff

8157
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ dnl Checks for programs.
AC_PROG_CC
AC_USE_SYSTEM_EXTENSIONS
AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind],[])
AC_CHECK_PROG([WINE],[wine],[wine],[])
AC_CHECK_PROG([WINE],[wine64],[wine64],[])
AC_CHECK_PROG([SDE],[sde],[sde],[])
AC_CHECK_PROG([ADVD2],[advd2],[advd2],[])
AM_CONDITIONAL(HAVE_ADVD2, [test x"$ADVD2" != x])
@ -36,7 +36,7 @@ AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h limits.h])
AC_CHECK_HEADERS([unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h])
AC_CHECK_HEADERS([pthread.h math.h])
AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/vfs.h sys/statfs.h sys/param.h sys/mount.h sys/sysmacros.h sys/mkdev.h])
AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/sysmacros.h sys/mkdev.h])
AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h mach/mach_time.h execinfo.h])
dnl Checks for typedefs, structures, and compiler characteristics.
@ -65,6 +65,38 @@ AC_CHECK_MEMBERS([struct stat.st_nlink, struct stat.st_mtim.tv_nsec, struct stat
#include <unistd.h>
#endif
]])
dnl Checks for library functions.
AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul])
AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf sigaction])
AC_CHECK_FUNCS([ftruncate fallocate access])
AC_CHECK_FUNCS([fsync posix_fadvise sync_file_range])
AC_CHECK_FUNCS([getc_unlocked ferror_unlocked fnmatch])
AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat])
AC_CHECK_FUNCS([fstatat flock])
AC_CHECK_FUNCS([mach_absolute_time])
AC_CHECK_FUNCS([backtrace backtrace_symbols])
AC_SEARCH_LIBS([clock_gettime], [rt])
AC_CHECK_FUNCS([clock_gettime])
AC_CHECK_CC_OPT([-pthread], CFLAGS="$CFLAGS -pthread", CFLAGS="$CFLAGS -D_REENTRANT")
AC_CHECK_FUNCS([pthread_create])
AC_SEARCH_LIBS([exp], [m])
dnl Checks for statfs for linux avoiding to include sys/mount.h that is required only in darwin
dnl In glibc since 7eae6a91e9b1670330c9f15730082c91c0b1d570, milestone 2.36, sys/mount.h defines fsconfig_command which conflicts with linux/mount.h
AC_CHECK_HEADERS([sys/vfs.h sys/statfs.h])
AC_CHECK_DECLS([statfs], [], [
AC_CHECK_HEADERS([sys/param.h sys/mount.h])
], [[
#if HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
]])
AC_CHECK_FUNCS([statfs])
AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
@ -79,6 +111,7 @@ AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[
#include <sys/statfs.h>
#endif
]])
AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
@ -94,22 +127,6 @@ AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[
#endif
]])
dnl Checks for library functions.
AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul])
AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf sigaction])
AC_CHECK_FUNCS([ftruncate fallocate access])
AC_CHECK_FUNCS([fsync posix_fadvise sync_file_range])
AC_CHECK_FUNCS([getc_unlocked ferror_unlocked fnmatch])
AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat])
AC_CHECK_FUNCS([fstatat flock statfs])
AC_CHECK_FUNCS([mach_absolute_time])
AC_CHECK_FUNCS([backtrace backtrace_symbols])
AC_SEARCH_LIBS([clock_gettime], [rt])
AC_CHECK_FUNCS([clock_gettime])
AC_CHECK_CC_OPT([-pthread], CFLAGS="$CFLAGS -pthread", CFLAGS="$CFLAGS -D_REENTRANT")
AC_CHECK_FUNCS([pthread_create])
AC_SEARCH_LIBS([exp], [m])
dnl Checks for libblkid
AC_ARG_WITH([blkid],
AS_HELP_STRING([--without-blkid], [Ignore presence of blkid and disable it]))
@ -135,6 +152,9 @@ AC_CHECK_CC_OPT([-Wextra], CFLAGS="$CFLAGS -Wextra", [])
AC_CHECK_CC_OPT([-Wuninitialized], CFLAGS="$CFLAGS -Wuninitialized", [])
AC_CHECK_CC_OPT([-Wshadow], CFLAGS="$CFLAGS -Wshadow", [])
dnl Disable warning about zero-length-bounds raised by gcc 10 on linux kernel header on the fm_extents field
AC_CHECK_CC_OPT([-Wno-zero-length-bounds], CFLAGS="$CFLAGS -Wno-zero-length-bounds", [])
dnl Checks for asm
AC_ARG_ENABLE([asm],
AS_HELP_STRING([--disable-asm], [Disable inline assembly]))
@ -179,7 +199,7 @@ dnl Checks for AS supporting the SSE4.2 instructions.
AC_MSG_CHECKING([for sse42])
asmsse42=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#if defined(__i386__) || defined(__x86_64__)
#if defined(__i386__) || defined(__x86_64__)
unsigned f(unsigned crc, unsigned char b)
{
asm volatile("crc32b %1, %0" : "+r" (crc) : "rm" (b));

46
debian/changelog vendored Normal file
View File

@ -0,0 +1,46 @@
snapraid (12.4-1) unstable; urgency=medium
* New upstream version 12.4
-- Mo Zhou <lumin@debian.org> Mon, 27 Jan 2025 00:21:49 -0500
snapraid (12.3-1) unstable; urgency=medium
* New upstream version 12.3
-- Mo Zhou <lumin@debian.org> Thu, 15 Feb 2024 13:56:08 -0500
snapraid (12.2-1) unstable; urgency=medium
* New upstream version 12.2
-- Mo Zhou <lumin@debian.org> Thu, 08 Sep 2022 21:54:28 -0400
snapraid (12.1-1) unstable; urgency=medium
* New upstream version 12.1
-- Mo Zhou <lumin@debian.org> Sun, 30 Jan 2022 12:47:06 -0500
snapraid (12.0-1) unstable; urgency=medium
[ Debian Janitor ]
* Trim trailing whitespace.
* Set upstream metadata fields: Repository, Repository-Browse.
[ Mo Zhou ]
* New upstream version 12.0 (Closes: #995324)
-- Mo Zhou <lumin@debian.org> Sat, 08 Jan 2022 11:49:08 -0500
snapraid (11.5-1) unstable; urgency=medium
* New upstream version 11.5
-- Mo Zhou <lumin@debian.org> Sat, 25 Jul 2020 15:20:50 +0800
snapraid (11.4-1~exp1) experimental; urgency=medium
* Initial release. (Closes: #960816)
-- Mo Zhou <lumin@debian.org> Fri, 22 May 2020 00:42:52 +0800

43
debian/control vendored Normal file
View File

@ -0,0 +1,43 @@
Source: snapraid
Section: admin
Homepage: https://github.com/amadvance/snapraid
Priority: optional
Standards-Version: 4.5.0
Vcs-Git: https://salsa.debian.org/debian/snapraid.git
Vcs-Browser: https://salsa.debian.org/debian/snapraid
Maintainer: Mo Zhou <lumin@debian.org>
Rules-Requires-Root: no
Build-Depends: debhelper-compat (= 12),
Package: snapraid
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends},
Pre-Depends: ${misc:Pre-Depends},
Description: backup program for disk arrays
SnapRAID is a backup program for disk arrays. It stores parity
information of your data and it recovers from up to six disk
failures.
.
SnapRAID is mainly targeted for a home media center, where you
have a lot of big files that rarely change.
.
Beside the ability to recover from disk failures, the other
features of SnapRAID are:
.
* You can use disk already filled with files, without the need to
reformat them. You will access them like now.
* All your data is hashed to ensure data integrity and to avoid
silent corruption.
* If the failed disks are too many to allow a recovery,
you lose the data only on the failed disks.
All the data in the other disks is safe.
* If you accidentally delete some files in a disk, you can
recover them.
* The disks can have different sizes.
* You can add disks at any time.
* It doesn't lock-in your data. You can stop using SnapRAID at any
time without the need to reformat or move data.
* To access a file, only a single disk needs to spin, saving power and
producing less noise.
.
The official site of SnapRAID is: http://www.snapraid.it/

166
debian/copyright vendored Normal file
View File

@ -0,0 +1,166 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://github.com/amadvance/snapraid
Files: *
cmdline/*
Copyright: 2011-2016, Andrea Mazzoleni
License: GPL-3.0+
Files: raid/*
Copyright: 2013-2015, Andrea Mazzoleni
License: GPL-2.0+
Files: tommyds/*
Copyright: 2010, Andrea Mazzoleni.
License: BSD-2-Clause
Files: cmdline/fnmatch.c
cmdline/fnmatch.h
Copyright: 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
License: LGPL-2.0+
Files: cmdline/metro.c
Copyright: 2019, Andrea Mazzoleni
License: Apache-2.0 AND GPL-3.0+
Files: cmdline/murmur3.c
Copyright: 2011, Andrea Mazzoleni
License: GPL-3.0+ AND public-domain
Files: debian/*
Copyright: 2020, Mo Zhou <lumin@debian.org>
License: LGPL-3.0+
##############################################################################
License: public-domain
This is free and unencumbered software released into the public domain.
.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
.
For more information, please refer to <http://unlicense.org/>
License: GPL-2.0+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
License: GPL-3.0+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
.
http://www.apache.org/licenses/LICENSE-2.0
.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
.
On Debian systems, the complete text of the Apache version 2.0 license
can be found in "/usr/share/common-licenses/Apache-2.0".
License: BSD-2-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: LGPL-2.0+
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU Lesser General
Public License can be found in "/usr/share/common-licenses/LGPL-2.0".
License: LGPL-3.0+
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU Lesser General
Public License can be found in "/usr/share/common-licenses/LGPL-3".

5
debian/rules vendored Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/make -f
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
%:
dh $@

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (quilt)

3
debian/upstream/metadata vendored Normal file
View File

@ -0,0 +1,3 @@
---
Repository: https://github.com/amadvance/snapraid.git
Repository-Browse: https://github.com/amadvance/snapraid

5
debian/watch vendored Normal file
View File

@ -0,0 +1,5 @@
version=4
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%snapraid-$1.tar.gz%" \
https://github.com/amadvance/snapraid/tags \
(?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate

View File

@ -1,501 +0,0 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2013-12-25.23; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

16
makecov.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
#
# Run the Coverage test
#
make distclean
if ! ./configure --enable-coverage --enable-sde; then
exit 1
fi
if ! make lcov_reset check lcov_capture lcov_html; then
exit 1
fi

47
makedist.sh Executable file
View File

@ -0,0 +1,47 @@
#!/bin/sh
#
CHECK=check
DEBUG=
if test "x$1" = "x-f"; then
CHECK=all
fi
if test "x$1" = "x-d"; then
DEBUG=--enable-debug
fi
make distclean
# Reconfigure (with force) to get the latest revision from git
autoreconf -f
if ! ./configure.windows-x86 $DEBUG; then
exit 1
fi
if ! make distwindows-x86 distclean; then
exit 1
fi
if ! ./configure.windows-x64 $DEBUG; then
exit 1
fi
if ! make -j4 $CHECK; then
exit 1
fi
if ! make distwindows-x64 distclean; then
exit 1
fi
if ! ./configure ; then
exit 1
fi
if ! make dist; then
exit 1
fi

67
makesan.sh Executable file
View File

@ -0,0 +1,67 @@
#!/bin/sh
#
# Run all the Sanitizers available
#
# Compiler to use
COMPILER=clang
# Options for configure
# --disable-asm
# Inline assembly is not supported by the Sanitizers
# --without-blkid
# External libraries are not supported by the Sanitizers
OPTIONS="--disable-asm --without-blkid"
# Source directory
SOURCE=`pwd`
# Dest directory
DEST=`mktemp -d`
make distclean
cd $DEST
# AddressSanitizer
if ! $SOURCE/configure --enable-asan $OPTIONS CC=$COMPILER; then
exit 1
fi
if ! make check distclean; then
exit 1
fi
# UndefinedBehaviourSanitizer
if ! $SOURCE/configure --enable-ubsan $OPTIONS CC=$COMPILER; then
exit 1
fi
if ! make check distclean; then
exit 1
fi
# MemorySanitizer
if ! $SOURCE/configure --enable-msan $OPTIONS CC=$COMPILER; then
exit 1
fi
if ! make check distclean; then
exit 1
fi
# ThreadSanitizer
if ! $SOURCE/configure --enable-tsan $OPTIONS CC=$COMPILER; then
exit 1
fi
if ! make check distclean; then
exit 1
fi
cd $SOURCE
if ! ./configure; then
exit 1
fi

30
makescan.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
#
# Run the Coverity Scan static analyzer
#
rm -r cov-int
make distclean
# Reconfigure (with force) to get the latest revision from git
autoreconf -f
if ! ./configure ; then
exit 1
fi
export PATH=$PATH:contrib/cov-analysis-linux64-2020.09/bin
if ! cov-build --dir cov-int make; then
exit 1
fi
REVISION=`sh autover.sh`
tar czf snapraid-$REVISION.tgz cov-int
rm -r cov-int
echo snapraid-$REVISION.tgz ready to upload to https://scan.coverity.com/projects/1986/builds/new

5
makesum.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
echo sha256 > CHECKSUMS
cd archive && sha256sum * | sort -k 2 -V >> ../CHECKSUMS

63
maketest.sh Executable file
View File

@ -0,0 +1,63 @@
#!/bin/sh
#
# Run all the Coverage and Valgrind tests
#
# Source directory
SOURCE=`pwd`
# Dest directory
DEST=`mktemp -d`
make distclean
cd $DEST
# Coverage
if ! $SOURCE/configure --enable-coverage --enable-sde; then
exit 1
fi
if ! make lcov_reset check lcov_capture lcov_html; then
exit 1
fi
cp -a cov $SOURCE/cov
if ! make distclean; then
exit 1
fi
# Valgrind
if ! $SOURCE/configure --enable-valgrind; then
exit 1
fi
if ! make check distclean; then
exit 1
fi
# Helgrind
if ! $SOURCE/configure --enable-helgrind; then
exit 1
fi
if ! make check distclean; then
exit 1
fi
# Drd
if ! $SOURCE/configure --enable-drd; then
exit 1
fi
if ! make check distclean; then
exit 1
fi
cd $SOURCE
if ! ./configure; then
exit 1
fi

215
missing
View File

@ -1,215 +0,0 @@
#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -303,16 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -335,5 +335,6 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

428
raid/mktables.c Normal file
View File

@ -0,0 +1,428 @@
/*
* Copyright (C) 2013 Andrea Mazzoleni
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <stdio.h>
#include <stdint.h>
/**
* Multiplication a*b in GF(2^8).
*/
static uint8_t gfmul(uint8_t a, uint8_t b)
{
uint8_t v;
v = 0;
while (b) {
if ((b & 1) != 0)
v ^= a;
if ((a & 0x80) != 0) {
a <<= 1;
a ^= 0x1d;
} else {
a <<= 1;
}
b >>= 1;
}
return v;
}
/**
* Inversion (1/a) in GF(2^8).
*/
uint8_t gfinv[256];
/**
* Number of parities.
* This is the number of rows of the generator matrix.
*/
#define PARITY 6
/**
* Number of disks.
* This is the number of columns of the generator matrix.
*/
#define DISK (257 - PARITY)
/**
* Setup the Cauchy matrix used to generate the parity.
*/
static void set_cauchy(uint8_t *matrix)
{
int i, j;
uint8_t inv_x, y;
/*
* The first row of the generator matrix is formed by all 1.
*
* The generator matrix is an Extended Cauchy matrix built from
* a Cauchy matrix adding at the top a row of all 1.
*
* Extending a Cauchy matrix in this way maintains the MDS property
* of the matrix.
*
* For example, considering a generator matrix of 4x6 we have now:
*
* 1 1 1 1 1 1
* - - - - - -
* - - - - - -
* - - - - - -
*/
for (i = 0; i < DISK; ++i)
matrix[0 * DISK + i] = 1;
/*
* Second row is formed with powers 2^i, and it's the first
* row of the Cauchy matrix.
*
* Each element of the Cauchy matrix is in the form 1/(x_i + y_j)
* where all x_i and y_j must be different for any i and j.
*
* For the first row with j=0, we choose x_i = 2^-i and y_0 = 0
* and we obtain a first row formed as:
*
* 1/(x_i + y_0) = 1/(2^-i + 0) = 2^i
*
* with 2^-i != 0 for any i
*
* In the example we get:
*
* x_0 = 1
* x_1 = 142
* x_2 = 71
* x_3 = 173
* x_4 = 216
* x_5 = 108
* y_0 = 0
*
* with the matrix:
*
* 1 1 1 1 1 1
* 1 2 4 8 16 32
* - - - - - -
* - - - - - -
*/
inv_x = 1;
for (i = 0; i < DISK; ++i) {
matrix[1 * DISK + i] = inv_x;
inv_x = gfmul(2, inv_x);
}
/*
* The rest of the Cauchy matrix is formed choosing for each row j
* a new y_j = 2^j and reusing the x_i already assigned in the first
* row obtaining :
*
* 1/(x_i + y_j) = 1/(2^-i + 2^j)
*
* with 2^-i + 2^j != 0 for any i,j with i>=0,j>=1,i+j<255
*
* In the example we get:
*
* y_1 = 2
* y_2 = 4
*
* with the matrix:
*
* 1 1 1 1 1 1
* 1 2 4 8 16 32
* 244 83 78 183 118 47
* 167 39 213 59 153 82
*/
y = 2;
for (j = 0; j < PARITY - 2; ++j) {
inv_x = 1;
for (i = 0; i < DISK; ++i) {
uint8_t x = gfinv[inv_x];
matrix[(j + 2) * DISK + i] = gfinv[y ^ x];
inv_x = gfmul(2, inv_x);
}
y = gfmul(2, y);
}
/*
* Finally we adjust the matrix multiplying each row for
* the inverse of the first element in the row.
*
* Also this operation maintains the MDS property of the matrix.
*
* Resulting in:
*
* 1 1 1 1 1 1
* 1 2 4 8 16 32
* 1 245 210 196 154 113
* 1 187 166 215 7 106
*/
for (j = 0; j < PARITY - 2; ++j) {
uint8_t f = gfinv[matrix[(j + 2) * DISK]];
for (i = 0; i < DISK; ++i)
matrix[(j + 2) * DISK + i] = gfmul(matrix[(j + 2) * DISK + i], f);
}
}
/**
* Setup the Power matrix used to generate the parity.
*/
static void set_power(uint8_t *matrix)
{
unsigned i;
uint8_t v;
v = 1;
for (i = 0; i < DISK; ++i)
matrix[0 * DISK + i] = v;
v = 1;
for (i = 0; i < DISK; ++i) {
matrix[1 * DISK + i] = v;
v = gfmul(2, v);
}
v = 1;
for (i = 0; i < DISK; ++i) {
matrix[2 * DISK + i] = v;
v = gfmul(0x8e, v);
}
}
/**
* Next power of 2.
*/
static unsigned np(unsigned v)
{
--v;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
++v;
return v;
}
int main(void)
{
uint8_t v;
int i, j, k, p;
uint8_t matrix[PARITY * 256];
printf("/*\n");
printf(" * Copyright (C) 2013 Andrea Mazzoleni\n");
printf(" *\n");
printf(" * This program is free software: you can redistribute it and/or modify\n");
printf(" * it under the terms of the GNU General Public License as published by\n");
printf(" * the Free Software Foundation, either version 2 of the License, or\n");
printf(" * (at your option) any later version.\n");
printf(" *\n");
printf(" * This program is distributed in the hope that it will be useful,\n");
printf(" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
printf(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
printf(" * GNU General Public License for more details.\n");
printf(" */\n");
printf("\n");
printf("#include \"internal.h\"\n");
printf("\n");
/* a*b */
printf("const uint8_t __aligned(256) raid_gfmul[256][256] =\n");
printf("{\n");
for (i = 0; i < 256; ++i) {
printf("\t{\n");
for (j = 0; j < 256; ++j) {
if (j % 8 == 0)
printf("\t\t");
v = gfmul(i, j);
if (v == 1)
gfinv[i] = j;
printf("0x%02x,", (unsigned)v);
if (j % 8 == 7)
printf("\n");
else
printf(" ");
}
printf("\t},\n");
}
printf("};\n\n");
/* 2^a */
printf("const uint8_t __aligned(256) raid_gfexp[256] =\n");
printf("{\n");
v = 1;
for (i = 0; i < 256; ++i) {
if (i % 8 == 0)
printf("\t");
printf("0x%02x,", v);
v = gfmul(v, 2);
if (i % 8 == 7)
printf("\n");
else
printf(" ");
}
printf("};\n\n");
/* 1/a */
printf("const uint8_t __aligned(256) raid_gfinv[256] =\n");
printf("{\n");
printf("\t/* note that the first element is not significative */\n");
for (i = 0; i < 256; ++i) {
if (i % 8 == 0)
printf("\t");
if (i == 0)
v = 0;
else
v = gfinv[i];
printf("0x%02x,", v);
if (i % 8 == 7)
printf("\n");
else
printf(" ");
}
printf("};\n\n");
/* power matrix */
set_power(matrix);
printf("/**\n");
printf(" * Power matrix used to generate parity.\n");
printf(" * This matrix is valid for up to %u parity with %u data disks.\n", 3, DISK);
printf(" *\n");
for (p = 0; p < 3; ++p) {
printf(" *");
for (i = 0; i < DISK; ++i)
printf(" %02x", matrix[p * DISK + i]);
printf("\n");
}
printf(" */\n");
printf("const uint8_t __aligned(256) raid_gfvandermonde[%u][256] =\n", 3);
printf("{\n");
for (p = 0; p < 3; ++p) {
printf("\t{\n");
for (i = 0; i < DISK; ++i) {
if (i % 8 == 0)
printf("\t\t");
printf("0x%02x,", matrix[p * DISK + i]);
if (i != DISK - 1) {
if (i % 8 == 7)
printf("\n");
else
printf(" ");
}
}
printf("\n\t},\n");
}
printf("};\n\n");
/* cauchy matrix */
set_cauchy(matrix);
printf("/**\n");
printf(" * Cauchy matrix used to generate parity.\n");
printf(" * This matrix is valid for up to %u parity with %u data disks.\n", PARITY, DISK);
printf(" *\n");
for (p = 0; p < PARITY; ++p) {
printf(" *");
for (i = 0; i < DISK; ++i)
printf(" %02x", matrix[p * DISK + i]);
printf("\n");
}
printf(" */\n");
printf("const uint8_t __aligned(256) raid_gfcauchy[%u][256] =\n", PARITY);
printf("{\n");
for (p = 0; p < PARITY; ++p) {
printf("\t{\n");
for (i = 0; i < DISK; ++i) {
if (i % 8 == 0)
printf("\t\t");
printf("0x%02x,", matrix[p * DISK + i]);
if (i != DISK - 1) {
if (i % 8 == 7)
printf("\n");
else
printf(" ");
}
}
printf("\n\t},\n");
}
printf("};\n\n");
printf("#ifdef CONFIG_X86\n");
printf("/**\n");
printf(" * PSHUFB tables for the Cauchy matrix.\n");
printf(" *\n");
printf(" * Indexes are [DISK][PARITY - 2][LH].\n");
printf(" * Where DISK is from 0 to %u, PARITY from 2 to %u, LH from 0 to 1.\n", DISK - 1, PARITY - 1);
printf(" */\n");
printf("const uint8_t __aligned(256) raid_gfcauchypshufb[%u][%u][2][16] =\n", DISK, np(PARITY - 2));
printf("{\n");
for (i = 0; i < DISK; ++i) {
printf("\t{\n");
for (p = 2; p < PARITY; ++p) {
printf("\t\t{\n");
for (j = 0; j < 2; ++j) {
printf("\t\t\t{ ");
for (k = 0; k < 16; ++k) {
v = gfmul(matrix[p * DISK + i], k);
if (j == 1)
v = gfmul(v, 16);
printf("0x%02x", (unsigned)v);
if (k != 15)
printf(", ");
}
printf(" },\n");
}
printf("\t\t},\n");
}
printf("\t},\n");
}
printf("};\n");
printf("#endif\n\n");
printf("#ifdef CONFIG_X86\n");
printf("/**\n");
printf(" * PSHUFB tables for generic multiplication.\n");
printf(" *\n");
printf(" * Indexes are [MULTIPLIER][LH].\n");
printf(" * Where MULTIPLIER is from 0 to 255, LH from 0 to 1.\n");
printf(" */\n");
printf("const uint8_t __aligned(256) raid_gfmulpshufb[256][2][16] =\n");
printf("{\n");
for (i = 0; i < 256; ++i) {
printf("\t{\n");
for (j = 0; j < 2; ++j) {
printf("\t\t{ ");
for (k = 0; k < 16; ++k) {
v = gfmul(i, k);
if (j == 1)
v = gfmul(v, 16);
printf("0x%02x", (unsigned)v);
if (k != 15)
printf(", ");
}
printf(" },\n");
}
printf("\t},\n");
}
printf("};\n");
printf("#endif\n\n");
return 0;
}

View File

@ -20,50 +20,50 @@
* the primitive polynomial x^8 + x^4 + x^3 + x^2 + 1 (285 decimal), and
* supporting up to six parity levels.
*
* For RAID5 and RAID6 it works as as described in the H. Peter Anvin's
* For RAID5 and RAID6, it works as described in H. Peter Anvin's
* paper "The mathematics of RAID-6" [1]. Please refer to this paper for a
* complete explanation.
*
* To support triple parity, it was first evaluated and then dropped, an
* To support triple parity, it was first evaluated and then dropped; an
* extension of the same approach, with additional parity coefficients set
* as powers of 2^-1, with equations:
*
* P = sum(Di)
* Q = sum(2^i * Di)
* R = sum(2^-i * Di) with 0<=i<N
* R = sum(2^-i * Di) with 0 <= i < N
*
* This approach works well for triple parity and it's very efficient,
* This approach works well for triple parity and is very efficient
* because we can implement very fast parallel multiplications and
* divisions by 2 in GF(2^8).
*
* It's also similar at the approach used by ZFS RAIDZ3, with the
* It is also similar to the approach used by ZFS RAIDZ3, with the
* difference that ZFS uses powers of 4 instead of 2^-1.
*
* Unfortunately it doesn't work beyond triple parity, because whatever
* Unfortunately, it doesn't work beyond triple parity because whatever
* value we choose to generate the power coefficients to compute other
* parities, the resulting equations are not solvable for some
* combinations of missing disks.
*
* This is expected, because the Vandermonde matrix used to compute the
* This is expected because the Vandermonde matrix used to compute the
* parity has no guarantee to have all submatrices not singular
* [2, Chap 11, Problem 7] and this is a requirement to have
* a MDS (Maximum Distance Separable) code [2, Chap 11, Theorem 8].
* [2, Chap 11, Problem 7], and this is a requirement to have
* an MDS (Maximum Distance Separable) code [2, Chap 11, Theorem 8].
*
* To overcome this limitation, we use a Cauchy matrix [3][4] to compute
* the parity. A Cauchy matrix has the property to have all the square
* submatrices not singular, resulting in always solvable equations,
* the parity. A Cauchy matrix has the property of having all square
* submatrices not singular, resulting in always solvable equations
* for any combination of missing disks.
*
* The problem of this approach is that it requires the use of
* The problem with this approach is that it requires the use of
* generic multiplications, and not only by 2 or 2^-1, potentially
* affecting badly the performance.
* affecting performance negatively.
*
* Hopefully there is a method to implement parallel multiplications
* using SSSE3 or AVX2 instructions [1][5]. Method competitive with the
* Hopefully, there is a method to implement parallel multiplications
* using SSSE3 or AVX2 instructions [1][5], a method competitive with the
* computation of triple parity using power coefficients.
*
* Another important property of the Cauchy matrix is that we can setup
* the first two rows with coefficients equal at the RAID5 and RAID6 approach
* Another important property of the Cauchy matrix is that we can set up
* the first two rows with coefficients equal to the RAID5 and RAID6 approach
* described, resulting in a compatible extension, and requiring SSSE3
* or AVX2 instructions only if triple parity or beyond is used.
*
@ -71,7 +71,7 @@
* to make the first column of all 1, to optimize the computation for
* the first disk.
*
* This results in the matrix A[row,col] defined as:
* This results in the matrix A[row, col] defined as:
*
* 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01...
* 01 02 04 08 10 20 40 80 1d 3a 74 e8 cd 87 13 26 4c 98 2d 5a b4 75...
@ -80,25 +80,25 @@
* 01 97 7f 9c 7c 18 bd a2 58 1a da 74 70 a3 e5 47 29 07 f5 80 23 e9...
* 01 2b 3f cf 73 2c d6 ed cb 74 15 78 8a c1 17 c9 89 68 21 ab 76 3b...
*
* This matrix supports 6 level of parity, one for each row, for up to 251
* This matrix supports 6 levels of parity, one for each row, for up to 251
* data disks, one for each column, with all the 377,342,351,231 square
* submatrices not singular, verified also with brute-force.
* submatrices not singular, verified also with brute force.
*
* This matrix can be extended to support any number of parities, just
* adding additional rows, and removing one column for each new row.
* (see mktables.c for more details in how the matrix is generated)
* adding additional rows and removing one column for each new row.
* (see mktables.c for more details on how the matrix is generated)
*
* In details, parity is computed as:
* In detail, parity is computed as:
*
* P = sum(Di)
* Q = sum(2^i * Di)
* Q = sum(2^i * Di)
* R = sum(A[2,i] * Di)
* S = sum(A[3,i] * Di)
* T = sum(A[4,i] * Di)
* U = sum(A[5,i] * Di) with 0<=i<N
* U = sum(A[5,i] * Di) with 0 <= i < N
*
* To recover from a failure of six disks at indexes x,y,z,h,v,w,
* with 0<=x<y<z<h<v<w<N, we compute the parity of the available N-6
* To recover from a failure of six disks at indexes x, y, z, h, v, w,
* with 0 <= x < y < z < h < v < w < N, we compute the parity of the available N-6
* disks as:
*
* Pa = sum(Di)
@ -106,7 +106,7 @@
* Ra = sum(A[2,i] * Di)
* Sa = sum(A[3,i] * Di)
* Ta = sum(A[4,i] * Di)
* Ua = sum(A[5,i] * Di) with 0<=i<N,i!=x,i!=y,i!=z,i!=h,i!=v,i!=w.
* Ua = sum(A[5,i] * Di) with 0 <= i < N, i != x, i != y, i != z, i != h, i != v, i != w.
*
* And if we define:
*
@ -126,13 +126,13 @@
* Td = A[4,x] * Dx + A[4,y] * Dy + A[4,z] * Dz + A[4,h] * Dh + A[4,v] * Dv + A[4,w] * Dw
* Ud = A[5,x] * Dx + A[5,y] * Dy + A[5,z] * Dz + A[5,h] * Dh + A[5,v] * Dv + A[5,w] * Dw
*
* A linear system always solvable because the coefficients matrix is
* always not singular due the properties of the matrix A[].
* A linear system is always solvable because the coefficients matrix is
* always not singular due to the properties of the matrix A[].
*
* Resulting speed in x64, with 8 data disks, using a stripe of 256 KiB,
* The resulting speed in x64, with 8 data disks, using a stripe of 256 KiB,
* for a Core i5-4670K Haswell Quad-Core 3.4GHz is:
*
* int8 int32 int64 sse2 ssse3 avx2
* int8 int32 int64 sse2 ssse3 avx2
* gen1 13339 25438 45438 50588
* gen2 4115 6514 21840 32201
* gen3 814 10154 18613
@ -143,18 +143,18 @@
* Values are in MiB/s of data processed by a single thread, not counting
* generated parity.
*
* You can replicate these results in your machine using the
* You can replicate these results on your machine using the
* "raid/test/speedtest.c" program.
*
* For comparison, the triple parity computation using the power
* coefficients "1,2,2^-1" is only a little faster than the one based on
* the Cauchy matrix if SSSE3 or AVX2 is present.
*
* int8 int32 int64 sse2 ssse3 avx2
* int8 int32 int64 sse2 ssse3 avx2
* genz 2337 2874 10920 18944
*
* In conclusion, the use of power coefficients, and specifically powers
* of 1,2,2^-1, is the best option to implement triple parity in CPUs
* of 1, 2, 2^-1, is the best option to implement triple parity in CPUs
* without SSSE3 and AVX2.
* But if a modern CPU with SSSE3 or AVX2 is available, the Cauchy
* matrix is the best option because it provides a fast and general

View File

@ -192,7 +192,7 @@ int raid_check(int nr, int *ir, int nd, int np, size_t size, void **v);
* This function identifies the failed data and parity blocks using the
* available redundancy.
*
* It uses a brute force method, and then the call can be expansive.
* It uses a brute force method, and then the call can be expensive.
* The expected execution time is proportional at the binomial coefficient
* @np + @nd choose @np - 1, usually written as:
*

View File

@ -14,76 +14,78 @@
#include "internal.h"
typedef void (void_f)(void);
static struct raid_func {
const char *name;
void (*p)();
void_f* func;
} RAID_FUNC[] = {
{ "int8", raid_gen3_int8 },
{ "int8", raid_gen4_int8 },
{ "int8", raid_gen5_int8 },
{ "int8", raid_gen6_int8 },
{ "int32", raid_gen1_int32 },
{ "int64", raid_gen1_int64 },
{ "int32", raid_gen2_int32 },
{ "int64", raid_gen2_int64 },
{ "int32", raid_genz_int32 },
{ "int64", raid_genz_int64 },
{ "int8", raid_rec1_int8 },
{ "int8", raid_rec2_int8 },
{ "int8", raid_recX_int8 },
{ "int8", (void_f*)raid_gen3_int8 },
{ "int8", (void_f*)raid_gen4_int8 },
{ "int8", (void_f*)raid_gen5_int8 },
{ "int8", (void_f*)raid_gen6_int8 },
{ "int32", (void_f*)raid_gen1_int32 },
{ "int64", (void_f*)raid_gen1_int64 },
{ "int32", (void_f*)raid_gen2_int32 },
{ "int64", (void_f*)raid_gen2_int64 },
{ "int32", (void_f*)raid_genz_int32 },
{ "int64", (void_f*)raid_genz_int64 },
{ "int8", (void_f*)raid_rec1_int8 },
{ "int8", (void_f*)raid_rec2_int8 },
{ "int8", (void_f*)raid_recX_int8 },
#ifdef CONFIG_X86
#ifdef CONFIG_SSE2
{ "sse2", raid_gen1_sse2 },
{ "sse2", raid_gen2_sse2 },
{ "sse2", raid_genz_sse2 },
{ "sse2", (void_f*)raid_gen1_sse2 },
{ "sse2", (void_f*)raid_gen2_sse2 },
{ "sse2", (void_f*)raid_genz_sse2 },
#endif
#ifdef CONFIG_SSSE3
{ "ssse3", raid_gen3_ssse3 },
{ "ssse3", raid_gen4_ssse3 },
{ "ssse3", raid_gen5_ssse3 },
{ "ssse3", raid_gen6_ssse3 },
{ "ssse3", raid_rec1_ssse3 },
{ "ssse3", raid_rec2_ssse3 },
{ "ssse3", raid_recX_ssse3 },
{ "ssse3", (void_f*)raid_gen3_ssse3 },
{ "ssse3", (void_f*)raid_gen4_ssse3 },
{ "ssse3", (void_f*)raid_gen5_ssse3 },
{ "ssse3", (void_f*)raid_gen6_ssse3 },
{ "ssse3", (void_f*)raid_rec1_ssse3 },
{ "ssse3", (void_f*)raid_rec2_ssse3 },
{ "ssse3", (void_f*)raid_recX_ssse3 },
#endif
#ifdef CONFIG_AVX2
{ "avx2", raid_gen1_avx2 },
{ "avx2", raid_gen2_avx2 },
{ "avx2", raid_rec1_avx2 },
{ "avx2", raid_rec2_avx2 },
{ "avx2", raid_recX_avx2 },
{ "avx2", (void_f*)raid_gen1_avx2 },
{ "avx2", (void_f*)raid_gen2_avx2 },
{ "avx2", (void_f*)raid_rec1_avx2 },
{ "avx2", (void_f*)raid_rec2_avx2 },
{ "avx2", (void_f*)raid_recX_avx2 },
#endif
#endif
#ifdef CONFIG_X86_64
#ifdef CONFIG_SSE2
{ "sse2e", raid_gen2_sse2ext },
{ "sse2e", raid_genz_sse2ext },
{ "sse2e", (void_f*)raid_gen2_sse2ext },
{ "sse2e", (void_f*)raid_genz_sse2ext },
#endif
#ifdef CONFIG_SSSE3
{ "ssse3e", raid_gen3_ssse3ext },
{ "ssse3e", raid_gen4_ssse3ext },
{ "ssse3e", raid_gen5_ssse3ext },
{ "ssse3e", raid_gen6_ssse3ext },
{ "ssse3e", (void_f*)raid_gen3_ssse3ext },
{ "ssse3e", (void_f*)raid_gen4_ssse3ext },
{ "ssse3e", (void_f*)raid_gen5_ssse3ext },
{ "ssse3e", (void_f*)raid_gen6_ssse3ext },
#endif
#ifdef CONFIG_AVX2
{ "avx2e", raid_gen3_avx2ext },
{ "avx2e", raid_genz_avx2ext },
{ "avx2e", raid_gen4_avx2ext },
{ "avx2e", raid_gen5_avx2ext },
{ "avx2e", raid_gen6_avx2ext },
{ "avx2e", (void_f*)raid_gen3_avx2ext },
{ "avx2e", (void_f*)raid_genz_avx2ext },
{ "avx2e", (void_f*)raid_gen4_avx2ext },
{ "avx2e", (void_f*)raid_gen5_avx2ext },
{ "avx2e", (void_f*)raid_gen6_avx2ext },
#endif
#endif
{ 0, 0 }
};
static const char *raid_tag(void (*func)())
static const char *raid_tag(void_f* func)
{
struct raid_func *i = RAID_FUNC;
while (i->name != 0) {
if (i->p == func)
if (i->func == func)
return i->name;
++i;
}
@ -95,51 +97,51 @@ static const char *raid_tag(void (*func)())
const char *raid_gen1_tag(void)
{
return raid_tag(raid_gen_ptr[0]);
return raid_tag((void_f*)raid_gen_ptr[0]);
}
const char *raid_gen2_tag(void)
{
return raid_tag(raid_gen_ptr[1]);
return raid_tag((void_f*)raid_gen_ptr[1]);
}
const char *raid_genz_tag(void)
{
return raid_tag(raid_genz_ptr);
return raid_tag((void_f*)raid_genz_ptr);
}
const char *raid_gen3_tag(void)
{
return raid_tag(raid_gen_ptr[2]);
return raid_tag((void_f*)raid_gen_ptr[2]);
}
const char *raid_gen4_tag(void)
{
return raid_tag(raid_gen_ptr[3]);
return raid_tag((void_f*)raid_gen_ptr[3]);
}
const char *raid_gen5_tag(void)
{
return raid_tag(raid_gen_ptr[4]);
return raid_tag((void_f*)raid_gen_ptr[4]);
}
const char *raid_gen6_tag(void)
{
return raid_tag(raid_gen_ptr[5]);
return raid_tag((void_f*)raid_gen_ptr[5]);
}
const char *raid_rec1_tag(void)
{
return raid_tag(raid_rec_ptr[0]);
return raid_tag((void_f*)raid_rec_ptr[0]);
}
const char *raid_rec2_tag(void)
{
return raid_tag(raid_rec_ptr[1]);
return raid_tag((void_f*)raid_rec_ptr[1]);
}
const char *raid_recX_tag(void)
{
return raid_tag(raid_rec_ptr[2]);
return raid_tag((void_f*)raid_rec_ptr[2]);
}

36
snapraid-rpm.spec Normal file
View File

@ -0,0 +1,36 @@
Name: snapraid
Summary: Disk array backup for many large rarely-changed files
Version: 12.2
Release: 3%{?dist}
License: GPLv3+
Group: Applications/System
URL: http://www.snapraid.it/
Source: https://github.com/amadvance/snapraid/releases/download/v%{version}/snapraid-%{version}.tar.gz
BuildRequires: gcc
%description
SnapRAID is a backup program for disk arrays. It stores parity
information of your data and it's able to recover from up to six disk
failures. SnapRAID is mainly targeted for a home media center, with a
lot of big files that rarely change.
%prep
%setup -q
%build
%configure
make %{?_smp_mflags}
%check
make check
%install
make install DESTDIR=%{buildroot}
%files
%doc COPYING AUTHORS HISTORY README
%{_bindir}/snapraid
%{_mandir}/man1/snapraid.1*
%changelog

View File

@ -68,42 +68,39 @@ snapraid [\-V, \-\-version] [\-H, \-\-help] [\-C, \-\-gen\-conf CONTENT]
.PP
.PD
.SH DESCRIPTION
SnapRAID is a backup program for disk arrays. It stores parity
information of your data and it recovers from up to six disk
failures.
SnapRAID is a backup program designed for disk arrays, storing
parity information for data recovery in the event of up to six
disk failures.
.PP
SnapRAID is mainly targeted for a home media center, with a lot of
big files that rarely change.
.PP
Beside the ability to recover from disk failures, other
features of SnapRAID are:
Primarily intended for home media centers with large,
infrequently changing files, SnapRAID offers several features:
.PD 0
.IP \(bu
You can use disk already filled with files, without the need to
reformat them. You will access them like now.
You can utilize disks already filled with files without the
need to reformat them, accessing them as usual.
.IP \(bu
All your data is hashed to ensure data integrity and to avoid
All your data is hashed to ensure data integrity and prevent
silent corruption.
.IP \(bu
If the failed disks are too many to allow a recovery,
you lose the data only on the failed disks.
All the data in the other disks is safe.
When the number of failed disks exceeds the parity count,
data loss is confined to the affected disks; data on
other disks remains accessible.
.IP \(bu
If you accidentally delete some files in a disk, you can
recover them.
If you accidentally delete files on a disk, recovery is
possible.
.IP \(bu
The disks can have different sizes.
Disks can have different sizes.
.IP \(bu
You can add disks at any time.
.IP \(bu
It doesn\'t lock\-in your data. You can stop using SnapRAID at any
time without the need to reformat or move data.
SnapRAID doesn\'t lock in your data; you can stop using it
anytime without reformatting or moving data.
.IP \(bu
To access a file, only a single disk needs to spin, saving power and
producing less noise.
To access a file, only a single disk needs to spin, saving
power and reducing noise.
.PD
.PP
The official site of SnapRAID is:
For more information, please visit the official SnapRAID site:
.PP
.RS 4
http://www.snapraid.it/
@ -118,30 +115,30 @@ consider before using it.
.PP
The main one is that if a disk fails, and you haven\'t recently synced,
you may be unable to do a complete recover.
More specifically, you may be unable to recover up to the size of the
amount of the changed or deleted files from the last sync operation.
More specifically, you may be unable to recover up to the size of
the changed or deleted files from the last sync operation.
This happens even if the files changed or deleted are not in the
failed disk. This is the reason because SnapRAID is better suited for
failed disk. This is why SnapRAID is better suited for
data that rarely change.
.PP
Instead the new added files don\'t prevent the recovering of the already
existing files. You may only lose the just added files, if they are on
On the other hand, newly added files don\'t prevent recovering already
existing files. You may only lose the recently added files, if they are on
the failed disk.
.PP
Other limitations are:
Other SnapRAID limitations are:
.PD 0
.IP \(bu
You have different file\-systems for each disk.
Using a RAID you have only a big file\-system.
With SnapRAID, you still have separate file\-systems for each disk.
With RAID you get a single large file\-system.
.IP \(bu
It doesn\'t stripe data.
SnapRAID doesn\'t stripe data.
With RAID you get a speed boost with striping.
.IP \(bu
It doesn\'t support real\-time recovery.
SnapRAID doesn\'t support real\-time recovery.
With RAID you do not have to stop working when a disk fails.
.IP \(bu
It\'s able to recover damages only from a limited number of disks.
With a Backup you are able to recover from a complete
SnapRAID is able to recover damages only from a limited number of disks.
With a Backup you can recover from a complete
failure of the whole disk array.
.IP \(bu
Only file, time\-stamps, symlinks and hardlinks are saved.
@ -1363,7 +1360,7 @@ WARNING! This option is for experts only, and it\'s highly
recommended to not change it. To change again this value in
future you\'ll have to recreate the whole parity!
.PP
A reason to use a different hashsize is if you have a lot of small
A reason to use a different blocksize is if you have a lot of small
files. In the order of many millions.
.PP
For each file, even of few bytes, a whole block of parity is allocated,

View File

@ -21,33 +21,30 @@ Synopsis
:snapraid [-V, --version] [-H, --help] [-C, --gen-conf CONTENT]
Description
SnapRAID is a backup program for disk arrays. It stores parity
information of your data and it recovers from up to six disk
failures.
SnapRAID is a backup program designed for disk arrays, storing
parity information for data recovery in the event of up to six
disk failures.
SnapRAID is mainly targeted for a home media center, with a lot of
big files that rarely change.
Primarily intended for home media centers with large,
infrequently changing files, SnapRAID offers several features:
Beside the ability to recover from disk failures, other
features of SnapRAID are:
* You can use disk already filled with files, without the need to
reformat them. You will access them like now.
* All your data is hashed to ensure data integrity and to avoid
* You can utilize disks already filled with files without the
need to reformat them, accessing them as usual.
* All your data is hashed to ensure data integrity and prevent
silent corruption.
* If the failed disks are too many to allow a recovery,
you lose the data only on the failed disks.
All the data in the other disks is safe.
* If you accidentally delete some files in a disk, you can
recover them.
* The disks can have different sizes.
* When the number of failed disks exceeds the parity count,
data loss is confined to the affected disks; data on
other disks remains accessible.
* If you accidentally delete files on a disk, recovery is
possible.
* Disks can have different sizes.
* You can add disks at any time.
* It doesn't lock-in your data. You can stop using SnapRAID at any
time without the need to reformat or move data.
* To access a file, only a single disk needs to spin, saving power and
producing less noise.
* SnapRAID doesn't lock in your data; you can stop using it
anytime without reformatting or moving data.
* To access a file, only a single disk needs to spin, saving
power and reducing noise.
The official site of SnapRAID is:
For more information, please visit the official SnapRAID site:
:http://www.snapraid.it/
@ -58,26 +55,26 @@ Limitations
The main one is that if a disk fails, and you haven't recently synced,
you may be unable to do a complete recover.
More specifically, you may be unable to recover up to the size of the
amount of the changed or deleted files from the last sync operation.
More specifically, you may be unable to recover up to the size of
the changed or deleted files from the last sync operation.
This happens even if the files changed or deleted are not in the
failed disk. This is the reason because SnapRAID is better suited for
failed disk. This is why SnapRAID is better suited for
data that rarely change.
Instead the new added files don't prevent the recovering of the already
existing files. You may only lose the just added files, if they are on
On the other hand, newly added files don't prevent recovering already
existing files. You may only lose the recently added files, if they are on
the failed disk.
Other limitations are:
Other SnapRAID limitations are:
* You have different file-systems for each disk.
Using a RAID you have only a big file-system.
* It doesn't stripe data.
* With SnapRAID, you still have separate file-systems for each disk.
With RAID you get a single large file-system.
* SnapRAID doesn't stripe data.
With RAID you get a speed boost with striping.
* It doesn't support real-time recovery.
* SnapRAID doesn't support real-time recovery.
With RAID you do not have to stop working when a disk fails.
* It's able to recover damages only from a limited number of disks.
With a Backup you are able to recover from a complete
* SnapRAID is able to recover damages only from a limited number of disks.
With a Backup you can recover from a complete
failure of the whole disk array.
* Only file, time-stamps, symlinks and hardlinks are saved.
Permissions, ownership and extended attributes are not saved.
@ -1062,7 +1059,7 @@ Configuration
recommended to not change it. To change again this value in
future you'll have to recreate the whole parity!
A reason to use a different hashsize is if you have a lot of small
A reason to use a different blocksize is if you have a lot of small
files. In the order of many millions.
For each file, even of few bytes, a whole block of parity is allocated,

View File

@ -28,33 +28,30 @@ snapraid [-V, --version] [-H, --help] [-C, --gen-conf CONTENT]
2 DESCRIPTION
=============
SnapRAID is a backup program for disk arrays. It stores parity
information of your data and it recovers from up to six disk
failures.
SnapRAID is a backup program designed for disk arrays, storing
parity information for data recovery in the event of up to six
disk failures.
SnapRAID is mainly targeted for a home media center, with a lot of
big files that rarely change.
Primarily intended for home media centers with large,
infrequently changing files, SnapRAID offers several features:
Beside the ability to recover from disk failures, other
features of SnapRAID are:
* You can use disk already filled with files, without the need to
reformat them. You will access them like now.
* All your data is hashed to ensure data integrity and to avoid
* You can utilize disks already filled with files without the
need to reformat them, accessing them as usual.
* All your data is hashed to ensure data integrity and prevent
silent corruption.
* If the failed disks are too many to allow a recovery,
you lose the data only on the failed disks.
All the data in the other disks is safe.
* If you accidentally delete some files in a disk, you can
recover them.
* The disks can have different sizes.
* When the number of failed disks exceeds the parity count,
data loss is confined to the affected disks; data on
other disks remains accessible.
* If you accidentally delete files on a disk, recovery is
possible.
* Disks can have different sizes.
* You can add disks at any time.
* It doesn't lock-in your data. You can stop using SnapRAID at any
time without the need to reformat or move data.
* To access a file, only a single disk needs to spin, saving power and
producing less noise.
* SnapRAID doesn't lock in your data; you can stop using it
anytime without reformatting or moving data.
* To access a file, only a single disk needs to spin, saving
power and reducing noise.
The official site of SnapRAID is:
For more information, please visit the official SnapRAID site:
http://www.snapraid.it/
@ -68,26 +65,26 @@ consider before using it.
The main one is that if a disk fails, and you haven't recently synced,
you may be unable to do a complete recover.
More specifically, you may be unable to recover up to the size of the
amount of the changed or deleted files from the last sync operation.
More specifically, you may be unable to recover up to the size of
the changed or deleted files from the last sync operation.
This happens even if the files changed or deleted are not in the
failed disk. This is the reason because SnapRAID is better suited for
failed disk. This is why SnapRAID is better suited for
data that rarely change.
Instead the new added files don't prevent the recovering of the already
existing files. You may only lose the just added files, if they are on
On the other hand, newly added files don't prevent recovering already
existing files. You may only lose the recently added files, if they are on
the failed disk.
Other limitations are:
Other SnapRAID limitations are:
* You have different file-systems for each disk.
Using a RAID you have only a big file-system.
* It doesn't stripe data.
* With SnapRAID, you still have separate file-systems for each disk.
With RAID you get a single large file-system.
* SnapRAID doesn't stripe data.
With RAID you get a speed boost with striping.
* It doesn't support real-time recovery.
* SnapRAID doesn't support real-time recovery.
With RAID you do not have to stop working when a disk fails.
* It's able to recover damages only from a limited number of disks.
With a Backup you are able to recover from a complete
* SnapRAID is able to recover damages only from a limited number of disks.
With a Backup you can recover from a complete
failure of the whole disk array.
* Only file, time-stamps, symlinks and hardlinks are saved.
Permissions, ownership and extended attributes are not saved.
@ -1138,7 +1135,7 @@ WARNING! This option is for experts only, and it's highly
recommended to not change it. To change again this value in
future you'll have to recreate the whole parity!
A reason to use a different hashsize is if you have a lot of small
A reason to use a different blocksize is if you have a lot of small
files. In the order of many millions.
For each file, even of few bytes, a whole block of parity is allocated,

View File

@ -35,7 +35,7 @@
* All the elements are reallocated in a single resize operation done inside
* tommy_hashdyn_insert() or tommy_hashdyn_remove().
*
* Note that the resize operation takes approximatively 100 [ms] with 1 million of elements,
* Note that the resize operation takes approximately 100 [ms] with 1 million of elements,
* and 1 [second] with 10 millions. This could be a problem in real-time applications.
*
* The resize also fragment the heap, as it involves allocating a double-sized table, copy elements,

7
valgrind.supp Normal file
View File

@ -0,0 +1,7 @@
{
printf reports false positives when printing more than one variables at time
exp-sgcheck:SorG
...
fun:printf
}