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

📄 inode.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 3 页
字号:
		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;	ntfs_attr_search_ctx *ctx;	u8 *al, *aln;	int al_len, al_allocated;	ATTR_LIST_ENTRY *ale;	ntfs_attr *na;	if (!ni) {		ntfs_log_trace("Invalid arguments.\n");		errno = EINVAL;		return -1;	}	ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);	if (NInoAttrList(ni) || ni->nr_extents) {		ntfs_log_trace("Inode already has got attribute list.\n");		errno = EEXIST;		return -1;	}	al_allocated = 0x40;	al_len = 0;	al = malloc(al_allocated);	ale = (ATTR_LIST_ENTRY *) al;	if (!al) {		ntfs_log_trace("Not enough memory.\n");		errno = ENOMEM;		return -1;	}	/* Form attribute list. */	ctx = ntfs_attr_get_search_ctx(ni, NULL);	if (!ctx) {		err = errno;		ntfs_log_trace("Couldn't get search context.\n");		goto err_out;	}	/* Walk through all attributes. */	while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {		if (ctx->attr->type == AT_ATTRIBUTE_LIST) {			err = EIO;			ntfs_log_trace("Eeek! Attribute list already present.\n");			goto put_err_out;		}		/* Calculate new length of attribute list. */		al_len += (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *					ctx->attr->name_length + 7) & ~7;		/* Allocate more memory if needed. */		while (al_len > al_allocated) {			al_allocated += 0x40;			aln = realloc(al, al_allocated);			if (!aln) {				ntfs_log_trace("Not enough memory.\n");				err = ENOMEM;				goto put_err_out;			}			ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al));			al = aln;		}		/* Add attribute to attribute list. */		ale->type = ctx->attr->type;		ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) +			sizeof(ntfschar) * ctx->attr->name_length + 7) & ~7);		ale->name_length = ctx->attr->name_length;		ale->name_offset = (u8 *)ale->name - (u8 *)ale;		if (ctx->attr->non_resident)			ale->lowest_vcn = ctx->attr->lowest_vcn;		else			ale->lowest_vcn = 0;		ale->mft_reference = MK_LE_MREF(ni->mft_no,			le16_to_cpu(ni->mrec->sequence_number));		ale->instance = ctx->attr->instance;		memcpy(ale->name, (u8 *)ctx->attr +				le16_to_cpu(ctx->attr->name_offset),				ctx->attr->name_length * sizeof(ntfschar));		ale = (ATTR_LIST_ENTRY *)(al + al_len);	}	/* Check for real error occurred. */	if (errno != ENOENT) {		err = errno;		ntfs_log_trace("Attribute lookup failed.\n");		goto put_err_out;	}	/* Deallocate trailing memory. */	aln = realloc(al, al_len);	if (!aln) {		err = errno;		ntfs_log_trace("realloc() failed.\n");		goto put_err_out;	}	al = aln;	/* Set in-memory attribute list. */	ni->attr_list = al;	ni->attr_list_size = al_len;	NInoSetAttrList(ni);	NInoAttrListSetDirty(ni);	/* Free space if there is not enough it for $ATTRIBUTE_LIST. */	if (le32_to_cpu(ni->mrec->bytes_allocated) -			le32_to_cpu(ni->mrec->bytes_in_use) <			offsetof(ATTR_RECORD, resident_end)) {		if (ntfs_inode_free_space(ni,				offsetof(ATTR_RECORD, resident_end))) {			/* Failed to free space. */			err = errno;			ntfs_log_trace("Failed to free space for "					"$ATTRIBUTE_LIST.\n");

⌨️ 快捷键说明

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