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

📄 mft.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
 */int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref){	MFT_RECORD *m;	int ret = -1;	ntfs_log_enter("Entering\n");		m = ntfs_calloc(vol->mft_record_size);	if (!m)		goto out;		if (ntfs_mft_record_layout(vol, mref, m))		goto free_m;		if (ntfs_mft_record_write(vol, mref, m))		goto free_m;		ret = 0;free_m:	free(m);out:		ntfs_log_leave("\n");	return ret;}static const char *es = "  Leaving inconsistent metadata.  Run chkdsk.";/** * ntfs_ffz - Find the first unset (zero) bit in a word * @word: * * Description... * * Returns: */static inline unsigned int ntfs_ffz(unsigned int word){	return ffs(~word) - 1;}#ifndef PAGE_SIZE#define PAGE_SIZE 4096#endif/** * ntfs_mft_bitmap_find_free_rec - find a free mft record in the mft bitmap * @vol:	volume on which to search for a free mft record * @base_ni:	open base inode if allocating an extent mft record or NULL * * Search for a free mft record in the mft bitmap attribute on the ntfs volume * @vol. * * If @base_ni is NULL start the search at the default allocator position. * * If @base_ni is not NULL start the search at the mft record after the base * mft record @base_ni. * * Return the free mft record on success and -1 on error with errno set to the * error code.  An error code of ENOSPC means that there are no free mft * records in the currently initialized mft bitmap. */static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni){	s64 pass_end, ll, data_pos, pass_start, ofs, bit;	ntfs_attr *mftbmp_na;	u8 *buf, *byte;	unsigned int size;	u8 pass, b;	int ret = -1;	ntfs_log_enter("Entering\n");		mftbmp_na = vol->mftbmp_na;	/*	 * Set the end of the pass making sure we do not overflow the mft	 * bitmap.	 */	size = PAGE_SIZE;	pass_end = vol->mft_na->allocated_size >> vol->mft_record_size_bits;	ll = mftbmp_na->initialized_size << 3;	if (pass_end > ll)		pass_end = ll;	pass = 1;	if (!base_ni)		data_pos = vol->mft_data_pos;	else		data_pos = base_ni->mft_no + 1;	if (data_pos < 24)		data_pos = 24;	if (data_pos >= pass_end) {		data_pos = 24;		pass = 2;		/* This happens on a freshly formatted volume. */		if (data_pos >= pass_end) {			errno = ENOSPC;			goto leave;		}	}	pass_start = data_pos;	buf = ntfs_malloc(PAGE_SIZE);	if (!buf)		goto leave;		ntfs_log_debug("Starting bitmap search: pass %u, pass_start 0x%llx, "			"pass_end 0x%llx, data_pos 0x%llx.\n", pass,			(long long)pass_start, (long long)pass_end,			(long long)data_pos);#ifdef DEBUG	byte = NULL;	b = 0;#endif	/* Loop until a free mft record is found. */	for (; pass <= 2; size = PAGE_SIZE) {		/* Cap size to pass_end. */		ofs = data_pos >> 3;		ll = ((pass_end + 7) >> 3) - ofs;		if (size > ll)			size = ll;		ll = ntfs_attr_pread(mftbmp_na, ofs, size, buf);		if (ll < 0) {			ntfs_log_perror("Failed to read $MFT bitmap");			free(buf);			goto leave;		}		ntfs_log_debug("Read 0x%llx bytes.\n", (long long)ll);		/* If we read at least one byte, search @buf for a zero bit. */		if (ll) {			size = ll << 3;			bit = data_pos & 7;			data_pos &= ~7ull;			ntfs_log_debug("Before inner for loop: size 0x%x, "					"data_pos 0x%llx, bit 0x%llx, "					"*byte 0x%hhx, b %u.\n", size,					(long long)data_pos, (long long)bit,					byte ? *byte : -1, b);			for (; bit < size && data_pos + bit < pass_end;					bit &= ~7ull, bit += 8) {				byte = buf + (bit >> 3);				if (*byte == 0xff)					continue;								/* Note: ffz() result must be zero based. */				b = ntfs_ffz((unsigned long)*byte);				if (b < 8 && b >= (bit & 7)) {					free(buf);					ret = data_pos + (bit & ~7ull) + b;					goto leave;				}			}			ntfs_log_debug("After inner for loop: size 0x%x, "					"data_pos 0x%llx, bit 0x%llx, "					"*byte 0x%hhx, b %u.\n", size,					(long long)data_pos, (long long)bit,					byte ? *byte : -1, b);			data_pos += size;			/*			 * If the end of the pass has not been reached yet,			 * continue searching the mft bitmap for a zero bit.			 */			if (data_pos < pass_end)				continue;		}		/* Do the next pass. */		pass++;		if (pass == 2) {			/*			 * Starting the second pass, in which we scan the first			 * part of the zone which we omitted earlier.			 */			pass_end = pass_start;			data_pos = pass_start = 24;			ntfs_log_debug("pass %i, pass_start 0x%llx, pass_end "					"0x%llx.\n", pass, (long long)pass_start,					(long long)pass_end);			if (data_pos >= pass_end)				break;		}	}	/* No free mft records in currently initialized mft bitmap. */	free(buf);	errno = ENOSPC;leave:	ntfs_log_leave("\n");	return ret;}/** * ntfs_mft_bitmap_extend_allocation_i - see ntfs_mft_bitmap_extend_allocation */static int ntfs_mft_bitmap_extend_allocation_i(ntfs_volume *vol){	LCN lcn;	s64 ll = 0; /* silence compiler warning */	ntfs_attr *mftbmp_na;	runlist_element *rl, *rl2 = NULL; /* silence compiler warning */	ntfs_attr_search_ctx *ctx;	MFT_RECORD *m = NULL; /* silence compiler warning */	ATTR_RECORD *a = NULL; /* silence compiler warning */	int err, mp_size;	u32 old_alen = 0; /* silence compiler warning */	BOOL mp_rebuilt = FALSE;	mftbmp_na = vol->mftbmp_na;	/*	 * Determine the last lcn of the mft bitmap.  The allocated size of the	 * mft bitmap cannot be zero so we are ok to do this.	 */	rl = ntfs_attr_find_vcn(mftbmp_na, (mftbmp_na->allocated_size - 1) >>			vol->cluster_size_bits);	if (!rl || !rl->length || rl->lcn < 0) {		ntfs_log_error("Failed to determine last allocated "				"cluster of mft bitmap attribute.\n");		if (rl)			errno = EIO;		return -1;	}	lcn = rl->lcn + rl->length;		rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE);	if (!rl2) {		ntfs_log_error("Failed to allocate a cluster for "				"the mft bitmap.\n");		return -1;	}	rl = ntfs_runlists_merge(mftbmp_na->rl, rl2);	if (!rl) {		err = errno;		ntfs_log_error("Failed to merge runlists for mft "				"bitmap.\n");		if (ntfs_cluster_free_from_rl(vol, rl2))			ntfs_log_error("Failed to deallocate "					"cluster.%s\n", es);		free(rl2);		errno = err;		return -1;	}	mftbmp_na->rl = rl;	ntfs_log_debug("Adding one run to mft bitmap.\n");	/* Find the last run in the new runlist. */	for (; rl[1].length; rl++)		;	/*	 * Update the attribute record as well.  Note: @rl is the last	 * (non-terminator) runlist element of mft bitmap.	 */	ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL);	if (!ctx)		goto undo_alloc;	if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,			mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx)) {		ntfs_log_error("Failed to find last attribute extent of "				"mft bitmap attribute.\n");		goto undo_alloc;	}	m = ctx->mrec;	a = ctx->attr;	ll = sle64_to_cpu(a->lowest_vcn);	rl2 = ntfs_attr_find_vcn(mftbmp_na, ll);	if (!rl2 || !rl2->length) {		ntfs_log_error("Failed to determine previous last "				"allocated cluster of mft bitmap attribute.\n");		if (rl2)			errno = EIO;		goto undo_alloc;	}	/* Get the size for the new mapping pairs array for this extent. */	mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll);	if (mp_size <= 0) {		ntfs_log_error("Get size for mapping pairs failed for "				"mft bitmap attribute extent.\n");		goto undo_alloc;	}	/* Expand the attribute record if necessary. */	old_alen = le32_to_cpu(a->length);	if (ntfs_attr_record_resize(m, a, mp_size +			le16_to_cpu(a->mapping_pairs_offset))) {		// TODO: Deal with this by moving this extent to a new mft		// record or by starting a new extent in a new mft record.		ntfs_log_error("Not enough space in this mft record to "				"accommodate extended mft bitmap attribute "				"extent.  Cannot handle this yet.\n");		errno = EOPNOTSUPP;		goto undo_alloc;	}	mp_rebuilt = TRUE;	/* Generate the mapping pairs array directly into the attr record. */	if (ntfs_mapping_pairs_build(vol, (u8*)a +			le16_to_cpu(a->mapping_pairs_offset), mp_size, rl2, ll,			NULL)) {		ntfs_log_error("Failed to build mapping pairs array for "				"mft bitmap attribute.\n");		errno = EIO;		goto undo_alloc;	}	/* Update the highest_vcn. */	a->highest_vcn = cpu_to_sle64(rl[1].vcn - 1);	/*	 * We now have extended the mft bitmap allocated_size by one cluster.	 * Reflect this in the ntfs_attr structure and the attribute record.	 */	if (a->lowest_vcn) {		/*		 * We are not in the first attribute extent, switch to it, but		 * first ensure the changes will make it to disk later.		 */		ntfs_inode_mark_dirty(ctx->ntfs_ino);		ntfs_attr_reinit_search_ctx(ctx);		if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,				mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) {			ntfs_log_error("Failed to find first attribute "					"extent of mft bitmap attribute.\n");			goto restore_undo_alloc;		}		a = ctx->attr;	}	mftbmp_na->allocated_size += vol->cluster_size;	a->allocated_size = cpu_to_sle64(mftbmp_na->allocated_size);	/* Ensure the changes make it to disk. */	ntfs_inode_mark_dirty(ctx->ntfs_ino);	ntfs_attr_put_search_ctx(ctx);	return 0;restore_undo_alloc:	err = errno;	ntfs_attr_reinit_search_ctx(ctx);	if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name,			mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx)) {		ntfs_log_error("Failed to find last attribute extent of "				"mft bitmap attribute.%s\n", es);		ntfs_attr_put_search_ctx(ctx);		mftbmp_na->allocated_size += vol->cluster_size;		/*		 * The only thing that is now wrong is ->allocated_size of the		 * base attribute extent which chkdsk should be able to fix.		 */		errno = err;		return -1;	}	m = ctx->mrec;	a = ctx->attr;	a->highest_vcn = cpu_to_sle64(rl[1].vcn - 2);	errno = err;undo_alloc:	err = errno;	/* Remove the last run from the runlist. */	lcn = rl->lcn;	rl->lcn = rl[1].lcn;	rl->length = 0;		/* FIXME: use an ntfs_cluster_free_* function */	if (ntfs_bitmap_clear_bit(vol->lcnbmp_na, lcn))		ntfs_log_error("Failed to free cluster.%s\n", es);	else		vol->free_clusters++;	if (mp_rebuilt) {		if (ntfs_mapping_pairs_build(vol, (u8*)a +				le16_to_cpu(a->mapping_pairs_offset),				old_alen - le16_to_cpu(a->mapping_pairs_offset),				rl2, ll, NULL))			ntfs_log_error("Failed to restore mapping "					"pairs array.%s\n", es);		if (ntfs_attr_record_resize(m, a, old_alen))			ntfs_log_error("Failed to restore attribute "					"record.%s\n", es);		ntfs_inode_mark_dirty(ctx->ntfs_ino);	}	if (ctx)		ntfs_attr_put_search_ctx(ctx);	errno = err;	return -1;}/** * ntfs_mft_bitmap_extend_allocation - extend mft bitmap attribute by a cluster * @vol:	volume on which to extend the mft bitmap attribute * * Extend the mft bitmap attribute on the ntfs volume @vol by one cluster. * * Note:  Only changes allocated_size, i.e. does not touch initialized_size or * data_size. * * Return 0 on success and -1 on error with errno set to the error code. */static int ntfs_mft_bitmap_extend_allocation(ntfs_volume *vol){	int ret;		ntfs_log_enter("Entering\n");	ret = ntfs_mft_bitmap_extend_allocation_i(vol);	ntfs_log_leave("\n");	return ret;}/** * ntfs_mft_bitmap_extend_initialized - extend mft bitmap initialized data * @vol:	volume on which to extend the mft bitmap attribute * * Extend the initialized portion of the mft bitmap attribute on the ntfs * volume @vol by 8 bytes. * * Note:  Only changes initialized_size and data_size, i.e. requires that * allocated_size is big enough to fit the new initialized_size. * * Return 0 on success and -1 on error with errno set to the error code.

⌨️ 快捷键说明

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