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

📄 inode.c

📁 一个在linux下挂载ntfs文件系统的好工具
💻 C
📖 第 1 页 / 共 3 页
字号:
	ntfs_attr_search_ctx *ctx;	u8 *al = NULL, *aln;	int al_len = 0;	ATTR_LIST_ENTRY *ale = NULL;	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;	}	/* 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)) {				int ale_size;				if (ctx->attr->type == AT_ATTRIBUTE_LIST) {			err = EIO;			ntfs_log_trace("Eeek! Attribute list already present.\n");			goto put_err_out;		}				ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *					ctx->attr->name_length + 7) & ~7;		al_len += ale_size;				aln = realloc(al, al_len);		if (!aln) {			err = errno;			ntfs_log_perror("Failed to realloc %d bytes", al_len);			goto put_err_out;		}		ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al));		al = aln;				memset(ale, 0, ale_size);				/* 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;	}	/* 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");			goto rollback;		}	}	/* Add $ATTRIBUTE_LIST to mft record. */	if (ntfs_resident_attr_record_add(ni,				AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0) < 0) {		err = errno;		ntfs_log_trace("Couldn't add $ATTRIBUTE_LIST to MFT record.\n");		goto rollback;	}	/* Resize it. */	na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);	if (!na) {		err = errno;		ntfs_log_trace("Failed to open just added $ATTRIBUTE_LIST.\n");		goto remove_attrlist_record;	}	if (ntfs_attr_truncate(na, al_len)) {		err = errno;		ntfs_log_trace("Failed to resize just added $ATTRIBUTE_LIST.\n");		ntfs_attr_close(na);		goto remove_attrlist_record;;	}		ntfs_attr_put_search_ctx(ctx);	ntfs_attr_close(na);	return 0;remove_attrlist_record:	/* Prevent ntfs_attr_recorm_rm from freeing attribute list. */	ni->attr_list = NULL;	NInoClearAttrList(ni);	/* Remove $ATTRIBUTE_LIST record. */	ntfs_attr_reinit_search_ctx(ctx);	if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0,				CASE_SENSITIVE, 0, NULL, 0, ctx)) {		if (ntfs_attr_record_rm(ctx))			ntfs_log_trace("Rollback failed. Failed to remove attribute "					"list record.\n");	} else		ntfs_log_trace("Rollback failed. Couldn't find attribute list "				"record.\n");	/* Setup back in-memory runlist. */	ni->attr_list = al;	ni->attr_list_size = al_len;	NInoSetAttrList(ni);rollback:	/*	 * Scan attribute list for attributes that placed not in the base MFT	 * record and move them to it.	 */	ntfs_attr_reinit_search_ctx(ctx);	ale = (ATTR_LIST_ENTRY*)al;	while ((u8*)ale < al + al_len) {		if (MREF_LE(ale->mft_reference) != ni->mft_no) {			if (!ntfs_attr_lookup(ale->type, ale->name,						ale->name_length,						CASE_SENSITIVE,						sle64_to_cpu(ale->lowest_vcn),						NULL, 0, ctx)) {				if (ntfs_attr_record_move_to(ctx, ni))					ntfs_log_trace("Rollback failed. Couldn't "						"back attribute to base MFT record.\n");			} else				ntfs_log_trace("Rollback failed. ntfs_attr_lookup "						"failed.\n");			ntfs_attr_reinit_search_ctx(ctx);		}		ale = (ATTR_LIST_ENTRY*)((u8*)ale + le16_to_cpu(ale->length));	}	/* Remove in-memory attribute list. */	ni->attr_list = NULL;	ni->attr_list_size = 0;	NInoClearAttrList(ni);	NInoAttrListClearDirty(ni);put_err_out:	ntfs_attr_put_search_ctx(ctx);err_out:	free(al);	errno = err;	return -1;}/** * ntfs_inode_free_space - free space in the MFT record of inode * @ni:		ntfs inode in which MFT record free space * @size:	amount of space needed to free * * Return 0 on success or -1 on error with errno set to the error code. */int ntfs_inode_free_space(ntfs_inode *ni, int size){	ntfs_attr_search_ctx *ctx;	int freed, err;	if (!ni || size < 0) {		ntfs_log_trace("Invalid arguments.\n");		errno = EINVAL;		return -1;	}	ntfs_log_trace("Entering for inode 0x%llx, size %d.\n",			(long long) ni->mft_no, size);	freed = (le32_to_cpu(ni->mrec->bytes_allocated) -				le32_to_cpu(ni->mrec->bytes_in_use));	if (size <= freed)		return 0;	ctx = ntfs_attr_get_search_ctx(ni, NULL);	if (!ctx) {		err = errno;		ntfs_log_trace("Failed to get attribute search context.\n");		errno = err;		return -1;	}	/*	 * Chkdsk complain if $STANDARD_INFORMATION is not in the base MFT	 * record. FIXME: I'm not sure in this, need to recheck. For now simply	 * do not move $STANDARD_INFORMATION at all.	 *	 * Also we can't move $ATTRIBUTE_LIST from base MFT_RECORD, so position	 * search context on first attribute after $STANDARD_INFORMATION and	 * $ATTRIBUTE_LIST.	 *	 * Why we reposition instead of simply skip this attributes during	 * enumeration? Because in case we have got only in-memory attribute	 * list ntfs_attr_lookup will fail when it will try to find	 * $ATTRIBUTE_LIST.	 */	if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL,				0, ctx)) {		if (errno != ENOENT) {			err = errno;			ntfs_log_trace("Attribute lookup failed.\n");			goto put_err_out;		}		if (ctx->attr->type == AT_END) {			err = ENOSPC;			goto put_err_out;		}	}	while (1) {		int record_size;		/*		 * Check whether attribute is from different MFT record. If so,		 * find next, because we don't need such.		 */		while (ctx->ntfs_ino->mft_no != ni->mft_no) {			if (ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE,						0, NULL, 0, ctx)) {				err = errno;				if (errno != ENOENT) {					ntfs_log_trace("Attribute lookup failed.\n");				} else					err = ENOSPC;				goto put_err_out;			}		}		record_size = le32_to_cpu(ctx->attr->length);		/* Move away attribute. */		if (ntfs_attr_record_move_away(ctx, 0)) {			err = errno;			ntfs_log_trace("Failed to move out attribute.\n");			break;		}		freed += record_size;		/* Check whether we done. */		if (size <= freed) {			ntfs_attr_put_search_ctx(ctx);			return 0;		}		/*		 * Reposition to first attribute after $STANDARD_INFORMATION and		 * $ATTRIBUTE_LIST (see comments upwards).		 */		ntfs_attr_reinit_search_ctx(ctx);		if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0,				NULL, 0, ctx)) {			if (errno != ENOENT) {				err = errno;				ntfs_log_trace("Attribute lookup failed.\n");				break;			}			if (ctx->attr->type == AT_END) {				err = ENOSPC;				break;			}		}	}put_err_out:	ntfs_attr_put_search_ctx(ctx);	if (err == ENOSPC)		ntfs_log_trace("No attributes left that can be moved out.\n");	errno = err;	return -1;}/** * ntfs_inode_update_atime - update access time for ntfs inode * @ni:		ntfs inode for which update access time * * This function usually get called when user read not metadata from inode. * Do not update time for system files. */void ntfs_inode_update_atime(ntfs_inode *ni){	if (!NVolReadOnly(ni->vol) && !NVolNoATime(ni->vol) && (ni->mft_no >=			FILE_first_user || ni->mft_no == FILE_root)) {		ni->last_access_time = time(NULL);		NInoFileNameSetDirty(ni);		NInoSetDirty(ni);	}}/** * ntfs_inode_update_time - update all times for ntfs inode * @ni:		ntfs inode for which update times * * This function updates last access, mft and data change times. Usually * get called when user write not metadata to inode. Do not update time for * system files. */void ntfs_inode_update_time(ntfs_inode *ni){	if (!NVolReadOnly(ni->vol) && !NVolNoATime(ni->vol) && (ni->mft_no >=			FILE_first_user || ni->mft_no == FILE_root)) {		time_t now;		now = time(NULL);		ni->last_access_time = now;		ni->last_data_change_time = now;		ni->last_mft_change_time = now;		NInoFileNameSetDirty(ni);		NInoSetDirty(ni);	}}/** * ntfs_inode_badclus_bad - check for $Badclus:$Bad data attribute * @mft_no:		mft record number where @attr is present * @attr:		attribute record used to check for the $Bad attribute * * Check if the mft record given by @mft_no and @attr contains the bad sector * list. Please note that mft record numbers describing $Badclus extent inodes * will not match the current $Badclus:$Bad check. *  * On success return 1 if the file is $Badclus:$Bad, otherwise return 0. * On error return -1 with errno set to the error code. */int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr){	int len, ret = 0;	ntfschar *ustr;	if (!attr) {		ntfs_log_error("Invalid argument.\n");		errno = EINVAL;		return -1;	}		if (mft_no != FILE_BadClus)	       	return 0;	if (attr->type != AT_DATA)	       	return 0;	if ((ustr = ntfs_str2ucs("$Bad", &len)) == NULL) {		ntfs_log_perror("Couldn't convert '$Bad' to Unicode");		return -1;	}	if (ustr && ntfs_names_are_equal(ustr, len,			(ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)),			attr->name_length, 0, NULL, 0))		ret = 1;	ntfs_ucsfree(ustr);	return ret;}

⌨️ 快捷键说明

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