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

📄 attrib.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		unmap_extent_mft_record(ni);	ctx->mrec = ctx->base_mrec;	ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +			le16_to_cpu(ctx->mrec->attrs_offset));	ctx->is_first = true;	ctx->ntfs_ino = base_ni;	ctx->base_ntfs_ino = NULL;	ctx->base_mrec = NULL;	ctx->base_attr = NULL;	/*	 * In case there are multiple matches in the base mft record, need to	 * keep enumerating until we get an attribute not found response (or	 * another error), otherwise we would keep returning the same attribute	 * over and over again and all programs using us for enumeration would	 * lock up in a tight loop.	 */	do {		err = ntfs_attr_find(type, name, name_len, ic, val, val_len,				ctx);	} while (!err);	ntfs_debug("Done, not found.");	return err;}/** * ntfs_attr_lookup - find an attribute in an ntfs inode * @type:	attribute type to find * @name:	attribute name to find (optional, i.e. NULL means don't care) * @name_len:	attribute name length (only needed if @name present) * @ic:		IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present) * @lowest_vcn:	lowest vcn to find (optional, non-resident attributes only) * @val:	attribute value to find (optional, resident attributes only) * @val_len:	attribute value length * @ctx:	search context with mft record and attribute to search from * * Find an attribute in an ntfs inode.  On first search @ctx->ntfs_ino must * be the base mft record and @ctx must have been obtained from a call to * ntfs_attr_get_search_ctx(). * * This function transparently handles attribute lists and @ctx is used to * continue searches where they were left off at. * * After finishing with the attribute/mft record you need to call * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any * mapped inodes, etc). * * Return 0 if the search was successful and -errno if not. * * When 0, @ctx->attr is the found attribute and it is in mft record * @ctx->mrec.  If an attribute list attribute is present, @ctx->al_entry is * the attribute list entry of the found attribute. * * When -ENOENT, @ctx->attr is the attribute which collates just after the * attribute being searched for, i.e. if one wants to add the attribute to the * mft record this is the correct place to insert it into.  If an attribute * list attribute is present, @ctx->al_entry is the attribute list entry which * collates just after the attribute list entry of the attribute being searched * for, i.e. if one wants to add the attribute to the mft record this is the * correct place to insert its attribute list entry into. * * When -errno != -ENOENT, an error occured during the lookup.  @ctx->attr is * then undefined and in particular you should not rely on it not changing. */int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,		const u32 name_len, const IGNORE_CASE_BOOL ic,		const VCN lowest_vcn, const u8 *val, const u32 val_len,		ntfs_attr_search_ctx *ctx){	ntfs_inode *base_ni;	ntfs_debug("Entering.");	BUG_ON(IS_ERR(ctx->mrec));	if (ctx->base_ntfs_ino)		base_ni = ctx->base_ntfs_ino;	else		base_ni = ctx->ntfs_ino;	/* Sanity check, just for debugging really. */	BUG_ON(!base_ni);	if (!NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)		return ntfs_attr_find(type, name, name_len, ic, val, val_len,				ctx);	return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn,			val, val_len, ctx);}/** * ntfs_attr_init_search_ctx - initialize an attribute search context * @ctx:	attribute search context to initialize * @ni:		ntfs inode with which to initialize the search context * @mrec:	mft record with which to initialize the search context * * Initialize the attribute search context @ctx with @ni and @mrec. */static inline void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,		ntfs_inode *ni, MFT_RECORD *mrec){	*ctx = (ntfs_attr_search_ctx) {		.mrec = mrec,		/* Sanity checks are performed elsewhere. */		.attr = (ATTR_RECORD*)((u8*)mrec +				le16_to_cpu(mrec->attrs_offset)),		.is_first = true,		.ntfs_ino = ni,	};}/** * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context * @ctx:	attribute search context to reinitialize * * Reinitialize the attribute search context @ctx, unmapping an associated * extent mft record if present, and initialize the search context again. * * This is used when a search for a new attribute is being started to reset * the search context to the beginning. */void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx){	if (likely(!ctx->base_ntfs_ino)) {		/* No attribute list. */		ctx->is_first = true;		/* Sanity checks are performed elsewhere. */		ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +				le16_to_cpu(ctx->mrec->attrs_offset));		/*		 * This needs resetting due to ntfs_external_attr_find() which		 * can leave it set despite having zeroed ctx->base_ntfs_ino.		 */		ctx->al_entry = NULL;		return;	} /* Attribute list. */	if (ctx->ntfs_ino != ctx->base_ntfs_ino)		unmap_extent_mft_record(ctx->ntfs_ino);	ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);	return;}/** * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context * @ni:		ntfs inode with which to initialize the search context * @mrec:	mft record with which to initialize the search context * * Allocate a new attribute search context, initialize it with @ni and @mrec, * and return it. Return NULL if allocation failed. */ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec){	ntfs_attr_search_ctx *ctx;	ctx = kmem_cache_alloc(ntfs_attr_ctx_cache, GFP_NOFS);	if (ctx)		ntfs_attr_init_search_ctx(ctx, ni, mrec);	return ctx;}/** * ntfs_attr_put_search_ctx - release an attribute search context * @ctx:	attribute search context to free * * Release the attribute search context @ctx, unmapping an associated extent * mft record if present. */void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx){	if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino)		unmap_extent_mft_record(ctx->ntfs_ino);	kmem_cache_free(ntfs_attr_ctx_cache, ctx);	return;}#ifdef NTFS_RW/** * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file * @vol:	ntfs volume to which the attribute belongs * @type:	attribute type which to find * * Search for the attribute definition record corresponding to the attribute * @type in the $AttrDef system file. * * Return the attribute type definition record if found and NULL if not found. */static ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,		const ATTR_TYPE type){	ATTR_DEF *ad;	BUG_ON(!vol->attrdef);	BUG_ON(!type);	for (ad = vol->attrdef; (u8*)ad - (u8*)vol->attrdef <			vol->attrdef_size && ad->type; ++ad) {		/* We have not found it yet, carry on searching. */		if (likely(le32_to_cpu(ad->type) < le32_to_cpu(type)))			continue;		/* We found the attribute; return it. */		if (likely(ad->type == type))			return ad;		/* We have gone too far already.  No point in continuing. */		break;	}	/* Attribute not found. */	ntfs_debug("Attribute type 0x%x not found in $AttrDef.",			le32_to_cpu(type));	return NULL;}/** * ntfs_attr_size_bounds_check - check a size of an attribute type for validity * @vol:	ntfs volume to which the attribute belongs * @type:	attribute type which to check * @size:	size which to check * * Check whether the @size in bytes is valid for an attribute of @type on the * ntfs volume @vol.  This information is obtained from $AttrDef system file. * * Return 0 if valid, -ERANGE if not valid, or -ENOENT if the attribute is not * listed in $AttrDef. */int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPE type,		const s64 size){	ATTR_DEF *ad;	BUG_ON(size < 0);	/*	 * $ATTRIBUTE_LIST has a maximum size of 256kiB, but this is not	 * listed in $AttrDef.	 */	if (unlikely(type == AT_ATTRIBUTE_LIST && size > 256 * 1024))		return -ERANGE;	/* Get the $AttrDef entry for the attribute @type. */	ad = ntfs_attr_find_in_attrdef(vol, type);	if (unlikely(!ad))		return -ENOENT;	/* Do the bounds check. */	if (((sle64_to_cpu(ad->min_size) > 0) &&			size < sle64_to_cpu(ad->min_size)) ||			((sle64_to_cpu(ad->max_size) > 0) && size >			sle64_to_cpu(ad->max_size)))		return -ERANGE;	return 0;}/** * ntfs_attr_can_be_non_resident - check if an attribute can be non-resident * @vol:	ntfs volume to which the attribute belongs * @type:	attribute type which to check * * Check whether the attribute of @type on the ntfs volume @vol is allowed to * be non-resident.  This information is obtained from $AttrDef system file. * * Return 0 if the attribute is allowed to be non-resident, -EPERM if not, and * -ENOENT if the attribute is not listed in $AttrDef. */int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPE type){	ATTR_DEF *ad;	/* Find the attribute definition record in $AttrDef. */	ad = ntfs_attr_find_in_attrdef(vol, type);	if (unlikely(!ad))		return -ENOENT;	/* Check the flags and return the result. */	if (ad->flags & ATTR_DEF_RESIDENT)		return -EPERM;	return 0;}/** * ntfs_attr_can_be_resident - check if an attribute can be resident * @vol:	ntfs volume to which the attribute belongs * @type:	attribute type which to check * * Check whether the attribute of @type on the ntfs volume @vol is allowed to * be resident.  This information is derived from our ntfs knowledge and may * not be completely accurate, especially when user defined attributes are * present.  Basically we allow everything to be resident except for index * allocation and $EA attributes. * * Return 0 if the attribute is allowed to be non-resident and -EPERM if not. * * Warning: In the system file $MFT the attribute $Bitmap must be non-resident *	    otherwise windows will not boot (blue screen of death)!  We cannot *	    check for this here as we do not know which inode's $Bitmap is *	    being asked about so the caller needs to special case this. */int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPE type){	if (type == AT_INDEX_ALLOCATION)		return -EPERM;	return 0;}/** * ntfs_attr_record_resize - resize an attribute record * @m:		mft record containing attribute record * @a:		attribute record to resize * @new_size:	new size in bytes to which to resize the attribute record @a * * Resize the attribute record @a, i.e. the resident part of the attribute, in * the mft record @m to @new_size bytes. * * Return 0 on success and -errno on error.  The following error codes are * defined: *	-ENOSPC	- Not enough space in the mft record @m to perform the resize. * * Note: On error, no modifications have been performed whatsoever. * * Warning: If you make a record smaller without having copied all the data you *	    are interested in the data may be overwritten. */int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size){	ntfs_debug("Entering for new_size %u.", new_size);	/* Align to 8 bytes if it is not already done. */	if (new_size & 7)		new_size = (new_size + 7) & ~7;	/* If the actual attribute length has changed, move things around. */	if (new_size != le32_to_cpu(a->length)) {		u32 new_muse = le32_to_cpu(m->bytes_in_use) -				le32_to_cpu(a->length) + new_size;		/* Not enough space in this mft record. */		if (new_muse > le32_to_cpu(m->bytes_allocated))			return -ENOSPC;		/* Move attributes following @a to their new location. */		memmove((u8*)a + new_size, (u8*)a + le32_to_cpu(a->length),				le32_to_cpu(m->bytes_in_use) - ((u8*)a -				(u8*)m) - le32_to_cpu(a->length));		/* Adjust @m to reflect the change in used space. */		m->bytes_in_use = cpu_to_le32(new_muse);		/* Adjust @a to reflect the new size. */		if (new_size >= offsetof(ATTR_REC, length) + sizeof(a->length))			a->length = cpu_to_le32(new_size);	}	return 0;}/** * ntfs_resident_attr_value_resize - resize the value of a resident attribute * @m:		mft record containing attribute record * @a:		attribute record whose value to resize * @new_size:	new size in bytes to which to resize the attribute value of @a * * Resize the value of the attribute @a in the mft record @m to @new_size bytes. * If the value is made bigger, the newly allocated space is cleared. * * Return 0 on success and -errno on error.  The following error codes are * defined: *	-ENOSPC	- Not enough space in the mft record @m to perform the resize. * * Note: On error, no modifications have been performed whatsoever. * * Warning: If you make a record smaller without having copied all the data you *	    are interested in the data may be overwritten. */int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,		const u32 new_size){	u32 old_size;	/* Resize the resident part of the attribute record. */	if (ntfs_attr_record_resize(m, a,			le16_to_cpu(a->data.resident.value_offset) + new_size))		return -ENOSPC;	/*	 * The resize succeeded!  If we made the attribute value bigger, clear	 * the area between the old size and @new_size.	 */	old_size = le32_to_cpu(a->data.resident.value_length);	if (new_size > old_size)		memset((u8*)a + le16_to_cpu(a->data.resident.value_offset) +				old_size, 0, new_size - old_size);	/* Finally update the length of the attribute value. */	a->data.resident.value_length = cpu_to_le32(new_size);

⌨️ 快捷键说明

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