mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 18:14:24 +08:00
Developped an option --unused-fast for faster ntfswipe
When the new option --unused-fast is used, clusters which appear as wiped are not written again. This is useful for avoiding virtual partitions to be extended to their full size. Contributed by michael
This commit is contained in:
parent
c358191f91
commit
a7aa91d73d
@ -77,6 +77,10 @@ because the allocations are always done by full clusters.
|
|||||||
Overwrite the space which is currently not allocated to any file (but
|
Overwrite the space which is currently not allocated to any file (but
|
||||||
may have been used in the past).
|
may have been used in the past).
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-U\fR, \fB\-\-unused-fast\fR
|
||||||
|
Overwrite the space which is currently not allocated to any file, trying
|
||||||
|
not to overwrite the space not written to since the previous wiping.
|
||||||
|
.TP
|
||||||
\fB\-v\fR, \fB\-\-verbose\fR
|
\fB\-v\fR, \fB\-\-verbose\fR
|
||||||
Display more debug/warning/error messages.
|
Display more debug/warning/error messages.
|
||||||
.TP
|
.TP
|
||||||
|
@ -169,6 +169,7 @@ static void usage(void)
|
|||||||
" -p --pagefile Wipe pagefile (swap space)\n"
|
" -p --pagefile Wipe pagefile (swap space)\n"
|
||||||
" -t --tails Wipe file tails\n"
|
" -t --tails Wipe file tails\n"
|
||||||
" -u --unused Wipe unused clusters\n"
|
" -u --unused Wipe unused clusters\n"
|
||||||
|
" -U --unused-fast Wipe unused clusters (fast)\n"
|
||||||
" -s --undel Wipe undelete data\n"
|
" -s --undel Wipe undelete data\n"
|
||||||
"\n"
|
"\n"
|
||||||
" -a --all Wipe all unused space\n"
|
" -a --all Wipe all unused space\n"
|
||||||
@ -262,7 +263,7 @@ static int parse_list(char *list, int **result)
|
|||||||
*/
|
*/
|
||||||
static int parse_options(int argc, char *argv[])
|
static int parse_options(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
static const char *sopt = "-ab:c:dfh?ilmnpqtuvVs";
|
static const char *sopt = "-ab:c:dfh?ilmnpqtuUvVs";
|
||||||
static struct option lopt[] = {
|
static struct option lopt[] = {
|
||||||
{ "all", no_argument, NULL, 'a' },
|
{ "all", no_argument, NULL, 'a' },
|
||||||
{ "bytes", required_argument, NULL, 'b' },
|
{ "bytes", required_argument, NULL, 'b' },
|
||||||
@ -279,6 +280,7 @@ static int parse_options(int argc, char *argv[])
|
|||||||
{ "quiet", no_argument, NULL, 'q' },
|
{ "quiet", no_argument, NULL, 'q' },
|
||||||
{ "tails", no_argument, NULL, 't' },
|
{ "tails", no_argument, NULL, 't' },
|
||||||
{ "unused", no_argument, NULL, 'u' },
|
{ "unused", no_argument, NULL, 'u' },
|
||||||
|
{ "unused-fast",no_argument, NULL, 'U' },
|
||||||
{ "undel", no_argument, NULL, 's' },
|
{ "undel", no_argument, NULL, 's' },
|
||||||
{ "verbose", no_argument, NULL, 'v' },
|
{ "verbose", no_argument, NULL, 'v' },
|
||||||
{ "version", no_argument, NULL, 'V' },
|
{ "version", no_argument, NULL, 'V' },
|
||||||
@ -370,6 +372,9 @@ static int parse_options(int argc, char *argv[])
|
|||||||
case 'u':
|
case 'u':
|
||||||
opts.unused++;
|
opts.unused++;
|
||||||
break;
|
break;
|
||||||
|
case 'U':
|
||||||
|
opts.unused_fast++;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
opts.verbose++;
|
opts.verbose++;
|
||||||
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
|
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
|
||||||
@ -442,7 +447,7 @@ static int parse_options(int argc, char *argv[])
|
|||||||
|
|
||||||
if (!opts.directory && !opts.logfile && !opts.mft &&
|
if (!opts.directory && !opts.logfile && !opts.mft &&
|
||||||
!opts.pagefile && !opts.tails && !opts.unused &&
|
!opts.pagefile && !opts.tails && !opts.unused &&
|
||||||
!opts.undel) {
|
!opts.unused_fast && !opts.undel) {
|
||||||
opts.info = 1;
|
opts.info = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -511,6 +516,120 @@ free:
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wipe_unused_fast - Faster wipe unused clusters
|
||||||
|
* @vol: An ntfs volume obtained from ntfs_mount
|
||||||
|
* @byte: Overwrite with this value
|
||||||
|
* @act: Wipe, test or info
|
||||||
|
*
|
||||||
|
* Read $Bitmap and wipe any clusters that are marked as not in use.
|
||||||
|
*
|
||||||
|
* - read/write on a block basis (64 clusters, arbitrary)
|
||||||
|
* - skip of fully used block
|
||||||
|
* - skip non-used block already wiped
|
||||||
|
*
|
||||||
|
* Return: >0 Success, the attribute was wiped
|
||||||
|
* 0 Nothing to wipe
|
||||||
|
* -1 Error, something went wrong
|
||||||
|
*/
|
||||||
|
static s64 wipe_unused_fast(ntfs_volume *vol, int byte, enum action act)
|
||||||
|
{
|
||||||
|
s64 i;
|
||||||
|
s64 total = 0;
|
||||||
|
s64 unused = 0;
|
||||||
|
s64 result;
|
||||||
|
u8 *buffer;
|
||||||
|
u8 *big_buffer;
|
||||||
|
u32 *u32_buffer;
|
||||||
|
u32 u32_bytes;
|
||||||
|
unsigned int blksize;
|
||||||
|
unsigned int j,k;
|
||||||
|
BOOL wipe_needed;
|
||||||
|
|
||||||
|
if (!vol || (byte < 0))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
big_buffer = (u8*)malloc(vol->cluster_size*64);
|
||||||
|
if (!big_buffer) {
|
||||||
|
ntfs_log_error("malloc failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < vol->nr_clusters; i+=64) {
|
||||||
|
blksize = vol->nr_clusters - i;
|
||||||
|
if (blksize > 64)
|
||||||
|
blksize = 64;
|
||||||
|
/* if all clusters in this block are used, ignore the block */
|
||||||
|
result = 0;
|
||||||
|
for (j = 0; j < blksize; j++) {
|
||||||
|
if (utils_cluster_in_use(vol, i+j))
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
unused += (blksize - result) * vol->cluster_size;
|
||||||
|
|
||||||
|
if (result == blksize) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* if all unused clusters in this block are already wiped,
|
||||||
|
* ignore the block
|
||||||
|
*/
|
||||||
|
if (ntfs_pread(vol->dev, vol->cluster_size * i,
|
||||||
|
vol->cluster_size * blksize, big_buffer)
|
||||||
|
!= vol->cluster_size * blksize) {
|
||||||
|
ntfs_log_error("Read failed at cluster %lld\n",
|
||||||
|
(long long)i);
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
wipe_needed = FALSE;
|
||||||
|
u32_bytes = (byte & 255)*0x01010101;
|
||||||
|
buffer = big_buffer;
|
||||||
|
for (j = 0; (j < blksize) && !wipe_needed; j++) {
|
||||||
|
u32_buffer = (u32*)buffer;
|
||||||
|
if (!utils_cluster_in_use(vol, i+j)) {
|
||||||
|
for (k = 0; (k < vol->cluster_size)
|
||||||
|
&& (*u32_buffer++ == u32_bytes); k+=4) {
|
||||||
|
}
|
||||||
|
if (k < vol->cluster_size)
|
||||||
|
wipe_needed = TRUE;
|
||||||
|
}
|
||||||
|
buffer += vol->cluster_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wipe_needed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* else wipe unused clusters in the block */
|
||||||
|
buffer = big_buffer;
|
||||||
|
|
||||||
|
for (j = 0; j < blksize; j++) {
|
||||||
|
if (!utils_cluster_in_use(vol, i+j)) {
|
||||||
|
memset(buffer, byte, vol->cluster_size);
|
||||||
|
total += vol->cluster_size;
|
||||||
|
}
|
||||||
|
buffer += vol->cluster_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((act == act_wipe)
|
||||||
|
&& (ntfs_pwrite(vol->dev, vol->cluster_size * i,
|
||||||
|
vol->cluster_size * blksize, big_buffer)
|
||||||
|
!= vol->cluster_size * blksize)) {
|
||||||
|
ntfs_log_error("Write failed at cluster %lld\n",
|
||||||
|
(long long)i);
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ntfs_log_quiet("wipe_unused_fast 0x%02x, %lld bytes"
|
||||||
|
" already wiped, %lld more bytes wiped\n",
|
||||||
|
byte, (long long)(unused - total), (long long)total);
|
||||||
|
free:
|
||||||
|
free(big_buffer);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wipe_compressed_attribute - Wipe compressed $DATA attribute
|
* wipe_compressed_attribute - Wipe compressed $DATA attribute
|
||||||
* @vol: An ntfs volume obtained from ntfs_mount
|
* @vol: An ntfs volume obtained from ntfs_mount
|
||||||
@ -1959,6 +2078,8 @@ static void print_summary(void)
|
|||||||
ntfs_log_quiet("%s is about to wipe:\n", EXEC_NAME);
|
ntfs_log_quiet("%s is about to wipe:\n", EXEC_NAME);
|
||||||
if (opts.unused)
|
if (opts.unused)
|
||||||
ntfs_log_quiet("\tunused disk space\n");
|
ntfs_log_quiet("\tunused disk space\n");
|
||||||
|
if (opts.unused_fast)
|
||||||
|
ntfs_log_quiet("\tunused disk space (fast)\n");
|
||||||
if (opts.tails)
|
if (opts.tails)
|
||||||
ntfs_log_quiet("\tfile tails\n");
|
ntfs_log_quiet("\tfile tails\n");
|
||||||
if (opts.mft)
|
if (opts.mft)
|
||||||
@ -2099,8 +2220,12 @@ int main(int argc, char *argv[])
|
|||||||
total += wiped;
|
total += wiped;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.unused) {
|
if (opts.unused || opts.unused_fast) {
|
||||||
wiped = wipe_unused(vol, byte, act);
|
if (opts.unused_fast)
|
||||||
|
wiped = wipe_unused_fast(vol, byte,
|
||||||
|
act);
|
||||||
|
else
|
||||||
|
wiped = wipe_unused(vol, byte, act);
|
||||||
if (wiped < 0)
|
if (wiped < 0)
|
||||||
goto umount;
|
goto umount;
|
||||||
else
|
else
|
||||||
|
@ -47,6 +47,7 @@ struct options {
|
|||||||
int pagefile; /* Wipe pagefile (swap space) */
|
int pagefile; /* Wipe pagefile (swap space) */
|
||||||
int tails; /* Wipe file tails */
|
int tails; /* Wipe file tails */
|
||||||
int unused; /* Wipe unused clusters */
|
int unused; /* Wipe unused clusters */
|
||||||
|
int unused_fast; /* Wipe unused clusters (fast) */
|
||||||
int undel; /* Wipe undelete data */
|
int undel; /* Wipe undelete data */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user