diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 419bfd83c88b9fdd86c8d3585f06deb3e2d01e90..0000000000000000000000000000000000000000 --- a/README.en.md +++ /dev/null @@ -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/) diff --git a/README.md b/README.md deleted file mode 100644 index b3d26566f731afc65aa5cb83ad181457cd60cf69..0000000000000000000000000000000000000000 --- a/README.md +++ /dev/null @@ -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/) diff --git a/sparsify.c b/sparsify.c new file mode 100644 index 0000000000000000000000000000000000000000..4c52e0075a0a05179d1256862e7f86d288dc3679 --- /dev/null +++ b/sparsify.c @@ -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 +#include +#include +#include + +#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; 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); + 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; +} diff --git a/zerofree-1.1.1.tgz b/zerofree-1.1.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..dabb2e3f730a455b75816b688c33d97d84db5018 Binary files /dev/null and b/zerofree-1.1.1.tgz differ diff --git a/zerofree.8 b/zerofree.8 new file mode 100644 index 0000000000000000000000000000000000000000..b0be0d28e45ccf95ffce3e9c8a3cf8fe7b50d12f --- /dev/null +++ b/zerofree.8 @@ -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 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 diff --git a/zerofree.spec b/zerofree.spec new file mode 100644 index 0000000000000000000000000000000000000000..1843315881f9d72a671ad4ccdac71628b1513abc --- /dev/null +++ b/zerofree.spec @@ -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 - 1.1.1-3 +- Package init