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

📄 inode.c

📁 NTFS 磁盘系统 加载源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  inode.c * *  Copyright (C) 1995,1996 Martin von L鰓is *  Copyright (C) 1996 Albert D. Cahalan *  Copyright (C) 1996 Regis Duchesne */#include <errno.h>#include "ntfs.h"#include "config.h"int ntfs_init_inode(ntfs_inode *ino,ntfs_volume* vol,int inum){	ntfs_debug("Initializing inode %x\n",inum);	ino->i_number=inum;	ino->vol=vol;	ino->attr=ntfs_malloc(vol->mft_recordsize);	if(ntfs_read_mft_record(vol,inum,ino->attr)==-1){		ntfs_debug("init inode: %x failed\n",inum);		return -1;	}	ntfs_debug("Init: got mft %x\n",inum);	ino->attr_count=0;	ino->record_count=0;	ino->records=0;	ino->attrs=0;	ntfs_load_attributes(ino);	ntfs_debug("Init: done %x\n",inum);	return 0;}void ntfs_clear_inode(ntfs_inode *ino){	int i;	ntfs_free(ino->attr);	ntfs_free(ino->records);	for(i=0;i<ino->attr_count;i++)	{		if(ino->attrs[i].name)			ntfs_free(ino->attrs[i].name);		if(RESIDENT(&ino->attrs[i].header))		{			if(ino->attrs[i].d.data)				ntfs_free(ino->attrs[i].d.data);		}else{			if(ino->attrs[i].d.r.runlist)				ntfs_free(ino->attrs[i].d.r.runlist);		}	}	ntfs_free(ino->attrs);}/* Insert all attributes from the record mftno of the MFT in the inode ino */void ntfs_insert_mft_attributes(ntfs_inode* ino,char *mft,int mftno){	int i;	char *it;	int type,len;	/* check for duplicate */	for(i=0;i<ino->record_count;i++)		if(ino->records[i]==mftno)			return;	/* (re-)allocate space if necessary */	if(ino->record_count % 8==0)	{		int *old=ino->records;		ino->records=ntfs_malloc((ino->record_count+8)*sizeof(int));		if(old) {			for(i=0;i<ino->record_count;i++)				ino->records[i]=old[i];			ntfs_free(old);		}	}	ino->records[ino->record_count]=mftno;	ino->record_count++;	it = mft + NTFS_GETU16(mft + 0x14);	do{		type=NTFS_GETU32(it);		len=NTFS_GETU32(it+4);		if(type!=-1)			ntfs_insert_attribute(ino,it);		it+=len;	}while(type!=-1); /* attribute list ends with type -1 */}/* Read and insert all the attributes of an 'attribute list' attribute */static int parse_attributes(ntfs_inode* ino,void *alist,int len){	char *mft;	int mftno,l;	int last_mft=-1;	mft=ntfs_malloc(ino->vol->mft_recordsize);	while(len>0)	{	        /* process an attribute description */		mftno=NTFS_GETU32(alist+0x10); /* BUG: this is u64 */		if(mftno!=last_mft){			last_mft=mftno;			/* FIXME: avoid loading record if it's 			   already processed */			if(ntfs_read_mft_record(ino->vol,mftno,mft)==-1)				return -1;			ntfs_insert_mft_attributes(ino,mft,mftno);		}		l=NTFS_GETU16(alist+4);		len-=l;		alist+=l;	}	ntfs_free(mft);	return 0;}void ntfs_load_attributes(ntfs_inode* ino){	ntfs_attribute *alist;	int datasize;	int offset,len;	char *buf;	ntfs_debug("load_attributes %x 1\n",ino->i_number);	ntfs_insert_mft_attributes(ino,ino->attr,ino->i_number);	ntfs_debug("load_attributes %x 2\n",ino->i_number);	alist=ntfs_find_attr(ino,AT_ATTRIBUTE_LIST,0);	ntfs_debug("load_attributes %x 3\n",ino->i_number);	if(!alist)		return;	ntfs_debug("load_attributes %x 4\n",ino->i_number);	datasize=DATASIZE(&alist->header);	if(RESIDENT(&alist->header))	{		parse_attributes(ino,alist->d.data,datasize);		return;	}	buf=ntfs_malloc(1024);	for(offset=0;datasize;datasize-=len)	{		ntfs_io io;		io.fn_put=ntfs_put;		io.fn_get=0;		io.param=buf;		len=min(datasize,1024);		/* FIXME: this is really broken if there the attribute list		   is larger than 1024 bytes and 1024 bytes is not a		   attribute record border */		ntfs_read_attr(ino,AT_ATTRIBUTE_LIST,0,offset,&io,len);		parse_attributes(ino,buf,len);	}	ntfs_debug("load_attributes %x 5\n",ino->i_number);	ntfs_free(buf);}	/* Check and fixup a MFT record */int ntfs_check_mft_record(ntfs_volume *vol,char *record){	return ntfs_fixup_record(vol, record, "FILE", vol->mft_recordsize);}/* Return (in result) the value indicating the next available attribute    chunk number. Works for inodes w/o extension records only */int ntfs_allocate_attr_number(ntfs_inode *ino, int *result){	if(ino->record_count!=1)		return EOPNOTSUPP;	*result=NTFS_GETU16(ino->attr+0x28);	NTFS_PUTU16(ino->attr+0x28, (*result)+1);	return 0;}/* find the location of an attribute in the inode. A name of NULL indicates   unnamed attributes. Return pointer to attribute or NULL if not found */char *ntfs_get_attr(ntfs_inode *ino,int attr,char *name){	/* location of first attribute */	char *it= ino->attr + NTFS_GETU16(ino->attr + 0x14);	int type;	int len;	/* Only check for magic DWORD here, fixup should have happened before */	if(!IS_MFT_RECORD(ino->attr))return 0;	do{		type=NTFS_GETU32(it);		len=NTFS_GETU16(it+4);		/* We found the attribute type. Is the name correct, too? */		if(type==attr)		{			int namelen=NTFS_GETU8(it+9);			char *name_it;			/* match given name and attribute name if present,			   make sure attribute name is Unicode */			for(name_it=it+NTFS_GETU16(it+10);namelen;			    name++,name_it+=2,namelen--)				if(*name_it!=*name || name_it[1])break;			if(!namelen)break;		}		it+=len;	}while(type!=-1); /* attribute list end with type -1 */	if(type==-1)return 0;	return it;}/* Search in an inode an attribute by type and name */ntfs_attribute* ntfs_find_attr(ntfs_inode *ino,int type,char *name){	int i;	if(!ino){		ntfs_error("ntfs_find_attr: NO INODE!\n");		return 0;	}	for(i=0;i<ino->attr_count;i++)	{		if(type==ino->attrs[i].type)		{			if(!name && !ino->attrs[i].name)				return ino->attrs+i;			if(name && !ino->attrs[i].name)				return 0;			if(!name && ino->attrs[i].name)				return 0;			if(ntfs_ua_strncmp(ino->attrs[i].name,name,ntfs_strlen(name))==0)				return ino->attrs+i;		}		if(type<ino->attrs[i].type)			return 0;	}	return 0;}int ntfs_get_attr_size(ntfs_inode*ino,int type,char*name){	ntfs_attribute *attr=ntfs_find_attr(ino,type,name);	if(!attr)return 0;	return DATASIZE(&attr->header);}	int ntfs_attr_is_resident(ntfs_inode*ino,int type,char*name){	ntfs_attribute *attr=ntfs_find_attr(ino,type,name);	if(!attr)return 0;	return RESIDENT(&attr->header);}	/* * A run is coded as a type indicator, an unsigned length, and a signed cluster * offset. * . To save space, length and offset are fields of variable length. The low *   nibble of the type indicates the width of the length :), the high nibble *   the width of the offset. * . The first offset is relative to cluster 0, later offsets are relative to *   the previous cluster. * * This function decodes a run. Length is an output parameter, data and cluster * are in/out parameters. */int decompress_run(unsigned char **data,int *length,int *cluster,int *ctype){	unsigned char type=*(*data)++;	*ctype=0;	switch(type & 0xF)	{	case 1: *length=NTFS_GETU8(*data);(*data)++;break;	case 2: *length=NTFS_GETU16(*data);		*data+=2;		break;	case 3: *length = NTFS_GETU24(*data);		*data+=3;		break;		/* TODO: case 4-8 */	default:		ntfs_error("Can't decode run type field %x\n",type);		return -1;	}	switch(type & 0xF0)	{	case 0:    *ctype=2;break;	case 0x10: *cluster+=NTFS_GETS8(*data);(*data)++;break;	case 0x20: *cluster+=NTFS_GETS16(*data);		*data+=2;		break;	case 0x30: 	*cluster+=NTFS_GETS24(*data);		*data+=3;		break;		/* TODO: case 0x40-0x80 */	default:		ntfs_error("Can't decode run type field %x\n",type);		return -1;	}	return 0;}/* Reads l bytes of the attribute (attr,name) of ino starting at offset   on vol into buf. Returns the number of bytes read. 0 is end of attribute,   -1 is error */int ntfs_readwrite_attr(ntfs_inode *ino,int type,	char *name,int offset,ntfs_io *dest,int l){	ntfs_attribute *attr;	int datasize,resident,rnum,compressed;	int cluster,s_cluster,vcn,len,chunk,copied;	int s_vcn,s_vcn_comp;	int clustersize;	attr=ntfs_find_attr(ino,type,name);	if(!attr)		return -1;	clustersize=ino->vol->clustersize;	datasize=DATASIZE(&attr->header);	if(dest->do_read)	{		if(offset>datasize)			return 0;		if(offset+l>=datasize)			l=datasize-offset;	}else{		/* if writing beyond end, extend attribute */	}	resident=RESIDENT(&attr->header);	if(resident)	{		if(dest->do_read)			dest->fn_put(dest,attr->d.data+offset,l);		else		{			dest->fn_get(attr->d.data+offset,dest,l);			update_inode(ino);		}		return l;	}	compressed=COMPRESSED(&attr->header);	vcn=0;	s_vcn = offset/clustersize;	s_vcn_comp = compressed ? (s_vcn/16)*16 : s_vcn;	for(rnum=0;vcn+attr->d.r.runlist[rnum].len<=s_vcn_comp;rnum++)		vcn+=attr->d.r.runlist[rnum].len;		copied=0;	while(l)	{		s_vcn = offset/clustersize;		s_vcn_comp = compressed ? (s_vcn/16)*16 : s_vcn;		cluster=attr->d.r.runlist[rnum].cluster;		len=attr->d.r.runlist[rnum].len;		if(compressed && cluster==-1)		{			/* We are in the middle of a sparse data block */			char *sparse = ntfs_malloc(512);			if(!sparse)return -1;			ntfs_bzero(sparse,512);			chunk = min((vcn+len)*clustersize-offset,l);			while(chunk)			{				int i=min(chunk,512);				dest->fn_put(dest,sparse,i);				chunk-= i;			}			/* restore original value */			chunk = min((vcn+len)*clustersize-offset,l);			ntfs_free(sparse);		}else if(compressed)		{			char *comp,*comp1;			char *decomp;			int got,vcn_comp1;			int offs1;			/* FIXME: writing compressed files */			if(!dest->do_read)				return -1;			if(!(comp= ntfs_malloc(16*clustersize)))				return -1;			if(!(decomp = ntfs_malloc(16*clustersize)))			{				ntfs_free(comp);				return -1;			}			comp1=comp;			got=0;			vcn_comp1=s_vcn_comp;			do{				ntfs_io io;				int l1=min(len*clustersize,16*clustersize-got);				io.do_read=1;				io.fn_put=ntfs_put;				io.fn_get=0;				io.param=comp1;				if(!ntfs_getput_clusters(ino->vol,cluster+vcn_comp1-vcn,0,							 l1,&io))				{					ntfs_free(comp);ntfs_free(decomp);return -1;				}				comp1+=len*clustersize;				if(l1==len*clustersize){					rnum++;					vcn+=len;					cluster=attr->d.r.runlist[rnum].cluster;					len=attr->d.r.runlist[rnum].len;					vcn_comp1=vcn;				}				got+=l1;			}while(cluster!=-1 && got<16*clustersize); /*until 'emtpy' run*/			offs1 = offset-s_vcn_comp*clustersize;			if(cluster!=-1){				/* uncompressible */				comp1 = comp;			}else{				ntfs_decompress(decomp,comp,min(offs1+l,16*clustersize));				comp1 = decomp;			}					chunk = min(16*clustersize-offs1,l);			dest->fn_put(dest,comp1+offs1,chunk);			ntfs_free(comp);			ntfs_free(decomp);		}else{			s_cluster = cluster+s_vcn-vcn;			chunk=min((vcn+len)*clustersize-offset,l);			if(!ntfs_getput_clusters(ino->vol,s_cluster,						 offset-s_vcn*clustersize,chunk,dest))			{				ntfs_error("Read error\n");				return copied;			}		}		l-=chunk;		copied+=chunk;		offset+=chunk;		if(l && offset>=((vcn+len)*clustersize))		{			rnum++;			vcn+=len;			cluster = attr->d.r.runlist[rnum].cluster;			len = attr->d.r.runlist[rnum].len;		}	}	return copied;}int ntfs_read_attr(ntfs_inode *ino,int attr,	char *name,int offset,ntfs_io *buf,int l){	buf->do_read=1;	return ntfs_readwrite_attr(ino,attr,name,offset,buf,l);}int ntfs_write_attr(ntfs_inode *ino,int attr,	char *name,int offset,ntfs_io *buf,int l){	buf->do_read=0;	return ntfs_readwrite_attr(ino,attr,name,offset,buf,l);}int ntfs_vcn_to_lcn(ntfs_inode *ino,int vcn){	int rnum;	ntfs_attribute *data=ntfs_find_attr(ino,AT_DATA,0);	/* It's hard to give an error code */	if(!data)return -1;	if(RESIDENT(&data->header))return -1;	if(COMPRESSED(&data->header))return -1;	if(DATASIZE(&data->header)<vcn*ino->vol->clustersize)return -1;	for(rnum=0;rnum<data->d.r.len && 		    vcn>data->d.r.runlist[rnum].len;rnum++)		vcn-=data->d.r.runlist[rnum].len;		return data->d.r.runlist[rnum].cluster+vcn;}/* copy len unicode characters from from to to :) */void ntfs_uni2ascii(char *to,char *from,int len){	int i;	for(i=0;i<len;i++)		to[i]=from[2*i];	to[i]='\0';}/* copy len asci characters from from to to :) */void ntfs_ascii2uni(short int *to,char *from,int len){	int i;	for(i=0;i<len;i++)		to[i]=from[i];	to[i]=0;}/* strncmp for Unicode strings */int ntfs_uni_strncmp(short int* a,short int *b,int n){	int i;	for(i=0;i<n;i++)	{		if(a[i]<b[i])			return -1;		if(b[i]<a[i])			return 1;	}	return 0;}/* strncmp between Unicode and ASCII strings */int ntfs_ua_strncmp(short int* a,char* b,int n){	int i;	for(i=0;i<n;i++)	{		if(a[i]<b[i])			return -1;		if(b[i]<a[i])			return 1;	}	return 0;}/* Convert the NT UTC (based 1.1.1601, in hundred nanosecond units)   into Unix UTC (based 1.1.1970, in seconds) */ntfs_time_t ntfs_ntutc2unixutc(ntfs_time64_t ntutc){/* * This is very gross because * 1: We must do 64-bit division on a 32-bit machine * 2: We can't use libgcc for long long operations in the kernel * 3: Floating point math in the kernel would corrupt user data */	const unsigned int D = 10000000;	unsigned int H = (ntutc >> 32);	unsigned int L = (unsigned int)ntutc;	unsigned int numerator2;	unsigned int lowseconds;	unsigned int result;	/* It is best to subtract 0x019db1ded53e8000 first. */	/* Then the 1601-based date becomes a 1970-based date. */	if(L < (unsigned)0xd53e8000) H--;	L -= (unsigned)0xd53e8000;	H -= (unsigned)0x019db1de;	/*	 * Now divide 64-bit numbers on a 32-bit machine :-)	 * With the subtraction already done, the result fits in 32 bits.	 * The numerator fits in 56 bits and the denominator fits	 * in 24 bits, so we can shift by 8 bits to make this work.	 */	numerator2  = (H<<8) | (L>>24);	result      = (numerator2 / D);   /* shifted 24 right!! */	lowseconds  = result << 24;	numerator2  = ((numerator2-result*D)<<8) | ((L>>16)&0xff);	result      = (numerator2 / D);   /* shifted 16 right!! */

⌨️ 快捷键说明

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