commit
0af5fc13d0
36
README.en.md
36
README.en.md
@ -1,36 +0,0 @@
|
||||
# zerofree
|
||||
|
||||
#### Description
|
||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
39
README.md
39
README.md
@ -1,39 +0,0 @@
|
||||
# zerofree
|
||||
|
||||
#### 介绍
|
||||
{**以下是码云平台说明,您可以替换此简介**
|
||||
码云是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
||||
无论是个人、团队、或是企业,都能够用码云实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 码云特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
|
||||
5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
274
sparsify.c
Normal file
274
sparsify.c
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* sparsify - a tool to make files on an ext2 filesystem sparse
|
||||
*
|
||||
* Copyright (C) 2004-2012 R M Yorston
|
||||
*
|
||||
* This file may be redistributed under the terms of the GNU General Public
|
||||
* License, version 2.
|
||||
*/
|
||||
#include <ext2fs/ext2fs.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 {
|
||||
unsigned char *buf;
|
||||
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 errcode;
|
||||
int i, group;
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for ( i=0; i < fs->blocksize; ++i ) {
|
||||
if ( p->buf[i] ) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 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;
|
||||
#if defined(BLOCK_FLAG_READ_ONLY)
|
||||
iter_flags |= BLOCK_FLAG_READ_ONLY;
|
||||
#endif
|
||||
break;
|
||||
case 'v' :
|
||||
verbose = 1;
|
||||
break;
|
||||
default :
|
||||
fprintf(stderr, USAGE, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( argc < optind+2 ) {
|
||||
fprintf(stderr, USAGE, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ( flags & EXT2_MF_MOUNTED ) {
|
||||
fprintf(stderr, "%s: filesystem %s is mounted\n",
|
||||
argv[0], argv[optind]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ext2fs_open(argv[optind], open_flags, superblock, blocksize,
|
||||
unix_io_manager, &fs);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: failed to open filesystem %s\n",
|
||||
argv[0], argv[optind]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pdata.buf = (unsigned char *)malloc(fs->blocksize);
|
||||
if ( pdata.buf == NULL ) {
|
||||
fprintf(stderr, "%s: out of memory (surely not?)\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ext2fs_read_inode_bitmap(fs);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: error while reading inode bitmap\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = ext2fs_read_block_bitmap(fs);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: error while reading block bitmap\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
root = cwd = EXT2_ROOT_INO;
|
||||
|
||||
for ( i=optind+1; i<argc; ++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_read_inode(fs, inum, &inode);
|
||||
if ( ret ) {
|
||||
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 blocks\n", argv[0],
|
||||
argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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 open inode (%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]);
|
||||
}
|
||||
}
|
||||
|
||||
ret = ext2fs_close(fs);
|
||||
if ( ret ) {
|
||||
fprintf(stderr, "%s: error while closing filesystem\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
zerofree-1.1.1.tgz
Normal file
BIN
zerofree-1.1.1.tgz
Normal file
Binary file not shown.
65
zerofree.8
Normal file
65
zerofree.8
Normal file
@ -0,0 +1,65 @@
|
||||
.TH "ZEROFREE" "8"
|
||||
.SH "NAME"
|
||||
zerofree \(em zero free blocks from ext2/3 file-systems
|
||||
.SH "SYNOPSIS"
|
||||
.PP
|
||||
\fBzerofree\fR [\fB-n\fP] [\fB-v\fP] \fIfilesystem\fR
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
\fBzerofree\fR finds the unallocated,
|
||||
non-zeroed blocks in an ext2 or ext3
|
||||
\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,
|
||||
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
|
||||
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:
|
||||
.IP " \(bu" 6
|
||||
it is slow;
|
||||
.IP " \(bu" 6
|
||||
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.
|
||||
.PP
|
||||
\fIfilesystem\fR has to be unmounted or
|
||||
mounted read-only for \fBzerofree\fR to work. It
|
||||
will exit with an error message if the
|
||||
\fIfilesystem\fR is mounted writable. To
|
||||
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.
|
||||
.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.
|
||||
.SH "OPTIONS"
|
||||
.IP "\fB-n\fP " 10
|
||||
Perform a dry run (do not modify the file-system);
|
||||
.IP "\fB-v\fP " 10
|
||||
Be verbose.
|
||||
.SH "SEE ALSO"
|
||||
.PP
|
||||
dd (1).
|
||||
.SH "AUTHOR"
|
||||
.PP
|
||||
This manual page was written by Thibaut Paumard <paumard@users.sourceforge.net> for
|
||||
the \fBDebian\fP system (but may be used by others). Permission is
|
||||
granted to copy, distribute and/or modify this document under
|
||||
the terms of the GNU General Public License, Version 2 or any
|
||||
later version published by the Free Software Foundation.
|
||||
|
||||
.PP
|
||||
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
|
||||
45
zerofree.spec
Normal file
45
zerofree.spec
Normal file
@ -0,0 +1,45 @@
|
||||
Name: zerofree
|
||||
Version: 1.1.1
|
||||
Release: 3
|
||||
Summary: Utility to force unused ext2/3/4 inodes and blocks to zero
|
||||
License: GPLv2
|
||||
URL: https://frippery.org/uml/
|
||||
Source0: https://frippery.org/uml/%{name}-%{version}.tgz
|
||||
Source1: https://frippery.org/uml/sparsify.c
|
||||
Source2: zerofree.8
|
||||
BuildRequires: e2fsprogs-devel
|
||||
|
||||
%description
|
||||
This module is a utility to set unused filesystem inodes and blocks of an ext2/3/4 filesystem to zero,
|
||||
which can improve the compressibility and privacy of an ext2/3/4 filesystem.
|
||||
|
||||
%package help
|
||||
Summary: man files for %{name}
|
||||
Requires: man
|
||||
|
||||
%description help
|
||||
This package includes man files for %{name}.
|
||||
|
||||
%prep
|
||||
%autosetup -p1
|
||||
cp -p %{SOURCE1} .
|
||||
|
||||
%build
|
||||
make CC="gcc $RPM_OPT_FLAGS"
|
||||
gcc $RPM_OPT_FLAGS sparsify.c -o sparsify -lext2fs
|
||||
|
||||
%install
|
||||
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 %{SOURCE2} $RPM_BUILD_ROOT%{_mandir}/man8/zerofree.8
|
||||
|
||||
%files
|
||||
%license COPYING
|
||||
%{_sbindir}/*
|
||||
|
||||
%files help
|
||||
%{_mandir}/man*/*
|
||||
|
||||
%changelog
|
||||
* Thu Dec 12 2019 openEuler Buildteam <buildteam@openeuler.org> - 1.1.1-3
|
||||
- Package init
|
||||
Loading…
x
Reference in New Issue
Block a user