Compare commits
33 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af0dbcb9b0 | ||
|
|
4cf4c0d223 | ||
|
|
d4e6241bd8 | ||
|
|
18215950b1 | ||
|
|
cbb4933d6c | ||
|
|
200192e08a | ||
|
|
3c46c06f40 | ||
| 9c9b0bfedc | |||
|
|
a410add3bf | ||
|
|
70a391b787 | ||
|
|
b430910f59 | ||
|
|
122852645b | ||
|
|
ba66b322c6 | ||
| 3f121b8d1a | |||
|
|
3410bc669a | ||
|
|
f3ec65ce87 | ||
|
|
2ed2b6647a | ||
|
|
b9db1a096f | ||
| e9c6fdf428 | |||
|
|
e104b41434 | ||
| 0de40d8416 | |||
| 20082ff14a | |||
|
|
047e2d842c | ||
|
|
eb72d1d66a | ||
|
|
f01c27fd84 | ||
|
|
6dd99fcb4e | ||
| ca0a900769 | |||
| 88a623c979 | |||
|
|
fab86631be | ||
|
|
171bdc1063 | ||
| 4a5bfd4eb8 | |||
|
|
4c51057fef | ||
|
|
8f17ae2ce0 |
8 changed files with 398 additions and 233 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1 +1 @@
|
|||
zerofree-1.0.1.tgz
|
||||
/zerofree-*.tgz
|
||||
|
|
|
|||
81
index.html
81
index.html
|
|
@ -1,5 +1,10 @@
|
|||
<html>
|
||||
<head>
|
||||
<!--
|
||||
Support idiotic mobile browsers that are incapable of rendering
|
||||
straightforward HTML properly
|
||||
-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Keeping filesystem images sparse</title>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -51,79 +56,43 @@ all the free space:
|
|||
The disadvantage of <code>dd</code> 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.
|
||||
zeroes. Also, filling up a live filesystem is probably a bad idea.
|
||||
<p>
|
||||
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, <a href="zerofree-1.0.1.tgz">zerofree-1.0.1.tgz</a>, is
|
||||
available for download.) The <code>zerofree</code> utility is faster
|
||||
than <code>dd</code>, especially when the filesystem is already partly sparse.
|
||||
The filesystem to be processed should be unmounted or mounted read-only.
|
||||
The source, <a href="zerofree-1.1.1.tgz">zerofree-1.1.1.tgz</a>, is
|
||||
available for download.
|
||||
<p>
|
||||
Better than either of these would be to have the guest kernel keep the free
|
||||
blocks empty. My original inspiration was the
|
||||
<a href="http://www.uwsg.iu.edu/hypermail/linux/kernel/0401.3/1058.html">
|
||||
ext2fs privacy (i.e. secure deletion) patch</a> described in a Linux
|
||||
kernel mailing list thread. I've also made use of a later patch for ext3
|
||||
entitled
|
||||
<a href="http://marc.theaimsgroup.com/?l=linux-fsdevel&m=113986429313502&w=2">Secure Deletion Functionality in ext3</a>
|
||||
from the linux-fsdevel mailing list. (See also the authors' paper on
|
||||
<a href="http://www.filesystems.org/project-sdfs.html">Secure Deletion File Systems</a>.)
|
||||
I've modified the patches to make them more suitable for the present purpose.
|
||||
<ul>
|
||||
<li><a href="linux-2.6.25-zerofree2.patch">linux-2.6.25-zerofree2.patch</a> (for ext2 filesystems)</li>
|
||||
<li><a href="linux-2.6.25-zerofree3.patch">linux-2.6.25-zerofree3.patch</a> (for ext3 filesystems)</li>
|
||||
<li>A cautious user would run fsck on the filesytem both before and after
|
||||
running zerofree.
|
||||
<li>The filesystem to be processed should be unmounted or mounted read-only.
|
||||
<li>The utility also works on ext3 or ext4 filesystems.
|
||||
<li>Binary packages are available in the standard repositories for Debian and Fedora.
|
||||
<li>The <a href="http://www.sysresccd.org/SystemRescueCd_Homepage">SystemRescueCd</a> live distribution includes zerofree.
|
||||
<li><a href="http://libguestfs.org/">guestfish</a> can run zerofree on many types of virtual machine filesystems.
|
||||
</ul>
|
||||
When a filesystem is mounted with the <code>zerofree</code> 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.
|
||||
<p>
|
||||
However, the above techniques are only half the story: the empty free
|
||||
However, this is 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. One approach would be to
|
||||
implement a system call, like the legendary
|
||||
<a href="http://www.uwsg.iu.edu/hypermail/linux/kernel/0106.3/1180.html">
|
||||
sys_punch</a>, which could be used to write a utility to make any
|
||||
suitable file sparse.
|
||||
must to be done to reclaim that space.
|
||||
<p>
|
||||
An existing alternative is to use the sparse file handling capabilities
|
||||
A common suggestion is to use the sparse file handling capabilities
|
||||
of the GNU <code>cp</code> command to take a copy of the filesystem image with
|
||||
<code>cp --sparse=always</code> (though this does require the original
|
||||
and sparse files to exist at the same time, which may be inconvenient).
|
||||
<p>
|
||||
As an alternative alternative I've written a utility which can make
|
||||
any specified files on an ext2 filesystem
|
||||
sparse, <a href="sparsify.c">sparsify.c</a>. 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.
|
||||
<p>
|
||||
(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. <code>e2fsck</code>
|
||||
is your friend.)
|
||||
<p>
|
||||
As an example, suppose we have an unmounted filesystem
|
||||
image, <code>fs.image</code>, in the directory <code>/data</code>, which is the
|
||||
root of the <code>/dev/hda2</code> filesystem. We can reclaim deleted
|
||||
blocks and make it sparse like so:
|
||||
<p>
|
||||
<pre>
|
||||
zerofree /data/fs.image
|
||||
umount /data
|
||||
sparsify /dev/hda2 /fs.image
|
||||
mount /data
|
||||
</pre>
|
||||
If your kernel and util-linux are sufficiently modern and you have a supported
|
||||
filesystem you can use <code>fallocate -d</code> to 'dig holes' in a file.
|
||||
This makes the file sparse in-place, without using extra disk space.
|
||||
<p>
|
||||
<hr>
|
||||
<address>
|
||||
<a href="mailto:rmy@tigress.co.uk">Ron Yorston</a><br>
|
||||
29th July 2008
|
||||
<a href="mailto:rmy@pobox.com">Ron Yorston</a><br>
|
||||
18th April 2004 (updated 19th February 2018)<br>
|
||||
Some <a href="obsolete.html">obsolete</a> information has been moved to a
|
||||
separate page.
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
2
sources
2
sources
|
|
@ -1 +1 @@
|
|||
a8c772fdd134448f25ab4e7e12004595 zerofree-1.0.1.tgz
|
||||
SHA512 (zerofree-1.1.1.tgz) = 2d7ee57a877bff2491c48054338a26d624ae75c238ac2b0568a75de88b6621c16cc1e7d65500879825d14d8ba44a5173587a061459072769c165bee47c3f9f1c
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
--- 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 ;
|
||||
273
sparsify.c
273
sparsify.c
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* sparsify - a tool to make files on an ext2 filesystem sparse
|
||||
*
|
||||
* Copyright (C) 2004 R M Yorston
|
||||
* Copyright (C) 2004-2012 R M Yorston
|
||||
*
|
||||
* This file may be redistributed under the terms of the GNU General Public
|
||||
* License.
|
||||
* License, version 2.
|
||||
*/
|
||||
#include <ext2fs/ext2fs.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -13,181 +13,262 @@
|
|||
|
||||
#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 dryrun ;
|
||||
int changed ;
|
||||
} ;
|
||||
int verbose;
|
||||
int dryrun;
|
||||
blk_t count;
|
||||
blk_t blocks;
|
||||
blk_t total_blocks;
|
||||
int old_percent;
|
||||
};
|
||||
|
||||
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 ret ;
|
||||
int i, group ;
|
||||
struct process_data *p;
|
||||
errcode_t errcode;
|
||||
int i, group;
|
||||
int ret = 0;
|
||||
|
||||
p = (struct process_data *)priv ;
|
||||
p = (struct process_data *)priv;
|
||||
|
||||
p->blocks++;
|
||||
if ( blockcnt >= 0 ) {
|
||||
ret = io_channel_read_blk(fs->io, *blocknr, 1, p->buf);
|
||||
if ( ret ) {
|
||||
return BLOCK_ABORT ;
|
||||
errcode = io_channel_read_blk(fs->io, *blocknr, 1, p->buf);
|
||||
if ( errcode ) {
|
||||
return BLOCK_ABORT;
|
||||
}
|
||||
|
||||
for ( i=0; i < fs->blocksize; ++i ) {
|
||||
if ( p->buf[i] ) {
|
||||
break ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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 ;
|
||||
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);
|
||||
}
|
||||
p->changed = 1 ;
|
||||
return BLOCK_CHANGED ;
|
||||
}
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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 blocksize = 0 ;
|
||||
ext2_filsys current_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 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;
|
||||
|
||||
while ( (c=getopt(argc, argv, "nv")) != -1 ) {
|
||||
switch (c) {
|
||||
case 'n' :
|
||||
dryrun = 1 ;
|
||||
break ;
|
||||
dryrun = 1;
|
||||
#if defined(BLOCK_FLAG_READ_ONLY)
|
||||
iter_flags |= BLOCK_FLAG_READ_ONLY;
|
||||
#endif
|
||||
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, ¤t_fs);
|
||||
unix_io_manager, &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(current_fs->blocksize) ;
|
||||
pdata.buf = (unsigned char *)malloc(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(current_fs);
|
||||
ret = ext2fs_read_inode_bitmap(fs);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: error while reading inode bitmap\n", argv[0]);
|
||||
return 1 ;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ext2fs_read_block_bitmap(current_fs);
|
||||
ret = ext2fs_read_block_bitmap(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; i<argc; ++i ) {
|
||||
if ( verbose ) {
|
||||
printf("processing %s\n", argv[i]) ;
|
||||
ret = ext2fs_namei(fs, root, cwd, argv[i], &inum);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: failed to find file %s\n", argv[0], argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = ext2fs_namei(current_fs, root, cwd, argv[i], &inum) ;
|
||||
ret = ext2fs_read_inode(fs, inum, &inode);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: failed to find file %s\n", argv[0], argv[i]) ;
|
||||
continue ;
|
||||
}
|
||||
|
||||
ret = ext2fs_read_inode(current_fs, inum, &inode) ;
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: failed to open inode %d\n", argv[0], inum) ;
|
||||
continue ;
|
||||
fprintf(stderr, "%s: failed to open inode %d\n", argv[0], inum);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !ext2fs_inode_has_valid_blocks(&inode) ) {
|
||||
fprintf(stderr, "%s: file %s has no valid inodes\n", argv[0],
|
||||
argv[i]) ;
|
||||
continue ;
|
||||
fprintf(stderr, "%s: file %s has no valid blocks\n", argv[0],
|
||||
argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
pdata.inode = &inode ;
|
||||
pdata.dryrun = dryrun ;
|
||||
pdata.changed = 0 ;
|
||||
ret = ext2fs_block_iterate2(current_fs, inum, BLOCK_FLAG_DATA_ONLY,
|
||||
NULL, process, &pdata) ;
|
||||
#if defined(EXT4_EXTENTS_FL) && API < 141
|
||||
if ( inode.i_flags & EXT4_EXTENTS_FL ) {
|
||||
fprintf(stderr, "%s: unable to process %s, it uses extents\n",
|
||||
argv[0], argv[i]);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && defined(EXT4_HUGE_FILE_FL)
|
||||
if ( (fs->super->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);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: failed to process file %s\n", argv[0],
|
||||
argv[i]) ;
|
||||
continue ;
|
||||
argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( pdata.changed ) {
|
||||
ret = ext2fs_write_inode(current_fs, inum, &inode) ;
|
||||
if ( pdata.count && !dryrun ) {
|
||||
ext2fs_mark_bb_dirty(fs);
|
||||
ext2fs_mark_super_dirty(fs);
|
||||
|
||||
ret = ext2fs_read_inode(fs, inum, &inode);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: failed to write inode data %s\n", argv[0],
|
||||
argv[i]) ;
|
||||
continue ;
|
||||
fprintf(stderr, "%s: failed to open inode (%s)\n", argv[0],
|
||||
argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
ext2fs_mark_bb_dirty(current_fs) ;
|
||||
ext2fs_mark_super_dirty(current_fs) ;
|
||||
#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]);
|
||||
}
|
||||
}
|
||||
|
||||
ret = ext2fs_close(current_fs) ;
|
||||
ret = ext2fs_close(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;
|
||||
}
|
||||
|
|
|
|||
61
zerofree.8
61
zerofree.8
|
|
@ -1,25 +1,36 @@
|
|||
.TH "ZEROFREE" "8"
|
||||
.SH "NAME"
|
||||
zerofree \(em zero free blocks from ext2/3 file-systems
|
||||
zerofree \(em zero free blocks from ext2, ext3 and ext4 file-systems
|
||||
.SH "SYNOPSIS"
|
||||
.PP
|
||||
\fBzerofree\fR [\fB-n\fP] [\fB-v\fP] \fIfilesystem\fR
|
||||
\fBzerofree\fR [\fB-n\fP] [\fB-v\fP] [\fB-f fillval\fP] \fIfilesystem\fR
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
\fBzerofree\fR finds the unallocated,
|
||||
non-zeroed blocks in an ext2 or ext3
|
||||
blocks with non-zero value content in an ext2, ext3 or ext4
|
||||
\fIfilesystem\fR (e.g. /dev/hda1) and
|
||||
fills them with zeroes. This is useful if the device on which
|
||||
this file-system resides is a disk image. In this case,
|
||||
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,
|
||||
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.
|
||||
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.
|
||||
|
||||
.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
|
||||
|
|
@ -27,7 +38,8 @@ 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
|
||||
|
|
@ -36,17 +48,36 @@ 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. It may however be useful in other
|
||||
situations.
|
||||
\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.
|
||||
|
||||
.SH "OPTIONS"
|
||||
.IP "\fB-n\fP " 10
|
||||
Perform a dry run (do not modify the file-system);
|
||||
.IP "\fB-v\fP " 10
|
||||
Be verbose.
|
||||
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.
|
||||
.SH "SEE ALSO"
|
||||
.PP
|
||||
dd (1).
|
||||
|
|
@ -62,4 +93,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, Wed 25 Nov 2009, 17:45
|
||||
.\" created by instant / docbook-to-man, Thu 31 Dec 2020, 01:06
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<!ENTITY dhfirstname "<firstname>Thibaut</firstname>">
|
||||
<!ENTITY dhsurname "<surname>Paumard</surname>">
|
||||
<!-- Please adjust the date whenever revising the manpage. -->
|
||||
<!ENTITY dhdate "<date>February 6, 2008</date>">
|
||||
<!ENTITY dhdate "<date>April 3rd, 2012</date>">
|
||||
<!ENTITY dhsection "<manvolnum>8</manvolnum>">
|
||||
<!ENTITY dhemail "<email><paumard@users.sourceforge.net></email>">
|
||||
<!ENTITY dhusername "Thibaut Paumard">
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
<refnamediv>
|
||||
<refname>&dhpackage;</refname>
|
||||
|
||||
<refpurpose>zero free blocks from ext2/3 file-systems</refpurpose>
|
||||
<refpurpose>zero free blocks from ext2, ext3 and ext4 file-systems</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
|
|
@ -54,6 +54,8 @@
|
|||
|
||||
<arg><option>-v</option></arg>
|
||||
|
||||
<arg><option>-f fillval</option></arg>
|
||||
|
||||
<arg choice=req><replaceable>filesystem</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
|
@ -61,14 +63,21 @@
|
|||
<title>DESCRIPTION</title>
|
||||
|
||||
<para><command>&dhpackage;</command> finds the unallocated,
|
||||
non-zeroed blocks in an ext2 or ext3
|
||||
blocks with non-zero value content in an ext2, ext3 or ext4
|
||||
<replaceable>filesystem</replaceable> (e.g. /dev/hda1) and
|
||||
fills them with zeroes. This is useful if the device on which
|
||||
this file-system resides is a disk image. In this case,
|
||||
fills them with zeroes (or another octet of your choice).
|
||||
|
||||
<para>Filling unused areas with zeroes 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.</para>
|
||||
|
||||
<para>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.</para>
|
||||
|
||||
<para>The usual way to achieve the same result (zeroing the
|
||||
unallocated blocks) is to run <command>dd</command> (1) to
|
||||
create a file full of zeroes that takes up the entire free
|
||||
|
|
@ -94,10 +103,19 @@
|
|||
<command>mount -o remount,ro
|
||||
<replaceable>filesystem</replaceable></command>.</para>
|
||||
|
||||
<para><command>&dhpackage;</command> 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.</para>
|
||||
<para><command>&dhpackage;</command> 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 (<command>VBoxManage modifyhd --compact</command>,
|
||||
provided with virtualbox, is able to do that for some disk image
|
||||
formats).</para>
|
||||
|
||||
<para>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.</para>
|
||||
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
|
|
@ -115,7 +133,19 @@
|
|||
<term><option>-v</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>Be verbose.</para>
|
||||
<para>Be verbose: show the number of blocks modified by
|
||||
<command>&dhpackage;</command> (or that would be modified,
|
||||
in case the <option>-n</option> is used), the number of free
|
||||
blocks and the total number of blocks on the
|
||||
filesystem;</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-f value</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>Specify the octet value to fill empty blocks with (defaults to
|
||||
0). Argument must be within the range 0 to 255.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
|
|
|||
154
zerofree.spec
154
zerofree.spec
|
|
@ -1,36 +1,26 @@
|
|||
Summary: Utility to force unused ext2 inodes and blocks to zero
|
||||
Summary: Utility to force unused ext2/3/4 inodes and blocks to zero
|
||||
Name: zerofree
|
||||
Version: 1.0.1
|
||||
Release: 13%{?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
|
||||
|
||||
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
|
||||
# zerofree.sgml is the source for the man page from Debian.
|
||||
# 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).
|
||||
# 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.
|
||||
Source3: zerofree.sgml
|
||||
Source4: zerofree.8
|
||||
|
||||
# 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: gcc
|
||||
BuildRequires: make
|
||||
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 filesystem to zero. This can improve the compressibility and
|
||||
privacy of an ext2 filesystem.
|
||||
ext2/3/4 filesystem to zero. This can improve the compressibility and
|
||||
privacy of an ext2/3/4 filesystem.
|
||||
|
||||
This tool was inspired by the ext2fs privacy (i.e. secure deletion)
|
||||
patch described in a Linux kernel mailing list thread.
|
||||
|
|
@ -39,40 +29,118 @@ 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} .
|
||||
cp -p %{SOURCE2} .
|
||||
%patch1 -p1
|
||||
|
||||
cp -p %{SOURCE1} %{SOURCE2} .
|
||||
|
||||
%build
|
||||
make CC="gcc $RPM_OPT_FLAGS"
|
||||
gcc $RPM_OPT_FLAGS sparsify.c -o sparsify -lext2fs
|
||||
|
||||
make CC="%{__cc} $RPM_OPT_FLAGS $RPM_LD_FLAGS"
|
||||
%{__cc} $RPM_OPT_FLAGS $RPM_LD_FLAGS -o sparsify sparsify.c -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
|
||||
%defattr(-,root,root,-)
|
||||
%doc COPYING index.html
|
||||
%license COPYING
|
||||
%doc index.html
|
||||
%{_sbindir}/zerofree
|
||||
%{_sbindir}/sparsify
|
||||
%{_mandir}/man8/zerofree.8*
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
|
||||
%changelog
|
||||
* Fri Jul 17 2026 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-18
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
|
||||
|
||||
* Sat Jan 17 2026 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-17
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild
|
||||
|
||||
* Fri Jul 25 2025 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-16
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
|
||||
|
||||
* Sun Jan 19 2025 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-15
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
|
||||
|
||||
* Sat Jul 20 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-14
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
|
||||
|
||||
* Sat Jan 27 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-13
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
|
||||
|
||||
* Sat Jul 22 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-12
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
|
||||
|
||||
* Sat Jan 21 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-11
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
|
||||
|
||||
* Sat Jul 23 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-10
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
|
||||
|
||||
* Sat Jan 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-9
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
|
||||
|
||||
* Fri Jul 23 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-8
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
|
||||
|
||||
* Thu Jan 28 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-7
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
|
||||
|
||||
* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-6
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
|
||||
|
||||
* Fri Jan 31 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-5
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
|
||||
|
||||
* Sat Jul 27 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||
|
||||
* Sun Feb 03 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||
|
||||
* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.1-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||
|
||||
* Tue Feb 20 2018 Robert Scheck <robert@fedoraproject.org> - 1.1.1-1
|
||||
- Upgrade to 1.1.1
|
||||
|
||||
* Mon Feb 19 2018 Robert Scheck <robert@fedoraproject.org> - 1.1.0-1
|
||||
- Upgrade to 1.1.0
|
||||
|
||||
* Fri Feb 09 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.3-10
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
||||
|
||||
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.3-9
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
|
||||
|
||||
* Thu Jul 27 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.3-8
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
|
||||
|
||||
* Sat Feb 11 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.3-7
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
|
||||
|
||||
* Wed Apr 06 2016 Robert Scheck <robert@fedoraproject.org> - 1.0.3-6
|
||||
- Build with ext4 support for RHEL 5 (#862934, thanks to Mike Swanson)
|
||||
|
||||
* Fri Feb 05 2016 Fedora Release Engineering <releng@fedoraproject.org> - 1.0.3-5
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
|
||||
|
||||
* Fri Jun 19 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.3-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
|
||||
|
||||
* Mon Aug 18 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.3-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
|
||||
|
||||
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.3-2
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
|
||||
|
||||
* Mon Nov 18 2013 Richard W.M. Jones <rjones@redhat.com> - 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 <rel-eng@lists.fedoraproject.org> - 1.0.1-13
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue