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

📄 attr.c

📁 NTFS 磁盘系统 加载源代码
💻 C
字号:
/* *  attr.c * *  Copyright (C) 1996 Martin von L鰓is *  Copyright (C) 1996 Regis Duchesne */#include <errno.h>#include "ntfs.h"/* Look if an attribute already exists in the inode, and if not, create it */static int new_attr(ntfs_inode *ino,int type,void *name,int namelen,		    int *pos, int *found){	int do_insert=0;	int i;	for(i=0;i<ino->attr_count;i++)	{		int n=min(namelen,ino->attrs[i].namelen);		int s=ntfs_uni_strncmp(ino->attrs[i].name,name,n);		/*		 * We assume that each attribute can be uniquely 		 * identified by inode		 * number, attribute type and attribute name.		 */		if(ino->attrs[i].type==type && ino->attrs[i].namelen==namelen && !s){			*found=1;			*pos=i;			return 0;		}		/* attributes are ordered by type, then by name */		if(ino->attrs[i].type>type || (ino->attrs[i].type==type && s==1)){			do_insert=1;			break;		}	}	/* re-allocate space */	if(ino->attr_count % 8 ==0)	{		ntfs_attribute* old=ino->attrs;		ino->attrs = (ntfs_attribute*)ntfs_malloc((ino->attr_count+8)*			     sizeof(ntfs_attribute));		if(old){			ntfs_memcpy(ino->attrs,old,ino->attr_count*sizeof(ntfs_attribute));			ntfs_free(old);		}	}	if(do_insert)		ntfs_memcpy(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){	int size=DATASIZE(&attr->header);	if(size>0){		/* FIXME: read data, free clusters */		return EOPNOTSUPP;	}	NTFS_PUTU8(((char*)&attr->header)+8,0);	NTFS_PUTU16(((char*)&attr->header)+0x10,size);	return 0;}/* Resize the attribute to a newsize */int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute* attr,int newsize){	int error=0;	int oldsize=DATASIZE(&attr->header);	int clustersize=ino->vol->clustersize;	int i,count,newlen,newcount;	ntfs_runlist *rl;	if(newsize==oldsize)		return 0;	/* modifying compressed attributes not supported yet */	if(COMPRESSED(&attr->header))		return EOPNOTSUPP;	/* modifying large files not supported yet */	if(ino->record_count>1)		return EOPNOTSUPP;	if(RESIDENT(&attr->header)){		void *v;		/* making resident attributes non-resident not supported yet */		/* FIXME: check is not sufficient */		if(newsize>ino->vol->mft_recordsize)			return EOPNOTSUPP;		v=attr->d.data;		if(newsize){			attr->d.data=ntfs_malloc(newsize);			if(!attr->d.data)				return ENOMEM;			ntfs_bzero(attr->d.data+oldsize,newsize);			ntfs_memcpy(attr->d.data,v,min(newsize,oldsize));		}else			attr->d.data=0;		ntfs_free(v);		NTFS_PUTU16((&attr->header)+0x10,newsize);		return 0;	}	/* non-resident attribute */	rl=attr->d.r.runlist;	if(newsize<oldsize){		for(i=0,count=0;i<attr->d.r.len;i++){			if((count+rl[i].len)*clustersize>newsize)				break;			count+=rl[i].len;		}		newlen=i+1;		/* free unused clusters in current run, unless sparse */		newcount=count;		if(rl[i].cluster!=-1){			int rounded=newsize-count*clustersize;			rounded=(rounded+clustersize-1)/clustersize;			error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster+rounded,						       rl[i].len-rounded);			if(error)				return error; /* FIXME: incomplete operation */			rl[i].len=rounded;			newcount=count+rounded;		}		/* free all other runs */		for(i++;i<attr->d.r.len;i++)			if(rl[i].cluster!=-1){				error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster,rl[i].len);				if(error)					return error; /* FIXME: incomplete operation */			}		/* FIXME? free space for extra runs in memory */		attr->d.r.len=newlen;	}else{		/* extend attribute */ 		return EOPNOTSUPP;	}	/* fill in new sizes */	NTFS_PUTU64(((char*)&(attr->header))+0x28,newcount*clustersize); /* allocated disk space */	NTFS_PUTU64(((char*)&(attr->header))+0x30,newsize); /*size*/	NTFS_PUTU64(((char*)&(attr->header))+0x38,newsize); /*initialized*/	if(!newsize)		error=ntfs_make_attr_resident(ino,attr);	return error;}int ntfs_create_attr(ntfs_inode *ino,int anum,char* aname,void *data,int dsize){	void *name;	int namelen;	int found,i;	int dstart;	int error;	ntfs_attribute *attr;	char *h;	if(dsize>ino->vol->mft_recordsize)		/* FIXME: non-resident attributes */		return EOPNOTSUPP;	if(aname){		namelen=ntfs_strlen(aname);		name=ntfs_malloc(2*namelen);		ntfs_ascii2uni(name,aname,namelen);	}else{		name=0;		namelen=0;	}	new_attr(ino,anum,name,namelen,&i,&found);	if(found){		ntfs_free(name);		return EEXIST;	}	attr=ino->attrs+i;	ntfs_bzero(attr->header,sizeof(attr->header));	h=attr->header;	NTFS_PUTU32(h,anum); /* type */	NTFS_PUTU8(h+8,0);      /* resident */	NTFS_PUTU8(h+9,namelen);	NTFS_PUTU8(h+0xA,0x18); /* start of name or resident data */	NTFS_PUTU8(h+0xC,0);    /* not compressed */	/* allocate a new number.	   FIXME: Should this happen on inode writeback?	   FIXME: extensions records not supported */	error=ntfs_allocate_attr_number(ino,&i);	if(error)		return error;	NTFS_PUTU16(h+0xE,i);	NTFS_PUTU16(h+0x10,dsize);	dstart=0x18+namelen*2;  /* start data after name */	dstart=(dstart+7)/8*8;  /* round to next multiple of 8 */	NTFS_PUTU16(h+0x14,dstart);	attr->d.data=ntfs_malloc(dsize);	ntfs_memcpy(attr->d.data,data,dsize);	return 0;}/* Store in the inode readable information about a run */void ntfs_insert_run(ntfs_attribute *attr,int cnum,int cluster,int len){	/* (re-)allocate space if necessary */	if(attr->d.r.len % 8 == 0) {		ntfs_runlist* old;		old=attr->d.r.runlist;		attr->d.r.runlist=ntfs_malloc((attr->d.r.len+8)*sizeof(ntfs_runlist));		if(old) {			ntfs_memcpy(attr->d.r.runlist,old,attr->d.r.len				    *sizeof(ntfs_runlist));			ntfs_free(old);		}	}	if(attr->d.r.len>cnum)		ntfs_memcpy(attr->d.r.runlist+cnum+1,attr->d.r.runlist+cnum,			    (attr->d.r.len-cnum)*sizeof(ntfs_runlist));	attr->d.r.runlist[cnum].cluster=cluster;	attr->d.r.runlist[cnum].len=len;	attr->d.r.len++;}/* Non-resident attributes are stored in runs (intervals of clusters). * * This function stores in the inode readable information about a non-resident * attribute. */static int process_runs(ntfs_inode *ino,ntfs_attribute* attr,	unsigned char *data){	int startvcn,endvcn;	int vcn,cnum;	int cluster,len,ctype;	startvcn = NTFS_GETU64(data+0x10);	endvcn = NTFS_GETU64(data+0x18);	/* check whether this chunk really belongs to the end */	for(cnum=0,vcn=0;cnum<attr->d.r.len;cnum++)		vcn+=attr->d.r.runlist[cnum].len;	if(vcn!=startvcn)	{		ntfs_error("Problem with runlist in extended record\n");		return -1;	}	if(!endvcn)	{		endvcn = NTFS_GETU64(data+0x28)-1; /* allocated length */		endvcn /= ino->vol->clustersize;	}	data=data+NTFS_GETU16(data+0x20);	cnum=attr->d.r.len;	cluster=0;	for(vcn=startvcn; vcn<=endvcn; vcn+=len)	{		if(decompress_run(&data,&len,&cluster,&ctype))			return -1;		if(ctype)			ntfs_insert_run(attr,cnum,-1,len);		else			ntfs_insert_run(attr,cnum,cluster,len);		cnum++;	}	return 0;}  /* Insert the attribute starting at attr in the inode ino */int ntfs_insert_attribute(ntfs_inode* ino,unsigned char* attr){	int i,found;	int type;	short int *name;	int namelen;	void *data;	int datasize;	type = NTFS_GETU32(attr);	namelen = NTFS_GETU8(attr+9);	/* read the attribute's name if it has one */	if(!namelen)		name=0;	else	{		/* 1 Unicode character fits in 2 bytes */		name=ntfs_malloc(2*namelen);		ntfs_memcpy(name,attr+NTFS_GETU16(attr+10),2*namelen);	}	new_attr(ino,type,name,namelen,&i,&found);	/* We can have in one inode two attributes with type 0x00000030 (File Name) 	   and without name */	if(found && /*FIXME*/type!=AT_FILE_NAME)	{		process_runs(ino,ino->attrs+i,attr);		return 0;	}  	ntfs_memcpy(&ino->attrs[i].header,attr,sizeof(ino->attrs[i].header));	datasize=DATASIZE(attr);	if(RESIDENT(attr)) {		data=attr+NTFS_GETU16(attr+0x14);		ino->attrs[i].d.data = (void*)ntfs_malloc(datasize);		ntfs_memcpy(ino->attrs[i].d.data,data,datasize);	}else{		ino->attrs[i].d.r.runlist=0;		ino->attrs[i].d.r.len=0;		process_runs(ino,ino->attrs+i,attr);	}	return 0;}/* * Local variables: * c-file-style: "linux" * End: */

⌨️ 快捷键说明

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