Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package dd_rescue for openSUSE:Factory 
checked in at 2026-11-03 17:51:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dd_rescue (Old)
 and      /work/SRC/openSUSE:Factory/.dd_rescue.new.1257 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "dd_rescue"

Tue Nov  3 17:51:24 2026 rev:70 rq:1394337 version:1.99.25

Changes:
--------
--- /work/SRC/openSUSE:Factory/dd_rescue/dd_rescue.changes      2026-10-20 
12:36:17.970447372 +0200
+++ /work/SRC/openSUSE:Factory/.dd_rescue.new.1257/dd_rescue.changes    
2026-11-03 17:51:27.041001006 +0100
@@ -1,0 +2,18 @@
+Tue Oct 27 09:48:06 CET 2026 - [email protected]
+
+- Update to dd_rescue-1.99.25:
+  * Another edge testcase (unaligned with hardbs = softbs). 
+  * Fix for this edge case.
+  * Improve buffer allocation to ensure alignment to cache line or
+    page size (for direct IO) even when plugins want space in front
+    of buffer (slack_pre).
+  * Increase frequency of status updates when using larger default
+    softbs with direct IO.
+  * More conservative (better) initial duration estimates.
+  * Add test case from Thomas Deutschmann, where odd offsets would
+    result on not getting progress updates.
+  * Fix by reducing granularity of offset checks.
+- Drop dd_rescue-ssp-strong.patch, as we no longer have a special
+  make rule that would override the flags. 
+
+-------------------------------------------------------------------

Old:
----
  dd_rescue-1.99.24.tar.bz2
  dd_rescue-1.99.24.tar.bz2.asc
  dd_rescue-ssp-strong.patch

New:
----
  dd_rescue-1.99.25.tar.bz2
  dd_rescue-1.99.25.tar.bz2.asc

----------(Old B)----------
  Old:  * Fix by reducing granularity of offset checks.
- Drop dd_rescue-ssp-strong.patch, as we no longer have a special
  make rule that would override the flags. 
----------(Old E)----------

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

Other differences:
------------------
++++++ dd_rescue.spec ++++++
--- /var/tmp/diff_new_pack.QnUe1z/_old  2026-11-03 17:51:28.039042723 +0100
+++ /var/tmp/diff_new_pack.QnUe1z/_new  2026-11-03 17:51:28.041042807 +0100
@@ -21,7 +21,7 @@
 %define _lto_cflags %{nil}
 %endif
 Name:           dd_rescue
-Version:        1.99.24
+Version:        1.99.25
 Release:        0
 Summary:        Data copying in the presence of I/O Errors
 License:        GPL-2.0-only OR GPL-3.0-only
@@ -30,10 +30,6 @@
 Source1:        
https://garloff.de/kurt/linux/ddrescue/%{name}-%{version}.tar.bz2.asc
 Source2:        %{name}.keyring
 Source99:       %{name}.changes
-# PATCH-FIX-OPENSUSE dd_rescue-ssp-strong.patch -- the libddr_lzo.po rule
-# appends basic -fstack-protector which downgrades the distro
-# -fstack-protector-strong from %%optflags; use strong instead
-Patch0:         dd_rescue-ssp-strong.patch
 BuildRequires:  lzop
 BuildRequires:  pkgconfig
 BuildRequires:  python3-base

++++++ dd_rescue-1.99.24.tar.bz2 -> dd_rescue-1.99.25.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.24/Makefile 
new/dd_rescue-1.99.25/Makefile
--- old/dd_rescue-1.99.24/Makefile      2026-10-09 14:15:02.000000000 +0200
+++ new/dd_rescue-1.99.25/Makefile      2026-10-18 08:13:36.546884414 +0200
@@ -1,7 +1,7 @@
 # (c) [email protected], 99/10/09, GNU GPL
 # (c) [email protected], 2010 -- 2021, GNU GPL v2 or v3
 
-VERSION = 1.99.24
+VERSION = 1.99.25
 
 DESTDIR = 
 THISMKFILE := $(lastword $(MAKEFILE_LIST))
@@ -9,7 +9,7 @@
 
 CC = gcc
 SHELL := bash
-RPM_OPT_FLAGS ?= -Os -Wall -g -D_FORTIFY_SOURCE=3
+RPM_OPT_FLAGS ?= -Os -Wall -g -D_FORTIFY_SOURCE=3 -fstack-protector
 CFLAGS = $(RPM_OPT_FLAGS) $(EXTRA_CFLAGS) -DHAVE_CONFIG_H -I .
 CFLAGS_OPT = $(CFLAGS) -O3
 INSTALL ?= install
@@ -337,10 +337,6 @@
 %.s: $(SRCDIR)/%.c config.h
        $(CC) $(CFLAGS) $(DEFINES) $(PIE) -S $<
 
-# Use stack protector for libddr_lzo ...
-libddr_lzo.po: $(SRCDIR)/libddr_lzo.c config.h
-       $(CC) $(CFLAGS) $(PIC) -fstack-protector -o $@ -c $<
-
 # The plugins
 libddr_hash.so: libddr_hash.po md5.po sha256.po $(SHAPOBJ) sha512.po sha1.po 
pbkdf2.po checksum_file.po
        $(CC) -shared -o $@ $^ $(EXTRA_LDFLAGS)
@@ -579,6 +575,10 @@
        $(INSTALL) $(INSTASROOT) -m 644 $(SRCDIR)/dd_rescue.1 
$(SRCDIR)/ddr_lzo.1 $(SRCDIR)/ddr_crypt.1 $(SRCDIR)/ddr_lzma.1 $(MANDIR)/man1/
        gzip -9f $(MANDIR)/man1/dd_rescue.1 $(MANDIR)/man1/ddr_lzo.1 
$(MANDIR)/man1/ddr_crypt.1 $(MANDIR)/man1/ddr_lzma.1
 
+.PHONY: check_progress
+check_progress: dd_rescue
+       bash $(SRCDIR)/test_progress.sh ./dd_rescue
+
 check: $(TARGETS) find_nonzero md5 sha1 sha256 sha512 fmt_no
        @echo "make check ... Pass VG=\"valgrind --options\" to use with 
valgrind"
        $(VG) ./dd_rescue --version
@@ -625,6 +625,7 @@
        @echo "***** dd_rescue ratecontrol test *****"
        # Test system must be fast enough to achieve ~20MB/s ...
        OLDDT=`date +%s`; $(VG) ./dd_rescue -m 64M -C 20M /dev/zero /dev/null; 
DT=`date +%s`; ARCH=$$(uname -m); test $$(($$DT-$$OLDDT)) = 3 -o 
$$(($$DT-$$OLDDT)) = 4 || test $$(($$DT-$$OLDDT)) -ge 5 -a $${ARCH:0:3} = ppc
+       $(MAKE) check_progress
        @echo "***** dd_rescue MD5 plugin tests *****"
        $(VG) ./md5 /dev/null
        $(VG) ./md5 /dev/null | md5sum -c
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.24/README.dd_rescue 
new/dd_rescue-1.99.25/README.dd_rescue
--- old/dd_rescue-1.99.24/README.dd_rescue      2026-10-09 12:43:34.000000000 
+0200
+++ new/dd_rescue-1.99.25/README.dd_rescue      2026-10-18 00:02:10.911059737 
+0200
@@ -243,6 +243,8 @@
   reflected in the exit code. It also fixes the positioning when overlapping
   copies are detected and the copy direction is changed.
 * 1.99.24 brings docu improvement and fine-tuning on remaining time estimates.
+* 1.99.25 fixes missing progress reports when starting with off offsets.
+  Thanks to Thomas Deutschmann for the report, testcase and fix inspiration.
 
 
 Building
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.24/REL-ID new/dd_rescue-1.99.25/REL-ID
--- old/dd_rescue-1.99.24/REL-ID        2026-10-09 14:46:34.000000000 +0200
+++ new/dd_rescue-1.99.25/REL-ID        2026-10-18 23:13:17.950495138 +0200
@@ -1 +1 @@
-DD_RESCUE_1_99_24
+DD_RESCUE_1_99_25
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.24/dd_rescue.1 
new/dd_rescue-1.99.25/dd_rescue.1
--- old/dd_rescue-1.99.24/dd_rescue.1   2026-10-09 11:31:52.000000000 +0200
+++ new/dd_rescue-1.99.25/dd_rescue.1   2026-10-17 23:59:16.835772574 +0200
@@ -1065,6 +1065,8 @@
 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.
 .PP
 Some additional information can be found on
 .br
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.24/dd_rescue.c 
new/dd_rescue-1.99.25/dd_rescue.c
--- old/dd_rescue-1.99.24/dd_rescue.c   2026-10-09 13:48:33.000000000 +0200
+++ new/dd_rescue-1.99.25/dd_rescue.c   2026-10-18 21:06:17.692183474 +0200
@@ -254,12 +254,13 @@
 
 
 /* Globals, shadowing opts/fstate info */
-char nocol;
-static unsigned int pagesize;
+int pagesize;
+short cachelinesize;
 
+char nocol;
+char in_report;
 /* Rate limit for status updates */
 const float printint = 0.1;
-char in_report;
 
 FILE *logfd;
 int ddr_loglevel = 2;
@@ -492,6 +493,13 @@
        }
        assert(slk_pre  == plug_max_slack_pre );
        assert(slk_post == plug_max_slack_post);
+       /* Align real start */
+       if (op->o_dir_in || op->o_dir_out)
+               plug_max_slack_pre = 
((plug_max_slack_pre+pagesize-1)/pagesize)*pagesize;
+       else
+               plug_max_slack_pre = 
((plug_max_slack_pre+cachelinesize-1)/cachelinesize)*cachelinesize;
+       if (plug_max_slack_pre)
+               fplog(stderr, DEBUG, "Plugins: Reserve %i bytes before 
buffer\n", plug_max_slack_pre);
 }
 
 int call_plugins_close(opt_t *op, fstate_t *fst)
@@ -1123,7 +1131,7 @@
 {
        static unsigned int ctr = 0;
        /* 1+ is there to avoid div by zero, difftimevtv also never returns 
zero */
-       float avgrate = (float)(1+prg->xfer)/t1;
+       float avgrate = (float)(1+prg->xfer)/(t1+0.1);
        float currate = (float)(1+prg->xfer-prg->lxfer)/t2;
        const char *bold = BOLD, *norm = NORM;
        /* We have two different moving averages
@@ -2397,6 +2405,7 @@
                        return errs;
                }
 #ifdef HAVE___BUILTIN_PREFETCH
+               /* Note: This assumes 64B cachelines */
                if (rd >= 512 && !eno) {
                        __builtin_prefetch(fst->buf,     0, 2);
                        __builtin_prefetch(fst->buf+64,  0, 2);
@@ -2485,14 +2494,16 @@
                }
 
                errno = 0;
+               const int upds = (updstat >= 2 && op->hardbs < op->softbs)? 
updstat/2: updstat;
+               const int syfr = (op->syncfreq >= 2 && op->hardbs < 
op->softbs)? op->syncfreq/2: op->syncfreq;
                /* If we sync regularly, let's print a status update on each 
sync */
-               if (op->syncfreq && !(fst->ipos % (op->syncfreq*op->softbs/2)))
+               if (op->syncfreq && !(fst->ipos/op->softbs % syfr))
                        printstatus((op->quiet? 0: stderr), 0, op->hardbs, 1, 
op, fst, prg, dop);
                /* else print regularly acc. to updstat if not quiet */
-               else if (!op->quiet && !(prg->xfer % (updstat*op->softbs/2)))
+               else if (!op->quiet && !(prg->xfer/op->softbs % upds))
                        printstatus(stderr, 0, op->hardbs, 0, op, fst, prg, 
dop);
                /* even if quiet, we need to call the printstatus if we do rate 
limiting */
-               else if (op->quiet && op->maxkbs && !(prg->xfer % 
(updstat*op->softbs/2)))
+               else if (op->quiet && op->maxkbs && !(prg->xfer/op->softbs % 
upds))
                        printstatus(0, 0, op->hardbs, 0, op, fst, prg, dop);
        } /* remain */
        return errs;
@@ -2548,6 +2559,7 @@
                        return errs;
                }
 #ifdef HAVE___BUILTIN_PREFETCH
+               /* Note: This assumes 64B cachelines */
                if (rd >= 512 && !eno) {
                        __builtin_prefetch(fst->buf,     0, 2);
                        __builtin_prefetch(fst->buf+64,  0, 2);
@@ -2630,13 +2642,13 @@
 
                errno = 0;
                /* If we sync regularly, let's print a status update on each 
sync */
-               if (op->syncfreq && !(fst->ipos % (op->syncfreq*op->softbs)))
+               if (op->syncfreq && !(fst->ipos/op->softbs % op->syncfreq))
                        printstatus((op->quiet? 0: stderr), 0, op->softbs, 1, 
op, fst, prg, dop);
                /* else print regularly acc. to updstat if not quiet */
-               else if (!op->quiet && !(prg->xfer % (updstat*op->softbs)))
+               else if (!op->quiet && !(prg->xfer/op->softbs % updstat))
                        printstatus(stderr, 0, op->softbs, 0, op, fst, prg, 
dop);
                /* even if quiet, we need to call the printstatus if we do rate 
limiting */
-               else if (op->quiet && op->maxkbs && !(prg->xfer % 
(updstat*op->softbs)))
+               else if (op->quiet && op->maxkbs && !(prg->xfer/op->softbs % 
updstat))
                        printstatus(0, 0, op->softbs, 0, op, fst, prg, dop);
        } /* remain */
        return errs;
@@ -2712,11 +2724,11 @@
                        fst->ipos = new_ipos; fst->opos = new_opos;
                }       
                advancepos(0, 0, 0, op, fst, prg);
-               if (op->syncfreq && !(prg->xfer % (op->syncfreq*op->softbs)))
+               if (op->syncfreq && !(prg->xfer/op->softbs % op->syncfreq))
                        printstatus((op->quiet? 0: stderr), 0, op->softbs, 1, 
op, fst, prg, dop);
-               else if (!op->quiet && !(prg->xfer % (updstat*op->softbs)))
+               else if (!op->quiet && !(prg->xfer/op->softbs % updstat))
                        printstatus(stderr, 0, op->softbs, 0, op, fst, prg, 
dop);
-               else if (op->quiet && op->maxkbs && !(prg->xfer % 
(updstat*op->softbs)))
+               else if (op->quiet && op->maxkbs && !(prg->xfer/op->softbs % 
updstat))
                        printstatus(0, 0, op->softbs, 0, op, fst, prg, dop);
        }
        close(fd_pipe[0]); close(fd_pipe[1]);
@@ -3048,6 +3060,8 @@
              YESNO(op->preserve), YESNO(op->dosplice), YESNO(op->avoidwrite));
        fplog(file, DEBUG, "fallocate: %s, Repeat: %s, O_DIRECT: %s/%s\n",
              YESNO(op->falloc), YESNO(op->i_repeat), YESNO(op->o_dir_in), 
YESNO(op->o_dir_out));
+       fplog(file, DEBUG, "pagesize: %i, cachelinesize: %i\n",
+             pagesize, cachelinesize);
        /*
        fplog(file, DEBUG, "verbose: %s, quiet: %s\n", 
              YESNO(op->verbose), YESNO(op->quiet));
@@ -3076,9 +3090,12 @@
              sig, strsignal(sig));
 }
 
-unsigned char* zalloc_aligned_buf(unsigned int bs, unsigned char**obuf)
+unsigned char* zalloc_aligned_buf(size_t bs, unsigned char**obuf)
 {
        unsigned char *ptr = 0;
+       if (bs < 512)
+               bs = 512;
+       const size_t to_alloc = bs + plug_max_slack_pre + plug_max_slack_post;
        /*
        fplog(stderr, DEBUG, "allocate zeroed aligned buffer with %i+%i+%i 
bytes\n",
                bs, plug_max_slack_pre, plug_max_slack_post);
@@ -3088,23 +3105,24 @@
 #ifndef HAVE_VALLOC_DECL
        void* valloc(size_t sz);
 #endif
-       ptr = plug_max_slack_pre%pagesize? 0: (unsigned char*)valloc(bs + 
plug_max_slack_pre + plug_max_slack_post);
+       ptr = plug_max_slack_pre%pagesize? 0: (unsigned char*)valloc(to_alloc);
 #elif defined(HAVE_POSIX_MEMALIGN)
        void *mp;
-       if (plug_max_slack_pre%pagesize || posix_memalign(&mp, pagesize, bs + 
plug_max_slack_pre + plug_max_slack_post))
+       if (plug_max_slack_pre%pagesize || posix_memalign(&mp, pagesize, 
to_alloc))
                ptr = 0;
        else
                ptr = (unsigned char*)mp;
-#endif /* NetBSD */
+#endif /* VALLOC (NetBSD) */
        if (obuf) 
                *obuf = ptr;
        if (!ptr) {
                if (0 == plug_max_slack_pre%pagesize)
-                       fplog(stderr, WARN, "allocation of aligned buffer 
failed -- use malloc\n");
-               ptr = (unsigned char*)malloc(bs + pagesize + plug_max_slack_pre 
+ plug_max_slack_post);
+                       fplog(stderr, WARN, "allocation of aligned buffer of 
size %zi failed -- use malloc\n",
+                             to_alloc);
+               ptr = (unsigned char*)malloc(to_alloc + pagesize);
                if (!ptr) {
-                       fplog(stderr, FATAL, "allocation of buffer of size %li 
failed!\n", 
-                               
bs+pagesize+plug_max_slack_pre+plug_max_slack_post);
+                       fplog(stderr, FATAL, "allocation of buffer of size %zi 
failed!\n", 
+                             to_alloc+pagesize);
                        cleanup(1); exit(18);
                }
                if (obuf)
@@ -3113,7 +3131,7 @@
                ptr -= (unsigned long)ptr % pagesize;
        } else
                ptr += plug_max_slack_pre;
-       memset(ptr-plug_max_slack_pre, 0, 
bs+plug_max_slack_pre+plug_max_slack_post);
+       memset(ptr-plug_max_slack_pre, 0, to_alloc);
        return ptr;
 }
 
@@ -3250,13 +3268,26 @@
        nocol = op->nocol;
 
 #ifdef _SC_PAGESIZE
-       op->pagesize = sysconf(_SC_PAGESIZE);
+       pagesize = sysconf(_SC_PAGESIZE);
+       if (pagesize <= 0) {
+               fplog(stderr, WARN, "Could not determine pagesize, using 4k\n");
+               pagesize = 4096;
+       }
 #else
 #warning Cant determine pagesize, setting to 4kiB
-       op->pagesize = 4096;
+       pagesize = 4096;
+#endif
+       op->pagesize = pagesize;
+#ifdef _SC_LEVEL1_DCACHE_LINESIZE
+       cachelinesize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
+       if (cachelinesize <= 0) {
+               fplog(stderr, DEBUG, "Could not determine cache line size, 
using 64\n");
+               cachelinesize = 64;
+       }
+#else
+#warning Cant determine cachelinesize, setting to 64
+       cachelinesize = 64;
 #endif
-       pagesize = op->pagesize;
-
        ofiles = NULL;
 
        int tmpfd = 0;
@@ -3354,9 +3385,10 @@
        }
        /* Defaults for blocksizes */
        if (op->softbs == 0) {
-               if (op->o_dir_in)
+               if (op->o_dir_in) {
                        op->softbs = DIO_SOFTBLOCKSIZE;
-               else
+                       updstat /= 4;
+               } else
                        op->softbs = BUF_SOFTBLOCKSIZE;
        }
        if (op->hardbs == 0) {
@@ -3681,7 +3713,6 @@
        if (op->falloc && !fst->o_chr)
                do_fallocate(fst->odes, op->oname, op, fst);
 #endif
-
        if (op->verbose)
                printinfo(stderr, op);
 
@@ -3710,6 +3741,8 @@
                        updstat = upd;
                }
        }
+       if (updstat == 0)
+               updstat = 1;
 #if 0
        if (op->verbose)
                fplog(stderr, DEBUG, "Update progress every %i kiB\n",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.24/secmem.c 
new/dd_rescue-1.99.25/secmem.c
--- old/dd_rescue-1.99.24/secmem.c      2024-08-22 19:41:01.000000000 +0200
+++ new/dd_rescue-1.99.25/secmem.c      2026-10-18 16:19:01.744901655 +0200
@@ -19,15 +19,15 @@
 #endif
 
 static unsigned char *optr;
-static unsigned int pagesize;
+static unsigned int _pagesize;
 
 sec_fields* secmem_init()
 {
 #ifdef _SC_PAGESIZE
-       pagesize = sysconf(_SC_PAGESIZE);
+       _pagesize = sysconf(_SC_PAGESIZE);
 #else
 #warning Cant determine pagesize, setting to 4kiB
-       pagesize = 4096;
+       _pagesize = 4096;
 #endif  
        unsigned char *ptr = 0;
 #ifdef HAVE_VALLOC
@@ -35,37 +35,37 @@
 #ifndef HAVE_VALLOC_DECL
        void* valloc(size_t sz);
 #endif
-       ptr = (unsigned char*)valloc(pagesize);
+       ptr = (unsigned char*)valloc(_pagesize);
 #elif defined(HAVE_POSIX_MEMALIGN)
        void *mp;
-       if (posix_memalign(&mp, pagesize, pagesize))
+       if (posix_memalign(&mp, _pagesize, _pagesize))
                ptr = 0;
        else
                ptr = (unsigned char*)mp;
 #endif /* NetBSD */
        if (!ptr) {
                //fplog(stderr, WARN, "allocation of aligned buffer failed -- 
use malloc\n");
-               ptr = (unsigned char*)malloc(2*pagesize);
+               ptr = (unsigned char*)malloc(2*_pagesize);
                if (!ptr) {
-                       fprintf(stderr, "Allocation of size %i failed!\n", 
2*pagesize);
+                       fprintf(stderr, "Allocation of size %i failed!\n", 
2*_pagesize);
                        /*
                        fplog(stderr, FATAL, "allocation of buffer of size %li 
failed!\n", 
-                               
bs+pagesize+plug_max_slack_pre+plug_max_slack_post);
+                               
bs+_pagesize+plug_max_slack_pre+plug_max_slack_post);
                        cleanup(); exit(18);
                         */
                        abort();
                }
-               ptr += pagesize-1;
-               ptr -= (unsigned long)ptr % pagesize;
+               ptr += _pagesize-1;
+               ptr -= (unsigned long)ptr % _pagesize;
        }
        optr = ptr;
-       memset(ptr, 0, pagesize);
-       if (mlock(ptr, pagesize)) {
+       memset(ptr, 0, _pagesize);
+       if (mlock(ptr, _pagesize)) {
                fprintf(stderr, "Can't lock page in memory: %s\n", 
strerror(errno));
                abort();
        }
 #ifdef MADV_DONTDUMP
-       if (madvise(ptr, pagesize, MADV_DONTDUMP)) {
+       if (madvise(ptr, _pagesize, MADV_DONTDUMP)) {
                fprintf(stderr, "Can't set to exclude from core: %s\n", 
strerror(errno));
                abort();
        }
@@ -98,10 +98,10 @@
                memset(sf, 0, offsetof(sec_fields, hashbuf1));
                abort();
        }
-       memset(ptr, 0, pagesize);
+       memset(ptr, 0, _pagesize);
        LFENCE;
-       munlock(ptr, pagesize);
-       if ((unsigned long)ptr - (unsigned long)optr < pagesize)
+       munlock(ptr, _pagesize);
+       if ((unsigned long)ptr - (unsigned long)optr < _pagesize)
                free(optr);
        else
                free(ptr);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/dd_rescue-1.99.24/test_progress.sh 
new/dd_rescue-1.99.25/test_progress.sh
--- old/dd_rescue-1.99.24/test_progress.sh      1970-01-01 01:00:00.000000000 
+0100
+++ new/dd_rescue-1.99.25/test_progress.sh      2026-10-18 22:43:23.326450093 
+0200
@@ -0,0 +1,81 @@
+#!/bin/bash
+# Regression tests for progress and rate control after a partial first block.
+# Usage: bash test_progress.sh [path/to/dd_rescue]
+# Only temporary regular files are written.
+set -euo pipefail
+export LC_ALL=C
+
+DDR=${1:-./dd_rescue}
+TESTDIR=$(mktemp -d "${TMPDIR:-/tmp}/dd-rescue-progress.XXXXXX")
+trap 'rm -rf "$TESTDIR"' EXIT
+
+MIB=1048576
+# Avoid an exact multiple of the update interval at the final partial block.
+LENGTH=$((16*MIB + 12345))
+# Same remainder modulo 1 MiB as the reported 23000277250048-byte offset.
+OFFSET=716800
+
+run_case()
+{
+       local name=$1 offset=$2 hard=$3 reverse=$4 quiet=$5
+       local length=${6:-$LENGTH}
+       local output="$TESTDIR/output" expected="$TESTDIR/expected"
+       local log="$TESTDIR/stderr" progress="$TESTDIR/progress"
+       local total=$((offset + length + MIB))
+       local -a options=(-w -b 1M -m "$length" -y 0 -C 8M)
+       if test "$hard" = 1; then options+=(-B 1M); fi
+       if test "$reverse" = 1; then
+               options+=(-r -S "$((offset + length))")
+       else
+               options+=(-S "$offset")
+       fi
+       if test "$quiet" = 1; then options+=(-q); fi
+
+       echo "Testing $name"
+       # Sentinel bytes on both sides detect rounding of the offset or length.
+       head -c "$total" /dev/zero | tr '\000' '\245' > "$output"
+       {
+               head -c "$offset" /dev/zero | tr '\000' '\245'
+               head -c "$length" /dev/zero
+               head -c "$MIB" /dev/zero | tr '\000' '\245'
+       } > "$expected"
+       SECONDS=0
+       if ! $VG "$DDR" "${options[@]}" /dev/zero "$output" 2> "$log"; then
+               cat "$log" >&2
+               return 1
+       fi
+       local elapsed=$SECONDS
+       # Require progress while copying, not just a status at 100% before the 
summary.
+       sed '/Summary for/,$d' "$log" > "$progress"
+       if test "$quiet" = 1; then
+               if grep -q 'ipos:' "$progress"; then
+                       echo "FAIL: $name printed progress in quiet mode" >&2
+                       return 1
+               fi
+       elif ! grep -Eq '[[:space:]][1-9][0-9]?%[[:space:]]+ETA:' "$progress"; 
then
+               echo "FAIL: $name did not print intermediate progress" >&2
+               cat "$log" >&2
+               return 1
+       fi
+       # 16 MiB at 8 MiB/s should take about 2 s; allow generous timing slack.
+       if test "$elapsed" -lt 1; then
+               echo "FAIL: $name bypassed rate control" >&2
+               return 1
+       fi
+       cmp "$expected" "$output"
+}
+
+# Match the existing test suite's optional valgrind wrapper.
+VG=${VG:-}
+run_case aligned 0 0 0 0
+run_case unaligned "$OFFSET" 0 0 0
+run_case unaligned-reverse "$OFFSET" 0 1 0
+run_case unaligned-hard-blocks "$OFFSET" 1 0 0
+run_case unaligned-hard-blocks-reverse "$OFFSET" 1 1 0
+run_case unaligned-quiet-rate-control "$OFFSET" 0 0 1
+run_case unaligned-hard-blocks-quiet-rate-control "$OFFSET" 1 0 1
+# The old doubled block count remains odd in these cases and skips every
+# update window, including at the final partial transfer.
+run_case unaligned-hard-blocks-reverse-17M "$OFFSET" 1 1 0 "$((17*MIB + 
12345))"
+run_case unaligned-hard-blocks-reverse-17M-quiet "$OFFSET" 1 1 1 "$((17*MIB + 
12345))"
+echo 'All progress tests passed'

Reply via email to