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

📄 attr.c

📁 EM85XX读NTFS修正代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * attr.c * * Copyright (C) 1996-1999 Martin von L鰓is * Copyright (C) 1996-1997 R間is Duchesne * Copyright (C) 1998 Joseph Malicki * Copyright (C) 1999 Steve Dodd * Copyright (C) 2001 Anton Altaparmakov (AIA) */#include "ntfstypes.h"#include "struct.h"#include "attr.h"#include <linux/errno.h>#include <linux/ntfs_fs.h>#include "macros.h"#include "support.h"#include "util.h"#include "super.h"#include "inode.h"#include "unistr.h"/** * ntfs_find_attr_in_mft_rec - find attribute in mft record * @vol:	volume on which attr resides * @m:		mft record to search * @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 if 1 or case sensitive if 0 (ignored if @name NULL) * @instance:	instance number to find * * Only search the specified mft record and it ignores the presence of an * attribute list attribute (unless it is the one being searched for, * obviously, in which case it is returned). */ntfs_u8* ntfs_find_attr_in_mft_rec(ntfs_volume *vol, ntfs_u8 *m, __u32 type,		wchar_t *name, __u32 name_len, int ic, __u16 instance){	ntfs_u8 *a;		/* Iterate over attributes in mft record @m. */	a = m + NTFS_GETU16(m + 20);	/* attrs_offset */	for (; a >= m && a <= m + vol->mft_record_size;				a += NTFS_GETU32(a + 4 /* length */)) {		/* We catch $END with this more general check, too... */		if (NTFS_GETU32(a + 0 /* type */) > type)			return NULL;		if (!NTFS_GETU32(a + 4 /* length */))			break;		if (NTFS_GETU32(a + 0 /* type */) != type)			continue;		/* If @name is present, compare the two names. */		if (name && !ntfs_are_names_equal(name, name_len, (wchar_t*)				(a + NTFS_GETU16(a + 10 /* name_offset */)),				a[9] /* name_length */, ic, vol->upcase,				vol->upcase_length)) {			register int rc;						rc = ntfs_collate_names(vol->upcase, vol->upcase_length,					name, name_len, (wchar_t*)(a +					NTFS_GETU16(a + 10 /* name_offset */)),					a[9] /* name_length */, 1, 1);			/*			 * If @name collates before a->name, there is no			 * matching attribute.			 */			if (rc == -1)				return NULL;			/* If the strings are not equal, continue search. */			if (rc)	 			continue;			rc = ntfs_collate_names(vol->upcase, vol->upcase_length,					name, name_len, (wchar_t*)(a +					NTFS_GETU16(a + 10 /* name_offset */)),					a[9] /* name_length */, 0, 1);			if (rc == -1)				return NULL;			if (rc)				continue;		}		/*		 * The names match or @name not present. Check instance number.		 * and if it matches we have found the attribute and are done.		 */		if (instance != NTFS_GETU16(a + 14 /* instance */))			continue;		ntfs_debug(DEBUG_FILE3, "ntfs_find_attr_in_mft_record: found: "			"attr type 0x%x, instance number = 0x%x.\n",			NTFS_GETU32(a + 0), instance);		return a;	}	ntfs_error("ntfs_find_attr_in_mft_record: mft record 0x%x is corrupt"			". Run chkdsk.\n", m);	return NULL;}/* Look if an attribute already exists in the inode, and if not, create it. */int ntfs_new_attr(ntfs_inode *ino, int type, void *name, int namelen,		  void *value, int value_len, int *pos, int *found){	int do_insert = 0;	int i, m;	ntfs_attribute *a;	for (i = 0; i < ino->attr_count; i++)	{		a = ino->attrs + i;		if (a->type < type)			continue;		if (a->type > type) {			do_insert = 1;			break;		}		/* If @name is present, compare the two names. */		if (namelen && !ntfs_are_names_equal((wchar_t*)name, namelen,				a->name, a->namelen /* name_length */,				1 /* ignore case*/, ino->vol->upcase,				ino->vol->upcase_length)) {			register int rc;			rc = ntfs_collate_names(ino->vol->upcase,					ino->vol->upcase_length, a->name,					a->namelen, (wchar_t*)name, namelen,					1 /* ignore case */, 1);			if (rc == -1)				continue;			if (rc == 1) {	 			do_insert = 1;				break;			}			rc = ntfs_collate_names(ino->vol->upcase,					ino->vol->upcase_length, a->name,					a->namelen, (wchar_t*)name, namelen,					0 /* case sensitive */, 1);			if (rc == -1)				continue;			if (rc == 1) {				do_insert = 1;				break;			}		}		/* Names are equal or no name was asked for. */		/* If a value was specified compare the values. */		if (value_len && a->resident) {			if (!a->resident) {				ntfs_error("ntfs_new_attr: Value specified but "					"attribute non-resident. Bug!\n");				return -EINVAL;			}			m = value_len;			if (m > a->size)				m = a->size;			m = memcmp(value, a->d.data, m);			if (m > 0)				continue;			if (m < 0) {				do_insert = 1;				break;			}			/* Values match until min of value lengths. */			if (value_len > a->size)				continue;			if (value_len < a->size) {				do_insert = 1;				break;			}		}		/* Full match! */		*found = 1;		*pos = i;		return 0;	}	/* Re-allocate space. */	if (ino->attr_count % 8 == 0)	{		ntfs_attribute* new;		new = (ntfs_attribute*)ntfs_malloc((ino->attr_count + 8) *							sizeof(ntfs_attribute));		if (!new)			return -ENOMEM;		if (ino->attrs) {			ntfs_memcpy(new, ino->attrs, ino->attr_count *							sizeof(ntfs_attribute));			ntfs_free(ino->attrs);		}		ino->attrs = new;	}	if (do_insert)		ntfs_memmove(ino->attrs + i + 1, ino->attrs + i,			     (ino->attr_count - i) * sizeof(ntfs_attribute));	ino->attr_count++;	ino->attrs[i].type = type;	ino->attrs[i].namelen = namelen;	ino->attrs[i].name = name;	*pos = i;	*found = 0;	return 0;}int ntfs_make_attr_resident(ntfs_inode *ino, ntfs_attribute *attr){	__s64 size = attr->size;	if (size > 0) {		/* FIXME: read data, free clusters */		return -EOPNOTSUPP;	}	attr->resident = 1;	return 0;}/* Store in the inode readable information about a run. */int ntfs_insert_run(ntfs_attribute *attr, int cnum, ntfs_cluster_t cluster,		     int len){	/* (re-)allocate space if necessary. */	if ((attr->d.r.len * sizeof(ntfs_runlist)) % PAGE_SIZE == 0) {		ntfs_runlist* new;		unsigned long new_size;		ntfs_debug(DEBUG_MALLOC, "ntfs_insert_run: re-allocating "				"space: old attr->d.r.len = 0x%x\n",				attr->d.r.len);		new_size = attr->d.r.len * sizeof(ntfs_runlist) + PAGE_SIZE;		if ((new_size >> PAGE_SHIFT) > num_physpages) {			ntfs_error("ntfs_insert_run: attempted to allocate "					"more pages than num_physpages."					"This might be a bug or a corrupt"					"file system.\n");			return -1;		}		new = ntfs_vmalloc(new_size);		if (!new) {			ntfs_error("ntfs_insert_run: ntfs_vmalloc(new_size = "					"0x%x) failed\n", new_size);			return -1;		}		if (attr->d.r.runlist) {			ntfs_memcpy(new, attr->d.r.runlist, attr->d.r.len					* sizeof(ntfs_runlist));			ntfs_vfree(attr->d.r.runlist);		}		attr->d.r.runlist = new;	}	if (attr->d.r.len > cnum)		ntfs_memmove(attr->d.r.runlist + cnum + 1,			     attr->d.r.runlist + cnum,			     (attr->d.r.len - cnum) * sizeof(ntfs_runlist));	attr->d.r.runlist[cnum].lcn = cluster;	attr->d.r.runlist[cnum].len = len;	attr->d.r.len++;	return 0;}/** * ntfs_extend_attr - extend allocated size of an attribute * @ino:	ntfs inode containing the attribute to extend * @attr:	attribute which to extend * @len:	desired new length for @attr (_not_ the amount to extend by) * * Extends an attribute. Allocate clusters on the volume which @ino belongs to. * Extends the run list accordingly, preferably by extending the last run of * the existing run list, first. * * Only modifies attr->allocated, i.e. doesn't touch attr->size, nor * attr->initialized. */int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, const __s64 len){	int rlen, rl2_len, err = 0;	ntfs_cluster_t cluster, clen;	ntfs_runlist *rl, *rl2;	if ((attr->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED)) ||			ino->record_count > 1)		return -EOPNOTSUPP;	/*	 * FIXME: Don't make non-resident if the attribute type is not right.	 * For example cannot make index attribute non-resident! (AIA)	 */	if (attr->resident) {		err = ntfs_make_attr_nonresident(ino, attr);		if (err)			return err;	}	if (len <= attr->allocated)		return 0;	/* Truly stupid things do sometimes happen. */	rl = attr->d.r.runlist;	rlen = attr->d.r.len;	if (rlen > 0)		cluster = rl[rlen - 1].lcn + rl[rlen - 1].len;	else		/* No preference for allocation space. */		cluster = (ntfs_cluster_t)-1;	/*	 * Calculate the extra space we need, and round up to multiple of	 * cluster size to get number of new clusters needed.	 */	clen = (len - attr->allocated + ino->vol->cluster_size - 1) >>			ino->vol->cluster_size_bits;	if (!clen)		return 0;	err = ntfs_allocate_clusters(ino->vol, &cluster, &clen, &rl2,			&rl2_len, DATA_ZONE);	if (err)		return err;	attr->allocated += (__s64)clen << ino->vol->cluster_size_bits;	if (rlen > 0) {		err = splice_runlists(&rl, &rlen, rl2, rl2_len);		ntfs_vfree(rl2);		if (err)			return err;	} else {		if (rl)			ntfs_vfree(rl);		rl = rl2;		rlen = rl2_len;	}	attr->d.r.runlist = rl;	attr->d.r.len = rlen;	return 0;}int ntfs_make_attr_nonresident(ntfs_inode *ino, ntfs_attribute *attr){	int error;	ntfs_io io;	void *data = attr->d.data;	__s64 len = attr->size;	attr->d.r.len = 0;	attr->d.r.runlist = NULL;	attr->resident = 0;	/*	 * ->allocated is updated by ntfs_extend_attr(), while ->initialized	 * and ->size are updated by ntfs_readwrite_attr(). (AIA)	 */	attr->allocated = attr->initialized = 0;	error = ntfs_extend_attr(ino, attr, len);	if (error)		return error; /* FIXME: On error, restore old values. */	io.fn_put = ntfs_put;	io.fn_get = ntfs_get;	io.param = data;	io.size = len;	io.do_read = 0;	return ntfs_readwrite_attr(ino, attr, 0, &io);}int ntfs_attr_allnonresident(ntfs_inode *ino){	int i, error = 0;        ntfs_volume *vol = ino->vol;	for (i = 0; !error && i < ino->attr_count; i++)	{		if (ino->attrs[i].type != vol->at_security_descriptor &&		    ino->attrs[i].type != vol->at_data)			continue;		error = ntfs_make_attr_nonresident(ino, ino->attrs + i);	}	return error;}/* * Resize the attribute to a newsize. attr->allocated and attr->size are * updated, but attr->initialized is not changed unless it becomes bigger than * attr->size, in which case it is set to attr->size. */int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 newsize){	int error = 0;	__s64 oldsize = attr->size;	int clustersizebits = ino->vol->cluster_size_bits;	int i, count, newcount;	ntfs_runlist *rl, *rlt;	if (newsize == oldsize)		return 0;	if (attr->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED))		return -EOPNOTSUPP;	if (attr->resident) {		void *v;		if (newsize > ino->vol->mft_record_size) {			error = ntfs_make_attr_nonresident(ino, attr);			if (error)				return error;			return ntfs_resize_attr(ino, attr, newsize);		}		v = attr->d.data;		if (newsize) {			__s64 minsize = newsize;			attr->d.data = ntfs_malloc(newsize);			if (!attr->d.data) {				ntfs_free(v);				return -ENOMEM;			}			if (newsize > oldsize) {				minsize = oldsize;				ntfs_bzero((char*)attr->d.data + oldsize,					   newsize - oldsize);			}			ntfs_memcpy((char*)attr->d.data, v, minsize);		} else			attr->d.data = 0;		ntfs_free(v);		attr->size = newsize;		return 0;	}	/* Non-resident attribute. */	rl = attr->d.r.runlist;	if (newsize < oldsize) {		int rl_size;		/*		 * FIXME: We might be going awfully wrong for newsize = 0,		 * possibly even leaking memory really badly. But considering		 * in that case there is more breakage due to -EOPNOTSUPP stuff		 * further down the code path, who cares for the moment... (AIA)		 */		for (i = 0, count = 0; i < attr->d.r.len; i++) {			if ((__s64)(count + rl[i].len) << clustersizebits >					newsize) {				i++;				break;			}			count += (int)rl[i].len;		}		newcount = count;		/* Free unused clusters in current run, unless sparse. */		if (rl[--i].lcn != (ntfs_cluster_t)-1) {			ntfs_cluster_t rounded = newsize - ((__s64)count <<					clustersizebits);			rounded = (rounded + ino->vol->cluster_size - 1) >>					clustersizebits;			error = ntfs_deallocate_cluster_run(ino->vol, 					rl[i].lcn + rounded,

⌨️ 快捷键说明

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