Hello community,

here is the log from the commit of package dd_rescue for openSUSE:Factory 
checked in at 2013-02-11 10:59:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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      2013-02-04 
19:29:56.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.dd_rescue.new/dd_rescue.changes 2013-02-11 
10:59:07.000000000 +0100
@@ -1,0 +2,8 @@
+Mon Feb 11 00:15:58 CET 2013 - [email protected]
+
+- Update to dd_rescue-1.32:
+  * New option -x to append to outfile.
+  * New option -Y (can be used multiple times) to specify 2ndary
+    output files.
+
+-------------------------------------------------------------------

Old:
----
  dd_rescue-1.31.tar.gz

New:
----
  dd_rescue-1.32.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dd_rescue.spec ++++++
--- /var/tmp/diff_new_pack.CsfUSS/_old  2013-02-11 10:59:08.000000000 +0100
+++ /var/tmp/diff_new_pack.CsfUSS/_new  2013-02-11 10:59:08.000000000 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           dd_rescue
-Version:        1.31
+Version:        1.32
 Release:        0
 Summary:        Data Copying in the Presence of I/O Errors
 License:        GPL-2.0 or GPL-3.0

++++++ dd_rescue-1.31.tar.gz -> dd_rescue-1.32.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue/Makefile new/dd_rescue/Makefile
--- old/dd_rescue/Makefile      2013-02-03 14:32:29.000000000 +0100
+++ new/dd_rescue/Makefile      2013-02-10 09:12:28.000000000 +0100
@@ -1,8 +1,8 @@
 # Makefile for dd_rescue
 # (c) [email protected], 99/10/09, GNU GPL
-# $Id: Makefile,v 1.46 2013/02/03 13:32:29 garloff Exp $
+# $Id: Makefile,v 1.48 2013/02/10 08:12:28 garloff Exp $
 
-VERSION = 1.31
+VERSION = 1.32
 
 DESTDIR = 
 
@@ -59,7 +59,7 @@
        rm -f *~
 
 dist: distclean
-       tar cvzf ../dd_rescue-$(VERSION).tar.gz -C.. --exclude=$(MYDIR)/CV* 
--exclude $(MYDIR)/dd_rescue2* --exclude $(MYDIR)/.*.sw? $(MYDIR)
+       tar cvzf ../dd_rescue-$(VERSION).tar.gz -C.. --exclude=$(MYDIR)/CV* 
--exclude $(MYDIR)/dd_rescue2* --exclude $(MYDIR)/.* $(MYDIR)
 
 install: $(TARGETS)
        mkdir -p $(INSTALLDIR)
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      2013-02-03 19:05:29.000000000 +0100
+++ new/dd_rescue/README.dd_rescue      2013-02-08 00:59:53.000000000 +0100
@@ -157,6 +157,10 @@
   (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/m07015.html
+* Starting with 1.32, you can write the data to multiple output files
+  at once (option -Y); it can be used more than once.
+  Also, if you want to concatenate data from multiple input files,
+  the option -x (extend/append) may prove useful.
 
 
 Copyright
@@ -199,4 +203,4 @@
 
 
 Kurt Garloff <[email protected]>, 2000-08-30
-$Id: README.dd_rescue,v 1.23 2013/02/03 18:03:26 garloff Exp $
+$Id: README.dd_rescue,v 1.24 2013/02/07 23:59:53 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   2013-02-03 19:05:29.000000000 +0100
+++ new/dd_rescue/dd_rescue.c   2013-02-10 22:37:10.000000000 +0100
@@ -37,7 +37,6 @@
  * - Optional colors
  * - Use dlopen to open libfallocate rather than linking to it ...
  * - Display more infos on errors by collecting info from syslog
- * - Allow seoncdary output file
  */
 
 #ifndef VERSION
@@ -47,7 +46,7 @@
 # define "(unknown compiler)"
 #endif
 
-#define ID "$Id: dd_rescue.c,v 1.149 2013/02/03 18:03:26 garloff Exp $"
+#define ID "$Id: dd_rescue.c,v 1.166 2013/02/10 21:37:10 garloff Exp $"
 
 #ifndef BUF_SOFTBLOCKSIZE
 # define BUF_SOFTBLOCKSIZE 65536
@@ -80,10 +79,12 @@
 #include <signal.h>
 #include <time.h>
 #include <utime.h>
+#include <limits.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 
 #include "frandom.h"
+#include "list.h"
 
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
@@ -140,6 +141,7 @@
 char noextend, avoidwrite;
 char prng_libc, prng_frnd;
 char bsim715, bsim715_4, bsim715_2ndpass;
+char extend;
 char* prng_sfile;
 
 void *prng_state, *prng_state2;
@@ -152,6 +154,19 @@
 
 unsigned int pagesize = 4096;
 
+/* multiple output files */
+typedef struct _ofile {
+       char* name;
+       int fd;
+       char cdev;
+} ofile_t;
+LISTDECL(ofile_t);
+LISTTYPE(ofile_t) *ofiles;
+
+typedef char* charp;
+LISTDECL(charp);
+LISTTYPE(charp) *freenames;
+
 #ifndef UP
 # define UP "\x1b[A"
 # define DOWN "\n"
@@ -254,24 +269,19 @@
        return fdes;
 }
 
-/** Checks whether files are seekable */
-static void check_seekable(const int id, const int od)
+/** Checks whether file is seekable */
+static void check_seekable(const int fd, char *ischr, char* msg)
 {
        errno = 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;
+       if (!*ischr && lseek(fd, (off_t)0, SEEK_SET) != 0) {
+               if (msg) {
+                       fplog(stderr, "dd_rescue: (warning): file %s is not 
seekable!\n", msg);
+                       fplog(stderr, "dd_rescue: (warning): %s\n", 
strerror(errno));
+               }
+               *ischr = 1;
        } //else
        //      lseek(id, (off_t)0, SEEK_SET);
        errno = 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;
-       } //else
-       //      lseek(od, (off_t)0, SEEK_SET);
-       errno = 0;
 }
 
 /** Calc position in graph */
@@ -368,7 +378,8 @@
        if (!quiet)
                fplog(stderr, "dd_rescue: (info): expect to copy %LikB from 
%s\n",
                        estxfer/1024, iname);
-       preparegraph();
+       if (!graph)
+               preparegraph();
 }
 
 int output_length()
@@ -441,22 +452,20 @@
                        fplog(stderr, "dd_rescue: (warning): %s is a block 
device; -a not recommended; -A recommended\n", oname);
                return;
        }
-       eff_opos = opos == -1? ipos: opos;
+       eff_opos = opos == -INT_MAX? ipos: opos;
        if (sparse && (eff_opos < stbuf.st_size))
                fplog(stderr, "dd_rescue: (warning): write into %s (@%li/%li): 
sparse not recommended\n", 
                                oname, eff_opos, stbuf.st_size);
 }
 
 #ifdef HAVE_FALLOCATE
-static void do_fallocate()
+static void do_fallocate(int fd, char* onm)
 {
        struct stat stbuf;
        off_t to_falloc, alloced;
-       if (o_chr)
-               return;
        if (!estxfer)
                return;
-       if (fstat(odes, &stbuf))
+       if (fstat(fd, &stbuf))
                return;
        if (!S_ISREG(stbuf.st_mode))
                return;
@@ -465,13 +474,13 @@
        if (to_falloc <= 0)
                return;
 #ifdef HAVE_LIBFALLOCATE
-       if (linux_fallocate64(odes, FALLOC_FL_KEEP_SIZE, 
+       if (linux_fallocate64(fd, FALLOC_FL_KEEP_SIZE, 
                              opos, to_falloc))
 #else
-       if (fallocate64(odes, 1, opos, to_falloc))
+       if (fallocate64(fd, 1, opos, to_falloc))
 #endif
               fplog(stderr, "dd_rescue: (warning): fallocate %s (%Li, %Li) 
failed: %s\n",
-                              oname, opos, to_falloc, strerror(errno));
+                              onm, opos, to_falloc, strerror(errno));
 }
 #endif
 
@@ -568,8 +577,13 @@
        FILE *report = (!quiet || nrerr)? stderr: 0;
        in_report = 1;
        if (report) {
-               fplog(report, "dd_rescue: (info): Summary for %s -> %s:\n", 
iname, oname);
-               fprintf(report, "%s%s%s%s", down, down, down, down);
+               fplog(report, "dd_rescue: (info): Summary for %s -> %s", iname, 
oname);
+               LISTTYPE(ofile_t) *of;
+               LISTFOREACH(ofiles, of)
+                       fplog(report, "; %s", LISTDATA(of).name);
+               if (logfd > 0)
+                       fprintf(logfd, ":\n");
+               fprintf(report, ":\n%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);
@@ -607,56 +621,65 @@
        return err;
 }
 
-static int mayexpandfile()
-{      
+static int mayexpandfile(char* onm)
+{
        struct stat st;
        off_t maxopos = opos;
        if (init_opos > opos)
                maxopos = init_opos;
-       stat(oname, &st);
+       stat(onm, &st);
        if (!S_ISREG(st.st_mode))
                return 0;
        if (st.st_size < maxopos)
-               return truncate(oname, maxopos);
+               return truncate(onm, maxopos);
        else 
                return 0;               
 }
 
-#define ZFREE(ptr)     \
-       do {            \
-         if(ptr)       \
-           free(ptr);  \
-         ptr = 0;      \
-       } while(0)
-
-int cleanup()
+int sync_close(int fd, char* nm, char chr)
 {
-       int rc, errs = 0;
-       if (odes != -1) {
+       int rc, err = 0;
+       if (fd != -1) {
                /* 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. */
                if (!avoidwrite) 
-                       rc = pwrite(odes, buf, 0, opos);
-               rc = fsync(odes);
-               if (rc && !o_chr) {
+                       rc = pwrite(fd, buf, 0, opos);
+               rc = fsync(fd);
+               if (rc && !chr) {
                        fplog(stderr, "dd_rescue: (warning): fsync %s (%.1fk): 
%s!\n", 
-                             oname, (float)opos/1024, strerror(errno));
-                       ++errs;
+                             nm, (float)opos/1024, strerror(errno));
+                       ++err;
                        errno = 0;
                }
-               rc = close(odes); 
+               rc = close(fd); 
                if (rc) {
                        fplog(stderr, "dd_rescue: (warning): close %s (%.1fk): 
%s!\n", 
-                             oname, (float)opos/1024, strerror(errno));
-                       ++errs;
+                             nm, (float)opos/1024, strerror(errno));
+                       ++err;
                }
-               if (sparse)
-                       rc = mayexpandfile();
+               if (sparse) {
+                       rc = mayexpandfile(nm);
                        if (rc)
                                fplog(stderr, "dd_rescue: (warning): seek %s 
(%1.fk): %s!\n",
-                                     oname, (float)opos/1024, strerror(errno));
+                                     nm, (float)opos/1024, strerror(errno));
+               }
+
        }
+       return err;
+}                       
+
+#define ZFREE(ptr)     \
+       do {            \
+         if (ptr)      \
+           free(ptr);  \
+         ptr = 0;      \
+       } while(0)
+
+int cleanup()
+{
+       int rc, errs = 0;
+       errs += sync_close(odes, oname, o_chr);
        if (ides != -1) {
                rc = close(ides);
                if (rc) {
@@ -667,12 +690,19 @@
        }
        if (logfd)
                fclose(logfd);
+       LISTTYPE(ofile_t) *of;
+       LISTFOREACH(ofiles, of) {
+               ofile_t *oft = &(LISTDATA(of));
+               rc = sync_close(oft->fd, oft->name, oft->cdev);
+       }
        ZFREE(buf2);
        ZFREE(buf);
        ZFREE(graph);
        if (preserve)
                copytimes(iname, oname);
-       ZFREE(oname);
+       LISTFOREACH(ofiles, of)
+               if (preserve)
+                       copytimes(iname, LISTDATA(of).name);
        if (prng_state2) {
                frandom_release(prng_state2);
                prng_state2 = 0;
@@ -681,6 +711,13 @@
                frandom_release(prng_state);
                prng_state = 0;
        }
+       LISTTREEDEL(ofiles, ofile_t);
+       LISTTYPE(charp) *onl;
+       LISTFOREACH(freenames, onl) {
+               free(LISTDATA(onl));
+               LISTDATA(onl) = 0;
+       }
+       LISTTREEDEL(freenames, charp);
        return errs;
 }
 
@@ -784,6 +821,25 @@
                }
                nrerr++;
        }
+       int oldeno = errno;
+       char oldochr = o_chr;
+       LISTTYPE(ofile_t) *of;
+       LISTFOREACH(ofiles, of) {
+               ssize_t e2, w2 = 0;
+               ofile_t *oft = &(LISTDATA(of));
+               o_chr = oft->cdev;
+               do {
+                       w2 += (e2 = mypwrite(oft->fd, buf+w2, towrite-w2, 
opos+w2-reverse*towrite));
+                       if (e2 == -1) 
+                               w2++;
+               } while ((e2 == -1 && (errno == EINTR || errno == EAGAIN))
+                         || (w2 < towrite && e2 > 0 && errno == 0));
+               if (w2 < towrite && e2 != 0) 
+                       fplog(stderr, "dd_rescue: (warning): 2ndary write %s 
(%.1fk): %s\n",
+                             oft->name, (float)opos/1024, strerror(errno));
+       }
+       o_chr = oldochr;
+       errno = oldeno; 
        return (/*err == -1? err:*/ wr);
 }
 
@@ -1059,24 +1115,25 @@
 {
        ssize_t toread;
        int fd_pipe[2];
+       LISTTYPE(ofile_t) *oft;
        if (pipe(fd_pipe) < 0)
                return copyfile_softbs(max);
        while ((toread  = blockxfer(max, softbs)) > 0) {
+               off_t old_ipos = ipos, old_opos = opos;
                ssize_t rd = splice(ides, &ipos, fd_pipe[1], NULL, toread,
                                        SPLICE_F_MOVE | SPLICE_F_MORE);
                if (rd < 0) {
-                       close(fd_pipe[0]); close(fd_pipe[1]);
                        if (!quiet)
                                fplog(stderr, "dd_rescue: (info): %s (%.1fk): 
fall back to userspace copy\n%s%s%s%s", 
                                      iname, (float)ipos/1024, down, down, 
down, down);
+                       close(fd_pipe[0]); close(fd_pipe[1]);
                        return copyfile_softbs(max);
                }
                if (rd == 0) {
                        if (!quiet)
                                fplog(stderr, "dd_rescue: (info): read %s 
(%.1fk): EOF (splice)\n", 
                                      iname, (float)ipos/1024);
-                       close(fd_pipe[0]); close(fd_pipe[1]);
-                       return 0;
+                       break;
                }
                while (rd) {
                        ssize_t wr = splice(fd_pipe[0], NULL, odes, &opos, rd,
@@ -1087,6 +1144,37 @@
                        }
                        rd -= wr; xfer += wr; sxfer += wr;
                }
+               off_t new_ipos = ipos, new_opos = opos;
+               LISTFOREACH(ofiles, oft) {
+                       ipos = old_ipos; opos = old_opos;
+                       rd = splice(ides, &ipos, fd_pipe[1], NULL, toread,
+                                       SPLICE_F_MOVE | SPLICE_F_MORE);
+                       /* Simplify error handling, it worked before ... */
+                       if (rd <= 0) {
+                               fplog(stderr, "dd_rescue: (error): Confused: 
splice() failed unexpectedly: %s\n%s%s%s%s",
+                                       strerror(errno), down, down, down, 
down);
+                               /* We should abort here .... */
+                               ipos = new_ipos; opos = new_opos;
+                               continue;
+                       }
+                       while (rd) {
+                               ssize_t wr = splice(fd_pipe[0], NULL, 
LISTDATA(oft).fd, &opos, rd,
+                                               SPLICE_F_MOVE | SPLICE_F_MORE);
+                               if (wr < 0) {   
+                                       fplog(stderr, "dd_rescue: (error): 
Confused: splice() failed unexpectedly: %s\n%s%s%s%s",
+                                               strerror(errno), down, down, 
down, down);
+                                       /* We should abort here .... */
+                                       ipos = new_ipos; opos = new_opos;
+                                       continue;
+                               }
+                       rd -= wr;
+                       }
+               }
+               if (ipos != new_ipos || opos != new_opos) {
+                       fplog(stderr, "dd_rescue: (error): Confused: splice 
progress inconsistent: %zi %zi %zi %zi\n%s%s%s%s",
+                               ipos, new_ipos, opos, new_opos, down, down, 
down, down);
+                       ipos = new_ipos; opos = new_opos;
+               }       
                advancepos(0, 0);
                if (syncfreq && !(xfer % (syncfreq*softbs)))
                        printstatus((quiet? 0: stderr), 0, softbs, 1);
@@ -1105,11 +1193,14 @@
        void* prng_state2 = frandom_stdup(prng_state);
        clock_t orig_startclock = startclock;
        struct timeval orig_starttime;
+       LISTTYPE(ofile_t) *of;
        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);
+       LISTFOREACH(ofiles, of)
+               fsync(LISTDATA(of).fd);
        /* TODO: better error handling */
        frandom_release(prng_state);
        prng_state = prng_state2; prng_state2 = 0;
@@ -1120,6 +1211,8 @@
        ret += copyfile_softbs(max);
        fprintf(stderr, "syncing ... \n%s", up);
        ret += fsync(odes);
+       LISTFOREACH(ofiles, of)
+               fsync(LISTDATA(of).fd);
        /* TODO: better error handling */
        bsim715_2ndpass = 0;
        if (bsim715_4) {
@@ -1130,6 +1223,8 @@
                ret += copyfile_softbs(max);
                fprintf(stderr, "syncing ... \n%s", up);
                ret += fsync(odes);
+               LISTFOREACH(ofiles, of)
+                       fsync(LISTDATA(of).fd);
                bsim715_2ndpass = 1;
                iname = "FRND+invFRND+FRND2+ZERO";
        } else
@@ -1191,7 +1286,7 @@
                                fplog(stderr, "dd_rescue: (fatal): failed to 
read 4 bytes from \"%s\"!\n", prng_sfile);
                                cleanup(); exit(29);
                        }
-                       srand(*sval);
+                       srand(*sval); rand();
                } else {
                        ln = read(fd, sbf, 256);
                        if (ln != 256) {
@@ -1202,10 +1297,10 @@
                }
        } else {
                if (!prng_seed)
-                       prng_seed = time(0) - getpid();
-               if (prng_libc)
-                       srand(prng_seed);
-               else
+                       prng_seed = frandom_getseedval();
+               if (prng_libc) {
+                       srand(prng_seed); rand();
+               } else
                        prng_state = frandom_init_lrand(prng_seed);
        }
 }
@@ -1245,6 +1340,7 @@
        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, "         -x         count opos from the end of outfile 
(eXtend)\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");
@@ -1267,12 +1363,13 @@
        fprintf(stderr, "         -i         interactive: ask before 
overwriting data (def=no),\n");
        fprintf(stderr, "         -f         force: skip some sanity checks 
(def=no),\n");
        fprintf(stderr, "         -p         preserve: preserve ownership / 
perms (def=no),\n");
+       fprintf(stderr, "         -Y oname   Secondary output file (multiple 
possible)\n");
        fprintf(stderr, "         -q         quiet operation,\n");
        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, " from libc or frandom (RC4 based) as input. SEED = 0 
means a time based seed;\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");
@@ -1348,7 +1445,53 @@
                return 0;
        return 1;
 }
-       
+
+char* retstrdupcat3(const char* dir, char dirsep, const char* inm)
+{
+       const char* ibase = basename(inm);
+       const int dlen = strlen(dir) + (dirsep>0? 1: dirsep);
+       char* ret = malloc(dlen + strlen(inm) + 1);
+       strcpy(ret, dir);
+       if (dirsep > 0) {
+               ret[dlen-1] = dirsep;
+               ret[dlen] = 0;
+       }
+       strcpy(ret+dlen, ibase);
+       LISTAPPEND(freenames, ret, charp);
+       return ret;
+}
+               
+
+/** Fix output filename if it's a directory */
+char* dirappfile(char* onm)
+{
+       size_t oln = strlen(onm);
+       if (!strcmp(onm, ".")) {
+               char* ret = strdup(basename(iname));
+               LISTAPPEND(freenames, ret, charp);
+               return ret;
+       }
+       if (oln > 0) {
+               char lastchr = onm[oln-1];
+               if (lastchr == '/') 
+                       return retstrdupcat3(onm, 0, iname);
+               else if ((lastchr == '.') &&
+                         (oln > 1 && onm[oln-2] == '/'))
+                       return retstrdupcat3(onm, -1, iname);
+               else if ((lastchr == '.') &&
+                          (oln > 2 && onm[oln-2] == '.' && onm[oln-3] == '/'))
+                       return retstrdupcat3(onm, '/', iname);
+               else { /* Not clear by name, so test */
+                       struct stat stbuf;
+                       int err = stat(onm, &stbuf);
+                       if (!err && S_ISDIR(stbuf.st_mode))
+                               return retstrdupcat3(onm, '/', iname);
+               }
+       }
+       return onm;
+}
+
+
 int main(int argc, char* argv[])
 {
        int c;
@@ -1356,7 +1499,7 @@
 
        /* defaults */
        softbs = 0; hardbs = 0; /* marker for defaults */
-       maxerr = 0; ipos = (off_t)-1; opos = (off_t)-1; maxxfer = 0; 
+       maxerr = 0; ipos = (off_t)-INT_MAX; opos = (off_t)-INT_MAX; maxxfer = 
0; 
        reverse = 0; dotrunc = 0; abwrerr = 0; sparse = 0; nosparse = 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;
@@ -1370,15 +1513,18 @@
        i_repeat = 0; i_rep_init = 0; i_rep_zero = 0;
        noextend = 0; avoidwrite = 0;
        bsim715 = 0; bsim715_4 = 0; bsim715_2ndpass = 0;
+       extend = 0;
        prng_libc = 0; prng_frnd = 0;
        prng_seed = 0; prng_sfile = 0;
        prng_state = 0; prng_state2 = 0;
 
+       ofiles = NULL;
+
 #ifdef _SC_PAGESIZE
        pagesize = sysconf(_SC_PAGESIZE);
 #endif
 
-       while ((c = getopt(argc, argv, 
":rtfihqvVwWaAdDkMRpPb:B:m:e:s:S:l:o:y:z:Z:3:4:")) != -1) {
+       while ((c = getopt(argc, argv, 
":rtfihqvVwWaAdDkMRpPb:B:m:e:s:S:l:o:y:z:Z:3:4:xY:")) != -1) {
                switch (c) {
                        case 'r': reverse = 1; break;
                        case 'R': i_repeat = 1; break;
@@ -1412,6 +1558,8 @@
                        case 'S': opos = readint(optarg); break;
                        case 'l': lname = optarg; break;
                        case 'o': bbname = optarg; break;
+                       case 'x': extend = 1; break;
+                       case 'Y': do { ofile_t of; of.name = optarg; of.fd = 
-1; of.cdev = 0; LISTAPPEND(ofiles, of, ofile_t); } while (0); 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;
@@ -1437,7 +1585,7 @@
                iname = argv[optind++];
 
        if (optind < argc) 
-               oname = strdup(argv[optind++]);
+               oname = argv[optind++];
        if (optind < argc) {
                fplog(stderr, "dd_rescue: (fatal): spurious options: %s ...\n", 
argv[optind]);
                printhelp();
@@ -1499,7 +1647,7 @@
                syncfreq = (syncsz + softbs - 1) / softbs;
 
        /* Have those been set by cmdline params? */
-       if (ipos == (off_t)-1) 
+       if (ipos == (off_t)-INT_MAX) 
                ipos = 0;
 
        if (dosplice && avoidwrite) {
@@ -1515,33 +1663,11 @@
                i_repeat = 1;
        }
 
-       /* Special case '.': same as iname (w/o path) */
-       if (!strcmp(oname, ".")) {
-               free(oname);
-               oname = strdup(basename(iname));
-       } else { /* Is oname a directory? */
-               size_t oln = strlen(oname);
-               if (oln > 0) {
-                       char lastchr = oname[oln-1];
-                       if (lastchr == '/')
-                               oname = safe_strcat(oname, basename(iname));
-                       else if ((lastchr == '.') &&
-                                 ((oln > 1 && oname[oln-2] == '/') ||
-                                  (oln > 2 && oname[oln-2] == '.' && 
oname[oln-3] == '/'))) {
-                                       oname = safe_strcat(oname, "/");
-                                       oname = safe_strcat(oname, 
basename(iname));
-                       } else { /* Not clear by name, so test */
-                               struct stat stbuf;
-                               int err = stat(oname, &stbuf);
-                               if (!err && S_ISDIR(stbuf.st_mode)) {
-                                       oname = safe_strcat(oname, "/");
-                                       oname = safe_strcat(oname, 
basename(iname));
-                               }
-                       }
-               }
-       }
+       /* Properly append input basename if output name is dir */
+       oname = dirappfile(oname);
 
        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(14);
@@ -1603,7 +1729,8 @@
        if (preserve)
                copyperm(ides, odes);
                        
-       check_seekable(ides, odes);
+       check_seekable(ides, &i_chr, "input");
+       check_seekable(odes, &o_chr, "output");
 
        sparse_output_warn();
        if (o_chr) {
@@ -1628,7 +1755,7 @@
                        fprintf(stderr, "dd_rescue: (info): ipos set to the 
end: %.1fk\n", 
                                (float)ipos/1024);
                /* if opos not set, assume same position */
-               if (opos == (off_t)-1) 
+               if (opos == (off_t)-INT_MAX) 
                        opos = ipos;
                /* if explicitly set to zero, assume end of _existing_ file */
                if (opos == 0) {
@@ -1647,15 +1774,9 @@
        }
 
        /* if opos not set, assume same position */
-       if (opos == (off_t)-1) 
+       if (opos == (off_t)-INT_MAX)
                opos = ipos;
 
-       if (ipos < 0 || opos < 0) {
-               fplog(stderr, "dd_rescue: (fatal): negative position requested 
(%.1fk)\n", (float)ipos/1024);
-               cleanup(); exit(25);
-       }
-
-
        if (identical) {
                fplog(stderr, "dd_rescue: (warning): infile and outfile are 
identical!\n");
                if (opos > ipos && !reverse && !force) {
@@ -1683,17 +1804,25 @@
                reverse = 0;
        }
 
-       if (noextend) {
+       if (noextend || extend) {
                if (output_length() == -1) {
-                       fplog(stderr, "dd_rescue: (fatal): asked not to extend 
output file but can't determine size\n");
+                       fplog(stderr, "dd_rescue: (fatal): asked to (not) 
extend output file but can't determine size\n");
                        cleanup(); exit(19);
                }
+               if (extend)
+                       opos += olen;
        }
        input_length();
 
+       if (ipos < 0 || opos < 0) {
+               fplog(stderr, "dd_rescue: (fatal): negative position requested 
(%.1fk)\n", (float)ipos/1024);
+               cleanup(); exit(25);
+       }
+
+
 #ifdef HAVE_FALLOCATE
-       if (falloc)
-               do_fallocate();
+       if (falloc && !o_chr)
+               do_fallocate(odes, oname);
 #endif
 
        if (verbose) {
@@ -1710,6 +1839,24 @@
                fplog(stderr, "dd_rescue: (warning): triple overwrite with 
non-seekable output!\n");
        }
 
+       LISTTYPE(ofile_t) *of;
+       LISTFOREACH(ofiles, of) {
+               int id;
+               ofile_t *oft = &(LISTDATA(of));
+               oft->name = dirappfile(oft->name);
+               id = check_identical(iname, oft->name);
+               if (id)
+                       fplog(stderr, "dd_rescue: (warning): Input file and 
secondary output file %s are identical!\n", oft->name);
+               oft->fd = openfile(oft->name, (avoidwrite? O_RDWR: O_WRONLY) | 
O_CREAT | o_dir_out | dotrunc);
+               check_seekable(oft->fd, &(oft->cdev), NULL);
+               if (preserve)
+                       copyperm(ides, oft->fd);
+#ifdef HAVE_FALLOCATE
+               if (falloc && !oft->cdev)
+                       do_fallocate(oft->fd, oft->name);
+#endif
+       }
+
        /* Install signal handler */
        signal(SIGHUP , breakhandler);
        signal(SIGINT , breakhandler);
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     2013-02-03 17:21:27.000000000 +0100
+++ new/dd_rescue/frandom.c     2013-02-10 09:06:41.000000000 +0100
@@ -19,6 +19,7 @@
 #include <asm/errno.h>
 #include <unistd.h>
 #include <time.h>
+#include <sys/time.h>
 
 #include "frandom.h"
 
@@ -125,13 +126,21 @@
                lbuf[i] = rand();
 }
 
+unsigned int frandom_getseedval()
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return (tv.tv_usec << 12) ^ tv.tv_sec ^ getpid();
+}
+
+
 void* frandom_init_lrand(int seedval)
 {
        u8 seedbuf[256];
 
        if (!seedval)
-               seedval = time(0) - getpid();
-       srand(seedval);
+               seedval = frandom_getseedval();
+       srand(seedval); rand();
        get_libc_rand_bytes(seedbuf, 256);
        return frandom_init(seedbuf);
 }
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     2013-02-03 14:19:43.000000000 +0100
+++ new/dd_rescue/frandom.h     2013-02-05 10:44:11.000000000 +0100
@@ -13,5 +13,6 @@
 void* frandom_init(unsigned char* seedbf);
 void* frandom_stdup(const void* rstate);
 void* frandom_stcopy(void* tostate, const void* fromstate);
+unsigned int frandom_getseedval();
 
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue/list.h new/dd_rescue/list.h
--- old/dd_rescue/list.h        1970-01-01 01:00:00.000000000 +0100
+++ new/dd_rescue/list.h        2013-02-06 11:37:25.000000000 +0100
@@ -0,0 +1,96 @@
+/** list.h 
+ * C version of linked lists
+ * (ab)uing macros ...
+ */
+
+#ifndef _LIST_H_
+#define _LIST_H
+
+#include <stdlib.h>
+
+#define LISTDECL(type)                         \
+struct _list_##type {                  \
+       struct _list_##type *next;      \
+       type data;                      \
+}
+
+
+#define LISTTYPE(type) struct _list_##type
+#define LISTNEXT(x) x->next
+#define LISTDATA(x) x->data
+
+#define LISTINSAFTER(l, x, type) do {                  \
+       struct _list_##type *newel = malloc(sizeof(struct _list_##type));       
\
+       newel->data = x;                                \
+       if (l) {                                        \
+               newel->next = l->next;                  \
+               l->next = newel;                        \
+       } else {                                        \
+               l = newel;                              \
+               newel->next = 0;                        \
+       }                                               \
+       } while(0)
+
+#define LISTINSBEFORE(lh, x, type) do {                        \
+       struct _list_##type *newel = malloc(sizeof(struct _list_##type));       
\
+       newel->data = x;                                \
+       newel->next = lh;                               \
+       lh = newel;                                     \
+       } while (0)
+
+#define LISTAPPEND(lh, x, type) do {           \
+       struct _list_##type *newel = malloc(sizeof(struct _list_##type));       
\
+       newel->data = x; newel->next = 0;       \
+       if (!lh)                                \
+               lh = newel;                     \
+       else {                                  \
+               struct _list_##type *el = lh;   \
+               while(el->next)                 \
+                       el = el->next;          \
+               el->next = newel;               \
+       }                                       \
+       } while (0)
+
+#define LISTDELNEXT(l, type)   do {            \
+       struct _list_##type *_nxt = l->next;    \
+       if (l->next) {                          \
+               l->next = l->next->next;        \
+               free(_nxt);                     \
+       } else {                                \
+               free(l);                        \
+               l = 0;                          \
+       } } while(0)
+
+#define LISTDEL(lh,type) do {                  \
+       struct _list_##type *_nxt = lh->next;   \
+       free(lh);                               \
+       lh = _nxt;                              \
+       } while (0)
+
+#define LISTTREEDEL(lh, type) do {             \
+       while (lh) {                            \
+               LISTDEL(lh, type);              \
+       }                                       \
+       lh = 0;                                 \
+       } while (0)
+
+#define LISTFOREACH(lh, x)                     \
+       for (x = lh; x; x = x->next)
+
+#ifdef __GNUC__
+#define LISTEL(lh, no, type) ({                        \
+       int _i = 0;                             \
+       struct _list_##type *el;                \
+       for (el = lh; el; ++_i, el = el->next)  \
+               if (_i == no) break;            \
+       el; })
+#define LISTSIZE(lh,type) ({                   \
+       struct _list_##type *el;                \
+       int _i = 0;                             \
+       for (el = lh; el; ++_i, el = el->next); \
+       _i; })
+#else
+/* TODO: create static inline functions ... */
+#endif
+
+#endif

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to