wipe_tails:

* proper implementation of wipe_compressed_attribute
* various fixes

(Logical change 1.444)
edge.strict_endians
(none)!yura 2004-06-28 23:05:50 +00:00
parent 2e579e14a7
commit 07ef30bdf6
1 changed files with 88 additions and 145 deletions

View File

@ -398,64 +398,47 @@ free:
* 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
* @byte: Overwrite with this value * @byte: Overwrite with this value
* @na: Opened ntfs attribute
* @act: Wipe, test or info * @act: Wipe, test or info
* @attr: A vaild $DATA attribute record
* @compr_unit: Compression unit obtained from first $DATA attribute (because in other
* it 0)
* @tail: If last is not compressed, how many we have to wipe in it end
* *
* Return: >0 Success, the atrribute was wiped * Return: >0 Success, the atrribute was wiped
* 0 Nothing to wipe * 0 Nothing to wipe
* -1 Error, something went wrong * -1 Error, something went wrong
*/ */
static s64 wipe_compressed_attribute (ntfs_volume *vol, int byte, enum action act, static s64 wipe_compressed_attribute (ntfs_volume *vol, int byte, ntfs_attr *na,
ATTR_RECORD *attr, u8 compr_unit, u32 tail) enum action act)
{ {
runlist *rl;
unsigned char *buf; unsigned char *buf;
s64 size; s64 size;
u64 offset; u64 offset;
u16 block_size; u16 block_size;
u64 wiped = 0;
s64 ret; s64 ret;
runlist *rlc; u64 wiped = 0;
u64 cu_mask; VCN cur_vcn = 0;
runlist *rlc = na->rl;
if (compr_unit != 4) u64 cu_mask = na->compression_block_clusters - 1;
Eprintf ("strange: compression unit is %u (not 4)\n", compr_unit);
if (!compr_unit) {
Vprintf ("Internal error\n");
Eprintf ("Compression unit could not be 0");
return -1;
}
cu_mask = (1 << compr_unit) - 1;
rl = ntfs_mapping_pairs_decompress(vol, attr, 0);
if (!rl) {
Vprintf ("Internal error\n");
Eprintf ("Could not decompress mapping pairs inode");
return -1;
}
rlc = rl;
while (rlc->length) { while (rlc->length) {
if ((!(rlc->length & cu_mask) && ((rlc+1)->length || !tail)) cur_vcn += rlc->length;
|| (rlc->lcn < 0)) { if ((cur_vcn & cu_mask) ||
(((rlc + 1)->length) && (rlc->lcn != LCN_HOLE))) {
rlc++; rlc++;
continue; continue;
} }
if (rlc->length & cu_mask) { if (rlc->lcn == LCN_HOLE) {
offset = (rlc->length & (~cu_mask)) << vol->cluster_size_bits; offset = cur_vcn - rlc->length;
if (offset == (offset & (~cu_mask))) {
rlc++;
continue;
}
offset = (offset & (~cu_mask)) << vol->cluster_size_bits;
while (1) { while (1) {
ret = ntfs_rl_pread (vol, rlc, offset, 2, &block_size); ret = ntfs_rl_pread (vol, na->rl, offset, 2, &block_size);
if (ret != 2) { if (ret != 2) {
Vprintf ("Internal error\n"); Vprintf ("Internal error\n");
Eprintf ("ntfs_rl_pread failed"); Eprintf ("ntfs_rl_pread failed");
wiped = -1; return -1;
goto free_rl;
} }
if (block_size == 0) { if (block_size == 0) {
offset += 2; offset += 2;
@ -464,15 +447,24 @@ static s64 wipe_compressed_attribute (ntfs_volume *vol, int byte, enum action ac
block_size &= 0x0FFF; block_size &= 0x0FFF;
block_size += 3; block_size += 3;
offset += block_size; offset += block_size;
if (offset >= (rlc->length << vol->cluster_size_bits) - 2) if (offset >= (((cur_vcn - rlc->length)
<< vol->cluster_size_bits) - 2))
goto next; goto next;
} }
size = (rlc->length << vol->cluster_size_bits) - offset; size = ((cur_vcn - rlc->length)
<< vol->cluster_size_bits) - offset;
} else { } else {
size = tail; size = na->allocated_size - na->data_size;
offset = (rlc->length << vol->cluster_size_bits) - tail; offset = (cur_vcn << vol->cluster_size_bits) - size;
} }
if (size < 0) {
Vprintf ("Internal error\n");
Eprintf ("bug or damaged fs: we want allocate buffer "
"size %lld bytes", size);
return -1;
}
if ((act == act_info) || (!size)) { if ((act == act_info) || (!size)) {
wiped += size; wiped += size;
rlc++; rlc++;
@ -483,26 +475,22 @@ static s64 wipe_compressed_attribute (ntfs_volume *vol, int byte, enum action ac
if (!buf) { if (!buf) {
Vprintf ("Not enough memory\n"); Vprintf ("Not enough memory\n");
Eprintf ("Not enough memory to allocate %lld bytes", size); Eprintf ("Not enough memory to allocate %lld bytes", size);
wiped = -1; return -1;
goto free_rl;
} }
memset (buf, byte, size); memset (buf, byte, size);
ret = ntfs_rl_pwrite (vol, rlc, offset, size, buf); ret = ntfs_rl_pwrite (vol, na->rl, offset, size, buf);
free (buf);
if (ret != size) { if (ret != size) {
Vprintf ("Internal error\n"); Vprintf ("Internal error\n");
Eprintf ("ntfs_rl_pwrite failed"); Eprintf ("ntfs_rl_pwrite failed");
free (buf); return -1;
wiped = -1;
goto free_rl;
} }
free (buf);
wiped += ret; wiped += ret;
next: next:
rlc++; rlc++;
} }
free_rl:
free (rl);
return wiped; return wiped;
} }
@ -510,19 +498,28 @@ free_rl:
* wipe_attribute - Wipe not compressed $DATA attribute * wipe_attribute - Wipe not compressed $DATA attribute
* @vol: An ntfs volume obtained from ntfs_mount * @vol: An ntfs volume obtained from ntfs_mount
* @byte: Overwrite with this value * @byte: Overwrite with this value
* @attr: A vaild $DATA attribute record * @na: Opened ntfs attribute
* @size: How many bytes to wipe * @act: Wipe, test or info
* @offset: Offset where start wiping
* *
* Return: >0 Success, the atrribute was wiped * Return: >0 Success, the atrribute was wiped
* 0 Nothing to wipe
* -1 Error, something went wrong * -1 Error, something went wrong
*/ */
static s64 wipe_attribute (ntfs_volume *vol, int byte, ATTR_RECORD *attr, static s64 wipe_attribute (ntfs_volume *vol, int byte, ntfs_attr *na, enum action act)
s64 size, u64 offset)
{ {
runlist *rl;
unsigned char *buf; unsigned char *buf;
s64 wiped; s64 wiped;
s64 size;
u64 offset = na->data_size;
if (!offset)
return 0;
if (NAttrEncrypted(na))
offset = (((offset - 1) >> 10) + 1) << 10;
size = (vol->cluster_size - offset) % vol->cluster_size;
if (act == act_info)
return size;
buf = malloc (size); buf = malloc (size);
if (!buf) { if (!buf) {
@ -532,22 +529,12 @@ static s64 wipe_attribute (ntfs_volume *vol, int byte, ATTR_RECORD *attr,
} }
memset (buf, byte, size); memset (buf, byte, size);
rl = ntfs_mapping_pairs_decompress(vol, attr, 0); wiped = ntfs_rl_pwrite (vol, na->rl, offset, size, buf);
if (!rl) {
Vprintf ("Internal error\n");
Eprintf ("Could not decompress mapping pairs");
wiped = -1;
goto free_buf;
}
wiped = ntfs_rl_pwrite (vol, rl, offset, size, buf);
if (wiped == -1) { if (wiped == -1) {
Vprintf ("Internal error\n"); Vprintf ("Internal error\n");
Eprintf ("Couldn't wipe tail"); Eprintf ("Couldn't wipe tail");
} }
free (rl);
free_buf:
free (buf); free (buf);
return wiped; return wiped;
} }
@ -569,9 +556,8 @@ static s64 wipe_tails (ntfs_volume *vol, int byte, enum action act)
{ {
s64 total = 0; s64 total = 0;
s64 inode_num; s64 inode_num;
ntfs_attr_search_ctx *ctx;
ntfs_inode *ni; ntfs_inode *ni;
ATTR_RECORD *attr; ntfs_attr *na;
if (!vol || (byte < 0)) if (!vol || (byte < 0))
return -1; return -1;
@ -583,94 +569,51 @@ static s64 wipe_tails (ntfs_volume *vol, int byte, enum action act)
Vprintf ("Could not open inode\n"); Vprintf ("Could not open inode\n");
continue; continue;
} }
if (ni->mrec->base_mft_record) { if (ni->mrec->base_mft_record) {
Vprintf ("Not base mft record. Skipping\n"); Vprintf ("Not base mft record. Skipping\n");
goto close_inode; goto close_inode;
} }
ctx = ntfs_attr_get_search_ctx(ni, 0); na = ntfs_attr_open (ni, AT_DATA, AT_UNNAMED, 0);
if (!ctx) { if (!na) {
Vprintf ("Internal error\n"); Vprintf ("Couldn't open $DATA attribute\n");
Eprintf ("Could not get search context (inode %lld)\n",inode_num);
goto close_inode; goto close_inode;
} }
u64 wiped_in_file = 0; if (!NAttrNonResident(na)) {
u8 compr_unit; Vprintf ("Resident $DATA atrribute. Skipping.\n");
s64 size = -1; goto close_attr;
u64 offset;
VCN last_vcn;
u32 tail;
ATTR_RECORD *first_attr = 0;
while (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
attr = ctx->attr;
if (!attr->non_resident) {
Vprintf ("Resident $DATA atrribute. Skipping.\n");
goto put_search_ctx;
}
if (!first_attr) {
first_attr = attr;
if (attr->compression_unit) {
compr_unit = attr->compression_unit;
tail = attr->allocated_size - attr->data_size;
}
}
s64 wiped;
if (first_attr->flags & ATTR_IS_COMPRESSED) {
Vprintf ("Compressed $DATA attribute. Not supported yet ;(\n");
goto put_search_ctx;
// wiped = wipe_compressed_attribute (vol, byte, act,
// attr, compr_unit, tail);
} else {
if (size == -1) {
offset = attr->data_size;
if (!offset)
break;
if (attr->flags & ATTR_IS_ENCRYPTED)
offset = (((offset - 1) >> 10) + 1) << 10;
size = (vol->cluster_size - offset) %
vol->cluster_size;
last_vcn = attr->data_size >>
vol->cluster_size_bits;
}
if (!size) {
wiped_in_file = 0;
break;
}
if (act == act_info) {
wiped_in_file = size;
break;
}
if (attr->highest_vcn == last_vcn)
wiped = wipe_attribute (vol, byte, attr,
size, offset);
else
continue;
}
if (wiped != -1)
wiped_in_file += wiped;
else {
Eprintf (" (inode %lld)\n", inode_num);
goto put_search_ctx;
}
} }
if (wiped_in_file) { if (ntfs_attr_map_whole_runlist(na)) {
Vprintf ("Wiped %llu bytes\n", wiped_in_file); Vprintf ("Internal error\n");
total += wiped_in_file; Eprintf ("Couldn't map runlist (inode %lld)", inode_num);
goto close_attr;
}
s64 wiped;
if (NAttrCompressed(na))
wiped = wipe_compressed_attribute (vol, byte, na, act);
else
wiped = wipe_attribute (vol, byte, na, act);
if (wiped == -1) {
Eprintf (" (inode %lld)\n", inode_num);
goto close_attr;
}
if (wiped) {
Vprintf ("Wiped %llu bytes\n", wiped);
total += wiped;
} else } else
Vprintf ("Nothing to wipe\n"); Vprintf ("Nothing to wipe\n");
put_search_ctx: close_attr:
ntfs_attr_put_search_ctx (ctx); ntfs_attr_close (na);
close_inode: close_inode:
ntfs_inode_close (ni); ntfs_inode_close (ni);
} }
Qprintf ("wipe_tails 0x%02x, %lld bytes\n", byte, (long long)total); Qprintf ("wipe_tails 0x%02x, %lld bytes\n", byte, total);
return total; return total;
} }