diff --git a/.gitignore b/.gitignore index dda2bde..021b6dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -/zerofree-*.tgz +zerofree-1.0.1.tgz diff --git a/index.html b/index.html index 2a0b312..92e5b0d 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,5 @@ - - Keeping filesystem images sparse @@ -56,43 +51,79 @@ all the free space: The disadvantage of dd in this context is that it destroys any sparseness that exists: free blocks that were originally represented as holes in the image file are replaced with actual blocks containing -zeroes. Also, filling up a live filesystem is probably a bad idea. +zeroes.

As an alternative approach, and as practice in mucking about with ext2 filesystems, I've written a utility which scans the free blocks in an ext2 filesystem and fills any non-zero blocks with zeroes. -The source, zerofree-1.1.1.tgz, is -available for download. +(The source, zerofree-1.0.1.tgz, is +available for download.) The zerofree utility is faster +than dd, especially when the filesystem is already partly sparse. +The filesystem to be processed should be unmounted or mounted read-only.

+Better than either of these would be to have the guest kernel keep the free +blocks empty. My original inspiration was the + +ext2fs privacy (i.e. secure deletion) patch described in a Linux +kernel mailing list thread. I've also made use of a later patch for ext3 +entitled +Secure Deletion Functionality in ext3 +from the linux-fsdevel mailing list. (See also the authors' paper on +Secure Deletion File Systems.) +I've modified the patches to make them more suitable for the present purpose.

+When a filesystem is mounted with the zerofree option (added +by these patches) all the blocks freed when a file is deleted are filled +with zeroes. +Remember, this extra work will hurt disk performance. +Note that the ext3 patch doesn't support data journalling +mode, so deleted metadata isn't zeroed. It also hasn't been tested +as thoroughly as the patch for ext2.

-However, this is only half the story: the empty free +However, the above techniques are only half the story: the empty free blocks still consume space in the underlying filesystem, so something -must to be done to reclaim that space. +must to be done to reclaim that space. One approach would be to +implement a system call, like the legendary + +sys_punch, which could be used to write a utility to make any +suitable file sparse.

-A common suggestion is to use the sparse file handling capabilities +An existing alternative is to use the sparse file handling capabilities of the GNU cp command to take a copy of the filesystem image with cp --sparse=always (though this does require the original and sparse files to exist at the same time, which may be inconvenient).

-If your kernel and util-linux are sufficiently modern and you have a supported -filesystem you can use fallocate -d to 'dig holes' in a file. -This makes the file sparse in-place, without using extra disk space. +As an alternative alternative I've written a utility which can make +any specified files on an ext2 filesystem +sparse, sparsify.c. This doesn't require any +additional disk space to work its magic, but it does require that the +filesystem containing the filesystem image is unmounted, which is just a +different sort of inconvenience. +

+(The usual disclaimers apply: this worked for me +when I tested it but it might destroy your data. Only use it on +disposable filesystems, or have a full backup available. e2fsck +is your friend.) +

+As an example, suppose we have an unmounted filesystem +image, fs.image, in the directory /data, which is the +root of the /dev/hda2 filesystem. We can reclaim deleted +blocks and make it sparse like so: +

+

+   zerofree /data/fs.image
+   umount /data
+   sparsify /dev/hda2 /fs.image
+   mount /data
+


-Ron Yorston
-18th April 2004 (updated 19th February 2018)
-Some obsolete information has been moved to a -separate page. +Ron Yorston
+29th July 2008
diff --git a/sources b/sources index 05a7873..2c5121c 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (zerofree-1.1.1.tgz) = 2d7ee57a877bff2491c48054338a26d624ae75c238ac2b0568a75de88b6621c16cc1e7d65500879825d14d8ba44a5173587a061459072769c165bee47c3f9f1c +a8c772fdd134448f25ab4e7e12004595 zerofree-1.0.1.tgz diff --git a/sparsify-opaque-group-desc.patch b/sparsify-opaque-group-desc.patch new file mode 100644 index 0000000..2db49f9 --- /dev/null +++ b/sparsify-opaque-group-desc.patch @@ -0,0 +1,14 @@ +--- zerofree-1.0.1.old/sparsify.c 2012-01-16 14:15:53.752724537 +0000 ++++ zerofree-1.0.1/sparsify.c 2012-01-16 14:27:18.546285148 +0000 +@@ -43,8 +43,9 @@ + + if ( i == fs->blocksize && !p->dryrun ) { + ext2fs_unmark_block_bitmap(fs->block_map, *blocknr) ; +- group = ext2fs_group_of_blk(fs, *blocknr); +- fs->group_desc[group].bg_free_blocks_count++; ++ group = ext2fs_group_of_blk2(fs, *blocknr); ++ ext2fs_bg_free_blocks_count_set(fs, group, ++ ext2fs_bg_free_blocks_count(fs, group) + 1); + fs->super->s_free_blocks_count++ ; + /* the inode counts blocks of 512 bytes */ + p->inode->i_blocks -= fs->blocksize / 512 ; diff --git a/sparsify.c b/sparsify.c index 4c52e00..fbcd71f 100644 --- a/sparsify.c +++ b/sparsify.c @@ -1,10 +1,10 @@ /* * sparsify - a tool to make files on an ext2 filesystem sparse * - * Copyright (C) 2004-2012 R M Yorston + * Copyright (C) 2004 R M Yorston * * This file may be redistributed under the terms of the GNU General Public - * License, version 2. + * License. */ #include #include @@ -13,262 +13,181 @@ #define USAGE "usage: %s [-n] [-v] filesystem filename ...\n" -/* initially assume pre-ext4 API version */ -#define API 140 - -#if defined(BLOCK_FLAG_READ_ONLY) -#undef API -#define API 141 -#endif - -#if defined(EXT2_FLAG_64BITS) -#undef API -#define API 142 -#endif - struct process_data { + struct ext2_inode *inode ; unsigned char *buf; - int verbose; - int dryrun; - blk_t count; - blk_t blocks; - blk_t total_blocks; - int old_percent; -}; + int dryrun ; + int changed ; +} ; static int process(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, blk_t ref_block, int ref_offset, void *priv) { - struct process_data *p; - errcode_t errcode; - int i, group; - int ret = 0; + struct process_data *p ; + errcode_t ret ; + int i, group ; - p = (struct process_data *)priv; + p = (struct process_data *)priv ; - p->blocks++; if ( blockcnt >= 0 ) { - errcode = io_channel_read_blk(fs->io, *blocknr, 1, p->buf); - if ( errcode ) { - return BLOCK_ABORT; + ret = io_channel_read_blk(fs->io, *blocknr, 1, p->buf); + if ( ret ) { + return BLOCK_ABORT ; } for ( i=0; i < fs->blocksize; ++i ) { if ( p->buf[i] ) { - break; + break ; } } - if ( i == fs->blocksize ) { - p->count++; - - if ( !p->dryrun ) { - ext2fs_unmark_block_bitmap(fs->block_map, *blocknr); - group = ext2fs_group_of_blk(fs, *blocknr); -#if API >= 142 - ext2fs_bg_free_blocks_count_set(fs, group, - ext2fs_bg_free_blocks_count(fs, group)+1); - ext2fs_free_blocks_count_add(fs->super, (blk64_t)1); -#else - fs->group_desc[group].bg_free_blocks_count++; - fs->super->s_free_blocks_count++; -#endif -#if API >= 141 - ext2fs_group_desc_csum_set(fs, group); -#endif - *blocknr = 0; - ret = BLOCK_CHANGED; - } - } - - if ( p->verbose ) { - double percent; - - percent = 100.0 * (double)p->blocks/(double)p->total_blocks; - - if ( (int)(percent*10) != p->old_percent ) { - fprintf(stderr, "\r%4.1f%%", percent); - p->old_percent = (int)(percent*10); + if ( i == fs->blocksize && !p->dryrun ) { + ext2fs_unmark_block_bitmap(fs->block_map, *blocknr) ; + group = ext2fs_group_of_blk(fs, *blocknr); + fs->group_desc[group].bg_free_blocks_count++; + fs->super->s_free_blocks_count++ ; + /* the inode counts blocks of 512 bytes */ + p->inode->i_blocks -= fs->blocksize / 512 ; + *blocknr = 0 ; + /* direct blocks need to be zeroed in the inode */ + if ( blockcnt < EXT2_NDIR_BLOCKS ) { + p->inode->i_block[blockcnt] = 0 ; } + p->changed = 1 ; + return BLOCK_CHANGED ; } } - return ret; + return 0 ; } int main(int argc, char **argv) { - int verbose = 0; - int dryrun = 0; - errcode_t ret; - int flags; - int superblock = 0; - int open_flags = EXT2_FLAG_RW; - int iter_flags = 0; - int blocksize = 0; - ext2_filsys fs = NULL; - struct ext2_inode inode; - ext2_ino_t root, cwd, inum; - int i, c; - struct process_data pdata; + int verbose = 0 ; + int dryrun = 0 ; + errcode_t ret ; + int flags ; + int superblock = 0 ; + int open_flags = EXT2_FLAG_RW ; + int blocksize = 0 ; + ext2_filsys current_fs = NULL; + struct ext2_inode inode ; + ext2_ino_t root, cwd, inum ; + int i, c ; + struct process_data pdata ; while ( (c=getopt(argc, argv, "nv")) != -1 ) { switch (c) { case 'n' : - dryrun = 1; -#if defined(BLOCK_FLAG_READ_ONLY) - iter_flags |= BLOCK_FLAG_READ_ONLY; -#endif - break; + dryrun = 1 ; + break ; case 'v' : - verbose = 1; - break; + verbose = 1 ; + break ; default : - fprintf(stderr, USAGE, argv[0]); - return 1; + fprintf(stderr, USAGE, argv[0]) ; + return 1 ; } } if ( argc < optind+2 ) { - fprintf(stderr, USAGE, argv[0]); - return 1; + fprintf(stderr, USAGE, argv[0]) ; + return 1 ; } - ret = ext2fs_check_if_mounted(argv[optind], &flags); + ret = ext2fs_check_if_mounted(argv[optind], &flags) ; if ( ret ) { fprintf(stderr, "%s: failed to determine filesystem mount state %s\n", - argv[0], argv[optind]); - return 1; + argv[0], argv[optind]) ; + return 1 ; } if ( flags & EXT2_MF_MOUNTED ) { fprintf(stderr, "%s: filesystem %s is mounted\n", - argv[0], argv[optind]); - return 1; + argv[0], argv[optind]) ; + return 1 ; } ret = ext2fs_open(argv[optind], open_flags, superblock, blocksize, - unix_io_manager, &fs); + unix_io_manager, ¤t_fs); if ( ret ) { fprintf(stderr, "%s: failed to open filesystem %s\n", - argv[0], argv[optind]); - return 1; + argv[0], argv[optind]) ; + return 1 ; } - pdata.buf = (unsigned char *)malloc(fs->blocksize); + pdata.buf = (unsigned char *)malloc(current_fs->blocksize) ; if ( pdata.buf == NULL ) { - fprintf(stderr, "%s: out of memory (surely not?)\n", argv[0]); - return 1; + fprintf(stderr, "%s: out of memory (surely not?)\n", argv[0]) ; + return 1 ; } - ret = ext2fs_read_inode_bitmap(fs); + ret = ext2fs_read_inode_bitmap(current_fs); if ( ret ) { fprintf(stderr, "%s: error while reading inode bitmap\n", argv[0]); - return 1; + return 1 ; } - ret = ext2fs_read_block_bitmap(fs); + ret = ext2fs_read_block_bitmap(current_fs); if ( ret ) { fprintf(stderr, "%s: error while reading block bitmap\n", argv[0]); - return 1; + return 1 ; } - root = cwd = EXT2_ROOT_INO; + root = cwd = EXT2_ROOT_INO ; for ( i=optind+1; isuper->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) - && (inode.i_flags & EXT4_HUGE_FILE_FL) ) { - fprintf(stderr, "%s: unable to process %s, it's huge\n", - argv[0], argv[i]); - continue; - } -#endif - - if ( verbose ) { - printf("processing %s\n", argv[i]); - } - - pdata.verbose = verbose; - pdata.dryrun = dryrun; - pdata.count = pdata.blocks = 0; - pdata.total_blocks = inode.i_blocks/(fs->blocksize >> 9); - pdata.old_percent = 1000; - ret = ext2fs_block_iterate2(fs, inum, iter_flags, NULL, - process, &pdata); + pdata.inode = &inode ; + pdata.dryrun = dryrun ; + pdata.changed = 0 ; + ret = ext2fs_block_iterate2(current_fs, inum, BLOCK_FLAG_DATA_ONLY, + NULL, process, &pdata) ; if ( ret ) { fprintf(stderr, "%s: failed to process file %s\n", argv[0], - argv[i]); - continue; + argv[i]) ; + continue ; } - if ( pdata.count && !dryrun ) { - ext2fs_mark_bb_dirty(fs); - ext2fs_mark_super_dirty(fs); - - ret = ext2fs_read_inode(fs, inum, &inode); + if ( pdata.changed ) { + ret = ext2fs_write_inode(current_fs, inum, &inode) ; if ( ret ) { - fprintf(stderr, "%s: failed to open inode (%s)\n", argv[0], - argv[i]); - continue; + fprintf(stderr, "%s: failed to write inode data %s\n", argv[0], + argv[i]) ; + continue ; } -#if API >= 141 - ret = ext2fs_iblk_sub_blocks(fs, &inode, (blk64_t)pdata.count); - if ( ret ) { - fprintf(stderr, "%s: failed to update block count (%s)\n", - argv[0], argv[i]); - continue; - } -#else - inode.i_blocks -= pdata.count * (fs->blocksize >> 9); -#endif - - ret = ext2fs_write_inode(fs, inum, &inode); - if ( ret ) { - fprintf(stderr, "%s: failed to write inode (%s)\n", - argv[0], argv[i]); - continue; - } - } - - if ( verbose ) { - printf("\r%d/%d/%d %s\n", pdata.count, pdata.blocks, - pdata.total_blocks, argv[i]); + ext2fs_mark_bb_dirty(current_fs) ; + ext2fs_mark_super_dirty(current_fs) ; } } - ret = ext2fs_close(fs); + ret = ext2fs_close(current_fs) ; if ( ret ) { - fprintf(stderr, "%s: error while closing filesystem\n", argv[0]); - return 1; + fprintf(stderr, "%s: error while closing filesystem\n", argv[0]) ; + return 1 ; } - return 0; + return 0 ; } diff --git a/zerofree.8 b/zerofree.8 index ee306b5..b0be0d2 100644 --- a/zerofree.8 +++ b/zerofree.8 @@ -1,36 +1,25 @@ .TH "ZEROFREE" "8" .SH "NAME" -zerofree \(em zero free blocks from ext2, ext3 and ext4 file-systems +zerofree \(em zero free blocks from ext2/3 file-systems .SH "SYNOPSIS" .PP -\fBzerofree\fR [\fB-n\fP] [\fB-v\fP] [\fB-f fillval\fP] \fIfilesystem\fR +\fBzerofree\fR [\fB-n\fP] [\fB-v\fP] \fIfilesystem\fR .SH "DESCRIPTION" .PP \fBzerofree\fR finds the unallocated, -blocks with non-zero value content in an ext2, ext3 or ext4 +non-zeroed blocks in an ext2 or ext3 \fIfilesystem\fR (e.g. /dev/hda1) and -fills them with zeroes (or another octet of your choice). - - -.PP -Filling unused areas with zeroes is useful if the device on -which this file-system resides is a disk image. In this case, +fills them with zeroes. This is useful if the device on which +this file-system resides is a disk image. In this case, depending on the type of disk image, a secondary utility may be able to reduce the size of the disk image after zerofree has -been run. - -.PP -Filling unused areas may also be useful with solid-state -drives (SSDs). On some SSDs, filling blocks with ones (0xFF) -is reported to trigger Flash block erasure by the firmware, -possibly giving a write performance increase. - +been run. .PP The usual way to achieve the same result (zeroing the unallocated blocks) is to run \fBdd\fR (1) to create a file full of zeroes that takes up the entire free space on the drive, and then delete this file. This has many -disadvantages, which zerofree alleviates: +disadvantages, which zerofree alleviates: .IP " \(bu" 6 it is slow; .IP " \(bu" 6 @@ -38,8 +27,7 @@ it makes the disk image (temporarily) grow to its maximal extent; .IP " \(bu" 6 it (temporarily) uses all free space on the disk, so other -concurrent write actions may fail. - +concurrent write actions may fail. .PP \fIfilesystem\fR has to be unmounted or mounted read-only for \fBzerofree\fR to work. It @@ -48,36 +36,17 @@ will exit with an error message if the remount the root file-system readonly, you can first switch to single user runlevel (\fBtelinit 1\fR) then use \fBmount \-o remount,ro -\fIfilesystem\fR\fR. - +\fIfilesystem\fR\fR. .PP -\fBzerofree\fR has been written to be run -from GNU/Linux systems installed as guest OSes inside a virtual -machine. In this case, it is typically run from within the guest -system, and a utility is then run from the host system to shrink -disk image (\fBVBoxManage modifyhd \-\-compact\fR, -provided with virtualbox, is able to do that for some disk image -formats). - -.PP -It may however be useful in other situations: for instance -it can be used to make it more difficult to retrieve deleted -data. Beware that securely deleting sensitive data is not in -general an easy task and usually requires writing several times -on the deleted blocks. - +\fBzerofree\fR has been written to be +run from GNU/Linux systems installed as guest OSes inside a +virtual machine. It may however be useful in other +situations. .SH "OPTIONS" .IP "\fB-n\fP " 10 Perform a dry run (do not modify the file-system); .IP "\fB-v\fP " 10 -Be verbose: show the number of blocks modified by -\fBzerofree\fR (or that would be modified, -in case the \fB-n\fP is used), the number of free -blocks and the total number of blocks on the -filesystem; -.IP "\fB-f value\fP " 10 -Specify the octet value to fill empty blocks with (defaults to -0). Argument must be within the range 0 to 255. +Be verbose. .SH "SEE ALSO" .PP dd (1). @@ -93,4 +62,4 @@ later version published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL-2. -.\" created by instant / docbook-to-man, Thu 31 Dec 2020, 01:06 +.\" created by instant / docbook-to-man, Wed 25 Nov 2009, 17:45 diff --git a/zerofree.sgml b/zerofree.sgml index 1c40f71..e5c43a3 100644 --- a/zerofree.sgml +++ b/zerofree.sgml @@ -9,7 +9,7 @@ Thibaut"> Paumard"> - April 3rd, 2012"> + February 6, 2008"> 8"> <paumard@users.sourceforge.net>"> @@ -44,7 +44,7 @@ &dhpackage; - zero free blocks from ext2, ext3 and ext4 file-systems + zero free blocks from ext2/3 file-systems @@ -54,8 +54,6 @@ - - filesystem @@ -63,21 +61,14 @@ DESCRIPTION &dhpackage; finds the unallocated, - blocks with non-zero value content in an ext2, ext3 or ext4 + non-zeroed blocks in an ext2 or ext3 filesystem (e.g. /dev/hda1) and - fills them with zeroes (or another octet of your choice). - - Filling unused areas with zeroes is useful if the device on - which this file-system resides is a disk image. In this case, + fills them with zeroes. This is useful if the device on which + this file-system resides is a disk image. In this case, depending on the type of disk image, a secondary utility may be able to reduce the size of the disk image after zerofree has been run. - Filling unused areas may also be useful with solid-state - drives (SSDs). On some SSDs, filling blocks with ones (0xFF) - is reported to trigger Flash block erasure by the firmware, - possibly giving a write performance increase. - The usual way to achieve the same result (zeroing the unallocated blocks) is to run dd (1) to create a file full of zeroes that takes up the entire free @@ -103,19 +94,10 @@ mount -o remount,ro filesystem. - &dhpackage; has been written to be run - from GNU/Linux systems installed as guest OSes inside a virtual - machine. In this case, it is typically run from within the guest - system, and a utility is then run from the host system to shrink - disk image (VBoxManage modifyhd --compact, - provided with virtualbox, is able to do that for some disk image - formats). - - It may however be useful in other situations: for instance - it can be used to make it more difficult to retrieve deleted - data. Beware that securely deleting sensitive data is not in - general an easy task and usually requires writing several times - on the deleted blocks. + &dhpackage; has been written to be + run from GNU/Linux systems installed as guest OSes inside a + virtual machine. It may however be useful in other + situations. @@ -133,19 +115,7 @@ - Be verbose: show the number of blocks modified by - &dhpackage; (or that would be modified, - in case the is used), the number of free - blocks and the total number of blocks on the - filesystem; - - - - - - - Specify the octet value to fill empty blocks with (defaults to - 0). Argument must be within the range 0 to 255. + Be verbose. diff --git a/zerofree.spec b/zerofree.spec index 45118bc..b24a7ff 100644 --- a/zerofree.spec +++ b/zerofree.spec @@ -1,26 +1,36 @@ -Summary: Utility to force unused ext2/3/4 inodes and blocks to zero +Summary: Utility to force unused ext2 inodes and blocks to zero Name: zerofree -Version: 1.1.1 -Release: 18%{?dist} -License: GPL-2.0-only -URL: https://frippery.org/uml/ -Source0: https://frippery.org/uml/%{name}-%{version}.tgz -Source1: https://frippery.org/uml/sparsify.c -Source2: https://frippery.org/uml/index.html +Version: 1.0.1 +Release: 12%{?dist} +License: GPL+ +Group: System Environment/Libraries + +Source0: http://intgat.tigress.co.uk/rmy/uml/%{name}-%{version}.tgz +Source1: http://intgat.tigress.co.uk/rmy/uml/sparsify.c +Source2: http://intgat.tigress.co.uk/rmy/uml/index.html + # zerofree.sgml is the source for the man page from Debian. -# Unfortunately we cannot build this in Fedora because we do not have -# docbook-to-man, just docbook2man and db2x_docbook2man. The included -# man page was generated on a Debian system from this source. +# Unfortunately we cannot build this in Fedora because of an apparent +# bug in our DocBook tools. Therefore I also include the generated +# man page (generated on a Debian system from this source). Source3: zerofree.sgml Source4: zerofree.8 -BuildRequires: gcc -BuildRequires: make + +# e2fsprogs >= 1.42 prevents you from accessing the block group +# descriptor struct directly. +Patch1: sparsify-opaque-group-desc.patch + +URL: http://intgat.tigress.co.uk/rmy/uml/ + BuildRequires: e2fsprogs-devel +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + + %description zerofree is a utility to set unused filesystem inodes and blocks of an -ext2/3/4 filesystem to zero. This can improve the compressibility and -privacy of an ext2/3/4 filesystem. +ext2 filesystem to zero. This can improve the compressibility and +privacy of an ext2 filesystem. This tool was inspired by the ext2fs privacy (i.e. secure deletion) patch described in a Linux kernel mailing list thread. @@ -29,121 +39,40 @@ WARNING: The filesystem to be processed should be unmounted or mounted read-only. The tool tries to check this before running, but you should be careful. + %prep %setup -q -cp -p %{SOURCE1} %{SOURCE2} . +cp -p %{SOURCE1} . +cp -p %{SOURCE2} . +%patch1 -p1 + %build -make CC="%{__cc} $RPM_OPT_FLAGS $RPM_LD_FLAGS" -%{__cc} $RPM_OPT_FLAGS $RPM_LD_FLAGS -o sparsify sparsify.c -lext2fs +make CC="gcc $RPM_OPT_FLAGS" +gcc $RPM_OPT_FLAGS sparsify.c -o sparsify -lext2fs + %install +rm -rf $RPM_BUILD_ROOT + install -D -p -m 755 zerofree $RPM_BUILD_ROOT%{_sbindir}/zerofree install -D -p -m 755 sparsify $RPM_BUILD_ROOT%{_sbindir}/sparsify install -D -p -m 644 %{SOURCE4} $RPM_BUILD_ROOT%{_mandir}/man8/zerofree.8 + %files -%license COPYING -%doc index.html +%defattr(-,root,root,-) +%doc COPYING index.html %{_sbindir}/zerofree %{_sbindir}/sparsify %{_mandir}/man8/zerofree.8* + +%clean +rm -rf $RPM_BUILD_ROOT + + %changelog -* Fri Jul 17 2026 Fedora Release Engineering - 1.1.1-18 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild - -* Sat Jan 17 2026 Fedora Release Engineering - 1.1.1-17 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild - -* Fri Jul 25 2025 Fedora Release Engineering - 1.1.1-16 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Sun Jan 19 2025 Fedora Release Engineering - 1.1.1-15 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Sat Jul 20 2024 Fedora Release Engineering - 1.1.1-14 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Sat Jan 27 2024 Fedora Release Engineering - 1.1.1-13 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Sat Jul 22 2023 Fedora Release Engineering - 1.1.1-12 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Sat Jan 21 2023 Fedora Release Engineering - 1.1.1-11 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Sat Jul 23 2022 Fedora Release Engineering - 1.1.1-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Sat Jan 22 2022 Fedora Release Engineering - 1.1.1-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Fri Jul 23 2021 Fedora Release Engineering - 1.1.1-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Thu Jan 28 2021 Fedora Release Engineering - 1.1.1-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Wed Jul 29 2020 Fedora Release Engineering - 1.1.1-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Fri Jan 31 2020 Fedora Release Engineering - 1.1.1-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Sat Jul 27 2019 Fedora Release Engineering - 1.1.1-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Sun Feb 03 2019 Fedora Release Engineering - 1.1.1-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Sat Jul 14 2018 Fedora Release Engineering - 1.1.1-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Tue Feb 20 2018 Robert Scheck - 1.1.1-1 -- Upgrade to 1.1.1 - -* Mon Feb 19 2018 Robert Scheck - 1.1.0-1 -- Upgrade to 1.1.0 - -* Fri Feb 09 2018 Fedora Release Engineering - 1.0.3-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Thu Aug 03 2017 Fedora Release Engineering - 1.0.3-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild - -* Thu Jul 27 2017 Fedora Release Engineering - 1.0.3-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Sat Feb 11 2017 Fedora Release Engineering - 1.0.3-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - -* Wed Apr 06 2016 Robert Scheck - 1.0.3-6 -- Build with ext4 support for RHEL 5 (#862934, thanks to Mike Swanson) - -* Fri Feb 05 2016 Fedora Release Engineering - 1.0.3-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild - -* Fri Jun 19 2015 Fedora Release Engineering - 1.0.3-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild - -* Mon Aug 18 2014 Fedora Release Engineering - 1.0.3-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild - -* Sat Jun 07 2014 Fedora Release Engineering - 1.0.3-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild - -* Mon Nov 18 2013 Richard W.M. Jones - 1.0.3-1 -- New upstream version 1.0.3. -- New upstream version of sparsify.c. -- Fix the license. -- Modernize the spec file. -- Remove sparsify patch (equivalent patch has gone upstream). - -* Sun Aug 04 2013 Fedora Release Engineering - 1.0.1-13 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild - * Fri Feb 15 2013 Fedora Release Engineering - 1.0.1-12 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild