dd_rescue(1)
πΈ NAME πΈ
dd_rescue(1) β Data recovery and protection tool. that's the whole vibe, bestie: it recovers data and it protects data. double threat energy π
β¨ SYNOPSIS β¨
dd_rescue [options] infile outfile
dd_rescue [options] [-2/-3/-4/-z/-Z seed/seedfile] outfile
dd_rescue [options] [--shred2/--shred3/--shred4/--random/--frandom
seed/seedfile] outfile
π DESCRIPTION π
okay so picture this: dd_rescue copies data from a source (file, block device, pipe, ...) to one (or several) output file(s). that's the gig. main character behavior π¦
if input and output files are seekable (block devices or regular files), dd_rescue does copy with large blocks (softbs) to increase performance. when a read error is encountered, dd_rescue falls back to reading smaller blocks (hardbs), to allow to recover the maximum amount of data. if blocks can still not be read, dd_rescue by default skips over them also in the output file, avoiding to overwrite data that might have been copied there successfully in a previous run. (Option -A / --alwayswrite changes this.). iykyk β¨
dd_rescue can copy in reverse direction as well, allowing to approach a bad spot from both directions. as trying to read over a bad spot of significant size can take very long (and potentially cause further damage), this is an important optimization when recovering data. the dd_rhelp tool takes advantage of this and automates data recovery. dd_rescue does not (by default) truncate the output file.
heads up, bestie: dd_rescue does not truncate the output file by default. not a drill. π
dd_rescue by default reports on progress, and optionally also writes into a logfile. it has a progress bar and gives an estimate for the remaining time. dd_rescue has a wealth of options that influence its behavior, such as the possibility to use direct IO for input/output, to use fallocate() to preallocate space for the output file, using splice copy (in kernel zerocopy) for efficiency, looking for empty blocks to create sparse files, or using a pseudo random number generator (PRNG) to quickly overwrite data with random numbers. obsessed with the range π
the modes to overwrite partitions or files with pseudo random numbers make dd_rescue a tool that can be used for secure data deletion and thus not just a data recovery and backup tool but also a data protection tool. secure data deletion ate π
you can use - as infile or outfile, meaning stdin or stdout. note that this means that either file is not seekable, limiting the usefulness of some of dd_rescue's features. vibe check: pipes are cute but not seekable π«Ά
π OPTIONS π
when parsing numbers, dd_rescue assumes bytes. it accepts the following suffixes:
bβ 512 size units (blocks)kβ 1024 size units (binary kilobytes, kiB)Mβ 1024^2 size units (binary megabytes, MiB)Gβ 1024^3 size units (binary gigabytes, GiB)
the following options may be used to modify the behavior of dd_rescue . let's get into the group chat of flags π
π«Ά General options
-h,--helpβ this option tellsdd_rescueto output a list of options and exit. the "help me help you" era π±-V,--versionβ display version number and exit. pop the version, queen π-q,--quietβ tellsdd_rescueto be less verbose. shhh era π-v,--verboseβ makesdd_rescuemore verbose. yap mode: on π£οΈ-c 0/1,--color=0/1β controls whetherdd_rescueuses colors. by default it does, unless the terminal type fromTERMis unknown or dumb or ends in-mor-mono. no TERM slander but okay π-f,--forceβ makesdd_rescueskip some sanity checks (e.g. automatically setting reverse direction when input and output file are the same andipos<opos). sanity checks? skipped. we move π-i,--interactiveβ tellsdd_rescueto ask before overwriting existing files. consent before overwrite, we love to see it π«Ά
π§ Block sizes
-b softbs,--softbs=softbs,--bs=softbsβ sets the (larger) block size tosoftbsbytes.dd_rescuewill transfer chunks of that size unless a read error is encountered (or the end of the input file or the maximum transfer size has been reached). the default value for this is64kfor buffered I/O and1Mfor direct I/O. big block energy π§±-B hardbs,--hardbs=hardbs,--block-size=hardbsβ sets the (smaller) fallback block size tohardbsbytes. whendd_rescueencounters read errors, it will fall back to copying data in chunks of this size. this value defaults to4kfor buffered I/O and512 bytesfor direct I/O.hardbsshould be equal to or smaller thansoftbs. if both block sizes are identical, no fallback mechanism (and thus no retry) will take place on read errors. small block, big rescue π©Ή-y syncsize,--syncfreq=syncsizeβ tellsdd_rescueto callfsync()on the output file everysyncsizebytes (will be rounded to multiples ofsoftbssized blocks). it will also update the progress indicator at least as often. by default,syncsizeis set to0, meaning thatfsync()is only issued at the end of the copy operation. sync checkpoint, bestie π
π¦ Positions and length
-s ipos,--ipos=ipos,--input-position=iposβ sets the starting position of the infile toipos. note thatiposis specified in bytes (but suffixes can be used, see above), not in terms ofsoftbsorhardbssized blocks. the default value for this is0. when reverse direction copy is used, aniposof0is treated specially, meaning the end of file. negative positions result in an error message. negative ipos? not the vibe π«-S opos,--opos=opos,--output-position=oposβ sets the starting position of the outfile toopos. if not specified,oposis set toipos, so the file offsets in input and output file are the same. for reverse direction copy, an explicitoposof0will position at the end of the output file. matching offsets, cute π-x,--extend,--appendβ changes the interpretation of the output position to start at the end of the existing output file, making appending to a file convenient. if the output file does not exist, an error will be reported anddd_rescueaborted. append era, but only if the file exists π-m maxxfer,--maxxfer=maxxfer,--max-size=maxxferβ specifies the maximum number of bytes (suffixes apply, but it's NOT counted in blocks) thatdd_rescuecopies. if EOF is encountered beforemaxxferbytes have been transferred, this option will be silently ignored. limit the transfer, not the drama βοΈ-M,--noextendβ tellsdd_rescueto not extend the output file. this option is particularly helpful when overwriting a file with random data or zeroes for safe data destruction. if the output file does not exist, an error message will be generated and the program be aborted. no extend, no exceptions π
π Error handling
-e maxerr,--maxerr=maxerrβ tellsdd_rescueto exit, aftermaxerrread errors have been encountered. by default, this is set to0, resulting indd_rescuetrying to move on until it hits EOF (ormaxxferbytes have been transferred). maxerr said peace out after this many βοΈ-w,--abort_weβ makesdd_rescueabort on any write errors. by default, on reported write errors,dd_rescuetries to rewrite the blocks with small block size writes, so a small failure in a larger block will not cause the whole block not to be written. note that this may be handled similarly by your Operating System kernel with buffered writes without the user ordd_rescuenoticing; the write retry logic indd_rescueis mostly useful for direct I/O writes where write errors can be reliably detected. write error detection with buffered writes is unreliable; the kernel reports success and traces of the failing writeback operations later may only appear in your syslog.dd_rescuedoes try to notice the user by callingfsync()and carefully checking the return values offsync()andclose()calls. note thatdd_rescuedoes exit if writes to the output file result in the Operating System reporting that no space is left. buffered writes are lowkey giving unreliable narrator π
π Sparse files and write avoidance
-A,--alwayswriteβ changes the behavior ofdd_rescueto write zeroes to the output file when the input file could not be read. by default, it just skips over, leaving whatever content was in the output file at the file position before. the default behavior may be desired, if e.g. previous copy operations may have resulted in good data being in place; it may be undesired if the output file may contain garbage (or sensitive information) that should rather be overwritten with zeroes. alwayswrite said no skipping today π§-a,--sparseβ will makedd_rescuelook for empty blocks (of at least half ofsoftbssize), i.e. blocks filled with zeroes. rather than writing those zeroes to the output file, it will then skip forward in the output file, resulting in a sparse file, saving space in the output file system (if it supports sparse files). note that if the output file does already exist and already has data stored at the location where zeroes are skipped over, this will result in an incomplete copy in that the output file is different from the input file at the location where blocks of zeroes were skipped over.dd_rescuetries to detect this and issues a warning, but it does not prevent this from happening. when dealing with sparse files,succxferwill report the data really written, not the pieces that have been skipped on writing. sparse file slay but read the warning, bestie β οΈ-W,--avoidwriteβ results indd_rescuereading a block (softbssized) from the output file prior to writing it. if it is already identical with the data that would be written to it, the writes are actually avoided. this option may be useful for devices, where e.g. writes should be avoided (e.g. because they may impact the remaining lifetime or because they are very slow compared to reads). avoidwrite: if it matches, we don't touch it π«Ά-@ readtime,--sparse_nonslow=readtimeβ is an optimization for sparse copies. when it is used to scrub a device (or partition) by overwriting itself, option-a(--sparse) may well be used to avoid writing zeros over unallocated space (on e.g. SSDs). if blocks however have been allocated before and are all-zeros, and they are very slow to read, we might want to make an exception and overwrite these with zeros again. it can detect this by reads being slow. so using this option, a limit (in seconds) can be set for the time reads may take before zero writes are performed in sparse mode. you may want to set this to3or so when reviving SSDs. slow reads get the zero-write exception, iconic π₯
π οΈ Other optimization π οΈ
Okay bestie, these are the extra lil optimization knobs β they change how dd_rescue moves data around, so pls read the caveats, mwah π
-R,--repeatβ tellsdd_rescueto only read one block (softbssized) and then repeatedly write it to the output file. Note that this means you never hit EOF on the input file, so use it with a limit for the transfer size (options-mor-M) or when filling up an output device completely. This option is automatically set if the input file name equals/dev/zero. π-u,--rmvtrimβ instructsdd_rescueto remove the output file after writing to it has completed and issue aFITRIMon the file system that contains the output file. This makes only sense if writing zeros (or random numbers) as opposed to useful content from another file. (dd_rescuewill ask for confirmation if this is specified with a normal input file and no-f(--force) is used.) This option may be used to ensure that all empty blocks of a file system are filled with zeros (rather than containing fragments of deleted files with possibly sensitive information). TheFITRIMioctl (on Linux) tells the storage to consider the freed space as unused (like thefstrimtool or the discard option) by issuingATA TRIMorSCS DISCARD/WRITE_SAMEcommands. This will only succeed with superuser privileges (but the error can otherwise be safely ignored). This is useful to ensure full performance of flash memory / SSDs or to free up space on thinly provisioned storage. Note thatFITRIMcan take a while on large file systems, especially if the file systems are not mounted with the discard option and have not been trimmed (with e.g.fstrim) for a while. Not all file systems and not all flash-based storage support this. π«Ά-k,--spliceβ tellsdd_rescueto use the Linux in-kernel zerocopysplice()copy operation rather than reading blocks into a user space buffer. Note that this operation mode does prevent the support of a number ofdd_rescuefeatures that can normally be used, such as falling back to smaller block sizes, avoiding writes, sparse mode, repeat optimization, reverse direction copy. A warning is issued to make the user aware. β οΈ-P,--fallocateβ results indd_rescuecallingfallocate()on the output file, telling the file system how much space to preallocate for the output file. (The size is determined by the expected last position, as inferred from the input file length andmaxxfer.) On file systems that support it, this results in them making better allocation decisions, avoiding fragmentation. (Note that it does not make sense to use sparse together withfallocate().) This option is only available ifdd_rescueis compiled withfallocate()support. For optimal support, it should be compiled with thelibfallocatelibrary. πΈ-C rate,--ratecontrol=rateβ limits the transfer speed ofdd_rescueto the rate (per second). The usual suffixes are allowed. Note that this limits the average speed; the current speed may be up to twice this limit. Default is unlimited. Note that you will have to use smallersoftblocksizesif you want to go below32k (kB/s). πββοΈπ¨
πΈ Misc options πΈ
-r,--reverseβ tellsdd_rescueto copy in reverse direction, starting atipos(with special case0meaning EOF) and working towards the beginning of the file. This is especially helpful if the input file has a bad spot which can be extremely slow to skip over, so approaching it from both directions saves a lot of time (and may prevent further damage). Note thatdd_rescuedoes automatically switch to reverse direction copy, if input and output file are identical and the input position is smaller than the output position, similar to the intelligence thatmemmove()uses to prevent loss of data when overlapping areas are copied. The option-f/--forcedoes prevent this intelligence from happening. π-p,--preserveβ when copying files, this option does result in file metadata (timestamps, ownership, access rights, xattrs) to be copied, similar to the option with the same name in thecpprogram. Note that ACLs and xattrs will only be copied ifdd_rescuehas been compiled withlibxattrsupport and the library can be dynamically loaded on the system. Also note that failing to copy the attributes with-pis not considered a failure and thus won't negatively affect the exit code ofdd_rescue. This can be changed with a second-p, resulting in an early exit (code26) for ownership and permission failures and a non-0exit code on times and xattr copy failures. π-t,--truncateβ tellsdd_rescueto open the output file withO_TRUNC, resulting in the output file (if it is a regular file) to be truncated to0bytes before writing to it, removing all previous content that the file may have contained. By default,dd_rescuedoes not remove previous content. βοΈ-T,--trunclastβ tellsdd_rescueto truncate the output file to the highest copied position after the copy operation completed, thus ensuring there's no data beyond the end of the data that has been copied in this run. π-d,--odir_inβ instructsdd_rescueto open infile withO_DIRECT, bypassing the kernel buffers. While this option has a negative effect on performance (the kernel does read-ahead for buffered I/O), it will result in errors to be detected more quickly (kernel won't retry) and allows for smaller I/O units (hardware sector size,512bytesfor most hard disks).O_DIRECTmay not be available on all platforms. π-D,--odir_outβ tellsdd_rescueto open outfile withO_DIRECT, bypassing kernel buffers. This has a significant negative effect on performance, as the program needs to wait for writes to hit the disks as opposed to the asynchronous nature of buffered writeback. On the flip side, the return status from writing is reliable this way and smaller I/O chunks (hardware sector size,512bytes) are possible. πΎ
π Logging π
-l logfile,--logfile=logfileβ Unless in quiet mode,dd_rescuedoes produce constant updates on the status of the copy operation tostderr. With this option, these updates are also written to the specified logfile. The control characters (to move the cursor up to overwrite the existing status lines) are not written to the logfile. π-o bbfile,--bbfile=bbfileβ instructsdd_rescueto write a list of bad blocks to bbfile. The file will contain a list of numbers (ASCII), one per line, where the numbers indicate the offset in terms ofhardbssized blocks. The file format is compatible with that ofbadblocks. Usingdd_rescueon a block device (partition) and settinghardbsto the block size of a file system that you want to create, you should be able to feed the bbfile tomke2fswith the option-l. π§Ύ
π Multiple output files π
-Y ofileX,--outfile=ofileX,--of=ofileXβ If you want to copy data to multiple files simultaneously, you can specify this option. It can be specified multiple times, so many copies can be made. Note that these files are secondary output files; they share file position with the primary output file outfile. Errors when writing to a secondary output file are ignored. π―ββοΈ
π₯ Data protection by overwriting with random numbers π₯
When you want to overwrite a file, partition or disk with random data, using /dev/urandom (on Linux) as input is not a very good idea; the interface has not been designed to yield a high bandwidth. It's better to use a user space Pseudo Random Number Generator (PRNG). With option -z / --random, the C library's PRNG is used. With -Z / --frandom and the -2/-3/-4 / --shred2/3/4 options, an RC4 based PRNG is used.
-z RANDSEED,--random=RANDSEEDβ uses the C library's PRNG.-Z RANDSEED,--frandom=RANDSEEDβ uses an RC4 based PRNG.-2 RANDSEED,--shred2=RANDSEEDβ one pass with RC4 generated PRNG, then zeroes are written.-3 RANDSEED,--shred3=RANDSEEDβ two passes with RC4 PRNG generated random numbers and a zero pass; the second PRNG pass writes the inverse (bit-wise reversed) numbers from the first pass.-4 RANDSEED,--shred4=RANDSEEDβ works like-3/--shred3, with an additional pass with independent random numbers as third pass.
Note that in this mode, there is no infile so the first non-option argument is the output file. π«Ά
The PRNG needs seeding; the C library's PRNG takes a 32bit integer (4 bytes); the RC4 based PRNG takes 256 bytes. If RANDSEED is an integer, the integer number will be used to seed the C library's PRNG. For the RC4 method, the C library's PRNG then generates the 256 bytes to seed it. This creates repeatable PRNG data. The RANDSEED value of 0 is special; it will create a seedval that's based on the current time and the process' PID with CPU randomness mixed in (if available) and should be different for multiple runs of dd_rescue.
If RANDSEED is not an integer, it's assumed to be a file name from which the seed values can be read. dd_rescue will read 4 or 256 bytes from the file to seed the C library's or the RC4 PRNG. For good pseudo random numbers, using /dev/urandom to seed is a good idea. π
The modes -2/-3/-4 resp. --shred2/--shred3/--shred4 will overwrite the output file multiple times; after each pass, fsync() will ensure that the data does indeed hit the file. The last pass for these modes will overwrite the file with zeroes. The rationale behind doing this is to make it easier to hide that important data may have been overwritten, to make it easier for intelligent storage systems (such as SSDs) to recycle the empty blocks and to allow for better compression of a file system image containing such data.
With -2 / --shred2, one pass with RC4 generated PRNG is happening and then zeroes are written. With -3 / --shred3, there are two passes with RC4 PRNG generated random numbers and a zero pass; the second PRNG pass writes the inverse (bit-wise reversed) numbers from the first pass. -4 / --shred4 works like -3 / --shred3, with an additional pass with independent random numbers as third pass. πβ¨
π§ Plugins π§
Since version 1.42, dd_rescue has an interface for plugins. Plugins have the ability to analyze the copied data or to transform it prior to it being written. π¦
-Lplugin1[=param1[:param2[:..]]][,plugin2[=..][,..]],--plugins=plugin1[=param1[:param2[:..]]][,plugin2[=..][,..]] β ok so this is the fun one π it loads plugins plugin1 ... and passes parameters to them. Every plugin should support at least thehelpparameter and spill the tea on how to use it. Plugins can put limits on dd_rescue, lowkey: plugins that look at the data can't work withsplice, because splice avoids copying data to user space. Also the interface currently does not facilitate reverse direction copy. Some plugins may impose further restrictions w.r.t. alignment of data in the file or not using sparse detection. Plugins can error out on initialization, abort the copy process when hitting a fatal error during the process, and also report errors upon finishing the process. You can chain several plugings (yes, iconic), e.g. calculate a hash value, then compress, then encrypt. You could then reverse this by decrypting, decompressing, and hashing again (and comparing the hash values to check the integrity). See section PLUGINS for an overview of available plugins.
π¦ PLUGINS π¦
π null π
The null plugin (ddr_null) does literally nothing, except if you specify the [no]lnchange or the [no]change options β in which case the plugin indicates to others that it transforms the length of the output or the data of the stream. (With the no prefix, it's reset to the default no-change indication again.) This may be helpful for testing or to influence which file the hash plugin considers for reading/writing extended attributes from/to, and for plugins to change their behavior with respect to hole detection.
ddr_null_ddr also allows you to specify debug, in which case it just reports the blocks that it passes on. π
π hash π
When the hash plugin (subsequently referred to as ddr_hash) is loaded, it will calculate a cryptographic hash and optionally also a HMAC over the copied data and print the result at the end of the copy operations. π§
The hash algorithm can be chosen by specifying alg[o[rithm]]=ALG where ALG is one of md5, sha1, sha256, sha224, sha512, sha384. (Specify alg=help to get a list.) To abbreviate the syntax, the alg= piece can be omitted.
For backwards compatibility, the hash plugin can also be referred to with the old MD5 name; it then defaults to the md5 algorithm.
The computed value should be identical to calling md5sum/sha256sum/... on the target file (unless you only write part of the file), but saves time by not accessing the (possibly large) file a second time. The hash plugin handles sparse writes and arbitrary offsets fine. β¨
multipart=CHUNKSIZE tells ddr_hash to calculate multiple checksums for file chunks of CHUNKSIZE each and then combine them into a combined checksum by creating a checksum over the piece checksums. This is how the checksum for S3 multipart objects is calculated (using the md5 hash); the output there is the combination checksum with a dash and the number of parts appended.
β οΈ Note that this feature is new in1.99.6and does not yet handle situations cleanly, where offsets plus block sizes do not happen to cleanly align with the CHUNKSIZE. The implementation for this will be completed later. Other features like theappend/prepend/hmacpieces also don't work well with multipart checksum calculation. π
ddr_hash also supports the parameter append=STRING which appends the given STRING to the output before computing the cryptographic hash. Treating the STRING as a shared secret, this can actually be used to protect against someone not knowing the secret altering the contents (and recomputing the hash) without anyone noticing. It's thus a cheap way of a cryptographic signature (but with preshared secrets as opposed to public key cryptography). Use HMAC for a somewhat better way to sign data with a shared secret.
ddr_hash also supports prepend=STRING which is likely harder to attack with brute force than an appended string. Note that ddr_hash always prepends multiples of the hash algorithm's block size and pads the STRING with 0 to match.
ddr_hash can be used to compute a HMAC (Hash-based Message Authentication Code) instead of the plain hash. The HMAC uses a password that's prepended and transformed twice to the data which is then hashed twice. HMAC is believed to protect somewhat better against extension or collision attacks than a plain hash (with a plain prepended secret), so it's a better way to authenticate data with a shared secret. (You can use append/prepend in addition to HMAC, if you have a need for a scheme with more than one secret.) π₯
When HMAC is enabled with one of the following parameters, both the plain hash and the HMAC are computed by ddr_hash. Both are output to the console/log, but the HMAC is used instead of the hash value to be written to a CHECKSUMS file or to an extended attribute or checked against (see below).
hmacpwd=STRINGβ sets the shared secret (password) for computing the HMAC. Passing the secret on the command line has the disadvantage that the shell may mistreat some bytes as special characters and that the command line may be visible to all logged in users on the system. πhmacpwdfd=INTβ sets a file descriptor from which the secret (password) for HMAC computation will be read. Specifying0means standard input, in which caseddr_hasheven prints a prompt for you ... Other numbers may be useful ifdd_rescueis called from another program that opens a pipe to pass the secret.hmacpwdnm=INNAMEβ sets a file from which the shared secret (password) is read. Note that all bytes (up to2048of them) are read and used, including trailing white space,0-bytes or newlines.
π Please note that the ddr_hash plugin at this point does NOT take a lot of care to prevent the password/pre/appended secret from remaining in memory or leaking into a swap/page file. (This will be improved once I look into encryption plugins.)
ddr_hash accepts the parameter output, which will cause ddr_hash to output the cryptographic hash to stdout in the same format that md5sum/sha256sum/... use. You can also specify outfd=INT to have the plugin write the hash to a different file descriptor specified by the integer number INT. Note that ddr_hash always processes data in binary mode and correctly indicates this with a star (*) in the output generated with output/outfd=.
The checksum can also be written to a file by giving the outnm=OUTNAME parameter. Then a file with OUTNAME will be created and a md5sum/sha256sum/... compatible line will be printed to the file. If the file exists and contains an entry for the file, it will be updated. If the file exists and does not contain an entry for the file, one will be appended. If OUTNAME is omitted, the file name CHECKSUMS.alg (or HMACS.alg if HMAC is enabled) will be used (alg is replaced by the chosen algorithm). If the checksum can't be written, a warning will be printed and the exit code of dd_rescue will become non-zero. π
The checksum can be validated using chknm=CHKNAME. The file will be read and ddr_hash will look for an md5sum/sha256sum/... compatible line with a matching file name to take the checksum from and compare it to the one computed. If NAME is omitted, the same default as described above (in outnm=...) will be used. You can also read the checksum from stdin if you prefer by specifying the check option.
π Note that in any case, the check is only performed after the copy operation is completed β a faulty checksum will thus NOT result in the copy not taking place. However, the exit code ofdd_rescuewill indicate the error. (If you want to avoid copying data with a broken checksum into the final target, use a temporary target that you delete upon error and only move to the final location ifdd_rescue's exit value is0; you can of course also copy to/dev/nullfor testing beforehand, but it might be too costly reading the input file twice.)
If in addition to chknm (or chk_xattr) the option chkadd is specified, then a missing checksum will not be reported as error, but instead an entry to the checksum file (or xattr) be added. A mismatch will still be reported as error and the checksum file will not be updated. πΈ
You can store the cryptographic hash into the files by using the set_xattr option. The hash will be stored into the extended attribute user.checksum.ALG by default (user.hmac.ALG if HMAC is enabled), but you can override the name of the attribute by specifying set_xattr=XATTR.NAME instead. If the xattr can't be written, an error will be reported, unless you also specify the fallb[ack][=CHKNAME] option. In that case, ddr_hash tries to write the checksum to the CHKNAME checksums file. (For the default for CHKNAME, see outnm= option above.)
chk_xattr will validate that the computed hash matches the one read from the extended attribute. The same default attribute name applies and you can likewise override it with chk_xattr=XATTR.NAME. A missing attribute is considered an error (although the same fallback is tried if you specify the fallback option). A broken checksum is of course considered an error as well, but just like with checknm=CHKNAME won't prevent the copy. See the discussion there. π«Ά
Note that for output, outfd=, outnm=, set_xattr ddr_hash will use the output file name to attach the checksum to (be it by setting xattr or the file name used in the checksum file), unless a plugin in the chain after ddr_hash indicates that it changes the data. In that case, it will warn and associate the checksum with the input file name, unless there's another plugin before ddr_hash in the chain which indicates data transformation as well. In that case, there is no file that the checksum could be associated with and ddr_hash will report an error.
Likewise for chknm=, check, chk_xattr ddr_hash will use the input file name to get the checksum (be it by reading the xattr or by looking for the input file name in a checksums file) unless there's a plugin in the chain before ddr_hash that indicates that it changes the data. The output file name will then be used, unless there's another plugin after ddr_hash indicating data change as well, in which case there's no file we could get the checksum for and thus an error is reported. π€
If your system supports extended attributes, those have the advantage of traveling with the files; thus a rename or copy (with dd_rescue -p) will maintain the checksum. Checksum files on the other hand can be handled everywhere (including the transfer via ftp or http) and can be cryptographically signed with PGP/GnuPG. π
okay so real talk about md5 real quick π β md5 is NOT recommended any more if you actually want good protection against someone maliciously hiding that your data got modified. It's genuinely not considered strong enough any more to prevent hash collisions. sha1 is a bit better, but bestieβ¦ it's been broken as well, as of 2017. π
So the recommendation is to use the SHA-2 family of hashes. On 32bit machines, I'd recommend sha256, while on 64bit machines, sha512 is faster and thus the best choice. And heads up: there's hardware acceleration on some x86-64 and most armv8/aarch64 CPUs for sha256, so it's actually faster there than sha512. dd_rescue detects and uses this acceleration (since 1.99.16) β¨
ddr_hash also supports using the HMAC code and hashes for deriving keys from passwords using the PKCS5 PBKDF2 (password-based key derivation function) β which lets you improve the protection from mediocre passwords by using a salt and a relatively expensive key stretching operation. π§ But lowkey this is only meant for testing and may be removed in the future. It's thus not documented in this man page. See the built-in help function for a brief summary on the usage. iykyk π«Ά
π crypt
The crypt plugin lets you encrypt and decrypt data on the fly β¨ It currently supports a variety of AES ciphers. See the ddr_crypt(1) man page for more details. π
π lzo
The lzo plugin lets you compress and decompress data using liblzo2. lzo is an algorithm that's faster than most other algorithms but does not compress as well. See the ddr_lzo(1) man page for more details. π¦
π§ ddr_lzma
The xz de/compression plugin using liblzma. Supports most of popular options from the xz utils. lzma is an algorithm that produces highly compressed files at the cost of being expensive in terms of CPU and memory consumption during compression. Decompression is fast. β‘ See the ddr_lzma(1) man page for more details.
π EXIT STATUS π
On successful completion, dd_rescue returns an exit code of 0. π Any other exit code indicates that the program has aborted because of an error condition or that copying of the data has not been entirely successful. π¬ So like, 0 = slay, anything else = check yourself.
π EXAMPLES π
bestie these examples are the whole personality of this tool, let's go π
dd_rescue -k -P -p -t infile outfile
copies infile to outfile and does truncate the output file on opening (so deleting any previous data in it), copies mode, times, ownership at the end, uses fallocate to reserve the space for the output file and uses efficient in kernel splice copy method. π
dd_rescue -A -d -D -b 512 /dev/sda /dev/sda
reads the contents of every sector of disk sda and writes it back to the same location. Typical hard disks reallocate flaky and faulty sectors on writes, so this operation may result in the complete disk being usable again when there were errors before. π₯ Unreadable blocks however will contain zeroes after this. β οΈ
dd_rescue -2 /dev/urandom -M outfile
overwrites the file outfile twice: once with good pseudo random numbers and then with zeroes. π²
dd_rescue -t -a image1.raw image2.raw
copies a file system image and looks for empty blocks to create a sparse output file to save disk space. (If the source file system has been used a bit, on that file system creating a large file with zeroes and removing it again prior to this operation will result in more sectors with zeroes. dd_rescue -u /dev/zero DUMMY will achieve this β¦) π¦
dd_rescue -ATL hash=md5:output,lzo=compress:bench,MD5:output in out.lzo
copies the file in to out.lzo with using lzo (lzo1x_1) compression and calculating an md5 hash (checksum) on both files. The md5 hashes for both are also written to stdout in the md5sum output format. Note that the compress parameter to lzo is not strictly required here; the plugin could have deduced it from the file names. This example shows that you can specify multiple plugins with multiple parameters; the plugins are forming a filter chain. You can specify the same plugin multiple times. πβ¨
dd_rescue -L hash=sha512:set_xattr:fallb,null=change infile /dev/null
reads the file infile and computes its sha512 hash. It stores it in the input file's user.checksum.sha512 attribute (and falls back to writing it to CHECKSUMS.sha512 if xattrs can't be written). Note the use of the null plugin with faking data change with the change parameter; this causes the hash plugin to write to the input file which it would not normally have done. Of course this will fail if you don't have the appropriate privileges to write xattrs to infile nor to write the checksum to CHECKSUMS.sha512. π
See also README.dd_rescue and ddr_lzo(1) to learn about the possibilities. π
π§ͺ TESTING π§ͺ
Untested code is buggy, almost always. π The author happens to have a damaged hard disk that gets used for testing dd_rescue from time to time. But to allow for automated testing of error recovery, it's better to have predictable failures for the program to deal with. So there is a fault injection framework. π―
Specifying -F 5w/1,17r/3,42r/-1,80-84r/0 on the command-line will result in in the 5th block (counted in hardblocksize) will fail to be written once (from which dd_rescue should recover, as it tries a second time for failed writes), block no 17 will fail to be read 3 times, block no 42 will read fine once, but then fail afterwards, whereas blocks 80 through 83 are completely unreadable (will fail infinite times). Note that the range excludes the last block (80-84 means 4 blocks starting @ 80). π
Block offsets are always counted in absolute positions, so starting in the middle of a file with -s or reverse copying won't affect the absolute position that is hit with the fault injection. (This has changed since 1.98.)
The option -H percent on the command line will cause read and write havoc by returning short reads and writes and by returning an indication that a read or write has to be redone as the system call was interrupted or would block. The percentage given will applied to both interrupted calls and short reads/writes. According to the GNU libc documentation, such things can happen; the fact they only do happen seldomly and only under certain circumstances makes it hard to test, thus this option to force it to randomly happen. π΅βπ« (This has led to bug fixes in 1.99.21.)
π BUGS/LIMITATIONS π
The source code does use the 64bit functions provided by glibc for file positioning. However, your kernel might not support it, so you might be unable to copy partitions larger then 2GB into a file. π
This program has been written using Linux and only tested on a couple of Linux systems. People have reported to have successfully used it on other Un*xish systems (such as xBSD or M*cOS), but these systems get little regular test coverage; so please be advised to test properly (possibly using the make check test suite included with the source distribution) before relying on dd_rescue on non Linux based systems. π§
Currently, the escape sequence for moving the cursor up is hard coded in the sources. It's fine for most terminal emulations (including vt100 and linux), but it should use the terminal description database instead. π
Since dd_rescue-1.10, non-seekable input or output files are supported, but there's of course limitations to recover errors in such cases.
dd_rescue does not automate the recovery of faulty files or partitions by automatically keeping a list of copied sectors and approaching bad spots from both sides. There is a helper script dd_rhelp from LAB Valentin that does this. Integration of such a mode into dd_rescue itself is non-trivial and due to the complexity of the source code might not happen. π«
There also is a tool, GNU ddrescue, that is a reimplementation of this tool and which contains the capabilities to automate recovery of bad files in the way dd_rhelp does. It does not have the feature richness of dd_rescue, but is reported to be easier to operate for error recovery than dd_rescue with dd_rhelp.
π¨ If your data is very valuable and you are considering sending your disk to a data recovery company, you might be better off NOT trying to use imaging tools likedd_rescue,dd_rhelporGNU ddrescue. If you're unlucky, the disk has suffered some mechanical damage (e.g. by having been dropped), and continuing to use it may make the head damage the surface further. You may be able to detect this condition by quickly raising error counts in the SMART attributes or by a clicking noise. π
Please report bugs to me via email. π§
π₯ Data destruction considerations π₯
The modes for overwriting data with pseudo random numbers to securely delete sensitive data on purpose only implement a limited number of overwrites. While Peter Gutmann's classic analysis concludes that the then current hard disk technology requires more overwrites to be really secure, the author believes that modern hard disk technology does not allow data restoration of sectors that have been overwritten with the --shred4 mode. This is in compliance with the recommendations from BSI GSDS M7.15. π
Overwriting whole partitions or disks with random numbers is a fairly safe way to destroy data, unless the underlying storage device does too much magic. SSDs are doing fancy stuff in their Flash Translation Layer (FTL), so this tool might be insufficient to get rid of data. Use SECURITY_ERASE (use hdparm) there or β if available β encrypt data with AES256 and safely destroy the key. π Normal hard disks have a small risk of leaking a few sectors due to reallocation of flaky sectors.
For securely destroying single files, your mileage may vary. The more advanced your file system, the less likely dd_rescue's destruction will be effective. In particular, journaling file systems may carry old data in the journal. File systems that do copy-on-write (COW) such as btrfs, are very likely to have old copies of your supposedly erased file. π It might help somewhat to fill the file systems with zeros (dd_rescue -u /dev/zero /path/to/fs/DUMMYNAME) to force the file system to release and overwrite non-current data after overwriting critical files with random numbers. If you can, better destroy a whole partition or disk. π
β SEE ALSO β
README.dd_rescue README.dd_rhelp ddr_lzo(1) wipe(1) shred(1) ddrescue(1) dd(1)
π AUTHOR π
Kurt Garloff <kurt@garloff.de>
π CREDITS π
Many little issues were reported by Valentin LAB, the author of dd_rhelp .
The RC4 PRNG (frandom) is a port from Eli Billauer's kernel mode PRNG.
A number of recent ideas and suggestions came from Thomas. π
π COPYRIGHT π
This program is protected by the GNU General Public License (GPL) v2 or v3 - at your option. β¨
π HISTORY π
okay bestie, storytime π β here's the whole glow-up timeline, and we are not skipping a single era:
- Since version
1.10β non seekable input and output files are supported. iconic. 1.15β splice copy-kis supported. slay.1.17β a progress bar exists. we love to see it.1.19β support for preallocation (fallocate)-Pexists.1.23β we default to-y0, enhancing performance. periodt.1.29β the Pseudo Random Number modes have been started.1.30β write avoidance-Whas been implemented.1.32β multiple output files-Yhave been added.1.33β long options and man page came with this.1.35β optimized sparse detection (SSE2, armv6, armv8 asm, AVX2) has been present since1.35and been enhanced until1.43.1.40β we support copying extended attributes since1.40using libxattr.1.41β removing and (fs)trimming the output file's file system exists since1.41. Support for compilation with bionic (Android's C library) with most features enabled also came with1.41.1.42β plugins exist since1.42, the MD5 plugin came with1.42, the lzo plugin with1.43.1.44β renamed the MD5 plugin to hash and added support for the SHA-2 family of hashes.1.45β added SHA-1 and the ability to store and validate checksums.1.98β brought encryption and the fault injection framework,1.99support for ARMv8 crypto acceleration.1.99.5β brought ratecontrol.1.99.6β brought S3 style multipart checksums.1.99.7-12β brought more crypto performance tuning and compatibility with openSSL-1.1 and -3.0.1.99.13-16β brought further optimizations, incl. sha256 acceleration.1.99.17β introduced support for liblzma (xz).1.99.18-19β further improved it, with support for holes.1.99.20-21β hardened complex plugin chains and systematically handled issues when retries are necessary also in the write path.1.99.23-24β fixed a corner case where an error from a plugin got lost and where the overlap detection for same-file copies did not treat positions according to user expectations.1.99.25β fixed an issue where progress reports would not be generated if starting with odd offsets.
want even more lore? Some additional information can be found on http://garloff.de/kurt/linux/ddrescue/
LAB Valentin's dd_rhelp can be found on http://www.kalysto.org/utilities/dd_rhelp/index.en.html
xoxo, your Unix bestie β footer vibes: dd_rescue(1), 2026-10-09, Kurt Garloff ππ¦
π¦ where this page comes from
- arch rolling: dd_rescue 1.99.25-1 Β· GPL
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms