Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/ntfstools
In directory usw-pr-cvs1:/tmp/cvs-serv5631/ntfstools
Modified Files:
mkntfs.c
Log Message:
The mkntfs saga continues.
Index: mkntfs.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/ntfstools/mkntfs.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -U2 -r1.11 -r1.12
--- mkntfs.c 2001/06/05 10:33:02 1.11
+++ mkntfs.c 2001/06/05 23:45:47 1.12
@@ -980,4 +980,33 @@
}
+/* Return 0 on success and -errno on error. */
+int resize_resident_attribute_value(MFT_RECORD *m, ATTR_RECORD *a,
+ const __u32 new_vsize)
+{
+ int new_alen, new_muse;
+
+ /* New attribute length and mft record bytes used. */
+ new_alen = le32_to_cpu(a->length) - le32_to_cpu(a->value_length) +
+ new_vsize + 7 & ~7;
+ new_muse = le32_to_cpu(m->bytes_in_use) - le32_to_cpu(a->length) +
+ new_alen;
+ /* Check for sufficient space. */
+ if (new_muse > le32_to_cpu(m->bytes_allocated) ) {
+ // Aarrgghh! Need to make space. Probably want generic function
+ // for this as we need to call it from other places, too.
+ return -ENOTSUP;
+ }
+ /* Move attributes behind @a to their new location. */
+ memmove((char*)a + new_alen, (char*)a + le32_to_cpu(a->length),
+ le32_to_cpu(m->bytes_in_use) - ((char*)a - (char*)m) -
+ le32_to_cpu(a->length));
+ /* Adjust @m to reflect change in used space. */
+ m->bytes_in_use = cpu_to_le32(new_muse);
+ /* Adjust @a to reflect new value size. */
+ a->length = cpu_to_le32(new_alen);
+ a->value_length = cpu_to_le32(new_vsize);
+ return -ENOTSUP;
+}
+
void deallocate_scattered_clusters(const run_list *rl)
{
@@ -1871,5 +1900,5 @@
uchar_t *uname;
char bmp[8];
- char *re_end;
+ char *re_start, *re_end;
int i, err, r_size, index_block_size;
@@ -1900,5 +1929,6 @@
r = (INDEX_ROOT*)((char*)a + le16_to_cpu(a->value_offset));
re_end = (char*)r + le32_to_cpu(a->value_length);
- re = (INDEX_ENTRY*)((char*)&r->index + r->index.entries_offset);
+ re_start = (char*)&r->index + le32_to_cpu(r->index.entries_offset);
+ re = (INDEX_ENTRY*)re_start;
index_block_size = le32_to_cpu(r->index_block_size);
memset(bmp, 0, sizeof(bmp));
@@ -1914,7 +1944,5 @@
/* Setup header. */
ia_val->magic = magic_INDX;
- /* should be at 0x28 */
ia_val->usa_ofs = cpu_to_le16(sizeof(INDEX_ALLOCATION));
- /* should be 9 */
if (index_block_size >= NTFS_SECTOR_SIZE)
ia_val->usa_count = cpu_to_le16(index_block_size /
@@ -1928,4 +1956,6 @@
"system created was corrupt.\nThank you.");
}
+ Dprintf("usa count in index block = %i\n",
+ cpu_to_le16(ia_val->usa_count));
/* Set USN to 1. */
*(__u16*)((char*)ia_val + le16_to_cpu(ia_val->usa_ofs)) =
@@ -1933,49 +1963,69 @@
ia_val->lsn = cpu_to_le64(0);
ia_val->index_block_vcn = cpu_to_le64(0);
+ ia_val->index.flags = LEAF_NODE;
/* Align to 8-byte boundary. */
- ia_val->index.entries_offset = cpu_to_le32((sizeof(INDEX_HEADER) +
- le16_to_cpu(ia_val->usa_count) * 2) + 7 & ~7);
+ ia_val->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER) +
+ le16_to_cpu(ia_val->usa_count) * 2 + 7 & ~7);
ia_val->index.allocated_size = cpu_to_le32(index_block_size -
(sizeof(INDEX_ALLOCATION) - sizeof(INDEX_HEADER)));
- ae = (INDEX_ENTRY*)((char*)ia_val +
- le32_to_cpu(ia_val->index.entries_offset));
- /* Move one entry. */
- memcpy(ae, re, le16_to_cpu(re->length));
- /* If there are more entries move them all. */
+ /* Find the last entry in the index root and save it in re. */
while ((char*)re < re_end && !(re->flags & INDEX_ENTRY_END)) {
/* Next entry in index root. */
re = (INDEX_ENTRY*)((char*)re + le16_to_cpu(re->length));
- /* Next entry in index allocation. */
- ae = (INDEX_ENTRY*)((char*)ae + le16_to_cpu(ae->length));
- /* Move the entry. */
- memcpy(ae, re, le16_to_cpu(re->length));
}
- ia_val->index.index_length = cpu_to_le32((char*)ae -
- (char*)&ia_val->index + le16_to_cpu(ae->length));
- /*
- * Finished with setting up of index allocation. Now fixup index root
- * to be empty and just to point to the index allocation VCN 0.
- */
- // Need to change the r->index.index_length and .allocated_size and
- // make the first entry to be a terminator with vcn and vcn = 0LL.
- // re at the moment points to the index root termination index entry
- // Also, need to resize the index root attribute! Especially so if it
- // was empty like it is in the mkntfs case as we are actualy making it
- // bigger by 8 bytes for the VCN in the termination entry!!! We would
- // overwrite the next attribute otherwise! BANG.
- r->index.index_length = cpu_to_le32((char*)ae -
- (char*)&ia_val->index + le16_to_cpu(ae->length));
+ /* Copy all the entries including the termination entry. */
+ i = (char*)re - re_start + le16_to_cpu(re->length);
+ memcpy((char*)ia_val + le32_to_cpu(ia_val->index.entries_offset),
+ re_start, i);
+ /* Finish setting up index allocation. */
+ ia_val->index.index_length = cpu_to_le32(i +
+ le32_to_cpu(ia_val->index.entries_offset));
+ /* Move the termination entry forward to the beginning if necessary. */
+ if ((char*)re > re_start) {
+ memmove(re_start, (char*)re, le16_to_cpu(re->length));
+ re = (INDEX_ENTRY*)re_start;
+ }
+ /* Now fixup empty index root with pointer to index allocation VCN 0. */
+ r->index.flags = LARGE_INDEX;
+ re->flags |= INDEX_ENTRY_NODE;
+ if (le16_to_cpu(re->length) < sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN))
+ re->length = cpu_to_le16(le16_to_cpu(re->length) + sizeof(VCN));
+ r->index.index_length = cpu_to_le32(le32_to_cpu(r->index.entries_offset)
+ + le16_to_cpu(re->length));
+ r->index.allocated_size = r->index.index_length;
+ /* Resize index root attribute. */
+ err = resize_resident_attribute_value(m, a, sizeof(INDEX_ROOT) -
+ sizeof(INDEX_HEADER) +
+ le32_to_cpu(r->index.allocated_size));
+ if (err) {
+ // TODO: Remove the added bitmap!
+ // Revert index root from index allocation.
+ free(ia_val);
+ return err;
+ }
+ /* Set VCN pointer to 0LL. */
+ *(VCN*)((char*)re + cpu_to_le16(re->length) - sizeof(VCN)) =
+ cpu_to_le64(0);
+ err = pre_write_mst_fixup((NTFS_RECORD*)ia_val, index_block_size);
+ if (!err) {
+ Eprintf("pre_write_mst_fixup() failed in "
+ "upgrade_to_large_index.\n");
+ free(ia_val);
+ return -EINVAL;
+ }
err = add_attr_index_alloc(m, name, name_len, ic, upcase, upcase_len,
(char*)ia_val, index_block_size);
if (err) {
// TODO: Remove the added bitmap!
- return err;
+ __post_read_mst_fixup((NTFS_RECORD*)ia_val, index_block_size);
+ // Revert index root from index allocation.
}
- err = -ENOTSUP;
+ free(ia_val);
return err;
}
/* Return 0 on success or -errno on error. */
-int insert_file_link_in_dir(MFT_RECORD *m)
+int insert_file_link_in_dir(MFT_RECORD *parent_dir, FILE_NAME *file_name,
+ __u32 file_name_size)
{
return -ENOTSUP;
@@ -2483,7 +2533,18 @@
opt.index_block_size);
if (!err)
- err = insert_file_link_in_dir(m);
- // add_attr_bitmap(m, );
- // add_attr_index_alloc(m, );
+ err = upgrade_to_large_index(m, "$I30", 4, IGNORE_CASE,
+ opt.upcase, opt.upcase_len);
+ if (!err) {
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.mrec = m;
+ /* There is exactly one file name so this is ok. */
+ if (!find_first_attr($FILE_NAME, NULL, 0, 0, NULL, 0, NULL, 0,
+ &ctx))
+ err_exit("BUG: $FILE_NAME attribute not found.\n");
+ a = ctx.attr;
+ err = insert_file_link_in_dir(m, (FILE_NAME*)((char*)a +
+ le16_to_cpu(a->value_offset)),
+ le32_to_cpu(a->value_length));
+ }
if (err < 0)
err_exit("Couldn't create root directory: %s\n",
@@ -2495,4 +2556,13 @@
err = add_attr_data_positioned(m, NULL, 0, 0, NULL, 0, 0, rl_mft, buf,
opt.mft_size);
+ // FIXME: Do a higher level directory link insertion so that we make
+ // a call simillar to the below but also with the parent dir and that
+ // call does the add_attr_file_name and the insert_file_link_in_dir
+ // and anything else necessary in one go.
+ // Also think about in general having the functions return the created
+ // attribute value so we can modify it in memory and at the end sync to
+ // disk rather than having each function call result in a disk read.
+ // Even though read/writes should be cached in the buffer cache so it
+ // shouldn't be too much of a problem.
if (!err)
err = add_attr_file_name(m, root_ref, opt.mft_size,
|