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

📄 inode.c

📁 一个在linux下挂载ntfs文件系统的好工具
💻 C
📖 第 1 页 / 共 3 页
字号:
				continue;			/* Verify the sequence number if given. */			seq_no = MSEQNO_LE(mref);			if (seq_no && seq_no != le16_to_cpu(					ni->mrec->sequence_number)) {				ntfs_log_debug("Found stale extent mft reference! "					"Corrupt file system. Run chkdsk.\n");				errno = EIO;				return NULL;			}			/* We are done, return the extent inode. */			return ni;		}	}	/* Wasn't there, we need to load the extent inode. */	ni = __ntfs_inode_allocate(base_ni->vol);	if (!ni)		return NULL;	if (ntfs_file_record_read(base_ni->vol, le64_to_cpu(mref), &ni->mrec,			NULL))		goto err_out;	ni->mft_no = mft_no;	ni->nr_extents = -1;	ni->base_ni = base_ni;	/* Attach extent inode to base inode, reallocating memory if needed. */	if (!(base_ni->nr_extents & 3)) {		i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);		extent_nis = ntfs_malloc(i);		if (!extent_nis)			goto err_out;		if (base_ni->nr_extents) {			memcpy(extent_nis, base_ni->extent_nis,					i - 4 * sizeof(ntfs_inode *));			free(base_ni->extent_nis);		}		base_ni->extent_nis = extent_nis;	}	base_ni->extent_nis[base_ni->nr_extents++] = ni;	return ni;err_out:	i = errno;	__ntfs_inode_release(ni);	errno = i;	ntfs_log_perror("Failed to open extent inode");	return NULL;}/** * ntfs_inode_attach_all_extents - attach all extents for target inode * @ni:		opened ntfs inode for which perform attach * * Return 0 on success and -1 on error with errno set to the error code. */int ntfs_inode_attach_all_extents(ntfs_inode *ni){	ATTR_LIST_ENTRY *ale;	u64 prev_attached = 0;	if (!ni) {		ntfs_log_trace("Invalid arguments.\n");		errno = EINVAL;		return -1;	}	if (ni->nr_extents == -1)		ni = ni->base_ni;	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);	/* Inode haven't got attribute list, thus nothing to attach. */	if (!NInoAttrList(ni))		return 0;	if (!ni->attr_list) {		ntfs_log_trace("Corrupt in-memory struct.\n");		errno = EINVAL;		return -1;	}	/* Walk through attribute list and attach all extents. */	errno = 0;	ale = (ATTR_LIST_ENTRY *)ni->attr_list;	while ((u8*)ale < ni->attr_list + ni->attr_list_size) {		if (ni->mft_no != MREF_LE(ale->mft_reference) &&				prev_attached != MREF_LE(ale->mft_reference)) {			if (!ntfs_extent_inode_open(ni,					MREF_LE(ale->mft_reference))) {				ntfs_log_trace("Couldn't attach extent inode.\n");				return -1;			}			prev_attached = MREF_LE(ale->mft_reference);		}		ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length));	}	return 0;}/** * ntfs_inode_sync_standard_information - update standard information attribute * @ni:		ntfs inode to update standard information * * Return 0 on success or -1 on error with errno set to the error code. */static int ntfs_inode_sync_standard_information(ntfs_inode *ni){	ntfs_attr_search_ctx *ctx;	STANDARD_INFORMATION *std_info;	int err;	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);	ctx = ntfs_attr_get_search_ctx(ni, NULL);	if (!ctx)		return -1;	if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,				0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {		err = errno;		ntfs_log_trace("Failed to receive STANDARD_INFORMATION "				"attribute.\n");		ntfs_attr_put_search_ctx(ctx);		errno = err;		return -1;	}	std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +			le16_to_cpu(ctx->attr->value_offset));	std_info->file_attributes = ni->flags;	std_info->creation_time = utc2ntfs(ni->creation_time);	std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time);	std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);	std_info->last_access_time = utc2ntfs(ni->last_access_time);	ntfs_inode_mark_dirty(ctx->ntfs_ino);	ntfs_attr_put_search_ctx(ctx);	return 0;}/** * ntfs_inode_sync_file_name - update FILE_NAME attributes * @ni:		ntfs inode to update FILE_NAME attributes * * Update all FILE_NAME attributes for inode @ni in the index. * * Return 0 on success or -1 on error with errno set to the error code. */static int ntfs_inode_sync_file_name(ntfs_inode *ni){	ntfs_attr_search_ctx *ctx = NULL;	ntfs_index_context *ictx;	ntfs_inode *index_ni;	FILE_NAME_ATTR *fn;	int err = 0;	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);	ctx = ntfs_attr_get_search_ctx(ni, NULL);	if (!ctx) {		err = errno;		ntfs_log_trace("Failed to get attribute search context.\n");		goto err_out;	}	/* Walk through all FILE_NAME attributes and update them. */	while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {		fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr +				le16_to_cpu(ctx->attr->value_offset));		if (MREF_LE(fn->parent_directory) == ni->mft_no) {			/*			 * WARNING: We cheater here and obtain 2 attribute			 * search contexts for one inode (first we obtained			 * above, second will be obtained inside			 * ntfs_index_lookup), it's acceptable for library,			 * but will lock kernel.			 */			index_ni = ni;		} else			index_ni = ntfs_inode_open(ni->vol,				le64_to_cpu(fn->parent_directory));		if (!index_ni) {			if (!err)				err = errno;			ntfs_log_trace("Failed to open inode with index.\n");			continue;		}		ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4);		if (!ictx) {			if (!err)				err = errno;			ntfs_log_trace("Failed to get index context.\n");			ntfs_inode_close(index_ni);			continue;		}		if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) {			if (!err) {				if (errno == ENOENT)					err = EIO;				else					err = errno;			}			ntfs_log_trace("Index lookup failed.\n");			ntfs_index_ctx_put(ictx);			ntfs_inode_close(index_ni);			continue;		}		/* Update flags and file size. */		fn = (FILE_NAME_ATTR *)ictx->data;		fn->file_attributes =				(fn->file_attributes & ~FILE_ATTR_VALID_FLAGS) |				(ni->flags & FILE_ATTR_VALID_FLAGS);		fn->allocated_size = cpu_to_sle64(ni->allocated_size);		fn->data_size = cpu_to_sle64(ni->data_size);		fn->creation_time = utc2ntfs(ni->creation_time);		fn->last_data_change_time = utc2ntfs(ni->last_data_change_time);		fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);		fn->last_access_time = utc2ntfs(ni->last_access_time);		ntfs_index_entry_mark_dirty(ictx);		ntfs_index_ctx_put(ictx);		if (ni != index_ni)			ntfs_inode_close(index_ni);	}	/* Check for real error occurred. */	if (errno != ENOENT) {		err = errno;		ntfs_log_trace("Attribute lookup failed.\n");		goto err_out;	}	ntfs_attr_put_search_ctx(ctx);	if (err) {		errno = err;		return -1;	}	return 0;err_out:	if (ctx)		ntfs_attr_put_search_ctx(ctx);	errno = err;	return -1;}/** * ntfs_inode_sync - write the inode (and its dirty extents) to disk * @ni:		ntfs inode to write * * Write the inode @ni to disk as well as its dirty extent inodes if such * exist and @ni is a base inode. If @ni is an extent inode, only @ni is * written completely disregarding its base inode and any other extent inodes. * * For a base inode with dirty extent inodes if any writes fail for whatever * reason, the failing inode is skipped and the sync process is continued. At * the end the error condition that brought about the failure is returned. Thus * the smallest amount of data loss possible occurs. * * Return 0 on success or -1 on error with errno set to the error code. * The following error codes are defined: *	EINVAL	- Invalid arguments were passed to the function. *	EBUSY	- Inode and/or one of its extents is busy, try again later. *	EIO	- I/O error while writing the inode (or one of its extents). */int ntfs_inode_sync(ntfs_inode *ni){	int err = 0;	if (!ni) {		errno = EINVAL;		return -1;	}	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);	/* Update STANDARD_INFORMATION. */	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&			ntfs_inode_sync_standard_information(ni)) {		if (!err || errno == EIO) {			err = errno;			if (err != EIO)				err = EBUSY;		}		ntfs_log_trace("Failed to sync standard information.\n");	}	/* Update FILE_NAME's in the index. */	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&			NInoFileNameTestAndClearDirty(ni) &&			ntfs_inode_sync_file_name(ni)) {		if (!err || errno == EIO) {			err = errno;			if (err != EIO)				err = EBUSY;		}		ntfs_log_trace("Failed to sync FILE_NAME attributes.\n");		NInoFileNameSetDirty(ni);	}	/* Write out attribute list from cache to disk. */	if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 &&			NInoAttrList(ni) && NInoAttrListTestAndClearDirty(ni)) {		ntfs_attr *na;		na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);		if (!na) {			if (!err || errno == EIO) {				err = errno;				if (err != EIO)					err = EBUSY;				ntfs_log_trace("Attribute list sync failed (open "						"failed).\n");			}			NInoAttrListSetDirty(ni);		} else {			if (na->data_size == ni->attr_list_size) {				if (ntfs_attr_pwrite(na, 0, ni->attr_list_size,							ni->attr_list) !=							ni->attr_list_size) {					if (!err || errno == EIO) {						err = errno;						if (err != EIO)							err = EBUSY;						ntfs_log_trace("Attribute list sync "							"failed (write failed).\n");					}					NInoAttrListSetDirty(ni);				}			} else {				err = EIO;				ntfs_log_trace("Attribute list sync failed (invalid size).\n");				NInoAttrListSetDirty(ni);			}			ntfs_attr_close(na);		}	}	/* Write this inode out to the $MFT (and $MFTMirr if applicable). */	if (NInoTestAndClearDirty(ni)) {		if (ntfs_mft_record_write(ni->vol, ni->mft_no, ni->mrec)) {			if (!err || errno == EIO) {				err = errno;				if (err != EIO)					err = EBUSY;			}			NInoSetDirty(ni);			ntfs_log_trace("Base MFT record sync failed.\n");		}	}	/* If this is a base inode with extents write all dirty extents, too. */	if (ni->nr_extents > 0) {		s32 i;		for (i = 0; i < ni->nr_extents; ++i) {			ntfs_inode *eni;			eni = ni->extent_nis[i];			if (NInoTestAndClearDirty(eni)) {				if (ntfs_mft_record_write(eni->vol, eni->mft_no,						eni->mrec)) {					if (!err || errno == EIO) {						err = errno;						if (err != EIO)							err = EBUSY;					}					NInoSetDirty(eni);					ntfs_log_trace("Extent MFT record sync "							"failed.\n");				}			}		}	}	if (!err)		return 0;	errno = err;	return -1;}/** * ntfs_inode_add_attrlist - add attribute list to inode and fill it * @ni: opened ntfs inode to which add attribute list * * Return 0 on success or -1 on error with errno set to the error code. * The following error codes are defined: *	EINVAL	- Invalid arguments were passed to the function. *	EEXIST	- Attribute list already exist. *	EIO	- Input/Ouput error occurred. *	ENOMEM	- Not enough memory to perform add. */int ntfs_inode_add_attrlist(ntfs_inode *ni){	int err;

⌨️ 快捷键说明

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