Hello community,
here is the log from the commit of package dd_rescue for openSUSE:Factory checked in at 2013-02-04 19:29:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dd_rescue (Old)
and /work/SRC/openSUSE:Factory/.dd_rescue.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "dd_rescue", Maintainer is ""
Changes:
--------
--- /work/SRC/openSUSE:Factory/dd_rescue/dd_rescue.changes 2012-05-29 10:33:12.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.dd_rescue.new/dd_rescue.changes 2013-02-04 19:29:56.000000000 +0100
@@ -1,0 +2,20 @@
+Sun Feb 3 21:54:54 CET 2013 - kurt@garloff.de
+
+- Update to dd_rescue-1.31:
+ * Some minor output cleanups.
+ * Implementation of safe triple overwrite (options -3 and -4)
+ following BSI GSDS M7.15.
+- Update to dd_rescue-1.30:
+ * Fix issue with double free (1.29)
+ * Fix output to stdout ("-")
+ * Rationalize messages a bit.
+ * Option to init PRNG from file (e.g. -Z /dev/urandom)
+ * Option -W to avoid writes (if output block is identical)
+- Update to dd_rescue-1.29:
+ * Correctly handle last bytes before EOF when hardbs == softbs.
+ * New option -M (dont extend output file).
+ * New option -R (repeated output of one block, auto for dev/zero)
+ * New options -z x, -Z x to use userspace pseudo RNG to overwrite
+ disks / files with random data.
+
+-------------------------------------------------------------------
Old:
----
dd_rescue-1.28.tar.gz
New:
----
dd_rescue-1.31.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ dd_rescue.spec ++++++
--- /var/tmp/diff_new_pack.dNHO4d/_old 2013-02-04 19:29:59.000000000 +0100
+++ /var/tmp/diff_new_pack.dNHO4d/_new 2013-02-04 19:29:59.000000000 +0100
@@ -1,7 +1,7 @@
#
# spec file for package dd_rescue
#
-# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -15,13 +15,14 @@
# Please submit bugfixes or comments via http://bugs.opensuse.org/
#
+
Name: dd_rescue
-Version: 1.28
+Version: 1.31
Release: 0
Summary: Data Copying in the Presence of I/O Errors
License: GPL-2.0 or GPL-3.0
-Url: http://www.garloff.de/kurt/linux/ddrescue/
Group: System/Base
+Url: http://www.garloff.de/kurt/linux/ddrescue/
Source0: http://garloff.de/kurt/linux/ddrescue/%{name}-%{version}.tar.gz
BuildRequires: libfallocate-devel-static
Requires: bc
@@ -34,7 +35,12 @@
%description
dd_rescue helps when nothing else can: your disk has crashed and you
try to copy it over to another one. While standard Unix tools like cp,
-cat, and dd wail "abort" on every I/O error, dd_rescue does not.
+cat, and dd will "abort" on every I/O error, dd_rescue does not.
+
+dd_rescue has many other goodies; optimization by using large blocks
+as long as no errors are in sight and falling back to small ones; reverse
+direction copy; splice in-kernel zerocopy; O_DIRECT support; preallocation
+with fallocate(); random number writing etc.
%prep
%setup -q -n dd_rescue
++++++ dd_rescue-1.28.tar.gz -> dd_rescue-1.31.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue/COPYING new/dd_rescue/COPYING
--- old/dd_rescue/COPYING 2000-01-14 18:02:23.000000000 +0100
+++ new/dd_rescue/COPYING 2013-01-25 17:08:18.000000000 +0100
@@ -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.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
- END OF TERMS AND CONDITIONS
-
- 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 @@
the "copyright" line and a pointer to where the full notice is found.
- 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,17 +303,16 @@
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
@@ -336,5 +335,5 @@
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.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue/Makefile new/dd_rescue/Makefile
--- old/dd_rescue/Makefile 2012-05-19 22:46:14.000000000 +0200
+++ new/dd_rescue/Makefile 2013-02-03 14:32:29.000000000 +0100
@@ -1,14 +1,15 @@
# Makefile for dd_rescue
# (c) garloff@suse.de, 99/10/09, GNU GPL
-# $Id: Makefile,v 1.42 2012/05/19 20:46:14 garloff Exp $
+# $Id: Makefile,v 1.46 2013/02/03 13:32:29 garloff Exp $
-VERSION = 1.28
+VERSION = 1.31
DESTDIR =
CC = gcc
RPM_OPT_FLAGS = -Os -Wall -g
CFLAGS = $(RPM_OPT_FLAGS) $(EXTRA_CFLAGS)
+CFLAGS_OPT = $(CFLAGS) -O3
INSTALL = install
INSTALLFLAGS = -s
prefix = $(DESTDIR)/usr
@@ -17,7 +18,7 @@
#MYDIR = dd_rescue-$(VERSION)
MYDIR = dd_rescue
TARGETS = dd_rescue
-OBJECTS = dd_rescue.o
+OBJECTS = dd_rescue.o frandom.o
DOCDIR = $(prefix)/share/doc/packages
INSTASROOT = -o root -g root
LIBDIR = /usr/lib
@@ -33,17 +34,20 @@
default: $(TARGETS)
-libfalloc: dd_rescue.c
- $(CC) $(CFLAGS) -DHAVE_FALLOCATE=1 -DHAVE_LIBFALLOCATE=1 $(DEFINES) $< -o dd_rescue -lfallocate
+frandom.o: frandom.c
+ $(CC) $(CFLAGS_OPT) -c $<
-libfalloc-static: dd_rescue.c
- $(CC) $(CFLAGS) -DHAVE_FALLOCATE=1 -DHAVE_LIBFALLOCATE=1 $(DEFINES) $< -o dd_rescue $(LIBDIR)/libfallocate.a
+libfalloc: dd_rescue.c frandom.o
+ $(CC) $(CFLAGS) -DHAVE_FALLOCATE=1 -DHAVE_LIBFALLOCATE=1 $(DEFINES) $^ -o dd_rescue -lfallocate
-falloc: dd_rescue.c
- $(CC) $(CFLAGS) -DHAVE_FALLOCATE=1 $(DEFINES) $< -o dd_rescue
+libfalloc-static: dd_rescue.c frandom.o
+ $(CC) $(CFLAGS) -DHAVE_FALLOCATE=1 -DHAVE_LIBFALLOCATE=1 $(DEFINES) $^ -o dd_rescue $(LIBDIR)/libfallocate.a
-dd_rescue: dd_rescue.c
- $(CC) $(CFLAGS) $(DEFINES) $< $(OUT)
+falloc: dd_rescue.c frandom.o
+ $(CC) $(CFLAGS) -DHAVE_FALLOCATE=1 $(DEFINES) $^ -o dd_rescue
+
+dd_rescue: dd_rescue.c frandom.o
+ $(CC) $(CFLAGS) $(DEFINES) $^ $(OUT)
strip: dd_rescue
strip -S $<
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue/README.dd_rescue new/dd_rescue/README.dd_rescue
--- old/dd_rescue/README.dd_rescue 2012-05-19 22:52:36.000000000 +0200
+++ new/dd_rescue/README.dd_rescue 2013-02-03 19:05:29.000000000 +0100
@@ -1,6 +1,7 @@
README file for dd_rescue
=========================
-(c) garloff@suse.de, 10/99, GNU GPL
+(c) garloff@suse.de, 10/99, GNU GPL
+(c) kurt@garloff.de 2011-2012, GNU GPL v2 or v3
Description of dd_rescue
@@ -46,6 +47,9 @@
* If you have one spot of bad sectors within the partition, it might be a
good idea, to approach this spot from both sides. Reverse direction copy
is helpful.
+ dd_rhelp (included in dd_rescue packages) does automate this approach.
+ There is a GNU ddrescue tool that is a redesigned dd_rescue and also has
+ automation for this built-in.
* The two block sizes are a performance optimization. Large block sizes
result in superior performance, but in case of errors, you want to try
to salvage every single sector. So hardbs is best be set to the hardware
@@ -88,16 +92,13 @@
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. It should be possible to port it easily to other Un*x
-platforms, but I have not tried.
+platforms, and I occasionally get hints from users of other *nix like
+systems that I take into account. Still, my own testing is limited to Linux.
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.
-Due to the way the program works (input and output are always written to the
-designated position, i.e. a seek() is done before the I/O operation is
-actually performed), char devices can not be read from or written to.
-Therefore you can't redirect output to stdout.
-This limitation has been lifted in version 1.10; though with non-seekable
-in- and our output, you can't recover from errors on that channel.
+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.
Goodies
@@ -128,20 +129,56 @@
* When overwriting a file with itself (but with some offsets, i.e.
moving data inside a file), dd_rescue figures out whether it
needs to do this backwards (-r) to not end up destroying the data.
+* Since 1.29, it has a repeat mode (-R) that allows duplicating one
+ block (of softbs size) many times. This is turned on automatically
+ when infile is /dev/zero (performance optimization).
+* Since 1.29, you can overwrite files with random numbers from userspace
+ PRNG (libc or included RC4 based frandom) which is 10x faster than
+ urandom. Using -Z /dev/urandom gives decent quality PRNGs.
+* With option -M (new 1.29), the output file won't be extended.
+* Option -W (since 1.30) tries to avoid writes: If the block in the
+ target file/partition is already identical to the source, no actual
+ write operation is performed. This can be useful, when write are
+ very expensive or have other effects that you want to avoid (e.g.
+ reducing lifetime of SSDs).
+* The option -3 (new in 1.31) does overwrite a disk/partition/file/...
+ three times; the first time with frandom generated random numbers,
+ the second time with the bitwise inversed of the first pass and the
+ third time with zeros. (Zero in the final pass is good for SSDs...)
+ Overwriting a disk with -3 /dev/urandom should provide a very good
+ protection level against data being recoverable. When overwriting
+ files, the option -M will probably be handy -- please note however
+ that overwriting files this way may or may not be a safe deletion,
+ depending on how the filesystem handles overwrites. (And for flash
+ devices, the FTL may also do reallocations that prevents in place
+ overwriting of data. TRIM and SECURITY_ERASE (see man hdparm) should
+ be used instead or in addition there.)
+ There's also a variant with 3xrandom numbers and a final zeroing
+ (option -4); this option has been designed to meet the BSI GSDS
+ M7.15 criteria for safe deletion of data.
+ https://www.bsi.bund.de/ContentBSI/grundschutz/baustein-datenschutz/html/m07...
Copyright
---------
-This little program is protected by the GNU General Public License (GPL).
+This program is protected by the GNU General Public License (GPL)
+v2 or v3 - at your option.
(See the file COPYING, which probably exists a few hundred times on your
- computer. If not: I will send you one.)
+ computer. If not: I will send you one or you can ask the FSF to do so.)
To summarize:
-* You are free to use this program for anything you like. However, if you
- release a program that uses code from this program, your program must be
- released under the terms of the GNU GPL again.
-* You are allowed to put this program on CDs or other media and charge a
- fee for copying and distributing it. You have to provide the source code
- (or a written offer to provide it) and the GPL text, too, then.
+* You are free to use this program for anything you like. (You are still
+ bound by the law of course, but the license does not put any additional
+ restrictions.)
+* You are allowed to distribute this program and e.g. put it on a CD or
+ other media and charge a fee for copying and distributing it. You have
+ to provide the source code (or a written offer to provide it) and the
+ GPL text, too, then and provide the same rights to your recipients
+ that you received by the GNU GPL. (You redistribute under the terms
+ of the GNU GPL.)
+* You can study and/or modify the program to meet your desires.
+ You may distribute modified versions under the terms of the GNU GPL
+ again. (If you base any work on this program and you distribute
+ your work, you *must* do so under the terms of the GNU GPL.)
* There is no warranty whatsoever for this program. If it crashes your
disks, it's at your risk.
* This summary does not replace reading the GNU GPL itself.
@@ -152,6 +189,8 @@
... is always welcome. Just send me an e-mail.
The web page of this program, BTW, is
http://www.garloff.de/kurt/linux/ddrescue/
+frandom.c is adapted from the kernel module from Eli Billauer
+http://www.billauer.co.il
Have fun!
@@ -160,4 +199,4 @@
Kurt Garloff , 2000-08-30
-$Id: README.dd_rescue,v 1.14 2012/05/19 20:52:36 garloff Exp $
+$Id: README.dd_rescue,v 1.23 2013/02/03 18:03:26 garloff Exp $
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue/dd_rescue.c new/dd_rescue/dd_rescue.c
--- old/dd_rescue/dd_rescue.c 2012-05-19 22:46:14.000000000 +0200
+++ new/dd_rescue/dd_rescue.c 2013-02-03 19:05:29.000000000 +0100
@@ -8,7 +8,7 @@
* for rescueing data of crashed disk, and that's the reason it has been
* written by me.
*
- * Copyright (C) Kurt Garloff , 11/1997 -- 05/2012
+ * Copyright (C) Kurt Garloff , 11/1997 -- 02/2013
*
* Improvements from LAB Valentin, see
* http://www.kalysto.org/utilities/dd_rhelp/index.en.html
@@ -25,10 +25,9 @@
* 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., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
- *
-*/
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
/**
* TODO:
@@ -38,8 +37,7 @@
* - Optional colors
* - Use dlopen to open libfallocate rather than linking to it ...
* - Display more infos on errors by collecting info from syslog
- * - Option to use frandom as virtual input device (Thomas)
- * - Option to avoid overwriting identical output to be nice to SSD (Thomas)
+ * - Allow seoncdary output file
*/
#ifndef VERSION
@@ -49,7 +47,7 @@
# define "(unknown compiler)"
#endif
-#define ID "$Id: dd_rescue.c,v 1.130 2012/05/19 20:46:14 garloff Exp $"
+#define ID "$Id: dd_rescue.c,v 1.149 2013/02/03 18:03:26 garloff Exp $"
#ifndef BUF_SOFTBLOCKSIZE
# define BUF_SOFTBLOCKSIZE 65536
@@ -84,6 +82,9 @@
#include
#include
#include
+
+#include "frandom.h"
+
#ifdef HAVE_GETOPT_H
#include
#endif
@@ -118,17 +119,31 @@
# endif
#endif
+/* fwd decls */
+int cleanup();
+/* Global vars and options */
unsigned int softbs, hardbs, syncfreq;
-int maxerr, nrerr, reverse, dotrunc, abwrerr, sparse, nosparse;
-int verbose, quiet, interact, force;
-unsigned char* buf;
+int maxerr, nrerr, dotrunc;
+char reverse, abwrerr, sparse, nosparse;
+char verbose, quiet, interact, force, in_report;
+unsigned char *buf, *buf2;
char *lname, *iname, *oname, *bbname = NULL;
-off_t ipos, opos, xfer, lxfer, sxfer, fxfer, maxxfer, init_opos, ilen, estxfer;
+off_t ipos, opos, xfer, lxfer, sxfer, fxfer, maxxfer, axfer, init_opos, ilen, olen, estxfer;
-int ides, odes, identical, pres, falloc;
-int o_dir_in, o_dir_out, dosplice;
+int ides, odes;
+int o_dir_in, o_dir_out;
+char identical, preserve, falloc, dosplice;
char i_chr, o_chr;
+char i_repeat, i_rep_init;
+int i_rep_zero, prng_seed;
+char noextend, avoidwrite;
+char prng_libc, prng_frnd;
+char bsim715, bsim715_4, bsim715_2ndpass;
+char* prng_sfile;
+
+void *prng_state, *prng_state2;
+
FILE *logfd;
struct timeval starttime, lasttime, currenttime;
@@ -225,7 +240,7 @@
{
int fdes;
if (!strcmp(fname, "-")) {
- if (flags & O_WRONLY)
+ if (flags & O_WRONLY || flags & O_RDWR)
fdes = 1; /* stdout */
else
fdes = 0; /* stdin */
@@ -243,14 +258,14 @@
static void check_seekable(const int id, const int od)
{
errno = 0;
- if (lseek(id, (off_t)0, SEEK_SET) != 0) {
+ if (!i_chr && lseek(id, (off_t)0, SEEK_SET) != 0) {
fplog(stderr, "dd_rescue: (warning): input file is not seekable!\n");
fplog(stderr, "dd_rescue: (warning): %s\n", strerror(errno));
i_chr = 1;
} //else
// lseek(id, (off_t)0, SEEK_SET);
errno = 0;
- if (lseek(od, (off_t)0, SEEK_SET) != 0) {
+ if (!o_chr && lseek(od, (off_t)0, SEEK_SET) != 0) {
fplog(stderr, "dd_rescue: (warning): output file is not seekable!\n");
fplog(stderr, "dd_rescue: (warning): %s\n", strerror(errno));
o_chr = 1;
@@ -292,8 +307,12 @@
return;
if (err)
graph[off] = 'x';
- else
- graph[off] = '-';
+ else {
+ if (bsim715_2ndpass)
+ graph[off] = '.';
+ else
+ graph[off] = '-';
+ }
}
/** Tries to determine size of input file */
@@ -334,7 +353,7 @@
return;
diff = ilen - stbuf.st_blocks*512;
if (diff >= 4096 && (float)diff/ilen > 0.05 && !quiet)
- fplog(stderr, "dd_rescue: (info) %s is sparse (%i%%) %s\n", iname, (int)(100.0*diff/ilen), (sparse? "": ", consider -a"));
+ fplog(stderr, "dd_rescue: (info): %s is sparse (%i%%) %s\n", iname, (int)(100.0*diff/ilen), (sparse? "": ", consider -a"));
}
if (!ilen)
return;
@@ -347,11 +366,64 @@
if (estxfer < 0)
estxfer = 0;
if (!quiet)
- fplog(stderr, "dd_rescue: (info) expect to copy %LikB from %s\n",
+ fplog(stderr, "dd_rescue: (info): expect to copy %LikB from %s\n",
estxfer/1024, iname);
preparegraph();
}
+int output_length()
+{
+ struct stat stbuf;
+ if (o_chr)
+ return -1;
+ if (fstat(odes, &stbuf))
+ return -1;
+ if (S_ISLNK(stbuf.st_mode))
+ return -1;
+ if (S_ISCHR(stbuf.st_mode)) {
+ o_chr = 1;
+ return -1;
+ }
+ if (S_ISBLK(stbuf.st_mode)) {
+ /* Do magic to figure size of block dev */
+ off_t p = lseek(odes, 0, SEEK_CUR);
+ if (p == -1)
+ return -1;
+ olen = lseek(odes, 0, SEEK_END) + 1;
+ lseek(odes, p, SEEK_SET);
+ } else {
+ off_t diff;
+ olen = stbuf.st_size;
+ if (!olen)
+ return -1;
+ diff = olen - stbuf.st_blocks*512;
+ if (diff >= 4096 && (float)diff/ilen > 0.05 && !quiet)
+ fplog(stderr, "dd_rescue: (info): %s is sparse (%i%%) %s\n", oname, (int)(100.0*diff/olen), (sparse? "": ", consider -a"));
+ }
+ if (!olen)
+ return -1;
+ if (!reverse) {
+ off_t newmax = olen - opos;
+ if (newmax < 0) {
+ fplog(stderr, "dd_rescue: (fatal): output position is beyond end of file but -M specified!\n");
+ cleanup();
+ exit(19);
+ }
+ if (!maxxfer || maxxfer > newmax) {
+ maxxfer = newmax;
+ if (!quiet)
+ fplog(stderr, "dd_rescue: (info): limit max xfer to %LikB\n",
+ maxxfer/1024);
+ }
+ } else if (opos > olen) {
+ fplog(stderr, "dd_rescue: (warning): change output position %LikB to endpos %Likb due to -M\n",
+ opos/1024, olen/1024);
+ opos = olen;
+ }
+ return 0;
+}
+
+
static void sparse_output_warn()
{
struct stat stbuf;
@@ -424,13 +496,18 @@
avgrate,
100.0*(cl-startclock)/(CLOCKS_PER_SEC*t1));
if (estxfer && avgrate > 0) {
- int sec = (estxfer-xfer)/(1024*avgrate);
+ int sec;
+ if (in_report)
+ sec = 0.5 + t1;
+ else
+ sec = 0.5 + (estxfer-xfer)/(1024*avgrate);
int hour = sec / 3600;
int min = (sec % 3600) / 60;
sec = sec % 60;
updgraph(0);
- fprintf(file, " %s %3i%% ETA: %2i:%02i:%02i \n",
- graph, (int)(100*xfer/estxfer), hour, min, sec);
+ fprintf(file, " %s %3i%% %s: %2i:%02i:%02i \n",
+ graph, (int)(100*xfer/estxfer), (in_report? "TOT": "ETA"),
+ hour, min, sec);
} else
fprintf(file, "\n");
@@ -489,10 +566,13 @@
{
/* report */
FILE *report = (!quiet || nrerr)? stderr: 0;
+ in_report = 1;
if (report) {
fplog(report, "dd_rescue: (info): Summary for %s -> %s:\n", iname, oname);
- fprintf(stderr, "%s%s%s%s", down, down, down, down);
+ fprintf(report, "%s%s%s%s", down, down, down, down);
printstatus(report, logfd, 0, 1);
+ if (avoidwrite)
+ fplog(report, "dd_rescue: (info): Avoided %LikB of writes (performed %LikB)\n", axfer/1024, (sxfer-axfer)/1024);
}
}
@@ -542,6 +622,13 @@
return 0;
}
+#define ZFREE(ptr) \
+ do { \
+ if(ptr) \
+ free(ptr); \
+ ptr = 0; \
+ } while(0)
+
int cleanup()
{
int rc, errs = 0;
@@ -549,7 +636,8 @@
/* Make sure, the output file is expanded to the last (first) position
* FIXME: 0 byte writes do NOT expand file -- mayexpandfile() will
* take care of that. */
- pwrite(odes, buf, 0, opos);
+ if (!avoidwrite)
+ rc = pwrite(odes, buf, 0, opos);
rc = fsync(odes);
if (rc && !o_chr) {
fplog(stderr, "dd_rescue: (warning): fsync %s (%.1fk): %s!\n",
@@ -579,29 +667,62 @@
}
if (logfd)
fclose(logfd);
- if (buf)
- free(buf);
- if (graph)
- free(graph);
- if (pres)
+ ZFREE(buf2);
+ ZFREE(buf);
+ ZFREE(graph);
+ if (preserve)
copytimes(iname, oname);
- if (oname)
- free(oname);
+ ZFREE(oname);
+ if (prng_state2) {
+ frandom_release(prng_state2);
+ prng_state2 = 0;
+ }
+ if (prng_state) {
+ frandom_release(prng_state);
+ prng_state = 0;
+ }
return errs;
}
+ssize_t fill_rand(void *bf, size_t ln)
+{
+ int i;
+ int* buf = (int*)bf;
+ for (i = 0; i < ln/sizeof(int); ++i)
+ buf[i] = rand();
+ return ln;
+}
+
/** is the block zero ? */
static int blockiszero(const unsigned char* blk, const int ln)
{
+ if (i_repeat && i_rep_zero)
+ return i_rep_zero;
unsigned long* ptr = (unsigned long*)blk;
while ((ptr-(unsigned long*)blk) < ln/sizeof(unsigned long))
if (*(ptr++))
- return (sizeof(unsigned long)*(ptr-(unsigned long*)blk));
+ return i_rep_zero = (sizeof(unsigned long)*(ptr-(unsigned long*)blk));
+ if (i_repeat)
+ i_rep_zero = ln;
return ln;
}
inline ssize_t mypread(int fd, void* bf, size_t sz, off_t off)
{
+ if (i_repeat) {
+ if (i_rep_init)
+ return sz;
+ else
+ i_rep_init = 1;
+ }
+ if (prng_libc)
+ return fill_rand(bf, sz);
+ if (prng_frnd) {
+ if (!bsim715_2ndpass)
+ return frandom_bytes(prng_state, bf, sz);
+ else
+ return frandom_bytes_inv(prng_state, bf, sz);
+ }
if (i_chr)
return read(fd, bf, sz);
else
@@ -612,8 +733,20 @@
{
if (o_chr)
return write(fd, bf, sz);
- else
- return pwrite(fd, bf, sz, off);
+ else {
+ if (avoidwrite) {
+ ssize_t ln = pread(fd, buf2, sz, off);
+ if (ln < sz)
+ return pwrite(fd, bf, sz, off);
+ if (memcmp(bf, buf2, ln))
+ return pwrite(fd, bf, sz, off);
+ else {
+ axfer += ln;
+ return ln;
+ }
+ } else
+ return pwrite(fd, bf, sz, off);
+ }
}
@@ -756,6 +889,22 @@
/* Some errnos are fatal */
exitfatalerr(eno);
/* Non fatal error */
+ /* This is the case, where we were not called from copyfile_softbs and thus have to assume harmless EOF */
+ if (softbs <= hardbs && eno == 0) {
+ int ret;
+ /* But first: write available data and advance (optimization) */
+ if ((ret = partialwrite(rd)) < 0)
+ return ret;
+ else
+ errs += ret;
+ xfer += rd; sxfer += rd;
+ if (reverse) {
+ ipos -= rd; opos -= rd;
+ } else {
+ ipos += rd; opos += rd;
+ }
+ continue;
+ }
/* Real error on small blocks: Don't retry */
nrerr++;
fplog(stderr, "dd_rescue: (warning): read %s (%.1fk): %s!\n",
@@ -814,7 +963,7 @@
int copyfile_softbs(const off_t max)
{
ssize_t toread;
- int errs = 0; int eno;
+ int errs = 0, rc; int eno;
errno = 0;
#if 0
fprintf(stderr, "%s%s%s%s copyfile (ipos=%.1fk, xfer=%.1fk, max=%.1fk, bs=%i) ##\n%s%s%s%s",
@@ -824,8 +973,8 @@
#endif
/* expand file to AT LEAST the right length
* FIXME: 0 byte writes do NOT expand file */
- if (!o_chr)
- pwrite(odes, buf, 0, opos);
+ if (!o_chr && !avoidwrite)
+ rc = pwrite(odes, buf, 0, opos);
while ((toread = blockxfer(max, softbs)) > 0) {
int err;
ssize_t rd = readblock(toread);
@@ -949,6 +1098,58 @@
}
#endif
+int tripleoverwrite(const off_t max)
+{
+ int ret = 0;
+ off_t orig_opos = opos;
+ void* prng_state2 = frandom_stdup(prng_state);
+ clock_t orig_startclock = startclock;
+ struct timeval orig_starttime;
+ memcpy(&orig_starttime, &starttime, sizeof(starttime));
+ fprintf(stderr, "%s%s%s%sdd_rescue: (info): Triple overwrite (BSI M7.15): first pass ... (frandom) \n\n\n\n\n", up, up, up, up);
+ ret += copyfile_softbs(max);
+ fprintf(stderr, "syncing ... \n%s", up);
+ ret += fsync(odes);
+ /* TODO: better error handling */
+ frandom_release(prng_state);
+ prng_state = prng_state2; prng_state2 = 0;
+ bsim715_2ndpass = 1;
+ opos = orig_opos; xfer = 0; ipos = 0;
+ startclock = clock(); gettimeofday(&starttime, NULL);
+ fprintf(stderr, "dd_rescue: (info): Triple overwrite (BSI M7.15): second pass ... (frandom_inv)\n\n\n\n\n");
+ ret += copyfile_softbs(max);
+ fprintf(stderr, "syncing ... \n%s", up);
+ ret += fsync(odes);
+ /* TODO: better error handling */
+ bsim715_2ndpass = 0;
+ if (bsim715_4) {
+ frandom_bytes(prng_state, buf, 16);
+ fprintf(stderr, "dd_rescue: (info): Triple overwrite (BSI M7.15): third pass ... (frandom) \n\n\n\n\n");
+ opos = orig_opos; xfer = 0; ipos = 0;
+ startclock = clock(); gettimeofday(&starttime, NULL);
+ ret += copyfile_softbs(max);
+ fprintf(stderr, "syncing ... \n%s", up);
+ ret += fsync(odes);
+ bsim715_2ndpass = 1;
+ iname = "FRND+invFRND+FRND2+ZERO";
+ } else
+ iname = "FRND+invFRND+ZERO";
+ fprintf(stderr, "dd_rescue: (info): Triple overwrite (BSI M7.15): last pass ... (zeros) \n\n\n\n\n");
+ frandom_release(prng_state); prng_state = 0;
+ memset(buf, 0, softbs);
+ i_repeat = 1; i_rep_init = 1;
+ opos = orig_opos; xfer = 0; ipos = 0;
+ startclock = clock(); gettimeofday(&starttime, NULL);
+ ret += copyfile_softbs(max);
+ startclock = orig_startclock;
+ memcpy(&starttime, &orig_starttime, sizeof(starttime));
+ xfer = sxfer;
+ if (ret)
+ fplog(stderr, "dd_rescue: (warning): There were %i errors! %s may not be safely overwritten!\n", ret, oname);
+ //fprintf(stderr, "syncing ... \n%s", up);
+ return ret;
+}
+
static off_t readint(const char* const ptr)
{
char *es; double res;
@@ -967,9 +1168,52 @@
return (off_t)res;
}
+void init_random()
+{
+ if (prng_sfile) {
+ int ln, fd = -1;
+ unsigned char sbf[256];
+ if (!strcmp(prng_sfile, "-")) {
+ fd = 0;
+ if (verbose)
+ fplog(stderr, "dd_rescue: (info): reading random seed from <stdin> ...\n");
+ } else
+ fd = open(prng_sfile, O_RDONLY);
+ if (fd == -1) {
+ fplog(stderr, "dd_rescue: (fatal): Could not open \"%s\" for random seed!\n", prng_sfile);
+ /* ERROR */
+ cleanup(); exit(28);
+ }
+ if (prng_libc) {
+ unsigned int* sval = (unsigned int*)sbf;
+ ln = read(fd, sbf, 4);
+ if (ln != 4) {
+ fplog(stderr, "dd_rescue: (fatal): failed to read 4 bytes from \"%s\"!\n", prng_sfile);
+ cleanup(); exit(29);
+ }
+ srand(*sval);
+ } else {
+ ln = read(fd, sbf, 256);
+ if (ln != 256) {
+ fplog(stderr, "dd_rescue: (fatal): failed to read 256 bytes from \"%s\"!\n", prng_sfile);
+ cleanup(); exit(29);
+ }
+ prng_state = frandom_init(sbf);
+ }
+ } else {
+ if (!prng_seed)
+ prng_seed = time(0) - getpid();
+ if (prng_libc)
+ srand(prng_seed);
+ else
+ prng_state = frandom_init_lrand(prng_seed);
+ }
+}
+
+
void printversion()
{
- fprintf(stderr, "\ndd_rescue Version %s, garloff@suse.de, GNU GPL\n", VERSION);
+ fprintf(stderr, "\ndd_rescue Version %s, kurt@garloff.de, GNU GPL v2/v3\n", VERSION);
fprintf(stderr, " (%s)\n", ID);
fprintf(stderr, " (compiled %s %s by %s)\n", __DATE__, __TIME__, __COMPILER__);
fprintf(stderr, " (features: ");
@@ -985,6 +1229,8 @@
fprintf(stderr, "splice ");
#endif
fprintf(stderr, ")\n");
+ fprintf(stderr, "dd_rescue is free software. It's protected by the terms of GNU GPL v2 or v3\n");
+ fprintf(stderr, " (at your option).\n");
}
void printhelp()
@@ -998,10 +1244,12 @@
fprintf(stderr, " -B hardbs fallback block size in case of errs (def=%i, %i for -d),\n", BUF_HARDBLOCKSIZE, DIO_HARDBLOCKSIZE);
fprintf(stderr, " -e maxerr exit after maxerr errors (def=0=infinite),\n");
fprintf(stderr, " -m maxxfer maximum amount of data to be transfered (def=0=inf),\n");
+ fprintf(stderr, " -M avoid extending outfile,\n");
fprintf(stderr, " -y syncfrq frequency of fsync calls on outfile (def=512*softbs),\n");
fprintf(stderr, " -l logfile name of a file to log errors and summary to (def=\"\"),\n");
fprintf(stderr, " -o bbfile name of a file to log bad blocks numbers (def=\"\"),\n");
fprintf(stderr, " -r reverse direction copy (def=forward),\n");
+ fprintf(stderr, " -R repeatedly write same block (def if infile is /dev/zero),\n");
fprintf(stderr, " -t truncate output file (def=no),\n");
#ifdef O_DIRECT
fprintf(stderr, " -d/D use O_DIRECT for input/output (def=no),\n");
@@ -1013,6 +1261,7 @@
fprintf(stderr, " -P use fallocate to preallocate target space\n");
#endif
fprintf(stderr, " -w abort on Write errors (def=no),\n");
+ fprintf(stderr, " -W read target block and avoid Writes if identical (def=no),\n");
fprintf(stderr, " -a spArse file writing (def=no),\n");
fprintf(stderr, " -A Always write blocks, zeroed if err (def=no),\n");
fprintf(stderr, " -i interactive: ask before overwriting data (def=no),\n");
@@ -1022,6 +1271,11 @@
fprintf(stderr, " -v verbose operation,\n");
fprintf(stderr, " -V display version and exit,\n");
fprintf(stderr, " -h display this help and exit.\n");
+ fprintf(stderr, "Instead of infile, -z/Z SEED or -z/Z SEEDFILE may be specified, taking the PRNG\n");
+ fprintf(stderr, " from libc or frandom (RC4 based) as input. SEED = 0 means time(0)-getpid();\n");
+ fprintf(stderr, " Using /dev/urandom as SEEDFILE gives good pseudo random numbers.\n");
+ fprintf(stderr, "Likewise, -3 SEED/SEEDFILE will overwrite ofile 3 times (r,ir,0, BSI M7.15).\n");
+ fprintf(stderr, " With -4 SEED/SEEDFILE you get an additional random pass (r,ir,r2,0).\n\n");
fprintf(stderr, "Sizes may be given in units b(=512), k(=1024), M(=1024^2) or G(1024^3) bytes\n");
fprintf(stderr, "This program is useful to rescue data in case of I/O errors, because\n");
fprintf(stderr, " it does not necessarily abort or truncate the output.\n");
@@ -1042,6 +1296,10 @@
YESNO(reverse), YESNO(dotrunc), YESNO(interact));
fplog(file, "dd_rescue: (info): abort on Write errs: %s, spArse write: %s\n",
YESNO(abwrerr), (sparse? "yes": (nosparse? "never": "if err")));
+ fplog(file, "dd_rescue: (info): preserve: %s, splice: %s, avoidWrite: %s\n",
+ YESNO(preserve), YESNO(dosplice), YESNO(avoidwrite));
+ fplog(file, "dd_rescue: (info): fallocate: %s, Repeat: %s, O_DIRECT: %s/%s\n",
+ YESNO(falloc), YESNO(i_repeat), YESNO(o_dir_in), YESNO(o_dir_out));
/*
fplog(file, "dd_rescue: (info): verbose: %s, quiet: %s\n",
YESNO(verbose), YESNO(quiet));
@@ -1058,34 +1316,72 @@
raise(sig);
}
-int main(int argc, char* argv[])
+unsigned char* zalloc_buf(unsigned int bs)
{
- int c;
- off_t syncsz = -1;
+ unsigned char *ptr;
#ifdef O_DIRECT
void *mp;
+ if (posix_memalign(&mp, pagesize, bs)) {
+ fplog(stderr, "dd_rescue: (fatal): allocation of aligned buffer failed!\n");
+ cleanup(); exit(18);
+ }
+ ptr = mp;
+#else
+ ptr = malloc(bs);
+ if (!ptr) {
+ fplog(stderr, "dd_rescue: (fatal): allocation of buffer failed!\n");
+ cleanup(); exit(18);
+ }
#endif
+ memset(ptr, 0, bs);
+ return ptr;
+}
+
+/** Heuristic: strings starting with - or a digit are numbers, ev.thing else a filename. A pure "-" is a filename. */
+int is_filename(char* arg)
+{
+ if (!arg)
+ return 0;
+ if (!strcmp(arg, "-"))
+ return 1;
+ if (isdigit(arg[0]) || arg[0] == '-')
+ return 0;
+ return 1;
+}
+
+int main(int argc, char* argv[])
+{
+ int c;
+ off_t syncsz = -1;
/* defaults */
softbs = 0; hardbs = 0; /* marker for defaults */
maxerr = 0; ipos = (off_t)-1; opos = (off_t)-1; maxxfer = 0;
reverse = 0; dotrunc = 0; abwrerr = 0; sparse = 0; nosparse = 0;
- verbose = 0; quiet = 0; interact = 0; force = 0; pres = 0;
+ verbose = 0; quiet = 0; interact = 0; force = 0; preserve = 0;
lname = 0; iname = 0; oname = 0; o_dir_in = 0; o_dir_out = 0;
dosplice = 0; falloc = 0;
/* Initialization */
- sxfer = 0; fxfer = 0; lxfer = 0; xfer = 0;
- ides = -1; odes = -1; logfd = 0; nrerr = 0; buf = 0;
+ sxfer = 0; fxfer = 0; lxfer = 0; xfer = 0; axfer = 0;
+ ides = -1; odes = -1; logfd = 0; nrerr = 0; buf = 0; buf2 = 0;
i_chr = 0; o_chr = 0;
+ i_repeat = 0; i_rep_init = 0; i_rep_zero = 0;
+ noextend = 0; avoidwrite = 0;
+ bsim715 = 0; bsim715_4 = 0; bsim715_2ndpass = 0;
+ prng_libc = 0; prng_frnd = 0;
+ prng_seed = 0; prng_sfile = 0;
+ prng_state = 0; prng_state2 = 0;
+
#ifdef _SC_PAGESIZE
pagesize = sysconf(_SC_PAGESIZE);
#endif
- while ((c = getopt(argc, argv, ":rtfihqvVwaAdDkpPb:B:m:e:s:S:l:o:y:")) != -1) {
+ while ((c = getopt(argc, argv, ":rtfihqvVwWaAdDkMRpPb:B:m:e:s:S:l:o:y:z:Z:3:4:")) != -1) {
switch (c) {
case 'r': reverse = 1; break;
+ case 'R': i_repeat = 1; break;
case 't': dotrunc = O_TRUNC; break;
case 'i': interact = 1; force = 0; break;
case 'f': interact = 0; force = 1; break;
@@ -1096,11 +1392,12 @@
#ifdef HAVE_SPLICE
case 'k': dosplice = 1; break;
#endif
- case 'p': pres = 1; break;
+ case 'p': preserve = 1; break;
case 'P': falloc = 1; break;
case 'a': sparse = 1; nosparse = 0; break;
case 'A': nosparse = 1; sparse = 0; break;
case 'w': abwrerr = 1; break;
+ case 'W': avoidwrite = 1; break;
case 'h': printhelp(); exit(0); break;
case 'V': printversion(); exit(0); break;
case 'v': quiet = 0; verbose = 1; break;
@@ -1108,12 +1405,17 @@
case 'b': softbs = (int)readint(optarg); break;
case 'B': hardbs = (int)readint(optarg); break;
case 'm': maxxfer = readint(optarg); break;
+ case 'M': noextend = 1; break;
case 'e': maxerr = (int)readint(optarg); break;
case 'y': syncsz = readint(optarg); break;
case 's': ipos = readint(optarg); break;
case 'S': opos = readint(optarg); break;
case 'l': lname = optarg; break;
case 'o': bbname = optarg; break;
+ case 'z': prng_libc = 1; if (is_filename(optarg)) prng_sfile = optarg; else prng_seed = readint(optarg); break;
+ case 'Z': prng_frnd = 1; if (is_filename(optarg)) prng_sfile = optarg; else prng_seed = readint(optarg); break;
+ case '3': prng_frnd = 1; if (is_filename(optarg)) prng_sfile = optarg; else prng_seed = readint(optarg); bsim715 = 1; break;
+ case '4': prng_frnd = 1; if (is_filename(optarg)) prng_sfile = optarg; else prng_seed = readint(optarg); bsim715 = 1; bsim715_4 = 1; break;
case ':': fplog (stderr, "dd_rescue: (fatal): option %c requires an argument!\n", optopt);
printhelp();
exit(11); break;
@@ -1126,8 +1428,14 @@
}
init_opos = opos;
- if (optind < argc)
+
+ if (prng_libc)
+ iname = "PRNG_libc";
+ else if (prng_frnd)
+ iname = "PRNG_frnd";
+ else if (optind < argc)
iname = argv[optind++];
+
if (optind < argc)
oname = strdup(argv[optind++]);
if (optind < argc) {
@@ -1159,7 +1467,8 @@
else
hardbs = BUF_HARDBLOCKSIZE;
}
- fplog(stderr, "dd_rescue: (info): Using softbs=%lu, hardbs=%lu\n", softbs, hardbs);
+ if (!quiet)
+ fplog(stderr, "dd_rescue: (info): Using softbs=%lu, hardbs=%lu\n", softbs, hardbs);
/* sanity checks */
#ifdef O_DIRECT
@@ -1193,21 +1502,18 @@
if (ipos == (off_t)-1)
ipos = 0;
-#ifdef O_DIRECT
- if (posix_memalign(&mp, pagesize, softbs)) {
- fplog(stderr, "dd_rescue: (fatal): allocation of aligned buffer failed!\n");
- cleanup(); exit(18);
- }
- buf = mp;
-#else
- buf = malloc(softbs);
- if (!buf) {
- fplog(stderr, "dd_rescue: (fatal): allocation of buffer failed!\n");
- cleanup(); exit(18);
+ if (dosplice && avoidwrite) {
+ fplog(stderr, "dd_rescue: (warning): disable write avoidance (-W) for splice copy\n");
+ avoidwrite = 0;
+ }
+ buf = zalloc_buf(softbs);
+
+ /* Optimization: Don't reread from /dev/zero over and over ... */
+ if (!dosplice && !strcmp(iname, "/dev/zero")) {
+ if (!i_repeat && verbose)
+ fplog(stderr, "dd_rescue: (info): turning on repeat (-R) for /dev/zero\n");
+ i_repeat = 1;
}
-#endif
-
- memset(buf, 0, softbs);
/* Special case '.': same as iname (w/o path) */
if (!strcmp(oname, ".")) {
@@ -1238,26 +1544,33 @@
identical = check_identical(iname, oname);
if (identical && dotrunc && !force) {
fplog(stderr, "dd_rescue: (fatal): infile and outfile are identical and trunc turned on!\n");
- cleanup(); exit(19);
+ cleanup(); exit(14);
}
/* Open input and output files */
- ides = openfile(iname, O_RDONLY | o_dir_in);
- if (ides < 0) {
- fplog(stderr, "dd_rescue: (fatal): %s: %s\n", iname, strerror(errno));
- cleanup(); exit(22);
+ if (prng_libc || prng_frnd) {
+ init_random();
+ i_chr = 1; /* ides = 0; */
+ dosplice = 0; sparse = 0;
+ } else {
+ ides = openfile(iname, O_RDONLY | o_dir_in);
+ if (ides < 0) {
+ fplog(stderr, "dd_rescue: (fatal): could not open %s: %s\n", iname, strerror(errno));
+ cleanup(); exit(22);
+ }
}
-
/* Overwrite? */
/* Special case '-': stdout */
if (strcmp(oname, "-"))
odes = open(oname, O_WRONLY | o_dir_out, 0640);
- else
- odes = 0;
+ else {
+ odes = 1;
+ o_chr = 1;
+ }
- if (odes > 0)
+ if (odes > 1)
close(odes);
- if (odes > 0 && interact) {
+ if (odes > 1 && interact) {
int a;
do {
fprintf(stderr, "dd_rescue: (question): %s existing %s [y/n] ?",
@@ -1269,14 +1582,25 @@
cleanup(); exit(23);
}
}
+ if (o_chr && avoidwrite) {
+ fplog(stderr, "dd_rescue: (warning): Disabling -Write avoidance b/c ofile is not seekable\n");
+ avoidwrite = 0;
+ }
+
+ if (odes != 1) {
+ if (avoidwrite) {
+ buf2 = zalloc_buf(softbs);
+ odes = openfile(oname, O_RDWR | O_CREAT | o_dir_out /*| O_EXCL*/ | dotrunc);
+ } else
+ odes = openfile(oname, O_WRONLY | O_CREAT | o_dir_out /*| O_EXCL*/ | dotrunc);
+ }
- odes = openfile(oname, O_WRONLY | O_CREAT | o_dir_out /*| O_EXCL*/ | dotrunc);
if (odes < 0) {
fplog(stderr, "dd_rescue: (fatal): %s: %s\n", oname, strerror(errno));
cleanup(); exit(24);
}
- if (pres)
+ if (preserve)
copyperm(ides, odes);
check_seekable(ides, odes);
@@ -1284,8 +1608,13 @@
sparse_output_warn();
if (o_chr) {
if (!nosparse)
- fprintf(stderr, "dd_rescue: (warning): Don't use sparse writes for non-seekable output\n");
+ fprintf(stderr, "dd_rescue: (warning): Not using sparse writes for non-seekable output\n");
nosparse = 1; sparse = 0; dosplice = 0;
+ if (avoidwrite) {
+ fplog(stderr, "dd_rescue: (warning): Disabling -Write avoidance b/c ofile is not seekable\n");
+ avoidwrite = 0;
+ ZFREE(buf2);
+ }
}
/* special case: reverse with ipos == 0 means ipos = end_of_file */
@@ -1350,15 +1679,18 @@
if (dosplice) {
if (!quiet)
- fplog(stderr, "dd_rescue: (info): splice copy, ignoring -a, -r, -y\n");
+ fplog(stderr, "dd_rescue: (info): splice copy, ignoring -a, -r, -y, -R, -W\n");
reverse = 0;
}
+ if (noextend) {
+ if (output_length() == -1) {
+ fplog(stderr, "dd_rescue: (fatal): asked not to extend output file but can't determine size\n");
+ cleanup(); exit(19);
+ }
+ }
input_length();
-#if 0
- fplog(stderr, "dd_rescue: (info): copy %Li bytes from file %s (%Li) to %s\n",
- estxfer, iname, ilen, oname);
-#endif
+
#ifdef HAVE_FALLOCATE
if (falloc)
do_fallocate();
@@ -1370,6 +1702,14 @@
printinfo(logfd);
}
+ if (bsim715 && avoidwrite) {
+ fplog(stderr, "dd_rescue: (warning): won't avoid writes for -3\n");
+ avoidwrite = 0;
+ }
+ if (bsim715 && o_chr) {
+ fplog(stderr, "dd_rescue: (warning): triple overwrite with non-seekable output!\n");
+ }
+
/* Install signal handler */
signal(SIGHUP , breakhandler);
signal(SIGINT , breakhandler);
@@ -1386,16 +1726,20 @@
printstatus(stderr, 0, softbs, 0);
}
+ if (bsim715) {
+ c = tripleoverwrite(maxxfer);
+ } else {
#ifdef HAVE_SPLICE
- if (dosplice)
- c = copyfile_splice(maxxfer);
- else
+ if (dosplice)
+ c = copyfile_splice(maxxfer);
+ else
#endif
- {
- if (softbs > hardbs)
- c = copyfile_softbs(maxxfer);
- else
- c = copyfile_hardbs(maxxfer);
+ {
+ if (softbs > hardbs)
+ c = copyfile_softbs(maxxfer);
+ else
+ c = copyfile_hardbs(maxxfer);
+ }
}
gettimeofday(¤ttime, NULL);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue/frandom.c new/dd_rescue/frandom.c
--- old/dd_rescue/frandom.c 1970-01-01 01:00:00.000000000 +0100
+++ new/dd_rescue/frandom.c 2013-02-03 17:21:27.000000000 +0100
@@ -0,0 +1,235 @@
+/*
+** frandom.c
+** Fast pseudo-random generator
+**
+** (c) Copyright 2003-2011 Eli Billauer
+** http://www.billauer.co.il
+**
+** 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.
+**
+**
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "frandom.h"
+
+#if defined(__arm__) /* || ... */
+# define INT_IS_FASTER
+/* # warning Using INT */
+#else
+/* # warning Using CHAR */
+#endif
+
+typedef unsigned char u8;
+
+
+struct frandom_state
+{
+ u8 S[256]; /* The state array */
+ u8 i, j;
+};
+
+static struct frandom_state *int_random_state;
+
+static inline void swap_byte(u8 *a, u8 *b)
+{
+ const u8 swapByte = *a;
+ *a = *b;
+ *b = swapByte;
+}
+
+static inline void swap_byte_notmp(u8 *a, u8 *b)
+{
+ *a -= *b;
+ *b += *a;
+ *a = *b - *a;
+}
+
+
+void init_rand_state(struct frandom_state *state, u8* seedbf)
+{
+ unsigned int k;
+ unsigned char i, j;
+ u8 *S;
+ S = state->S;
+ for (k=0; k<256; ++k)
+ *S++ = k;
+
+ j = 0;
+ S = state->S;
+
+ for (k=0; k<256; ++k) {
+ j = (j + S[k] + seedbf[k]) & 0xff;
+ swap_byte(&S[k], &S[j]);
+ }
+
+ /* It's considered good practice to discard the first 256 bytes
+ generated. So we do it:
+ */
+
+ i = 0; j = 0;
+ for (k=0; k<256; ++k) {
+ i = (i + 1);
+ j = (j + S[i]);
+ swap_byte(&S[i], &S[j]);
+ }
+
+ state->i = i; /* Save state */
+ state->j = j;
+}
+
+void* frandom_init(unsigned char* seedbf)
+{
+ struct frandom_state *state;
+
+ state = malloc(sizeof(struct frandom_state));
+ if (!state)
+ return NULL;
+
+ init_rand_state(state, seedbf);
+ if (!int_random_state)
+ int_random_state = state;
+
+ return state; /* Success */
+}
+
+void* frandom_stdup(const void* fst)
+{
+ struct frandom_state *newst = malloc(sizeof(struct frandom_state));
+ if (!newst)
+ return 0;
+ memcpy(newst, fst, sizeof(struct frandom_state));
+ return newst;
+}
+
+void* frandom_stcopy(void* target, const void* fst)
+{
+ memcpy(target, fst, sizeof(struct frandom_state));
+ return target;
+}
+
+static void get_libc_rand_bytes(u8 *buf, size_t len)
+{
+ int *lbuf = (int*)buf;
+ int i;
+ for (i = 0; i < len/sizeof(int); ++i)
+ lbuf[i] = rand();
+}
+
+void* frandom_init_lrand(int seedval)
+{
+ u8 seedbuf[256];
+
+ if (!seedval)
+ seedval = time(0) - getpid();
+ srand(seedval);
+ get_libc_rand_bytes(seedbuf, 256);
+ return frandom_init(seedbuf);
+}
+
+int frandom_release(void* rstate)
+{
+ struct frandom_state *state = rstate;
+ if (!state)
+ state = int_random_state;
+ if (!state)
+ return -ENOMEM;
+
+ free(state);
+ if (state == int_random_state)
+ int_random_state = 0;
+ return 0;
+}
+
+ssize_t frandom_bytes(void *rstate, u8 *buf, size_t count)
+{
+ struct frandom_state *state = rstate;
+ u8 *S;
+#ifdef INT_IS_FASTER
+ unsigned int i, j;
+#else
+ unsigned char i, j;
+#endif
+ const ssize_t ret = count;
+
+ if (!state)
+ state = int_random_state;
+ if (!state)
+ state = frandom_init_lrand(0);
+
+ i = state->i;
+ j = state->j;
+ S = state->S;
+
+ while (count--) {
+#ifdef INT_IS_FASTER
+ i = (i + 1) & 0xff;
+ j = (j + S[i]) & 0xff;
+ swap_byte(&S[i], &S[j]);
+ *buf++ = S[(S[i] + S[j]) & 0xff];
+#else
+ i = i + 1;
+ j = j + S[i];
+ swap_byte(&S[i], &S[j]);
+ *buf++ = S[(unsigned char)(S[i] + S[j])];
+#endif
+ }
+
+ state->i = i;
+ state->j = j;
+
+ return ret;
+}
+
+
+ssize_t frandom_bytes_inv(void *rstate, u8 *buf, size_t count)
+{
+ struct frandom_state *state = rstate;
+ u8 *S;
+#ifdef INT_IS_FASTER
+ unsigned int i, j;
+#else
+ unsigned char i, j;
+#endif
+ const ssize_t ret = count;
+
+ if (!state)
+ state = int_random_state;
+ if (!state)
+ state = frandom_init_lrand(0);
+
+ i = state->i;
+ j = state->j;
+ S = state->S;
+
+ while (count--) {
+#ifdef INT_IS_FASTER
+ i = (i + 1) & 0xff;
+ j = (j + S[i]) & 0xff;
+ swap_byte(&S[i], &S[j]);
+ *buf++ = S[(S[i] + S[j]) & 0xff] ^ 0xff;
+#else
+ i = i + 1;
+ j = j + S[i];
+ swap_byte(&S[i], &S[j]);
+ *buf++ = S[(unsigned char)(S[i] + S[j])] ^ 0xff;
+#endif
+ }
+
+ state->i = i;
+ state->j = j;
+
+ return ret;
+}
+
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dd_rescue/frandom.h new/dd_rescue/frandom.h
--- old/dd_rescue/frandom.h 1970-01-01 01:00:00.000000000 +0100
+++ new/dd_rescue/frandom.h 2013-02-03 14:19:43.000000000 +0100
@@ -0,0 +1,17 @@
+/* Header file for frandom.c */
+
+#ifndef _FRANDOM_H
+#define _FRANDOM_H
+
+#include
+
+/* frandom.c */
+ssize_t frandom_bytes(void *rstate, unsigned char *buf, size_t count);
+ssize_t frandom_bytes_inv(void *rstate, unsigned char *buf, size_t count);
+int frandom_release(void* rstate);
+void* frandom_init_lrand(int seedval);
+void* frandom_init(unsigned char* seedbf);
+void* frandom_stdup(const void* rstate);
+void* frandom_stcopy(void* tostate, const void* fromstate);
+
+#endif
N§²æìržyéZ)z{.±ç(húéì¹»®&Þ¢§²ë¢ž¢¶v+b¢v¥rŠjwlzf¢^ˬyÊ&+~
éi¢§²ë¢ž