zpaqfranz 65.14
DO NOT USE IN PRODUCTION: IT IS STILL TO BE STABILIZED
The quickest way to check a backup: the same line, with t
zpaqfranz a z:\backup.zpaq c:\data -not "*.log"
zpaqfranz t z:\backup.zpaq c:\data -not "*.log" -ssd
The line of the backup typed again, with t in place of a and -ssd at
the end. t with a path compares every file of c:\data with the archive:
the SHA-1 of every fragment of the file on the disk against the ones stored
in the archive, and its CRC-32. Nothing is decompressed: the time is the
time to read the files. With -ssd (65.14f) many files are read at once,
one thread each (-t, default all the cores), and a file over 256 MB is
cut in pieces read by more threads (65.14g).
BTW you can use -ssd -t1 (to get the nice dashboard) on HDD
t with a path, 116,725 files, 6.5 GB (warm cache, 32 threads)
| 65.14e | 65.14n |
|---|---|---|
t z:\msys.zpaq c:\msys64
| 12.0 s | 9.5 s |
t z:\msys.zpaq c:\msys64 -ssd
| - | 2.0 s |
t z:\msys.zpaq c:\msys64 -verify (the hash of every whole file too)
| 12.6 s | |
t z:\msys.zpaq c:\msys64 -verify -ssd
| - | 2.0 s |
One file of 2 GB with -ssd: 1.8 s read by one thread (65.14f), 0.63 s in
pieces with -t4, 0.42 s with -t8 (65.14g).
The report is the one of t without -ssd, line by line, and so is the
exit code: 0 if every file is the same, 2 if one is not.
zpaqfranz t z:/demo14m/backup.zpaq z:/demo14m/data -ssd
SHA-1-chunked verify
Comparing archive content to folder(s)
<<z:/demo14m/backup.zpaq>>:
1 versions, 845 files, 51.018.575 bytes (48.65 MB)
----------------------------------------------------------------------------
845 in <<z:/demo14m/data>>
----------------------------------------------------------------------------
Total files found: 845
100% 129.79 MB/ 129.79 MB @ 636.11 MB/s ETA 00:00:00 parts 823/823 different 0
00000845 = same (files 823 and folders 22)
Total different file size: 0 bytes
0.219s (00:00:00,1.23MB) (all OK)
One file changed, one deleted, one new:
# 2026-10-23 16:33:37 4.376 z:/demo14m/data/doc/bash/README
! 2026-10-23 16:34:43 4.376 z:/demo14m/data/doc/bash/README
+ 2026-10-23 16:34:43 6 z:/demo14m/data/doc/nuovo.txt
- 2026-10-23 16:33:37 30.174 z:/demo14m/data/bin/cygpath.exe
00000843 = same (files 821 and folders 22)
00000001 #different
00000001 +external (file missing in ZPAQ)
00000001 -internal (file in ZPAQ but not on disk)
Total different file size: 38.932 bytes
0.218s (00:00:00,1.23MB) (with errors)
exit code 2.
On a console, -ssd shows a bar for every thread (more threads on one row
if the console has fewer rows), as long as what that thread reads, that
fills as it goes: green while all is the same, red once a file is not.
The pieces of the big files are a lighter grey. A sketch:
Comparing 116.725 files (6.50 GB) with 32 threads (-ssd)
T01-02 ██████████████████████████████░░░░░░░░░░░░░░░░
T03-04 ████████████████████████████████████░░░░░░░░░░
...
T31-32 ███████████████████████████░░░░░░░░░░░░░░░░░░░
61% 3.97 GB/ 6.50 GB @ 3.25 GB/s ETA 00:00:00 parts 70.112/116.725 different 0
Redirected (a log, a script), the last line alone, once a second.
The same in one line: a ... -test -ssd adds, then compares the folder
with the archive in the same way.
zpaqfranz a z:\backup.zpaq c:\data -test -ssd
The switches of the backup, without typing them again: -writeini
saves the switches of a line in a file, -ini reads them back (65.14a):
zpaqfranz a z:\backup.zpaq c:\data -not "*.log" -m1 -ssd -writeini z:\backup.ini
-writeini <<z:/backup.ini>>: 3 switch(es) written
zpaqfranz t z:\backup.zpaq c:\data -ini z:\backup.ini
Switches from <<z:/backup.ini>>: 3 switch(es) loaded
What t with a path says, and what it does not. It says that the
archive holds every file of the folder as the file is on the disk now:
none missing (+external), none different (#), none only in the
archive (-internal). It does not decompress the archive: that the data
blocks decompress well is t without a path (every block, the CRC-32 of
every file), or w ... -test -verify (below: every file decompressed in
RAM and compared with the one on the disk). Not on spinning drives: many
threads on one disk that turns are slower than one. On an SSD, often -t4
is the limit (measured: 143 GB, 31 big files, -t16 49 s,
-t4 35 s).
From 65.13n to 65.14n: about 5,850 new lines (256,458 to 262,305); most of
them are the help, now data, in English, Italian and Russian.
This document has three parts:
- Part one: what is new, in short, for everybody
- Part two: the same things in more detail, for power users
- Part three: "lo spiegone", how it works inside, and why, for developers
Part one, what is new, for the user
twith a path and-ssdw -test -verify: the archive decompressed in RAM against the disk-iniand-writeini- The help: search, and in Italian and Russian
acfrom Windows PEvand the empty files- Smaller things
1. t with a path and -ssd
See the top of this document.
In short:
t archive path -ssd: many files compared at once, the same report,
the same exit code. Without-ssd: one file at a time, as before.- A file over 256 MB: in pieces, read by more threads (not with
-verify,-checksum,-paranoid: they want the hash of the whole
file, read in one go). - Every file is read in blocks of 1 MB (it was 4 KB: on Windows one
ReadFileevery 4 KB, 1.6 million of them for 6.5 GB). Without-ssd
too, and forx -force, that compares a file before writing it again:
12.0 s became 9.5 s. a ... -test -ssd: the add, then the same comparison.
2. w -test -verify: the archive decompressed in RAM against the disk
zpaqfranz w z:\1.zpaq -test -verify -ssd
zpaqfranz w z:\1.zpaq -to z:\copy -test -verify -ssd
The other side of t with a path (65.14i). Every file is decompressed in
RAM (nothing is written on the disk) and compared with the file on the
disk: where it was saved from, or, with -to, where x -to would write
it. The hash of the whole file in RAM, the hash of the file on the disk and
the hash stored in the archive must be the same. An archive without hashes
(zpaq 7.15, -nochecksum): RAM and disk byte by byte. The bars of t -ssd
(a lighter grey for the work in RAM, darker for the disk), the names of
what differs, exit code 2.
-test -verify: -ramdisk on (the files are compared from RAM)
...
Stage VEF 0001 : errors 0 (0=good)
============================================================================
Verify against the filesystem: 823 files (129.77 MB) all the same
t with a path is quicker (it decompresses nothing); w -test -verify
decompresses everything, so it checks the archive too.
3. -ini and -writeini
zpaqfranz a z:\1.zpaq c:\data -not "*.tmp" -key pippo -writeini z:\my.ini
zpaqfranz a z:\1.zpaq c:\data -ini z:\my.ini
-writeini X writes the switches of the line in X, and the command goes on.
-ini X puts the switches of X on the line, as if typed (65.14a). More
-ini: in order. In X: #, ::, rem comments, "a b" for blanks.
- The same switch typed on the line and in X: the one on the line wins.
-not,-only,-always: they add up (the ones of X and the ones
typed).- A password in X (
-key,-franzen) is in clear text: zpaqfranz says it
and shows how to protect the file (icacls/chmod 600), or to leave the
password out (-keyalone asks for it;FRANZKEY/FRANZFRANZEN). - In cyan, after the banner:
Switches from <<X>>: N switch(es) loaded
(65.14e),-verboseevery switch (passwords hidden).
4. The help: search, and in Italian and Russian
zpaqfranz h -ssd -n where -ssd is, in every command
zpaqfranz h a -n the switches of a
zpaqfranz h t -it the help of t, in Italian
zpaqfranz h t -ru in Russian
- The help is data now (65.14b): one table, every line with its
number.h -X -nfinds a switch in the help of every command. - Italian and Russian (65.14l, 65.14m):
-eng,-it,-ruon the
line; elseZPAQFRANZ_LANG(en,it,ru); else the language of the
system. Only the help: the messages stay in English. The Russian is
automatic only on a UTF-8 console. - The usage (zpaqfranz with nothing) has two new rows:
Language : zpaqfranz -eng English -it Italian -ru Russian
Search : zpaqfranz h -key -n (switches in every command) zpaqfranz h a -n
- A comparison of the help with the parser (every switch of the help is a
switch, and the other way round) found switches with wrong names in the
help (-checkspaceis-checksize,-noonedriveis-onedrive,
-blake 3,-find/replace), and help lines about switches *nix does not
have (f -gui,f -ntfs,z -longpath): fixed, or gone from the *nix
help.
**The Russian translation is to be reviewed by people who speak it :-) **
5. ac from Windows PE
zpaqfranz ac e:\pc.zpaq
zpaqfranz ac e:\pc.zpaq d:
From a Windows PE (booted from a stick, the one on SourceForge or any
other), ac stopped at once: "cannot open disk -1" (it took the X: of the
PE, a RAM disk, for the Windows to save). Now (65.14j, an issue on GitHub):
- In Windows PE
acfinds the Windows to save by itself (a volume with
\Windows\System32\config\SYSTEM, not the X: of the PE). That Windows is
not running: no shadow copy, noSystemPartitionfrom the registry. - More than one:
ac archive D:says which one. - A volume with a Windows and no letter (a GPT disk in a PE can come
so) gets the first free letter (65.14k): "the volume of 63.00 GB with a
Windows (\?\Volume{..}) had no letter: now it is E:". It was the first
real try: the Windows of disk 0 had no letter. - Out of Windows PE,
ac archive C:is not refused: the letter is ignored
(66009, a warning) andacsaves the disk of the Windows running, as
before.
6. v and the empty files
v (and a -verify) did not check the empty files (65.14c, an issue). Now
an empty file still empty is OK, one written after the archive is a FAIL
(exit code 2), one gone is "not found" (exit code 1).
7. Smaller things
-distinct(pakka): every version of a file on its own line.pakka
used it, but no switch turned it on: catpaq showed "?" in place of the
name of the second version of a file (65.14d).- On *nix
-sfx,-sfxto,-sfxnot,-sfxonly,-sfxuntil,-sfxforce,
-sfxallwere taken and ignored: now they are unknown switches there
("00562! Unknown option ignored"), as they are in the help (Windows only). - The line "Scan ... block/s" of the reading of a big archive could stay
half under the totals: "(30.93 GB)block/s)" (65.14h). twith a path, "N = same (files X and folders Y)": X counted a
file different twice (its line of the archive and its line of the disk)
and the files on one side only:843 = same (files 825 and folders 22)
with 821 files the same. Now X + Y = N (65.14n). It was so long before
65.14, with or without-ssd; the verdicts and the exit code were right.
Part two, the details, for power users
t -ssd: the rulesw -test -verify: the rules-ini: the rules- The language: the rules
acfrom Windows PE: the rules- What can change for a script
1. t -ssd: the rules
- In parallel only
t(anda -test) with a path, with-ssd, and two
files or more to compare. Else, one at a time, as before. - Threads:
-t N; default all the cores; never more than the jobs (the
files, and the pieces of the big ones). - The work goes to the threads from the biggest file down, every file to
the thread with fewer bytes so far: the bars are about as long. - A file over 256 MB (
ZPAQ_TPEZZO, a#define): pieces of about that
size, cut on the borders of its fragments, in the same queue. The file is
the same if every piece is; its CRC-32 is put together from the CRC-32 of
the pieces. Before reading: a file whose size or fragments do not match
the archive is different without reading it. Not with-verify,
-checksum,-paranoid,-quick: those big files are read whole by
one thread. - The report: the one of
twithout-ssd, the same lines in the same
order. Exit code: the same. - The bars: on a console. Redirected: the info line (
parts done/all,
different N) once a second;-noeta: nothing. -nand-find/-replace: as without-ssd.
2. w -test -verify: the rules
- Which file on the disk: the path stored in the archive; with
-to, the
onex -towould write (one-toat most: 02570, exit code 2). The
-tofolder need not be empty, and nothing is asked: nothing is
written there. - The hash: of the whole file, with the algorithm stored. Disk = RAM =
stored. No hash stored (7.15,-nochecksum,-crc32only): RAM and disk
byte by byte. - Without
-ramdisk: turned on by itself (02444). -test -paranoid: refused (02443, exit code 1:-paranoidwrites on the
disk).- Exit code 2: a file different, missing, that cannot be read, or that in
RAM is not as stored ("DECOMPRESSED NOT AS STORED": the archive). 1: other
errors. - A file bigger than the RAM window: its hash goes from one window to the
next, the verdict at the last one; an extraction that stops: "NOT
CHECKED". - Empty files: they must be there and empty. Folders: not compared. Files
deleted in that version: left out. *nix: regular files only. -verifywithout-test, and-paranoid: as before.
3. -ini: the rules
- The switches of X go on the line after the command, the archive and the
files, before the first switch typed. - A switch that is there twice is kept once, by its meaning:
-outand
-outputare one,-m1and-m5are one (the method),-t4and-t8
are one,-turboand-noturboare one, every hash is one. The one typed wins; between two-ini, or
inside one, the last. - They add up:
-not,-only,-always(and-sfxnot,-sfxonly).
Replaced:-to,-mailattach,-mailzip. - In X: switches only (no command, archive, file: 03621); no
-inior
-writeini(03620).-iniand-writeinion the same line: refused
(03618). - Comments:
#::remat the start of a line (after blanks);#at
the start of a word: the rest of the line."a b": one word with a
blank;""inside the quotes: one quote. No backslash escapes
("c:\program files\"is fine). A quote not closed: an error with its
line number. UTF-8, with or without BOM,\r\ntoo. -writeini: the line as the parser read it, on one line; without the
switches zpaqfranz adds when it starts itself again elevated (-elevated
and so on). Refused if X is the archive (03622). A write that fails:
exit code 2, the command does not start.- Codes 03616 - 03628, 03643.
4. The language: the rules
-eng,-it,-ruanywhere on the line (and in a-ini): the last
wins; the one typed wins over the one of an ini.- Else
ZPAQFRANZ_LANG=en,it,ru. - Else the system: Windows
GetUserDefaultUILanguage, *nixLC_ALL,
LC_MESSAGES,LANG. Russian only if the console is UTF-8 (on Windows a
console, not-noconsole; on *nix a UTF-8 locale). Else English. - A line whose English changed after it was translated comes out in
English (every translation keeps a fingerprint of its English). -helpid: the number of every line of the help (for who translates).- Italian: with the apostrophe (
e',piu'), no accented letters.
5. ac from Windows PE: the rules
- Windows PE: the key
HKLM\SYSTEM\CurrentControlSet\Control\MiniNT. - The Windows: the fixed and removable volumes with
\Windows\System32\config\SYSTEM, not the one of the PE. One: taken.
None: 66022 (BitLocker:manage-bde -unlockfirst). More: 66023 "which
one? ... ac archive E:". A letter given without a Windows: 66024. - A volume without a letter and with a Windows (only in the search by
itself, not with a letter given): the first free letter from C: (it
stays until the PE is turned off), 66028; none free or it fails: 66027. - From the PE: no shadow copy (with
-vss: a warning), no
SystemPartition; the metafile sayswindows=not running, on E: (saved from Windows PE)andwinpe=yes. - A volume on no physical disk: 66026 (it was "cannot open disk -1").
- Out of the PE, a letter: 66009, ignored.
6. What can change for a script
- The help is in the language of the system: on an Italian or Russian
computerh, the usage and the help come out translated. A script that
reads them:ZPAQFRANZ_LANG=en(or-eng). The messages are not
translated. v/a -verifyon an empty file written after the archive: 2 (it was
0); an empty file gone: 1 (it was 0).ac archive C:out of Windows PE: it goes on (it was refused, 66000).- *nix: the
-sfx...switches are unknown (ignored, with 00562). -distinctis a switch (it was "Unknown option ignored").t -ssdwith a path: the same report and exit code; the info line
(03645) is new when redirected.twith a path, when something differs: the numbers in "same (files X
and folders Y)" are smaller (only what is the same).
Part three, lo spiegone, for developers
testverify_ssd- The big files in pieces
equal()by 1 MBfranzbarrew -test -verify:wconfrontafranziniandini_espandi- The help as data
- The translations
acin Windows PE- Known limits and open points
1. testverify_ssd
testverify() builds its filelist as before (every file of the disk
after its file of the archive, then the files of the archive only). With
-ssd, before its loop, testverify_ssd(filelist, esiti) takes the pairs
archive/disk that are files, decodes their franz_block on the main thread
(hash type, hash, CRC-32), orders them from the biggest down and gives each
one to the thread with fewer bytes (LPT). The threads (tverifica_thread,
a friend of Jidac: equal() is private) call equal() and write the
result in tconfronto, by the index of filelist. Then the loop of
testverify() runs as ever, and where a thread did the work it takes its
result in place of calling equal(): the output is the one without
-ssd, by construction. The main thread looks at the counters every 200
ms (the bars, the info line).
2. The big files in pieces
A file over ZPAQ_TPEZZO (256 MB) is cut in pieces of about that size on
the borders of its fragments (tlavoro.grosso, primo, ultimo,
inizio), in the same queue as the files. Jidac::testverify_grosso
first: a regular file, the size, the fragments there and as long as the
file (else: different, nothing read). Jidac::equalpezzo: the SHA-1 of the
fragments of its piece and the CRC-32 of the piece, never past it. The
CRC-32 of the file: crc32_combine of the pieces in order. The counters
are volatile, x= x + 1 (++ on a volatile is a warning of gcc 16).
Measured with a build with -DZPAQ_TPEZZO=1048576 too (every file in
pieces).
3. equal() by 1 MB
Jidac::equal() read the file 4 KB at a time; now 1 MB, and the fragments
are hashed from memory. int64_t *o_fatti is the counter of the thread
(the bars); with it, no percentage per file. Every caller has it: t, x -force (that skips the identical files), 205402.
4. franzbarre
The area is printed once, then vai() as franzdash (gotoxy on Windows,
relative moves on *nix). The bars: U+2588 / U+2591 / U+2592 (or #, X,
. without UTF-8), usb_colore 1 green, 3 red, 5 grey, \x1b[37m the
lighter grey. More threads than rows: threads grouped on a row (T01-02).
usb_colore was inside the #ifndef ANCIENT of the command f: ESX and
the NAS builds (ANCIENT) did not link from 65.14f to 65.14h. Moved before
franzbarre (65.14i).
5. w -test -verify: wconfronta
struct twfile, twconti, g_wconti and the wconfronta_* before
Jidac::extractw; wconfronta() (threads and bars) after
testverify_ssd. Every file is two jobs (RAM, disk) in the LPT queue.
extractqueue2 has a twfile *i_grande for the files bigger than a
window: the hashes go on from one window to the next (wconfronta_inizia,
the verdict at the last window, wconfronta_lascia if the extraction
stops). The thread of the disk compares the hash of the disk with the
stored one at once (wconfronta_discodiverso): red bars, different N.
Found and fixed on the way:
-checksumon files bigger than a window of RAM checked nothing
(extractqueue2went out before): now it does, in a real extraction too.scriviramtodisk:franz_do_hash::update(char*, int)with the size of
the whole file: from 2 GB up, a wrong hash, a false "ERROR hash" and exit
code 1. Now in blocks of 1 MB.- In the loop of the windows, with
-test -verifya file different no
longer stops the others.
6. franzini and ini_espandi
class franzini (near stessoarchivio()): load / save of a file of
switches; its only line of platform is _wfopen. ini_espandi, at the top
of zpaq_main_internal (before mail, tui, franzscegli), puts the words of
the ini on the line; on Windows \ becomes / (as wtou); the doubles go
by key (ini_chiave: the aliases, the short forms, the pairs, the hashes).
ini_scrivi: the parser decides what a switch is (iniinizi, where every
piece starts in the loop of loadparameters; inioriginale, the line
before -dummyhash); written right after that loop. Tested apart too:
tortura\ini\banco.cpp (the class alone, -std=c++98 -pedantic, 31 cases
and 20,000 random load(save(x)) == x).
7. The help as data
The 94 help_X() and their pieces, converted once (a Perl script) into
g_helprighe[]: macros HU HS HRIGA HSTD HE HESEMPIO HTESTO HESEMPI HINCLUDI HGENERA HBREVE, with the #ifdefs and the NOSFTPSTART/END of
the old code. | is a new line, || a real |. help_stampa() prints as
before (the English byte by byte the same as 65.14a, but for the fixes).
help_cerca (h -X -n) at the top of zpaq_main_internal, before
ini_espandi (so h -key does not ask for a password). The hidden
-helpcheck (help_controlla): the cli_* of the parser register their
names, the help is compared with them. Codes 03629 - 03642.
A trap: flagtest is there twice, a global and a member of Jidac. Moved
into a free function, &flagtest was the global one: x was a -test
(nothing written). Seen by the batteries, fixed passing the address.
8. The translations
Every line has a number (id, 1 - 1791; next free 1792, -helpcheck
says it) and its translations under it: HIT(id, 0xFINGERPRINT, "..."),
HRU(...). The fingerprint is a FNV-1a of the English: if the English
changes, the old translation is not used (English shown). Phrases that are
not lines of a command (the usage, h, h h, the categories,
"Examples:") are found by their English (help_t). lingua_scegli runs
before help_cerca and again after ini_espandi, and takes -eng -it -ru -helpid off the line. moreprint, scrivi() and the columns count
UTF-8 characters, and cut between one and the next. From 65.14m on, the
lines are written by hand (the converter of 65.14l would number them
again). Codes 03648 - 03662 (03660 and 03661, of -lang, gone in
65.14m).
9. ac in Windows PE
g_acpe (the MiniNT key, or the hidden -winpefake for the tests);
ac_windowsspento() looks for the Windows; ac_dailettere()
(FindFirstVolumeW, the volumes without paths, SetVolumeMountPointW)
gives a letter to the one without. Tested on a Windows 11 VM with
-winpefake: the disk restored from it is the same (SHA-256) as the one
from ac -acfake of the same disk (the way already tried with a real
boot).
10. Known limits and open points
-ssdon a spinning drive: slower. Many threads on one SSD: often
-t4is the limit.- The Russian is to be reviewed; a real Windows console in Russian was
not seen here.