diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e18b1eb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/scrub-2.6.1.tar.gz
diff --git a/.scrub.metadata b/.scrub.metadata
new file mode 100644
index 0000000..ffb4796
--- /dev/null
+++ b/.scrub.metadata
@@ -0,0 +1 @@
+baac394cd8a414f36c01320bfe8771c8246af396 SOURCES/scrub-2.6.1.tar.gz
diff --git a/SOURCES/scrub-2.5.2-test-use-power-2-filesizes.patch b/SOURCES/scrub-2.5.2-test-use-power-2-filesizes.patch
new file mode 100644
index 0000000..cfdb0dd
--- /dev/null
+++ b/SOURCES/scrub-2.5.2-test-use-power-2-filesizes.patch
@@ -0,0 +1,239 @@
+From 9f37f5d29f255285cbc7822788963681a8f659dd Mon Sep 17 00:00:00 2001
+From: rpm-build <rpm-build>
+Date: Tue, 26 Jan 2021 15:22:57 -0500
+Subject: [PATCH] test: use a power of 2 for file sizes
+
+Reduce the change of tests failing due to block size round-up.
+Freebsd was failing that way.
+
+Upstream: https://github.com/chaos/scrub/commit/5c66fc0537f4ecb21d4c3dcdd9020a02c8a2d819
+---
+ test/t02     |  2 +-
+ test/t02.exp |  2 +-
+ test/t03     |  2 +-
+ test/t03.exp |  2 +-
+ test/t04     |  2 +-
+ test/t04.exp |  2 +-
+ test/t05     |  2 +-
+ test/t05.exp |  2 +-
+ test/t06     |  2 +-
+ test/t06.exp |  2 +-
+ test/t07     |  2 +-
+ test/t11     |  2 +-
+ test/t11.exp |  2 +-
+ test/t12     |  8 ++++----
+ test/t12.exp | 12 ++++++------
+ 15 files changed, 23 insertions(+), 23 deletions(-)
+
+diff --git a/test/t02 b/test/t02
+index d09a517..14c5ca7 100755
+--- a/test/t02
++++ b/test/t02
+@@ -1,6 +1,6 @@
+ #!/bin/sh
+ TESTFILE=${TMPDIR:-/tmp}/scrub-testfile.$$
+ rm -f $TESTFILE
+-./pad 400k $TESTFILE || exit 1
++./pad 512k $TESTFILE || exit 1
+ $PATH_SCRUB -r $TESTFILE 2>&1 | sed -e "s!${TESTFILE}!file!" >t02.out || exit 1
+ diff t02.exp t02.out >t02.diff
+diff --git a/test/t02.exp b/test/t02.exp
+index 848c9b7..e026a17 100644
+--- a/test/t02.exp
++++ b/test/t02.exp
+@@ -1,5 +1,5 @@
+ scrub: using NNSA NAP-14.1-C patterns
+-scrub: scrubbing file 409600 bytes (~400KB)
++scrub: scrubbing file 524288 bytes (~512KB)
+ scrub: random  |................................................|
+ scrub: random  |................................................|
+ scrub: 0x00    |................................................|
+diff --git a/test/t03 b/test/t03
+index db9ca61..917ec52 100755
+--- a/test/t03
++++ b/test/t03
+@@ -1,6 +1,6 @@
+ #!/bin/sh
+ TESTFILE=${TMPDIR:-/tmp}/scrub-testfile.$$
+ rm -f $TESTFILE
+-./pad 400k $TESTFILE || exit 1
++./pad 512k $TESTFILE || exit 1
+ $PATH_SCRUB -r -p dod $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >t03.out || exit 1
+ diff t03.exp t03.out >t03.diff
+diff --git a/test/t03.exp b/test/t03.exp
+index e7e8015..4456149 100644
+--- a/test/t03.exp
++++ b/test/t03.exp
+@@ -1,5 +1,5 @@
+ scrub: using DoD 5220.22-M patterns
+-scrub: scrubbing file 409600 bytes (~400KB)
++scrub: scrubbing file 524288 bytes (~512KB)
+ scrub: random  |................................................|
+ scrub: 0x00    |................................................|
+ scrub: 0xff    |................................................|
+diff --git a/test/t04 b/test/t04
+index 3dd4165..a33e9cd 100755
+--- a/test/t04
++++ b/test/t04
+@@ -1,6 +1,6 @@
+ #!/bin/sh
+ TESTFILE=${TMPDIR:-/tmp}/scrub-testfile.$$
+ rm -f $TESTFILE
+-./pad 400k $TESTFILE || exit 1
++./pad 512k $TESTFILE || exit 1
+ $PATH_SCRUB -r -p bsi $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >t04.out || exit 1
+ diff t04.exp t04.out >t04.diff
+diff --git a/test/t04.exp b/test/t04.exp
+index 2bb6822..ac98d54 100644
+--- a/test/t04.exp
++++ b/test/t04.exp
+@@ -1,5 +1,5 @@
+ scrub: using BSI patterns
+-scrub: scrubbing file 409600 bytes (~400KB)
++scrub: scrubbing file 524288 bytes (~512KB)
+ scrub: 0xff    |................................................|
+ scrub: 0xfe    |................................................|
+ scrub: 0xfd    |................................................|
+diff --git a/test/t05 b/test/t05
+index 474fcd3..d9a6061 100755
+--- a/test/t05
++++ b/test/t05
+@@ -1,6 +1,6 @@
+ #!/bin/sh
+ TESTFILE=${TMPDIR:-/tmp}/scrub-testfile.$$
+ rm -f $TESTFILE
+-./pad 400k $TESTFILE || exit 1
++./pad 512k $TESTFILE || exit 1
+ $PATH_SCRUB -r -p fastold $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >t05.out || exit 1
+ diff t05.exp t05.out >t05.diff
+diff --git a/test/t05.exp b/test/t05.exp
+index 48ba9b7..118d7e4 100644
+--- a/test/t05.exp
++++ b/test/t05.exp
+@@ -1,5 +1,5 @@
+ scrub: using pre v1.7 scrub (skip random) patterns
+-scrub: scrubbing file 409600 bytes (~400KB)
++scrub: scrubbing file 524288 bytes (~512KB)
+ scrub: 0x00    |................................................|
+ scrub: 0xff    |................................................|
+ scrub: 0xaa    |................................................|
+diff --git a/test/t06 b/test/t06
+index 28eb856..48bde5a 100755
+--- a/test/t06
++++ b/test/t06
+@@ -1,7 +1,7 @@
+ #!/bin/sh
+ TESTFILE=${TMPDIR:-/tmp}/scrub-testfile.$$
+ rm -f $TESTFILE
+-./pad 400k $TESTFILE || exit 1
++./pad 512k $TESTFILE || exit 1
+ $PATH_SCRUB -r -p old $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >t06.out || exit 1
+ diff t06.exp t06.out >t06.diff
+ rc=$?
+diff --git a/test/t06.exp b/test/t06.exp
+index 49967ec..e84360a 100644
+--- a/test/t06.exp
++++ b/test/t06.exp
+@@ -1,5 +1,5 @@
+ scrub: using pre v1.7 scrub patterns
+-scrub: scrubbing file 409600 bytes (~400KB)
++scrub: scrubbing file 524288 bytes (~512KB)
+ scrub: 0x00    |................................................|
+ scrub: 0xff    |................................................|
+ scrub: 0xaa    |................................................|
+diff --git a/test/t07 b/test/t07
+index cb935bf..69eab76 100755
+--- a/test/t07
++++ b/test/t07
+@@ -1,7 +1,7 @@
+ #!/bin/sh
+ TESTFILE=${TMPDIR:-/tmp}/scrub-testfile.$$
+ rm -f $TESTFILE
+-./pad 400k $TESTFILE
++./pad 512k $TESTFILE
+ (./tsig $TESTFILE && ./tsig $TESTFILE) >t07.out 2>&1
+ diff t07.exp t07.out >t07.diff 
+ rc=$?
+diff --git a/test/t11 b/test/t11
+index 5a17b46..dd5444f 100755
+--- a/test/t11
++++ b/test/t11
+@@ -1,7 +1,7 @@
+ #!/bin/sh
+ TESTFILE=${TMPDIR:-/tmp}/scrub-testfile.$$
+ rm -f $TESTFILE
+-./pad 400k $TESTFILE || exit 1
++./pad 512k $TESTFILE || exit 1
+ $PATH_SCRUB -r -p gutmann $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >t11.out || exit 1
+ diff t11.exp t11.out >t11.diff
+ rc=$?
+diff --git a/test/t11.exp b/test/t11.exp
+index abd2abf..895d903 100644
+--- a/test/t11.exp
++++ b/test/t11.exp
+@@ -1,5 +1,5 @@
+ scrub: using Gutmann patterns
+-scrub: scrubbing file 409600 bytes (~400KB)
++scrub: scrubbing file 524288 bytes (~512KB)
+ scrub: random  |................................................|
+ scrub: random  |................................................|
+ scrub: random  |................................................|
+diff --git a/test/t12 b/test/t12
+index c312220..260198f 100755
+--- a/test/t12
++++ b/test/t12
+@@ -1,14 +1,14 @@
+ #!/bin/sh
+ TESTFILE=${TMPDIR:-/tmp}/scrub-testfile.$$
+ rm -f $TESTFILE
+-./pad 400k $TESTFILE || exit 1
+-$PATH_SCRUB -s 400k $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >t12.out
++./pad 512k $TESTFILE || exit 1
++$PATH_SCRUB -s 512k $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >t12.out
+ test $? = 0 || exit 1
+ ./tsize $TESTFILE >>t12.out 2>&1
+-$PATH_SCRUB -f -s 300k $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >>t12.out
++$PATH_SCRUB -f -s 256k $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >>t12.out
+ test $? = 0 || exit 1
+ ./tsize $TESTFILE >>t12.out 2>&1
+-$PATH_SCRUB -f -s 500k $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >>t12.out
++$PATH_SCRUB -f -s 1024k $TESTFILE 2>&1 | sed -e "s!$TESTFILE!file!" >>t12.out
+ test $? = 0 || exit 1
+ ./tsize $TESTFILE >>t12.out 2>&1
+ diff t12.exp t12.out >t12.diff
+diff --git a/test/t12.exp b/test/t12.exp
+index 33f2c97..4c5d987 100644
+--- a/test/t12.exp
++++ b/test/t12.exp
+@@ -1,22 +1,22 @@
+ scrub: using NNSA NAP-14.1-C patterns
+-scrub: scrubbing file 409600 bytes (~400KB)
++scrub: scrubbing file 524288 bytes (~512KB)
+ scrub: random  |................................................|
+ scrub: random  |................................................|
+ scrub: 0x00    |................................................|
+ scrub: verify  |................................................|
+-409600
++524288
+ scrub: warning: -s size < file size
+ scrub: using NNSA NAP-14.1-C patterns
+-scrub: scrubbing file 307200 bytes (~300KB)
++scrub: scrubbing file 262144 bytes (~256KB)
+ scrub: random  |................................................|
+ scrub: random  |................................................|
+ scrub: 0x00    |................................................|
+ scrub: verify  |................................................|
+-409600
++524288
+ scrub: using NNSA NAP-14.1-C patterns
+-scrub: scrubbing file 512000 bytes (~500KB)
++scrub: scrubbing file 1048576 bytes (~1024KB)
+ scrub: random  |................................................|
+ scrub: random  |................................................|
+ scrub: 0x00    |................................................|
+ scrub: verify  |................................................|
+-512000
++1048576
+-- 
+2.27.0
+
diff --git a/SOURCES/scrub-2.6.1-analyzer-fixes.patch b/SOURCES/scrub-2.6.1-analyzer-fixes.patch
new file mode 100644
index 0000000..350c2ab
--- /dev/null
+++ b/SOURCES/scrub-2.6.1-analyzer-fixes.patch
@@ -0,0 +1,31 @@
+diff -up scrub-2.6.1/src/fillfile.c.analyzer-fixes scrub-2.6.1/src/fillfile.c
+--- scrub-2.6.1/src/fillfile.c.analyzer-fixes	2021-03-18 10:42:37.201845461 -0400
++++ scrub-2.6.1/src/fillfile.c	2021-03-18 10:43:38.358151439 -0400
+@@ -131,10 +131,13 @@ refill_init(struct memstruct **mpp, refi
+ 
+     if (!(mp = malloc(sizeof(struct memstruct))))
+         goto nomem;
+-    if (!(mp->buf = malloc(memsize)))
++    if (!(mp->buf = malloc(memsize))) {
++        free(mp);
+         goto nomem;
++    }
+     mp->size = memsize;
+     mp->refill = refill;
++    mp->thd = 0;
+ #if WITH_PTHREADS
+     if (!no_threads) {
+         if ((mp->err = pthread_create(&mp->thd, NULL, refill_thread, mp))) {
+diff -up scrub-2.6.1/src/scrub.c.analyzer-fixes scrub-2.6.1/src/scrub.c
+diff -up scrub-2.6.1/src/sig.c.analyzer-fixes scrub-2.6.1/src/sig.c
+--- scrub-2.6.1/src/sig.c.analyzer-fixes	2021-03-18 10:44:20.715363360 -0400
++++ scrub-2.6.1/src/sig.c	2021-03-18 10:44:54.319531489 -0400
+@@ -74,7 +74,7 @@ writesig(char *path)
+         goto nomem;
+     if ((fd = open(path, O_RDWR)) < 0)
+         goto error;
+-    if ((n = read_all(fd, buf, blocksize)) < 0)
++    if (read_all(fd, buf, blocksize) < 0)
+         goto error;
+     memcpy(buf, SCRUB_MAGIC, sizeof(SCRUB_MAGIC));
+     if (lseek(fd, 0, SEEK_SET) < 0)
diff --git a/SOURCES/scrub-2.6.1-extentonly.patch b/SOURCES/scrub-2.6.1-extentonly.patch
new file mode 100644
index 0000000..bb58a06
--- /dev/null
+++ b/SOURCES/scrub-2.6.1-extentonly.patch
@@ -0,0 +1,665 @@
+diff -up scrub-2.6.1/libscrub/Makefile.am.extent-only scrub-2.6.1/libscrub/Makefile.am
+--- scrub-2.6.1/libscrub/Makefile.am.extent-only	2014-08-20 17:33:43.000000000 -0400
++++ scrub-2.6.1/libscrub/Makefile.am	2021-02-22 14:24:32.439635010 -0500
+@@ -13,6 +13,7 @@ libscrub_la_SOURCES = \
+ 	libscrub.c \
+ 	scrub.h \
+ 	../src/aes.c \
++	../src/fextent_apply.c \
+ 	../src/filldentry.c \
+ 	../src/fillfile.c \
+ 	../src/genrand.c \
+diff -up scrub-2.6.1/man/scrub.1.in.extent-only scrub-2.6.1/man/scrub.1.in
+--- scrub-2.6.1/man/scrub.1.in.extent-only	2014-08-20 17:33:43.000000000 -0400
++++ scrub-2.6.1/man/scrub.1.in	2021-02-22 14:24:32.439635010 -0500
+@@ -110,6 +110,13 @@ Do everything but write to targets.
+ .TP
+ \fI-h\fR, \fI--help\fR
+ Print a summary of command line options on stderr.
++.TP
++\fI-E\fR, \fI--extent-only\fR
++When scrubbing regular files, scrub only the file extents. This option is
++useful in combination with large sparse files. If used, scrub will skip
++the holes in the sparse file. Use this option with caution, the result may not
++be compliant with cited standards and information about the actual on-disk
++data allocation may leak since only the allocated parts will be scrubbed.
+ .SH SCRUB METHODS
+ .TP
+ .I "nnsa"
+diff -up scrub-2.6.1/src/fextent_apply.c.extent-only scrub-2.6.1/src/fextent_apply.c
+--- scrub-2.6.1/src/fextent_apply.c.extent-only	2021-02-22 14:24:32.439635010 -0500
++++ scrub-2.6.1/src/fextent_apply.c	2021-02-22 14:25:20.590843156 -0500
+@@ -0,0 +1,142 @@
++/*
++ * Copyright 2021 Red Hat, Inc.
++ * All Rights Reserved.
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * 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, see:
++ * <https://www.gnu.org/licenses/>.
++ *
++ * Authors:
++ *      Daniel Kopecek <dkopecek@redhat.com>
++ */
++#include <stdio.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <errno.h>
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/ioctl.h>
++#include <sys/file.h>
++
++#include <linux/fs.h>
++#include <linux/fiemap.h>
++
++#ifndef NDEBUG
++# define dP(...)                               \
++    do { int  __tmp_errno = errno;             \
++       fprintf(stderr, "DEBUG: "__VA_ARGS__);  \
++       errno = __tmp_errno;                    \
++    } while(0)
++#else
++# define dP(...) while(0)
++#endif
++
++int fextent_apply(int fd, int (*function)(int, struct fiemap_extent *, void *), void *arg)
++{
++    int ret = -1;
++    struct stat st;
++    struct fiemap *em;
++    uint32_t extent_count, i;
++
++    // lock, sync, stat
++    if (flock(fd, LOCK_EX) != 0) {
++       dP("flock(%d, LOCK_EX) failed: %s, %d.\n", fd, strerror(errno), errno);
++       return -1;
++    }
++    if (fsync(fd) != 0) {
++       dP("fsync(%d) failed: %s, %d.\n", fd, strerror(errno), errno);
++       goto exit_1;
++    }
++    if (fstat(fd, &st) != 0) {
++       dP("fstat(%d) failed: %s, %d.\n", fd, strerror(errno), errno);
++       goto exit_1;
++    }
++
++    /*
++     * fiemap => get extent count
++     */
++    em = malloc(sizeof(struct fiemap));
++
++    if (em == NULL) {
++       dP("malloc(%zu) returned NULL!\n", sizeof(struct fiemap));
++       goto exit_1;
++    }
++
++    memset(em, 0, sizeof(struct fiemap));
++
++    em->fm_start = 0;
++    em->fm_length = st.st_size;
++    em->fm_extent_count = 0;
++    em->fm_mapped_extents = 0;
++    em->fm_flags = 0;
++
++    if (ioctl(fd, FS_IOC_FIEMAP, em) != 0) {
++       dP("FS_IOC_FIEMAP: %s, %d.\n", strerror(errno), errno);
++       goto exit_0;
++    }
++
++    extent_count = em->fm_mapped_extents;
++    free(em);
++
++    /*
++     * fiemap => get extents
++     */
++    em = malloc (sizeof(struct fiemap)
++                + (sizeof(struct fiemap_extent) * extent_count));
++
++    if (em == NULL) {
++       dP("malloc(%zu) returned NULL!\n", sizeof(struct fiemap)
++          + (sizeof (struct fiemap_extent) * extent_count));
++       goto exit_0;
++    }
++
++    memset(em, 0, sizeof(struct fiemap)
++          + (sizeof(struct fiemap_extent) * extent_count));
++
++    em[0].fm_start = 0;
++    em[0].fm_length = st.st_size;
++    em[0].fm_extent_count = extent_count;
++    em[0].fm_flags = 0;
++
++    if (ioctl(fd, FS_IOC_FIEMAP, em) != 0) {
++       dP("FS_IOC_FIEMAP: %s, %d.\n", strerror(errno), errno);
++       goto exit_0;
++    }
++
++    for (i = 0; i < extent_count; ++i) {
++       // seek to extent start
++       if (lseek(fd, em->fm_extents[i].fe_logical, SEEK_SET) == (off_t)-1) {
++           dP("lseek(%d, %llu, SET) failed: %s, %d.\n",
++              fd, em->fm_extents[i].fe_logical, strerror(errno), errno);
++           goto exit_0;
++       }
++
++       ret = function(fd, em->fm_extents + i, arg);
++       if (ret != 0)
++           goto exit_0;
++    }
++
++    ret = 0;
++  exit_0:
++    // release resources
++    free (em);
++  exit_1:
++    // unlock
++    if (flock(fd, LOCK_UN) != 0)
++       ret = -1;
++
++    return ret;
++}
+diff -up scrub-2.6.1/src/fextent_apply.h.extent-only scrub-2.6.1/src/fextent_apply.h
+--- scrub-2.6.1/src/fextent_apply.h.extent-only	2021-02-22 14:24:32.439635010 -0500
++++ scrub-2.6.1/src/fextent_apply.h	2021-02-22 14:24:32.439635010 -0500
+@@ -0,0 +1,30 @@
++/*
++ * Copyright 2021 Red Hat, Inc.
++ * All Rights Reserved.
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * 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, see:
++ * <https://www.gnu.org/licenses/>.
++ *
++ * Authors:
++ *      Daniel Kopecek <dkopecek@redhat.com>
++ */
++#ifndef FEXTENT_APPLY_H
++#define FEXTENT_APPLY_H
++
++#include <linux/fs.h>
++#include <linux/fiemap.h>
++
++int fextent_apply(int fd, int (*function)(int, struct fiemap_extent *, void *), void *arg);
++
++#endif /* FEXTENT_APPLY_H */
+diff -up scrub-2.6.1/src/fillfile.c.extent-only scrub-2.6.1/src/fillfile.c
+--- scrub-2.6.1/src/fillfile.c.extent-only	2014-08-20 17:33:43.000000000 -0400
++++ scrub-2.6.1/src/fillfile.c	2021-02-22 14:24:32.439635010 -0500
+@@ -41,6 +41,7 @@
+ 
+ #include "util.h"
+ #include "fillfile.h"
++#include "fextent_apply.h"
+ 
+ static int no_threads = 0;
+ 
+@@ -56,6 +57,20 @@ struct memstruct {
+ 
+ extern char *prog;
+ 
++struct fillfile_args {
++    char *path;
++    off_t filesize;
++    unsigned char *mem;
++    int memsize;
++    progress_t progress;
++    void *arg;
++    refill_t refill;
++    unsigned char *buf;
++};
++
++int fillextent(int fd, struct fiemap_extent *extent, void *pa);
++int checkextent(int fd, struct fiemap_extent *extent, void *pa);
++
+ #if defined(O_DIRECT) && (defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN))
+ # define MY_O_DIRECT O_DIRECT
+ #else
+@@ -154,11 +169,12 @@ refill_fini(struct memstruct *mp)
+  * If 'sparse' is true, only scrub first and last blocks (for testing).
+  * The number of bytes written is returned.
+  * If 'creat' is true, open with O_CREAT and allow ENOSPC to be non-fatal.
++ * If 'extentonly' is true, fill only file extents with the given pattern.
+  */
+ off_t
+ fillfile(char *path, off_t filesize, unsigned char *mem, int memsize,
+          progress_t progress, void *arg, refill_t refill, 
+-         bool sparse, bool creat)
++         bool sparse, bool creat, bool extentonly)
+ {
+     int fd = -1;
+     off_t n;
+@@ -178,34 +194,52 @@ fillfile(char *path, off_t filesize, uns
+     }
+     if (fd < 0)
+         goto error;
+-    do {
+-        if (written + memsize > filesize)
+-            memsize = filesize - written;
+-        if (refill && !sparse) {
+-            if (!mp)
+-                if (refill_init(&mp, refill, memsize) < 0)
+-                    goto error;
+-            if (refill_memcpy(mp, mem, memsize, filesize, written) < 0)
+-                goto error;
+-        }
+-        if (sparse && !(written == 0) && !(written + memsize == filesize)) {
+-            if (lseek(fd, memsize, SEEK_CUR) < 0)
+-                goto error;
+-            written += memsize;
+-        } else {
+-            n = write_all(fd, mem, memsize);
+-            if (creat && n < 0 && errno == ENOSPC)
+-                break;
+-            if (n == 0) {
+-                errno = EINVAL; /* write past end of device? */
+-                goto error;
+-            } else if (n < 0)
+-                goto error;
+-            written += n;
++
++    if (extentonly) {
++        struct fillfile_args fa;
++
++        fa.path = path;
++        fa.filesize = filesize;
++        fa.mem = mem;
++        fa.memsize = memsize;
++        fa.progress = progress;
++        fa.refill = refill;
++        fa.arg = arg;
++
++        if (fextent_apply(fd, fillextent, &fa) == 0) {
++            written = filesize;
+         }
+-        if (progress)
+-            progress(arg, (double)written/filesize);
+-    } while (written < filesize);
++    } else {
++        do {
++            if (written + memsize > filesize)
++                memsize = filesize - written;
++            if (refill && !sparse) {
++                if (!mp)
++                    if (refill_init(&mp, refill, memsize) < 0)
++                        goto error;
++                if (refill_memcpy(mp, mem, memsize, filesize, written) < 0)
++                    goto error;
++            }
++            if (sparse && !(written == 0) && !(written + memsize == filesize)) {
++                if (lseek(fd, memsize, SEEK_CUR) < 0)
++                    goto error;
++                written += memsize;
++            } else {
++                n = write_all(fd, mem, memsize);
++                if (creat && n < 0 && errno == ENOSPC)
++                    break;
++                if (n == 0) {
++                    errno = EINVAL; /* write past end of device? */
++                    goto error;
++                } else if (n < 0)
++                    goto error;
++                written += n;
++            }
++            if (progress)
++                progress(arg, (double)written/filesize);
++        } while (written < filesize);
++    }
++
+     if (fsync(fd) < 0) {
+         if (errno != EINVAL)
+             goto error;
+@@ -232,7 +266,7 @@ error:
+  */
+ off_t
+ checkfile(char *path, off_t filesize, unsigned char *mem, int memsize,
+-          progress_t progress, void *arg, bool sparse)
++          progress_t progress, void *arg, bool sparse, bool extentonly)
+ {
+     int fd = -1;
+     off_t n;
+@@ -240,8 +274,6 @@ checkfile(char *path, off_t filesize, un
+     unsigned char *buf = NULL;
+     int openflags = O_RDONLY;
+ 
+-    if (!(buf = alloc_buffer(memsize)))
+-        goto nomem;
+     if (filetype(path) != FILE_CHAR)
+         openflags |= MY_O_DIRECT;
+     fd = open(path, openflags);
+@@ -252,32 +284,58 @@ checkfile(char *path, off_t filesize, un
+     }
+     if (fd < 0)
+         goto error;
+-    do {
+-        if (verified + memsize > filesize)
+-            memsize = filesize - verified;
+-        if (sparse && !(verified == 0) && !(verified + memsize == filesize)) {
+-            if (lseek(fd, memsize, SEEK_CUR) < 0)
+-                goto error;
+-            verified += memsize;
+-        } else {
+-            n = read_all(fd, buf, memsize);
+-            if (n < 0)
+-                goto error;
+-            if (n == 0) {
+-                errno = EINVAL; /* early EOF */
+-                goto error;
+-            }
+-            if (memcmp(mem, buf, memsize) != 0) {
+-                break; /* return < filesize means verification failure */
+-            }
+-            verified += n;
++    if (extentonly) {
++        struct fillfile_args fa;
++
++        fa.path = path;
++        fa.filesize = filesize;
++        fa.mem = mem;
++        fa.memsize = memsize;
++        fa.progress = progress;
++        fa.arg = arg;
++        fa.buf = alloc_buffer(memsize);
++
++        if (fa.buf == NULL) {
++            goto nomem;
+         }
+-        if (progress)
+-            progress(arg, (double)verified/filesize);
+-    } while (verified < filesize);
++
++        if (fextent_apply(fd, checkextent, &fa) == 0)
++            verified = filesize;
++
++        free(fa.buf);
++    } else {
++        if (!(buf = alloc_buffer(memsize)))
++            goto nomem;
++        do {
++            if (verified + memsize > filesize)
++                memsize = filesize - verified;
++            if (sparse && !(verified == 0) && !(verified + memsize == filesize)) {
++                if (lseek(fd, memsize, SEEK_CUR) < 0)
++                    goto error;
++                verified += memsize;
++            } else {
++                n = read_all(fd, buf, memsize);
++                if (n < 0)
++                    goto error;
++                if (n == 0) {
++                    errno = EINVAL; /* early EOF */
++                    goto error;
++                }
++                if (memcmp(mem, buf, memsize) != 0) {
++                    break; /* return < filesize means verification failure */
++                }
++                verified += n;
++            }
++            if (progress)
++                progress(arg, (double)verified/filesize);
++        } while (verified < filesize);
++    }
++
+     if (close(fd) < 0)
+         goto error;
+-    free(buf);
++    if (buf != NULL) {
++        free(buf);
++    }
+     return verified;
+ nomem:
+     errno = ENOMEM;
+@@ -295,6 +353,63 @@ disable_threads(void)
+     no_threads = 1;
+ }
+ 
++int fillextent(int fd, struct fiemap_extent *extent, void *pa)
++{
++    off_t n;
++    off_t written = 0LL;
++    struct fillfile_args args = *(struct fillfile_args *)(pa);
++    
++    do {
++        if (args.refill)
++            args.refill(args.mem, args.memsize);
++
++        if (written + args.memsize > extent->fe_length)
++            args.memsize = extent->fe_length - written;
++
++        n = write_all(fd, args.mem, args.memsize);
++
++        if (n < 0) {
++            fprintf(stderr, "%s: write %s: %s\n", prog, args.path, strerror(errno));
++            exit(1);
++        }
++        written += n;
++
++        if (args.progress)
++            args.progress(args.arg, (double)(extent->fe_logical + written)/args.filesize);
++    } while (written < extent->fe_length);
++
++    return 0;
++}
++
++int checkextent(int fd, struct fiemap_extent *extent, void *pa)
++{
++    off_t n;
++    off_t verified = 0LL;
++    struct fillfile_args args = *(struct fillfile_args *)(pa);
++
++    do {
++        if (verified + args.memsize > extent->fe_length)
++            args.memsize = extent->fe_length - verified;
++
++        n = read_all(fd, args.buf, args.memsize);
++        if (n < 0) {
++            return -1;
++        }
++        if (n == 0) {
++            errno = EINVAL;
++            return -1;
++        }
++        if (memcmp(args.mem, args.buf, args.memsize) != 0) {
++            break;
++        }
++        verified += n;
++        if (args.progress)
++            args.progress(args.arg, (double)(extent->fe_logical+verified)/args.filesize);
++    } while (verified < extent->fe_length);
++
++    return 0;
++}
++
+ /*
+  * vi:tabstop=4 shiftwidth=4 expandtab
+  */
+diff -up scrub-2.6.1/src/fillfile.h.extent-only scrub-2.6.1/src/fillfile.h
+--- scrub-2.6.1/src/fillfile.h.extent-only	2014-08-20 17:33:43.000000000 -0400
++++ scrub-2.6.1/src/fillfile.h	2021-02-22 14:24:32.440635014 -0500
+@@ -3,9 +3,9 @@ typedef void (*refill_t) (unsigned char
+ 
+ off_t fillfile(char *path, off_t filesize, unsigned char *mem, int memsize,
+         progress_t progress, void *arg, refill_t refill, 
+-        bool sparse, bool creat);
++        bool sparse, bool creat, bool extentonly);
+ off_t checkfile(char *path, off_t filesize, unsigned char *mem, int memsize,
+-        progress_t progress, void *arg, bool sparse);
++        progress_t progress, void *arg, bool sparse, bool extentonly);
+ void  disable_threads(void);
+ 
+ /*
+diff -up scrub-2.6.1/src/Makefile.am.extent-only scrub-2.6.1/src/Makefile.am
+--- scrub-2.6.1/src/Makefile.am.extent-only	2021-02-22 14:24:32.438635006 -0500
++++ scrub-2.6.1/src/Makefile.am	2021-02-22 14:24:32.440635014 -0500
+@@ -1,6 +1,8 @@
+ bin_PROGRAMS = scrub
+ 
+ scrub_SOURCES = \
++	fextent_apply.c \
++	fextent_apply.h \
+ 	filldentry.c \
+ 	filldentry.h \
+ 	fillfile.c \
+diff -up scrub-2.6.1/src/scrub.c.extent-only scrub-2.6.1/src/scrub.c
+--- scrub-2.6.1/src/scrub.c.extent-only	2021-02-22 14:24:32.438635006 -0500
++++ scrub-2.6.1/src/scrub.c	2021-02-22 14:24:32.440635014 -0500
+@@ -68,10 +68,11 @@ struct opt_struct {
+     bool nofollow;
+     bool nohwrand;
+     bool nothreads;
++    bool extentonly;
+ };
+ 
+ static bool       scrub(char *path, off_t size, const sequence_t *seq,
+-                      int bufsize, bool nosig, bool sparse, bool enospc);
++                      int bufsize, bool nosig, bool sparse, bool enospc, bool extentonly);
+ static void       scrub_free(char *path, const struct opt_struct *opt);
+ static void       scrub_dirent(char *path, const struct opt_struct *opt);
+ static void       scrub_file(char *path, const struct opt_struct *opt);
+@@ -82,7 +83,7 @@ static void       scrub_disk(char *path,
+ static int        scrub_object(char *path, const struct opt_struct *opt,
+                                bool noexec, bool dryrun);
+ 
+-#define OPTIONS "p:D:Xb:s:fSrvTLRthn"
++#define OPTIONS "p:D:Xb:s:fSrvTELRthn"
+ #if HAVE_GETOPT_LONG
+ #define GETOPT(ac,av,opt,lopt) getopt_long(ac,av,opt,lopt,NULL)
+ static struct option longopts[] = {
+@@ -96,6 +97,7 @@ static struct option longopts[] = {
+     {"remove",           no_argument,        0, 'r'},
+     {"version",          no_argument,        0, 'v'},
+     {"test-sparse",      no_argument,        0, 'T'},
++    {"extent-only",      no_argument,        0, 'E'},
+     {"no-link",          no_argument,        0, 'L'},
+     {"no-hwrand",        no_argument,        0, 'R'},
+     {"no-threads",       no_argument,        0, 't'},
+@@ -123,6 +125,7 @@ usage(void)
+ "  -f, --force             scrub despite signature from previous scrub\n"
+ "  -S, --no-signature      do not write scrub signature after scrub\n"
+ "  -r, --remove            remove file after scrub\n"
++"  -E, --extent-only       scrub only file extents\n"
+ "  -L, --no-link           do not scrub link target\n"
+ "  -R, --no-hwrand         do not use a hardware random number generator\n"
+ "  -t, --no-threads        do not compute random data in a parallel thread\n"
+@@ -212,6 +215,9 @@ main(int argc, char *argv[])
+         case 'T':   /* --test-sparse */
+             opt.sparse = true;
+             break;
++        case 'E':   /* --extent-only */
++            opt.extentonly = true;
++            break;
+         case 'L':   /* --no-link */
+             opt.nofollow = true;
+             break;
+@@ -430,14 +436,14 @@ static int progress_col (const sequence_
+  */
+ static bool
+ scrub(char *path, off_t size, const sequence_t *seq, int bufsize, 
+-      bool nosig, bool sparse, bool enospc)
++      bool nosig, bool sparse, bool enospc, bool extentonly)
+ {
+     unsigned char *buf;
+     int i;
+     prog_t p;
+     char sizestr[80];
+     bool isfull = false;
+-    off_t written, checked;
++    off_t written = (off_t)-1, checked = (off_t)-1;
+     int pcol = progress_col(seq);
+ 
+     if (!(buf = alloc_buffer(bufsize))) {
+@@ -468,7 +474,7 @@ scrub(char *path, off_t size, const sequ
+ #endif /* HAVE_LIBGCRYPT. */
+                 written = fillfile(path, size, buf, bufsize, 
+                                    (progress_t)progress_update, p, 
+-                                   (refill_t)genrand, sparse, enospc);
++                                   (refill_t)genrand, sparse, enospc, extentonly);
+                 if (written == (off_t)-1) {
+                     fprintf(stderr, "%s: %s: %s\n", prog, path,
+                              strerror(errno));
+@@ -482,7 +488,7 @@ scrub(char *path, off_t size, const sequ
+                 memset_pat(buf, seq->pat[i], bufsize);
+                 written = fillfile(path, size, buf, bufsize, 
+                                    (progress_t)progress_update, p, 
+-                                   NULL, sparse, enospc);
++                                   NULL, sparse, enospc, extentonly);
+                 if (written == (off_t)-1) {
+                     fprintf(stderr, "%s: %s: %s\n", prog, path,
+                              strerror(errno));
+@@ -496,7 +502,7 @@ scrub(char *path, off_t size, const sequ
+                 memset_pat(buf, seq->pat[i], bufsize);
+                 written = fillfile(path, size, buf, bufsize, 
+                                    (progress_t)progress_update, p, 
+-                                   NULL, sparse, enospc);
++                                   NULL, sparse, enospc, extentonly);
+                 if (written == (off_t)-1) {
+                     fprintf(stderr, "%s: %s: %s\n", prog, path,
+                              strerror(errno));
+@@ -506,7 +512,7 @@ scrub(char *path, off_t size, const sequ
+                 printf("%s: %-8s", prog, "verify");
+                 progress_create(&p, pcol);
+                 checked = checkfile(path, written, buf, bufsize, 
+-                                    (progress_t)progress_update, p, sparse);
++                                    (progress_t)progress_update, p, sparse, extentonly);
+                 if (checked == (off_t)-1) {
+                     fprintf(stderr, "%s: %s: %s\n", prog, path,
+                              strerror(errno));
+@@ -600,7 +606,7 @@ scrub_free(char *dirpath, const struct o
+     do {
+         snprintf(path, sizeof(path), "%s/scrub.%.3d", dirpath, fileno++);
+         isfull = scrub(path, size, opt->seq, opt->blocksize, opt->nosig,
+-                       false, true);
++                       false, true, false);
+     } while (!isfull);
+     while (--fileno >= 0) {
+         snprintf(path, sizeof(path), "%s/scrub.%.3d", dirpath, fileno);
+@@ -678,7 +684,7 @@ scrub_file(char *path, const struct opt_
+                     prog, path, (int)(size - sb.st_size)); 
+         }
+     }
+-    scrub(path, size, opt->seq, opt->blocksize, opt->nosig, opt->sparse, false);
++    scrub(path, size, opt->seq, opt->blocksize, opt->nosig, opt->sparse, false, opt->extentonly);
+ }
+ 
+ /* Scrub apple resource fork component of file.
+@@ -706,7 +712,7 @@ scrub_resfork(char *path, const struct o
+         printf("%s: padding %s with %d bytes to fill last fs block\n", 
+                         prog, rpath, (int)(rsize - rsb.st_size)); 
+     }
+-    scrub(rpath, rsize, opt->seq, opt->blocksize, false, false, false);
++    scrub(rpath, rsize, opt->seq, opt->blocksize, false, false, false, false);
+ }
+ #endif
+ 
+@@ -728,7 +734,7 @@ scrub_disk(char *path, const struct opt_
+         printf("%s: please verify that device size below is correct!\n", prog);
+     }
+     scrub(path, devsize, opt->seq, opt->blocksize, opt->nosig, opt->sparse,
+-          false);
++          false, false);
+ }
+ 
+ /*
diff --git a/SOURCES/scrub-2.6.1-symlinks-to-block-device.patch b/SOURCES/scrub-2.6.1-symlinks-to-block-device.patch
new file mode 100644
index 0000000..578f8d8
--- /dev/null
+++ b/SOURCES/scrub-2.6.1-symlinks-to-block-device.patch
@@ -0,0 +1,122 @@
+From 499a491c21b5a18be79334282dfa11fd4f408c49 Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Wed, 27 Jan 2021 09:42:15 -0300
+Subject: [PATCH] scrub should work for symlinks pointing to block devices
+
+In [1] (add -L option to avoid scrubbing symlink target [Tim
+Boronczyk]), scrub introduced a -L (--no-link) option so that it would
+not scrub the target, if it was a link and this new option was set.
+
+A side-effect of that change is that scrub stopped working for links
+pointing to a block device, whereas it would still work for links
+pointing to regular files -- it is not clear from the commit changelog
+and the added documentation for this new option that this was an
+intended change.
+
+In this commit we fix this regression, and scrub works again for links
+pointing to block devices. -L/--no-link option also works for these
+links.
+
+[1] https://github.com/chaos/scrub/commit/01915c442288b4b274261fa07e42e116fb9d6b60
+---
+ src/scrub.c | 13 ++++++++-----
+ src/util.c  | 13 +++++++++----
+ src/util.h  |  2 +-
+ 3 files changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/src/scrub.c b/src/scrub.c
+index 1dada28..178dfe7 100644
+--- a/src/scrub.c
++++ b/src/scrub.c
+@@ -334,6 +334,10 @@ static int scrub_object(char *filename, const struct opt_struct *opt,
+                 fprintf(stderr, "%s: %s already scrubbed? (-f to force)\n",
+                         prog, filename);
+                 errcount++;
++            } else if (is_symlink(filename) && opt->nofollow) {
++                fprintf(stderr, "%s: skipping symlink %s because --no-link (-L) option was set\n",
++                        prog, filename);
++                errcount++;
+             } else if (!noexec) {
+                 if (dryrun) {
+                     printf("%s: (dryrun) scrub special file %s\n",
+@@ -343,8 +347,8 @@ static int scrub_object(char *filename, const struct opt_struct *opt,
+                 }
+             }
+             break;
+-        case FILE_LINK:
+-            if (opt->nofollow) {
++        case FILE_REGULAR:
++            if (is_symlink(filename) && opt->nofollow) {
+                 if (opt->remove && !noexec) {
+                     if (dryrun) {
+                         printf("%s: (dryrun) unlink %s\n", prog, filename);
+@@ -359,8 +363,7 @@ static int scrub_object(char *filename, const struct opt_struct *opt,
+                 }
+                 break;
+             }
+-            /* FALL THRU */
+-        case FILE_REGULAR:
++
+             if (access(filename, R_OK|W_OK) < 0) {
+                 fprintf(stderr, "%s: no rw access to %s\n", prog, filename);
+                 errcount++;
+@@ -670,7 +673,7 @@ scrub_file(char *path, const struct opt_struct *opt)
+     filetype_t ftype = filetype(path);
+     off_t size = opt->devsize;
+ 
+-    assert(ftype == FILE_REGULAR || ftype == FILE_LINK);
++    assert(ftype == FILE_REGULAR);
+ 
+     if (stat(path, &sb) < 0) {
+         fprintf(stderr, "%s: stat %s: %s\n", prog, path, strerror(errno));
+diff --git a/src/util.c b/src/util.c
+index 96dd59b..fb85368 100644
+--- a/src/util.c
++++ b/src/util.c
+@@ -71,6 +71,15 @@ write_all(int fd, const unsigned char *buf, int count)
+     return n;
+ }
+ 
++/* Indicates whether the file represented by 'path' is a symlink.
++ */
++int
++is_symlink(char *path)
++{
++    struct stat sb;
++    return lstat(path, &sb) == 0 && S_ISLNK(sb.st_mode);
++}
++
+ /* Return the type of file represented by 'path'.
+  */
+ filetype_t
+@@ -80,10 +89,6 @@ filetype(char *path)
+ 
+     filetype_t res = FILE_NOEXIST;
+ 
+-    if (lstat(path, &sb) == 0 && S_ISLNK(sb.st_mode)) {
+-        return FILE_LINK;
+-    }
+-
+     if (stat(path, &sb) == 0) {
+         if (S_ISREG(sb.st_mode))
+             res = FILE_REGULAR;
+diff --git a/src/util.h b/src/util.h
+index 513ae48..04246df 100644
+--- a/src/util.h
++++ b/src/util.h
+@@ -13,7 +13,6 @@ typedef enum {
+     FILE_REGULAR,
+     FILE_CHAR,
+     FILE_BLOCK,
+-    FILE_LINK,
+     FILE_OTHER,
+ } filetype_t;
+ 
+@@ -21,6 +20,7 @@ typedef enum { UP, DOWN } round_t;
+ 
+ int         read_all(int fd, unsigned char *buf, int count);
+ int         write_all(int fd, const unsigned char *buf, int count);
++int         is_symlink(char *path);
+ filetype_t  filetype(char *path);
+ off_t       blkalign(off_t offset, int blocksize, round_t rtype);
+ void *      alloc_buffer(int bufsize);
diff --git a/SOURCES/scrub-2.6.1-use-libgcrypt.patch b/SOURCES/scrub-2.6.1-use-libgcrypt.patch
new file mode 100644
index 0000000..26a0fa4
--- /dev/null
+++ b/SOURCES/scrub-2.6.1-use-libgcrypt.patch
@@ -0,0 +1,229 @@
+diff -up scrub-2.6.1/configure.ac.libgcrypt scrub-2.6.1/configure.ac
+--- scrub-2.6.1/configure.ac.libgcrypt	2014-08-26 14:15:12.000000000 -0400
++++ scrub-2.6.1/configure.ac	2021-02-22 13:42:48.489217200 -0500
+@@ -70,6 +70,25 @@ AC_CHECK_FUNCS( \
+ X_AC_CHECK_PTHREADS
+ 
+ ##
++# gcrypt library
++##
++have_libgcrypt=no
++AC_ARG_WITH(libgcrypt, AS_HELP_STRING([--without-libgcrypt], [build without libgcrypt;
++                                         fallback to custom AES implementation]))
++AS_IF([test "x$with_libgcrypt" != "xno"],
++  [AM_PATH_LIBGCRYPT([1.5.0],
++    [AC_DEFINE([HAVE_LIBGCRYPT], [1], [libgcrypt API available])
++      gcrypt_CFLAGS="$LIBGCRYPT_CFLAGS"
++      gcrypt_LIBS="$LIBGCRYPT_LIBS"
++      have_libgcrypt=yes
++    ]
++  )]
++)
++AM_CONDITIONAL([LIBGCRYPT], [test "$have_libgcrypt" = "yes"])
++AC_SUBST([gcrypt_CFLAGS])
++AC_SUBST([gcrypt_LIBS])
++
++##
+ # Arrange for large file support
+ ## 
+ AC_SYS_LARGEFILE
+diff -up scrub-2.6.1/src/genrand.c.libgcrypt scrub-2.6.1/src/genrand.c
+--- scrub-2.6.1/src/genrand.c.libgcrypt	2014-08-20 17:33:43.000000000 -0400
++++ scrub-2.6.1/src/genrand.c	2021-02-22 13:42:48.490217204 -0500
+@@ -37,21 +37,27 @@
+ #include <assert.h>
+ #include <libgen.h>
+ 
+-#include "aes.h"
+ #include "util.h"
+ #include "genrand.h"
+ #include "hwrand.h"
+ 
+-#define PATH_URANDOM    "/dev/urandom"
+-
+-#define PAYLOAD_SZ  16
+-#define KEY_SZ      16
++#ifdef HAVE_LIBGCRYPT
++#include <gcrypt.h>
++#else
++#include "aes.h"
++#endif /* HAVE_LIBGCRYPT. */
+ 
+ extern char *prog;
+ 
+ static bool no_hwrand = false;
+ static hwrand_t gen_hwrand;
+ 
++#ifndef HAVE_LIBGCRYPT
++#define PATH_URANDOM    "/dev/urandom"
++
++#define PAYLOAD_SZ  16
++#define KEY_SZ      16
++
+ static aes_context  ctx;
+ static unsigned char ctr[PAYLOAD_SZ];
+ 
+@@ -140,17 +146,26 @@ churnrand(void)
+ error:
+     return -1;
+ }
++#endif /* HAVE_LIBGCRYPT. */
+ 
+ /* Initialize the module.
+  */
+ int
+ initrand(void)
+ {
++#ifndef HAVE_LIBGCRYPT
+     struct timeval tv;
++#else
++    if (!gcry_check_version(GCRYPT_VERSION)) {
++        goto error;
++    }
++    gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
++#endif /* HAVE_LIBGCRYPT */
+ 
+     if (!no_hwrand)
+         gen_hwrand = init_hwrand();
+ 
++#ifndef HAVE_LIBGCRYPT
+     /* Always initialize the software random number generator as backup */
+ 
+     if (gettimeofday(&tv, NULL) < 0)
+@@ -163,6 +178,7 @@ initrand(void)
+ #endif
+     if (churnrand() < 0)
+         goto error;
++#endif /* HAVE_LIBGCRYPT. */
+     return 0;
+ error:
+     return -1;
+@@ -173,9 +189,11 @@ error:
+ void 
+ genrand(unsigned char *buf, int buflen)
+ {
++#ifndef HAVE_LIBGCRYPT
+     int i;
+     unsigned char out[PAYLOAD_SZ];
+     int cpylen = PAYLOAD_SZ;
++#endif /* HAVE_LIBGCRYPT. */
+ 
+     if (gen_hwrand) {
+         bool hwok = gen_hwrand(buf, buflen);
+@@ -183,6 +201,7 @@ genrand(unsigned char *buf, int buflen)
+             return;
+     }
+ 
++#ifndef HAVE_LIBGCRYPT
+     for (i = 0; i < buflen; i += cpylen) {
+         aes_encrypt(&ctx, ctr, out);
+         incr128(ctr);
+@@ -191,6 +210,9 @@ genrand(unsigned char *buf, int buflen)
+         memcpy(&buf[i], out, cpylen);
+     }
+     assert(i == buflen);
++#else
++    gcry_randomize(buf, buflen, GCRY_STRONG_RANDOM);
++#endif /* HAVE_LIBGCRYPT. */
+ }
+ 
+ /*
+diff -up scrub-2.6.1/src/genrand.h.libgcrypt scrub-2.6.1/src/genrand.h
+--- scrub-2.6.1/src/genrand.h.libgcrypt	2014-08-20 17:33:43.000000000 -0400
++++ scrub-2.6.1/src/genrand.h	2021-02-22 13:42:48.490217204 -0500
+@@ -1,8 +1,14 @@
++#include "config.h"
++
+ void disable_hwrand(void);
+ int initrand(void);
+-int churnrand(void);
+ void genrand(unsigned char *buf, int buflen);
+ 
++#ifndef HAVE_LIBGCRYPT
++int churnrand(void);
++#endif /* HAVE_LIBGCRYPT. */
++
++
+ /*
+  * vi:tabstop=4 shiftwidth=4 expandtab
+  */
+diff -up scrub-2.6.1/src/Makefile.am.libgcrypt scrub-2.6.1/src/Makefile.am
+--- scrub-2.6.1/src/Makefile.am.libgcrypt	2014-08-20 17:33:43.000000000 -0400
++++ scrub-2.6.1/src/Makefile.am	2021-02-22 13:43:47.008492696 -0500
+@@ -1,8 +1,6 @@
+ bin_PROGRAMS = scrub
+ 
+ scrub_SOURCES = \
+-	aes.c \
+-	aes.h \
+ 	filldentry.c \
+ 	filldentry.h \
+ 	fillfile.c \
+@@ -24,3 +22,9 @@ scrub_SOURCES = \
+ 	util.h
+ 
+ scrub_LDADD = $(LIBPTHREAD)
++
++if LIBGCRYPT
++scrub_LDADD += $(gcrypt_LIBS)
++else
++scrub_SOURCES += aes.c aes.h
++endif
+diff -up scrub-2.6.1/src/scrub.c.libgcrypt scrub-2.6.1/src/scrub.c
+--- scrub-2.6.1/src/scrub.c.libgcrypt	2021-02-22 13:42:48.488217195 -0500
++++ scrub-2.6.1/src/scrub.c	2021-02-22 13:42:48.490217204 -0500
+@@ -459,11 +459,13 @@ scrub(char *path, off_t size, const sequ
+             case PAT_RANDOM:
+                 printf("%s: %-8s", prog, "random");
+                 progress_create(&p, pcol);
++#ifndef HAVE_LIBGCRYPT
+                 if (churnrand() < 0) {
+                     fprintf(stderr, "%s: churnrand: %s\n", prog,
+                              strerror(errno));
+                     exit(1);
+                 }
++#endif /* HAVE_LIBGCRYPT. */
+                 written = fillfile(path, size, buf, bufsize, 
+                                    (progress_t)progress_update, p, 
+                                    (refill_t)genrand, sparse, enospc);
+diff -up scrub-2.6.1/test/Makefile.am.libgcrypt scrub-2.6.1/test/Makefile.am
+--- scrub-2.6.1/test/Makefile.am.libgcrypt	2014-08-26 14:11:14.000000000 -0400
++++ scrub-2.6.1/test/Makefile.am	2021-02-22 13:44:59.301833042 -0500
+@@ -1,8 +1,8 @@
+-check_PROGRAMS = pad trand aestest tprogress tgetsize tsig tsize pat
++check_PROGRAMS = pad trand tprogress tgetsize tsig tsize pat
+ 
+ TESTS_ENVIRONMENT = env 
+ TESTS_ENVIRONMENT += "PATH_SCRUB=$(top_builddir)/src/scrub"
+-TESTS = t00 t01 t02 t03 t04 t05 t06 t07 t08 t09 t10 t11 t12 t13 t14 t15 t16 \
++TESTS = t01 t02 t03 t04 t05 t06 t07 t08 t09 t10 t11 t12 t13 t14 t15 t16 \
+ 	t17 t18 t19 t20 t21 t22
+ 
+ CLEANFILES = *.out *.diff testfile
+@@ -13,17 +13,24 @@ common_sources = \
+ 	$(top_srcdir)/src/getsize.c \
+ 	$(top_srcdir)/src/genrand.c \
+ 	$(top_srcdir)/src/hwrand.c \
+-	$(top_srcdir)/src/aes.c \
+ 	$(top_srcdir)/src/util.c \
+ 	$(top_srcdir)/src/progress.c \
+ 	$(top_srcdir)/src/sig.c
+ 
+ pad_SOURCES = pad.c $(common_sources)
+ trand_SOURCES = trand.c $(common_sources)
+-aestest_SOURCES = aestest.c $(common_sources)
+ tprogress_SOURCES = tprogress.c $(common_sources)
+ tgetsize_SOURCES = tgetsize.c $(common_sources)
+ tsig_SOURCES = tsig.c $(common_sources)
+ pat_SOURCES = pat.c $(common_sources)
+ 
++if LIBGCRYPT
++AM_LDFLAGS = $(gcrypt_LIBS)
++else
++check_PROGRAMS += aestest
++TESTS += t00
++common_sources += $(top_srcdir)/src/aes.c
++aestest_SOURCES = aestest.c $(common_sources)
++endif
++
+ EXTRA_DIST = $(TESTS) $(TESTS:%=%.exp)
diff --git a/SPECS/scrub.spec b/SPECS/scrub.spec
new file mode 100644
index 0000000..8832ad3
--- /dev/null
+++ b/SPECS/scrub.spec
@@ -0,0 +1,168 @@
+Name:		scrub
+Version:	2.6.1
+Release:	4%{?dist}
+Summary:	Disk scrubbing program
+License:	GPLv2+
+URL:		https://github.com/chaos/scrub/
+Source0:	https://github.com/chaos/scrub/releases/download/%{version}/scrub-%{version}.tar.gz
+# https://github.com/chaos/scrub/commit/b90fcb2330d00dbd1e9aeaa2e1a9807f8b80b922.patch
+Patch0:		scrub-2.6.1-symlinks-to-block-device.patch
+# https://github.com/chaos/scrub/commit/27f6452a658f057e3ba6bf9dfda070b6dffc6798.patch
+Patch1:		scrub-2.6.1-use-libgcrypt.patch
+Patch2:		scrub-2.6.1-extentonly.patch
+Patch3:		scrub-2.5.2-test-use-power-2-filesizes.patch
+# https://github.com/chaos/scrub/commit/864a454f16ac3e47103064b0e4fe3a9111593e49
+Patch4:		scrub-2.6.1-analyzer-fixes.patch
+BuildRequires:	make
+BuildRequires:	gcc
+BuildRequires:	libgcrypt-devel
+BuildRequires:	autoconf, automake, libtool
+
+%description
+Scrub writes patterns on files or disk devices to make
+retrieving the data more difficult.  It operates in one of three
+modes: 1) the special file corresponding to an entire disk is scrubbed
+and all data on it is destroyed;  2) a regular file is scrubbed and
+only the data in the file (and optionally its name in the directory
+entry) is destroyed; or 3) a regular file is created, expanded until
+the file system is full, then scrubbed as in 2).
+
+%prep
+%setup -q
+%patch0 -p1 -b .symlinks-to-block-devices
+%patch1 -p1 -b .libgcrypt
+%patch2 -p1 -b .extent-only
+%patch3 -p1 -b .test-use-power-2-filesizes
+%patch4 -p1 -b .analyzer-fixes
+autoreconf -ifv --include=config
+
+%build
+%configure
+%{make_build}
+
+%install
+%{make_install}
+
+%files
+%license COPYING
+%doc DISCLAIMER
+%doc README ChangeLog
+%{_bindir}/scrub
+%{_mandir}/man1/scrub.1*
+
+%changelog
+* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 2.6.1-4
+- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
+  Related: rhbz#1991688
+
+* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 2.6.1-3
+- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
+
+* Thu Mar 18 2021 Tom Callaway <spot@fedoraproject.org> - 2.6.1-2
+- apply analyzer fixes from upstream
+
+* Wed Feb 24 2021 Tom Callaway <spot@fedoraproject.org> - 2.6.1-1
+- update to 2.6.1
+- update URLs
+- merge patches from Red Hat and upstream
+
+* Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-18
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
+
+* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-17
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
+
+* Thu Jan 30 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-16
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
+
+* Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-15
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Sat Feb 02 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-14
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-13
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Fri Feb 09 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-12
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-11
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Thu Jul 27 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-10
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
+* Sat Feb 11 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-9
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
+
+* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 2.5.2-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
+
+* Fri Jun 19 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.5.2-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
+
+* Mon Aug 18 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.5.2-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Sun Jun 08 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.5.2-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Sun Aug 04 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.5.2-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
+
+* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.5.2-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
+
+* Sat Jul 21 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.5.2-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Mon Jun 25 2012 Tom Callaway <spot@fedoraproject.org> - 2.5.2-1
+- update to 2.5.2
+
+* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.4.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Tue Aug 30 2011 Tom Callaway <spot@fedoraproject.org> - 2.4.1-1
+- update to 2.4.1
+
+* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Thu Nov  4 2010 Tom "spot" Callaway <tcallawa@redhat.com> - 2.4-1
+- update to 2.4
+
+* Tue Jun 29 2010 Tom "spot" Callaway <tcallawa@redhat.com> - 2.2-1
+- update to 2.2, new url, source location
+
+* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Fri Nov 14 2008 Tom "spot" Callaway <tcallawa@redhat.com> - 2.1-1
+- update to 2.1
+
+* Tue Feb 19 2008 Fedora Release Engineering <rel-eng@fedoraproject.org> - 1.9-3
+- Autorebuild for GCC 4.3
+
+* Mon Aug 27 2007 Tom "spot" Callaway <tcallawa@redhat.com> 1.9-2
+- license tag fix
+- ppc32 rebuild
+
+* Mon Jul  9 2007 Tom "spot" Callaway <tcallawa@redhat.com> 1.9-1
+- bump to 1.9
+
+* Mon Sep  4 2006 Tom "spot" Callaway <tcallawa@redhat.com> 1.8-1
+- bump to 1.8
+
+* Mon Feb 20 2006 Tom "spot" Callaway <tcallawa@redhat.com> 1.7-1
+- bump to 1.7, update URL, Source0
+- use Ben Woodard's description
+
+* Sat May 21 2005 Tom "spot" Callaway <tcallawa@redhat.com> 1.6-2
+- cleanups
+
+* Thu May 19 2005 Tom "spot" Callaway <tcallawa@redhat.com> 1.6-1
+- initial package for Fedora Extras