more code juggling

try and sort out transfer
edge.strict_endians
flatcap 2005-09-20 00:05:49 +00:00
parent 374f5ac4f7
commit 7f8ad30c09
1 changed files with 521 additions and 108 deletions

View File

@ -43,7 +43,7 @@ GEN_PRINTF (Eprintf, stderr, NULL, FALSE)
GEN_PRINTF (Vprintf, stdout, &opts.verbose, TRUE)
GEN_PRINTF (Qprintf, stdout, &opts.quiet, FALSE)
#define RM_WRITE 1
#define RM_WRITE 0
/**
* version - Print version information about the program
@ -857,46 +857,6 @@ static int ntfs_inode_close2 (ntfs_inode *ni)
return ntfs_inode_close (ni);
}
/**
* utils_index_init
*/
static int utils_index_init (ntfs_volume *vol, u8 *buffer, int size)
{
INDEX_ALLOCATION *alloc;
INDEX_ENTRY_HEADER *header;
if (!vol)
return 1;
if (!buffer)
return 1;
if (size < 512)
return 1;
memset (buffer, 0, size);
alloc = (INDEX_ALLOCATION*) buffer;
alloc->magic = magic_INDX;
alloc->usa_ofs = 0x28;
alloc->usa_count = (size >> vol->sector_size_bits) + 1;
alloc->lsn = 0;
alloc->index_block_vcn = 0;
alloc->index.entries_offset = 0x40;
alloc->index.index_length = 0x10;
alloc->index.allocated_size = size - 0x18;
alloc->index.flags = 0;
header = (INDEX_ENTRY_HEADER*) (buffer + 0x40);
header->indexed_file = 0;
header->length = 0x10;
header->key_length = 0;
header->flags = INDEX_ENTRY_END;
return 0;
}
/**
* ntfs_dt_free
@ -1049,7 +1009,46 @@ static BOOL ntfs_dt_create_children2 (struct ntfs_dt *dt, int count)
memset ((u8*)dt->sub_nodes + old, 0, (new - old) * sizeof (*dt->sub_nodes));
memset ((u8*)dt->inodes + old, 0, (new - old) * sizeof (*dt->inodes));
return (dt->children && dt->sub_nodes && dt->inodes);
return TRUE;
}
/**
* ntfs_dt_resize_children3
*/
static BOOL ntfs_dt_resize_children3 (struct ntfs_dt *dt, int new)
{
int old;
// XXX calculate for 2K and 4K indexes max and min filenames (inc/exc VCN)
// XXX assumption: sizeof (*dt->children) == sizeof (*dt->sub_nodes) == sizeof (*dt->inodes)
// XXX put back blocking factor
if (!dt)
return FALSE;
old = dt->child_count;
if (old == new)
return TRUE;
dt->child_count = new;
old *= sizeof (*dt->children);
new *= sizeof (*dt->children);
dt->children = realloc (dt->children, new);
dt->sub_nodes = realloc (dt->sub_nodes, new);
dt->inodes = realloc (dt->inodes, new);
if (!dt->children || !dt->sub_nodes || !dt->inodes)
return FALSE;
if (new > old) {
memset ((u8*)dt->children + old, 0, (new - old));
memset ((u8*)dt->sub_nodes + old, 0, (new - old));
memset ((u8*)dt->inodes + old, 0, (new - old));
}
return TRUE;
}
/**
@ -1087,8 +1086,7 @@ static int ntfs_dt_root_count (struct ntfs_dt *dt)
while (ptr < (buffer + size)) {
entry = (INDEX_ENTRY*) ptr;
dt->child_count++;
ntfs_dt_create_children2 (dt, dt->child_count); // XXX retval
ntfs_dt_resize_children3 (dt, dt->child_count + 1); // XXX retval
if (entry->flags & INDEX_ENTRY_NODE) {
vcn = ntfs_ie_get_vcn ((INDEX_ENTRY*) ptr);
@ -1142,11 +1140,11 @@ static int ntfs_dt_alloc_count (struct ntfs_dt *dt)
//printf ("block size %d\n", block->index.index_length);
dt->child_count = 0;
//printf ("start = 0x%02X, end = 0x%02X\n", 0x18 + block->index.entries_offset, 0x18 + block->index.index_length);
while (ptr < (buffer + 0x18 + block->index.index_length)) {
entry = (INDEX_ENTRY*) ptr;
dt->child_count++;
ntfs_dt_create_children2 (dt, dt->child_count); // XXX retval
ntfs_dt_resize_children3 (dt, dt->child_count + 1); // XXX retval
if (entry->flags & INDEX_ENTRY_NODE) {
vcn = ntfs_ie_get_vcn ((INDEX_ENTRY*) ptr);
@ -1171,6 +1169,48 @@ static int ntfs_dt_alloc_count (struct ntfs_dt *dt)
return dt->child_count;
}
/**
* ntfs_dt_initialise2
*/
static int ntfs_dt_initialise2 (ntfs_volume *vol, struct ntfs_dt *dt)
{
INDEX_ALLOCATION *alloc;
INDEX_ENTRY *entry;
if (!vol)
return 1;
if (!dt)
return 1;
memset (dt->data, 0, dt->data_len);
alloc = (INDEX_ALLOCATION*) dt->data;
alloc->magic = magic_INDX;
alloc->usa_ofs = 0x28;
alloc->usa_count = (dt->data_len >> vol->sector_size_bits) + 1;
alloc->lsn = 0;
alloc->index_block_vcn = 0;
alloc->index.entries_offset = 0x28;
alloc->index.index_length = 0x10 + 0x28;
alloc->index.allocated_size = dt->data_len - 0x18;
alloc->index.flags = 0;
entry = (INDEX_ENTRY*) (dt->data + 0x40);
entry->indexed_file = 0;
entry->length = 0x10;
entry->key_length = 0;
entry->flags = INDEX_ENTRY_END;
ntfs_dt_resize_children3 (dt, 1); // XXX retval
dt->children[0] = entry;
return 0;
}
/**
* ntfs_dt_create
*/
@ -1209,7 +1249,7 @@ static struct ntfs_dt * ntfs_dt_create (struct ntfs_dir *dir, struct ntfs_dt *pa
//printf ("%lld\n", ntfs_attr_mst_pread (dir->ialloc, vcn*512, 1, dt->data_len, dt->data));
ntfs_attr_mst_pread (dir->ialloc, vcn*512, 1, dt->data_len, dt->data);
} else {
utils_index_init (dir->vol, dt->data, dt->data_len);
ntfs_dt_initialise2 (dir->vol, dt);
}
//utils_dump_mem (dt->data, 0, dt->data_len, DM_DEFAULTS);
@ -1643,52 +1683,6 @@ static int ntfs_dt_alloc_freespace (struct ntfs_dt *dt)
return recsize - inuse;
}
/**
* ntfs_dt_initialise
*/
static int ntfs_dt_initialise (struct ntfs_dt *dt, VCN vcn)
{
INDEX_BLOCK *block;
INDEX_ENTRY *ie;
if (!dt || !dt->data)
return -1;
memset (dt->data, 0, dt->data_len);
// Ought to check these are empty
free (dt->children);
free (dt->sub_nodes);
dt->children = NULL;
dt->sub_nodes = NULL;
if (!ntfs_dt_create_children2 (dt, 1))
return -1;
block = (INDEX_BLOCK*) dt->data;
block->magic = magic_INDX;
block->usa_ofs = 0x28;
block->usa_count = (dt->data_len >> 9) + 1;
block->index_block_vcn = vcn;
block->index.entries_offset = 0x28;
block->index.index_length = 0x38;
block->index.allocated_size = dt->data_len - 0x18;
ie = (INDEX_ENTRY*) (dt->data + block->index.entries_offset + 0x18);
ie->length = 0x10;
ie->flags = INDEX_ENTRY_END;
dt->children[0] = ie;
dt->sub_nodes[0] = NULL;
//utils_dump_mem (dt->data, 0, block->index.index_length+0x18, DM_DEFAULTS);
return 0;
}
/**
* ntfs_dt_transfer
*/
@ -1789,8 +1783,7 @@ static int ntfs_dt_transfer (struct ntfs_dt *old, struct ntfs_dt *new, int start
//printf ("dst = %d, len = %d\n", dst - old->data, len);
memset (dst, 0, len);
new->child_count += count;
if (!ntfs_dt_create_children2 (new, new->child_count))
if (!ntfs_dt_resize_children3 (new, new->child_count + count))
return -1;
src = (u8*) &old->sub_nodes[start+count-1];
@ -1805,8 +1798,427 @@ static int ntfs_dt_transfer (struct ntfs_dt *old, struct ntfs_dt *new, int start
memmove (dst, src, len);
old->child_count -= count;
if (!ntfs_dt_create_children2 (old, old->child_count))
if (!ntfs_dt_resize_children3 (old, old->child_count - count))
return -1;
src = (u8*) new->children[0];
for (i = 0; i < new->child_count; i++) {
new->children[i] = (INDEX_ENTRY*) src;
src += new->children[i]->length;
}
src = (u8*) old->children[0];
for (i = 0; i < old->child_count; i++) {
old->children[i] = (INDEX_ENTRY*) src;
src += old->children[i]->length;
}
old->header->index_length -= need;
new->header->index_length += need;
// resize children and sub_nodes
// memmove keys in new
// memcpy old to new
// memmove keys in old
// rebuild old/new children/sub_nodes without destroying tree
// update old/new headers
old->changed = TRUE;
new->changed = TRUE;
printf (GREEN "Modified: inode %lld, $INDEX_ALLOCATION vcn %lld-%lld\n" END, old->dir->inode->mft_no, old->vcn, old->vcn + (old->dir->index_size>>9) - 1);
printf (GREEN "Modified: inode %lld, $INDEX_ALLOCATION vcn %lld-%lld\n" END, new->dir->inode->mft_no, new->vcn, new->vcn + (new->dir->index_size>>9) - 1);
return 0;
}
/**
* ntfs_dt_alloc_insert
*/
static int ntfs_dt_alloc_insert (struct ntfs_dt *dt, INDEX_ENTRY *first, int count)
{
// XXX don't bother measuring, just subtract the children pointers
int i;
int need;
INDEX_ENTRY *ie;
INDEX_ALLOCATION *alloc;
u8 *src;
u8 *dst;
int len;
if (!dt)
return 1;
if (!first)
return 1;
need = 0;
ie = first;
for (i = 0; i < count; i++) {
need += ie->length;
ie = (INDEX_ENTRY*) ((u8*)ie + ie->length);
}
printf ("alloc insert %d bytes\n", need);
alloc = (INDEX_ALLOCATION*) dt->data;
printf ("entries_offset = %d\n", alloc->index.entries_offset);
printf ("index_length = %d\n", alloc->index.index_length);
printf ("allocated_size = %d\n", alloc->index.allocated_size);
printf ("insert has %d children\n", dt->child_count);
printf ("children = %p\n", dt->children);
//utils_dump_mem (dt->data, 0, 128, DM_DEFAULTS);
ie = dt->children[dt->child_count-1];
printf ("last child = %p (%ld)\n", ie, (long)ie - (long)dt->data);
printf ("size = %d\n", ie->length);
src = (u8*) ie;
dst = src + need;
len = ie->length;
memmove (dst, src, len);
src = (u8*) first;
dst = (u8*) ie;
len = need;
memcpy (dst, src, len);
// use create children
// measure need and update children list
// adjust headers
utils_dump_mem (dt->data, 0, 256, DM_DEFAULTS);
return 0;
}
/**
* ntfs_dt_alloc_insert2
*/
static INDEX_ENTRY * ntfs_dt_alloc_insert2 (struct ntfs_dt *dt, int before, int count, int bytes)
{
int space;
u8 *src;
u8 *dst;
int len;
// XXX don't bother measuring, just subtract the children pointers
if (!dt)
return NULL;
if (before < 0)
return NULL;
if (count < 1)
return NULL;
if (bytes < 1)
return NULL;
// check alloc has enough space
space = ntfs_dt_alloc_freespace (dt);
if (bytes > space)
return NULL;
// move data
src = (u8*) dt->children[before];
dst = src + bytes;
len = dt->header->index_length - ((int)dt->children[before] - (int)dt->data) + 24;
//printf ("%d, %d, %d\n", (int)src - (int)dt->data, (int)dst - (int)dt->data, len);
memmove (dst, src, len);
memset (dst, 0, bytes);
// resize arrays
ntfs_dt_resize_children3 (dt, dt->child_count + count);
// move keys (children)
src = (u8*) (dt->children + before);
dst = src + (count * sizeof (u8*));
len = (dt->child_count - count - before) * sizeof (u8*);
memmove (dst, src, len);
memset (src, 0, count * sizeof (u8*));
// move keys (inodes)
src = (u8*) (dt->inodes + before);
dst = src + (count * sizeof (u8*));
len = (dt->child_count - count - before) * sizeof (u8*);
memmove (dst, src, len);
memset (src, 0, count * sizeof (u8*));
// move keys (sub_nodes)
src = (u8*) (dt->sub_nodes + before);
dst = src + (count * sizeof (u8*));
len = (dt->child_count - count - before) * sizeof (u8*);
memmove (dst, src, len);
memset (src, 0, count * sizeof (u8*));
return NULL;
}
/**
* ntfs_dt_root_insert
*/
static int ntfs_dt_root_insert (struct ntfs_dt *dt, INDEX_ENTRY *first, int count)
{
if (!dt)
return 1;
if (!first)
return 1;
return count;
}
/**
* utils_array_insert
*/
static int utils_array_insert (void *ptr, int asize, int before, int count)
{
static int esize = sizeof (u8*);
u8 *src;
u8 *dst;
int len;
if (!ptr)
return -1;
src = (u8*) ptr + (before * esize);
dst = src + (count * esize);
len = (asize - before) * esize;
// XXX what about realloc?
memmove (dst, src, len);
len = count * esize;
memset (src, 0, len);
return 0;
}
/**
* utils_array_remove
*/
static int utils_array_remove (void *ptr, int asize, int first, int count)
{
static int esize = sizeof (u8*);
u8 *src;
u8 *dst;
int len;
if (!ptr)
return -1;
dst = (u8*) ptr + (first * esize);
src = dst + (count * esize);
len = (asize - first) * esize;
memmove (dst, src, len);
src = (u8*) ptr + ((asize - count) * esize);
len = count * esize;
memset (src, 0, len);
// XXX don't want to memset, want to realloc
return 0;
}
/**
* ntfs_dt_alloc_remove2
*/
static int ntfs_dt_alloc_remove2 (struct ntfs_dt *dt, int start, int count)
{
int i;
int size;
if (!dt)
return 1;
size = 0;
for (i = start; i < (start+count); i++) {
size += dt->children[i]->length;
}
return start + count;
}
/**
* ntfs_dt_root_remove2
*/
static int ntfs_dt_root_remove2 (struct ntfs_dt *dt, int start, int count)
{
int i;
int size;
if (!dt)
return -1;
if ((start < 0) || (start >= dt->child_count))
return -1;
if ((count < 1) || ((start + count - 1) >= dt->child_count))
return -1;
printf ("s c/t %d %d/%d\n", start, count, dt->child_count);
size = 0;
for (i = start; i < (start + count); i++)
size += dt->children[i]->length;
printf ("size1 = %d\n", size);
size = (int) dt->children[start+count] - (int) dt->children[start];
printf ("size2 = %d\n", size);
size = (int) dt->children[start+count-1] - (int) dt->children[start] + dt->children[start+count-1]->length;
printf ("size3 = %d\n", size);
// XXX what shall we do with the inodes?
// transfer them to the dir (commit them for now)
// are they _our_ responsibility? probably not
// rearrange arrays
// shrink attribute
ntfs_dt_resize_children3 (dt, dt->child_count - count);
printf ("ntfs_dt_root_remove2\n");
return dt->child_count;
}
/**
* ntfs_dt_transfer2
*/
static int ntfs_dt_transfer2 (struct ntfs_dt *old, struct ntfs_dt *new, int start, int count)
{
int i;
int need;
int space;
INDEX_ENTRY *mov_ie;
u8 *src;
u8 *dst;
int len;
int insert;
//FILE_NAME_ATTR *file;
if (!old || !new)
return -1;
if ((start < 0) || (count < 0))
return -1;
if ((start + count) >= old->child_count)
return -1;
printf ("\n");
printf (BOLD YELLOW "Transferring children\n" END);
need = 0;
for (i = start; i < (start+count); i++) {
mov_ie = old->children[i];
need += mov_ie->length;
//file = &mov_ie->key.file_name; printf ("\ttrn name: "); ntfs_name_print (file->file_name, file->file_name_length); printf ("\n");
}
if (ntfs_dt_isroot (new))
space = ntfs_dt_root_freespace (new);
else
space = ntfs_dt_alloc_freespace (new);
printf ("\tneed = %d\n", need);
printf ("\tspace = %d\n", space);
if (need > space)
return -1;
if (ntfs_dt_isroot (new))
ntfs_dt_root_insert (new, old->children[0], count);
else
ntfs_dt_alloc_insert2 (new, 0, count, need);
if (ntfs_dt_isroot (old))
ntfs_dt_root_remove2 (old, 0, count);
else
ntfs_dt_alloc_remove2 (old, 0, count);
if (1) return -1;
if (0) ntfs_dt_alloc_insert (NULL, NULL, 0);
if (new->child_count == 1) {
i = -1;
} else {
ntfschar *n1, *n2;
int l1, l2;
n1 = new->children[0]->key.file_name.file_name;
l1 = new->children[0]->key.file_name.file_name_length;
n2 = old->children[start]->key.file_name.file_name;
l2 = old->children[start]->key.file_name.file_name_length;
i = ntfs_names_collate (n1, l1, n2, l2,
2, IGNORE_CASE,
old->dir->vol->upcase,
old->dir->vol->upcase_len);
}
if ((i == 0) || (i == 2))
return -1;
// determine the insertion point
if (i == 1)
insert = 0;
else
insert = new->child_count-1;
src = (u8*) new->children[insert];
dst = src + need;
len = (u8*) new->children[new->child_count-1] + new->children[new->child_count-1]->length - src;
//printf ("src = %d, dst = %d, len = %d\n", src - new->data, dst - new->data, len);
memmove (dst, src, len);
dst = src;
src = (u8*) old->children[start];
len = need;
memcpy (dst, src, len);
src = (u8*) old->children[start+count-1];
dst = (u8*) old->children[start];
len = (u8*) old->children[old->child_count-1] + old->children[old->child_count-1]->length - src;
//printf ("src = %d, dst = %d, len = %d\n", src - old->data, dst - old->data, len);
memmove (dst, src, len);
dst += len;
len = old->data + old->dir->index_size - dst;
//printf ("dst = %d, len = %d\n", dst - old->data, len);
memset (dst, 0, len);
if (!ntfs_dt_resize_children3 (new, new->child_count + count))
return -1;
src = (u8*) &old->sub_nodes[start+count-1];
dst = (u8*) &old->sub_nodes[start];
len = (old->child_count - start - count + 1) * sizeof (struct ntfs_dt*);
memmove (dst, src, len);
src = (u8*) &new->sub_nodes[insert];
dst = (u8*) &new->sub_nodes[insert+count-1];
len = (new->child_count - insert - count + 1) * sizeof (struct ntfs_dt*);
memmove (dst, src, len);
if (!ntfs_dt_resize_children3 (old, old->child_count - count))
return -1;
src = (u8*) new->children[0];
@ -2183,13 +2595,12 @@ static int ntfs_mft_add_index (struct ntfs_dir *dir)
// can't replace ie yet, there may not be room
ntfs_ie_free (ie);
//ntfs_dt_transfer (dir->index, dt, 0, 7);
ntfs_dt_transfer2 (dir->index, dt, 0, dir->index->child_count - 1);
printf ("root has %d children\n", dir->index->child_count);
printf ("node has %d children\n", dt->child_count);
ntfs_dt_free (dt);
//utils_index_init (vol, buffer, dir->index_size);
// create a new dt
// attach dt to dir
@ -2523,7 +2934,6 @@ static BOOL ntfs_dt_root_remove (struct ntfs_dt *del, int del_num)
del->data = realloc (del->data, del->data_len);
del->header = (INDEX_HEADER*) (del->data + 0x10);
//utils_dump_mem (del->data, 0, del->data_len, DM_GREEN | DM_RED);
src = (u8*) (&del->children[del_num+1]);
@ -2865,6 +3275,7 @@ static int ntfs_dt_root_add (struct ntfs_dt *parent, int index_num, INDEX_ENTRY
src = parent->data + 0x18 + parent->header->entries_offset;
len = parent->data_len - 0x18 - parent->header->entries_offset;
// XXX can we rebase the children more simply? (in alloc_add too)
while (src < (parent->data + parent->data_len)) {
entry = (INDEX_ENTRY*) src;
@ -2988,7 +3399,9 @@ ascend:
//printf ("\tnode has %d children\n", suc->child_count);
// initialise new node
ntfs_dt_initialise (new, vcn);
// XXX ntfs_dt_initialise (new, vcn);
goto done;
// find median key
median = (suc->child_count+1) / 2;
@ -3506,6 +3919,7 @@ static int ntfs_volume_umount2 (ntfs_volume *vol, const BOOL force)
static ntfs_volume * ntfs_volume_mount2 (const char *device, unsigned long flags, BOOL force)
{
// XXX can we replace these and search by mft number? Hmm... NO.
// unless I have a recursive search for an MFT number
static ntfschar bmp[8] = {
const_cpu_to_le16('$'),
const_cpu_to_le16('B'),
@ -3573,7 +3987,7 @@ static ntfs_volume * ntfs_volume_mount2 (const char *device, unsigned long flags
//$Bitmap
num = -1;
found = ntfs_dt_find2 (root, bmp, 7, &num);
found = ntfs_dt_find2 (root, bmp, sizeof (bmp) - 1, &num);
if ((!found) || (num < 0)) {
printf ("can't find $Bitmap\n");
ntfs_volume_umount2 (vol, FALSE);
@ -3586,7 +4000,7 @@ static ntfs_volume * ntfs_volume_mount2 (const char *device, unsigned long flags
//$MFT
num = -1;
found = ntfs_dt_find2 (root, mft, 4, &num);
found = ntfs_dt_find2 (root, mft, sizeof (mft) - 1, &num);
if ((!found) || (num < 0)) {
printf ("can't find $MFT\n");
ntfs_volume_umount2 (vol, FALSE);
@ -3599,7 +4013,7 @@ static ntfs_volume * ntfs_volume_mount2 (const char *device, unsigned long flags
//$MFTMirr
num = -1;
found = ntfs_dt_find2 (root, mftmirr, 8, &num);
found = ntfs_dt_find2 (root, mftmirr, sizeof (mftmirr) - 1, &num);
if ((!found) || (num < 0)) {
printf ("can't find $MFTMirr\n");
ntfs_volume_umount2 (vol, FALSE);
@ -3940,19 +4354,15 @@ static int ntfs_file_remove (ntfs_volume *vol, struct ntfs_dt *del, int del_num)
printf (BOLD YELLOW "Find childless parent:\n" END);
#if 0
for (par = del->parent, old = par; par; old = par, par = par->parent) {
printf (CYAN "marker 1\n" END);
if (par->child_count > 1)
break;
printf (CYAN "marker 2\n" END);
par_num = ntfs_dt_find_parent (par);
}
#endif
printf (CYAN "marker 3\n" END); fflush (stdout);
printf ("del = %p, parent = %p\n", del, del->parent);
par = del->parent;
par_num = ntfs_dt_find_parent (del);
printf (CYAN "marker 4\n" END); fflush (stdout);
//utils_dump_mem (par->data, 0, par->data_len, DM_BLUE|DM_GREEN|DM_INDENT);
@ -4365,6 +4775,9 @@ done:
if (0) utils_pathname_to_inode2 (NULL, NULL, NULL, NULL);
if (0) ntfs_ie_remove_name (NULL);
if (0) ntfs_dt_transfer2 (NULL, NULL, 0, 0);
if (0) utils_array_remove (NULL, 0, 0, 0);
if (0) utils_array_insert (NULL, 0, 0, 0);
return result;
}