⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mft.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 4 页
字号:
	mft_na->data_size = old_data_size;undo_mftbmp_alloc:	err = errno;	if (ntfs_bitmap_clear_bit(mftbmp_na, bit))		ntfs_log_error("Failed to clear bit in mft bitmap.%s\n", es);	errno = err;err_out:	if (!errno)		errno = EIO;	return NULL;}/** * ntfs_mft_record_free - free an mft record on an ntfs volume * @vol:	volume on which to free the mft record * @ni:		open ntfs inode of the mft record to free * * Free the mft record of the open inode @ni on the mounted ntfs volume @vol. * Note that this function calls ntfs_inode_close() internally and hence you * cannot use the pointer @ni any more after this function returns success. * * On success return 0 and on error return -1 with errno set to the error code. */int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni){	u64 mft_no;	int err;	u16 seq_no, old_seq_no;	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);	if (!vol || !vol->mftbmp_na || !ni) {		errno = EINVAL;		return -1;	}	/* Cache the mft reference for later. */	mft_no = ni->mft_no;	/* Mark the mft record as not in use. */	ni->mrec->flags &= ~MFT_RECORD_IN_USE;	/* Increment the sequence number, skipping zero, if it is not zero. */	old_seq_no = ni->mrec->sequence_number;	seq_no = le16_to_cpu(old_seq_no);	if (seq_no == 0xffff)		seq_no = 1;	else if (seq_no)		seq_no++;	ni->mrec->sequence_number = cpu_to_le16(seq_no);	/* Set the inode dirty and write it out. */	ntfs_inode_mark_dirty(ni);	if (ntfs_inode_sync(ni)) {		err = errno;		goto sync_rollback;	}	/* Clear the bit in the $MFT/$BITMAP corresponding to this record. */	if (ntfs_bitmap_clear_bit(vol->mftbmp_na, mft_no)) {		err = errno;		// FIXME: If ntfs_bitmap_clear_run() guarantees rollback on		//	  error, this could be changed to goto sync_rollback;		goto bitmap_rollback;	}	/* Throw away the now freed inode. */	if (!ntfs_inode_close(ni))		return 0;	err = errno;	/* Rollback what we did... */bitmap_rollback:	if (ntfs_bitmap_set_bit(vol->mftbmp_na, mft_no))		ntfs_log_debug("Eeek! Rollback failed in ntfs_mft_record_free().  "				"Leaving inconsistent metadata!\n");sync_rollback:	ni->mrec->flags |= MFT_RECORD_IN_USE;	ni->mrec->sequence_number = old_seq_no;	ntfs_inode_mark_dirty(ni);	errno = err;	return -1;}#ifndef __VISOPSYS__#ifdef NTFS_RICH#include "bitmap.h"#include "dir.h"#include "tree.h"#include "index.h"#include "rich.h"/** * ntfs_mft_remove_attr - Remove an attribute from an MFT record * @bmp: * @inode: * @type: * * Description... * * Returns: */int ntfs_mft_remove_attr(struct ntfs_bmp *bmp, ntfs_inode *inode, ATTR_TYPES type){	ATTR_RECORD *attr20, *attrXX;	MFT_RECORD *mft;	u8 *src, *dst;	int len;	if (!inode)		return 1;	ntfs_log_trace ("\n");	attr20 = find_first_attribute(AT_ATTRIBUTE_LIST, inode->mrec);	if (attr20)		return 1;	ntfs_log_debug("remove inode %lld, attr 0x%02X\n", inode->mft_no, type);	attrXX = find_first_attribute(type, inode->mrec);	if (!attrXX)		return 1;	if (utils_free_non_residents3(bmp, inode, attrXX))		return 1;	// remove entry	// inode->mrec	mft = inode->mrec;	//utils_dump_mem(mft, 0, mft->bytes_in_use, DM_DEFAULTS); ntfs_log_debug("\n");	//utils_dump_mem(attrXX, 0, attrXX->length, DM_DEFAULTS); ntfs_log_debug("\n");	//ntfs_log_debug("mrec = %p, attr = %p, diff = %d (0x%02X)\n", mft, attrXX, (u8*)attrXX - (u8*)mft, (u8*)attrXX - (u8*)mft);	// memmove	dst = (u8*) attrXX;	src = dst + attrXX->length;	len = (((u8*) mft + mft->bytes_in_use) - src);	// fix mft header	mft->bytes_in_use -= attrXX->length;#if 0	ntfs_log_debug("dst = 0x%02X, src = 0x%02X, len = 0x%02X\n", (dst - (u8*)mft), (src - (u8*)mft), len);	ntfs_log_debug("attr %02X, len = 0x%02X\n", attrXX->type, attrXX->length);	ntfs_log_debug("bytes in use = 0x%02X\n", mft->bytes_in_use);	ntfs_log_debug("\n");#endif	memmove(dst, src, len);	//utils_dump_mem(mft, 0, mft->bytes_in_use, DM_DEFAULTS); ntfs_log_debug("\n");	NInoSetDirty(inode);	return 0;}/** * ntfs_mft_add_attr - Add an attribute to an MFT record * @inode: * @type: * @data: * @data_len: * * Description... * * Returns: */ATTR_RECORD * ntfs_mft_add_attr(ntfs_inode *inode, ATTR_TYPES type, u8 *data, int data_len){	MFT_RECORD *mrec;	ATTR_RECORD *attr;	u8 *ptr;	u8 *src;	u8 *dst;	int len;	int attr_size;	if (!inode)		return NULL;	if (!data)		return NULL;	ntfs_log_trace ("inode %p, mft %lld, attr 0x%02x, len %d\n", inode, inode->mft_no, type, data_len);	attr_size = ATTR_SIZE(data_len);	mrec = inode->mrec;	if (!mrec)		return NULL;	if ((mrec->bytes_in_use + attr_size + 0x18) > mrec->bytes_allocated) {		ntfs_log_debug("attribute is too big to fit in the record\n");		return NULL;	}	ptr = (u8*) inode->mrec + mrec->attrs_offset;	while (1) {		attr = (ATTR_RECORD*) ptr;		if (type < attr->type)			break;		ptr += attr->length;	}	//ntfs_log_debug("insert before attr 0x%02X\n", attr->type);	len = ((u8*) mrec + mrec->bytes_in_use) - ((u8*) attr);	src = (u8*) attr;	dst = src + attr_size + 0x18;	memmove(dst, src, len);	src = data;	dst = (u8*) attr + 0x18;	len = data_len;	// XXX wipe slack space after attr?	memcpy(dst, src, len);	mrec->bytes_in_use += attr_size + 0x18;	memset(attr, 0, 0x18);	*(u32*)((u8*) attr + 0x00) = type;	*(u32*)((u8*) attr + 0x04) = attr_size + 0x18;	*(u16*)((u8*) attr + 0x0E) = mrec->next_attr_instance;	*(u32*)((u8*) attr + 0x10) = data_len;	*(u32*)((u8*) attr + 0x14) = 0x18;	mrec->next_attr_instance++;	return attr;}/** * ntfs_mft_resize_resident - Resize a resident attribute in an MFT record * @inode: * @type: * @name: * @name_len: * @data: * @data_len: * * Description... * * Returns: */int ntfs_mft_resize_resident(ntfs_inode *inode, ATTR_TYPES type, ntfschar *name, int name_len, u8 *data, int data_len){	int mft_size;	int mft_usage;	int mft_free;	int attr_orig;	int attr_new;	u8 *src;	u8 *dst;	u8 *end;	int len;	ntfs_attr_search_ctx *ctx = NULL;	ATTR_RECORD *arec = NULL;	MFT_RECORD *mrec = NULL;	int res = -1;	ntfs_log_trace ("\n");	// XXX only works when attr is in base inode	if ((!inode) || (!inode->mrec))		return -1;	if ((!data) || (data_len < 0))		return -1;	mrec = inode->mrec;	ntfs_log_debug("inode = %lld\n", MREF(inode->mft_no));	//utils_dump_mem(mrec, 0, 1024, DM_DEFAULTS);	mft_size  = mrec->bytes_allocated;	mft_usage = mrec->bytes_in_use;	mft_free  = mft_size - mft_usage;	//ntfs_log_debug("mft_size  = %d\n", mft_size);	//ntfs_log_debug("mft_usage = %d\n", mft_usage);	//ntfs_log_debug("mft_free  = %d\n", mft_free);	//ntfs_log_debug("\n");	ctx = ntfs_attr_get_search_ctx(inode, NULL);	if (!ctx)		goto done;	ntfs_name_print(name, name_len);	ntfs_log_debug(" type = 0x%02x\n", type);	if (ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE, 0, NULL, 0, ctx) != 0)		goto done;	arec = ctx->attr;	if (arec->non_resident) {		ntfs_log_debug("attribute isn't resident\n");		goto done;	}	attr_orig = arec->value_length;	attr_new  = data_len;	ntfs_log_debug("attr orig = %d\n", attr_orig);	ntfs_log_debug("attr new  = %d\n", attr_new);	//ntfs_log_debug("\n");	if ((attr_new - attr_orig + mft_usage) > mft_size) {		ntfs_log_debug("attribute won't fit into mft record\n");		goto done;	}	//ntfs_log_debug("new free space = %d\n", mft_size - (attr_new - attr_orig + mft_usage));	src = (u8*)arec + arec->length;	dst = src + (attr_new - attr_orig);	end = (u8*)mrec + mft_usage;	len  = end - src;	//ntfs_log_debug("src = %d\n", src - (u8*)mrec);	//ntfs_log_debug("dst = %d\n", dst - (u8*)mrec);	//ntfs_log_debug("end = %d\n", end - (u8*)mrec);	//ntfs_log_debug("len = %d\n", len);	if (src != dst)		memmove(dst, src, len);	memcpy((u8*)arec + arec->value_offset, data, data_len);	mrec->bytes_in_use += (attr_new - attr_orig);	arec->length       += (attr_new - attr_orig);	arec->value_length += (attr_new - attr_orig);	memset((u8*)mrec + mrec->bytes_in_use, 0, mft_size - mrec->bytes_in_use);	mft_usage += (attr_new - attr_orig);	//utils_dump_mem(mrec, 0, mft_size, DM_DEFAULTS);	res = 0;done:	ntfs_attr_put_search_ctx(ctx);	return res;}/** * ntfs_mft_free_space - Calculate the free space (bytes) in an MFT record * @dir: * * Description... * * Returns: */int ntfs_mft_free_space(struct ntfs_dir *dir){	int res = 0;	MFT_RECORD *mft;	if ((!dir) || (!dir->inode))		return -1;	ntfs_log_trace ("\n");	mft = (MFT_RECORD*) dir->inode->mrec;	res = mft->bytes_allocated - mft->bytes_in_use;	return res;}/** * ntfs_mft_add_index - Add an index (directory) to an MFT record * @dir: * * Description... * * Returns: */int ntfs_mft_add_index(struct ntfs_dir *dir){	ntfs_volume *vol;	u8 *buffer = NULL;	ATTR_RECORD *attr = NULL;	struct ntfs_dt *dt = NULL;	INDEX_ENTRY *ie = NULL;	if (!dir)		return 1;	if (dir->bitmap && dir->ialloc)		return 0;	if (dir->bitmap || dir->ialloc)		return 1;	if (dir->index_size < 512)		return 1;	ntfs_log_trace ("\n");	vol = dir->vol;	ntfs_log_debug("add two attrs to "); ntfs_name_print(dir->name, dir->name_len); ntfs_log_debug("\n");	ntfs_log_debug("index size = %d\n", dir->index_size);	buffer = malloc(dir->index_size);	if (!buffer)		return 1;	dt = ntfs_dt_create(dir, dir->index, -1);	if (!dt)		return 1;	dt->vcn = 0;		// New alloc record	ie = ntfs_ie_copy(dir->index->children[dir->index->child_count-1]);	ie = ntfs_ie_set_vcn(ie, dt->vcn);	// can't replace ie yet, there may not be room	ntfs_ie_free(ie);	ntfs_dt_transfer2(dir->index, dt, 0, dir->index->child_count - 1);	ntfs_log_debug("root has %d children\n", dir->index->child_count);	ntfs_log_debug("node has %d children\n", dt->child_count);	ntfs_dt_free(dt);	// create a new dt	// attach dt to dir	// move entries into alloc	// shrink root	// transfer keys to new node	// hook up root & alloc dts	// need disk allocation before here	// Index Allocation	memset(buffer, 0, 128);	attr = ntfs_mft_add_attr(dir->inode, AT_INDEX_ALLOCATION, buffer, 0x48);	// Bitmap	memset(buffer, 0, 8);	buffer[0] = 0x01;	//ntfs_log_debug("inode = %p\n", dir->inode);	attr = ntfs_mft_add_attr(dir->inode, AT_BITMAP, buffer, 8);	// attach alloc and bitmap to dir	// need to create ntfs_attr's for them	// one indx record	// 8 bits of bitmap	if (0) ntfs_bmp_find_space(NULL, 0, 0);	//ntfs_log_debug("m1 = %lld\n", vol->mft_zone_start);	//ntfs_log_debug("m2 = %lld\n", vol->mft_zone_end);	//ntfs_log_debug("m3 = %lld\n", vol->mft_zone_pos);	//ntfs_log_debug("z1 = %lld\n", vol->data1_zone_pos);	//ntfs_log_debug("z2 = %lld\n", vol->data2_zone_pos);	free(buffer);	return 0;}#endif /* NTFS_RICH *//** * ntfs_mft_usn_dec - Decrement USN by one * @mrec:	pointer to an mft record * * On success return 0 and on error return -1 with errno set. */int ntfs_mft_usn_dec(MFT_RECORD *mrec){	u16 usn, *usnp;	if (!mrec) {		errno = EINVAL;		return -1;	}	usnp = (u16 *)((char *)mrec + le16_to_cpu(mrec->usa_ofs));	usn = le16_to_cpup(usnp);	if (usn-- <= 1)		usn = 0xfffe;	*usnp = cpu_to_le16(usn);	return 0;}#endif /* __VISOPSYS__ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -