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

📄 super.c

📁 NTFS 磁盘系统 加载源代码
💻 C
字号:
/* *  super.c * *  Copyright (C) 1995 Martin von L鰓is *  Copyright (C) 1996 Regis Duchesne */#include <stdio.h>#include <fcntl.h>#include <errno.h>#include "ntfs.h"#include "config.h"/* * All important structures in NTFS use 2 consistency checks : * . a magic structure identifier (FILE, INDX, RSTR, ...) * . a fixup technique : the last word of each sector (called a fixup) of a *   structure's record should end with the word at offset <n> of the first *   sector, and if it is the case, must be replaced with the words following *   <n>. The value of <n> and the number of fixups is taken from the fields *   at the offsets 4 and 6. * * This function perform these 2 checks, and _fails_ if : * . the magic identifier is wrong * . the size is given and does not match the number of sectors * . a fixup is invalid */int ntfs_fixup_record(ntfs_volume* vol,char *record, char *magic, int size){	int start, count, offset;	short fixup;	if(!IS_MAGIC(record,magic))		return 0;	start=NTFS_GETU16(record+4);	count=NTFS_GETU16(record+6);	count--;	if(size && vol->blocksize*count != size)		return 0;	fixup = NTFS_GETU16(record+start);	start+=2;	offset=vol->blocksize-2;	while(count--){		if(NTFS_GETU16(record+offset)!=fixup)			return 0;		NTFS_PUTU16(record+offset, NTFS_GETU16(record+start));		start+=2;		offset+=vol->blocksize;	}	return 1;}/* Get vital informations about the ntfs partition from the boot sector */void ntfs_init_volume(ntfs_volume *vol,char *boot){	vol->blocksize=NTFS_GETU16(boot+0xB);	vol->clusterfactor=NTFS_GETU8(boot+0xD);	vol->mft_clusters_per_record=NTFS_GETS8(boot+0x40);	vol->index_clusters_per_record=NTFS_GETS8(boot+0x44);		/* Just some consistency checks */	if(NTFS_GETU32(boot+0x40)>256)		ntfs_error("Unexpected data #1 in boot block\n");	if(NTFS_GETU32(boot+0x44)>256)		ntfs_error("Unexpected data #2 in boot block\n");	if(vol->index_clusters_per_record<0){		ntfs_error("Unexpected data #3 in boot block\n");		/* If this really means a fraction, setting it to 1		   should be safe. */		vol->index_clusters_per_record=1;	}	/* in some cases, 0xF6 meant 1024 bytes. Other strange values have not	   been observed */	if(vol->mft_clusters_per_record<0 && vol->mft_clusters_per_record!=-10)		ntfs_error("Unexpected data #4 in boot block\n");	vol->clustersize=vol->blocksize*vol->clusterfactor;	if(vol->mft_clusters_per_record>0)		vol->mft_recordsize=			vol->clustersize*vol->mft_clusters_per_record;	else		vol->mft_recordsize=1<<(-vol->mft_clusters_per_record);	vol->index_recordsize=vol->clustersize*vol->index_clusters_per_record;	/* FIXME: long long value */	vol->mft_cluster=NTFS_GETU64(boot+0x30);	vol->upcase=0;	vol->upcase_length=0;	/* this will be initialized later */	vol->mft_ino=0;}int ntfs_load_special_files(ntfs_volume *vol){	ntfs_inode upcase;	vol->mft_ino=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));	if(!vol->mft_ino || ntfs_init_inode(vol->mft_ino,vol,FILE_MFT)==-1)	{		ntfs_error("Problem loading MFT\n");		return -1;	}	ntfs_init_inode(&upcase,vol,FILE_UPCASE);	ntfs_init_upcase(&upcase);	ntfs_clear_inode(&upcase);	return 0;}void ntfs_init_upcase(ntfs_inode *upcase){	ntfs_io io;#define UPCASE_LENGTH  256	upcase->vol->upcase = ntfs_malloc(2*UPCASE_LENGTH);	upcase->vol->upcase_length = UPCASE_LENGTH;	io.fn_put=ntfs_put;	io.fn_get=0;	io.param=upcase->vol->upcase;	ntfs_read_attr(upcase,AT_DATA,NULL,0,&io,2*UPCASE_LENGTH);}int ntfs_get_volumesize(ntfs_volume *vol){	ntfs_io io;	char *cluster0=ntfs_malloc(vol->clustersize);	int size;	io.fn_put=ntfs_put;	io.fn_get=ntfs_get;	io.param=cluster0;	io.do_read=1;	ntfs_getput_clusters(vol,0,0,vol->clustersize,&io);	size=NTFS_GETU64(cluster0+0x28);	ntfs_free(cluster0);	return size;}static int nc[16]={4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0};int ntfs_get_free_cluster_count(ntfs_inode *bitmap){	unsigned char bits[2048];	int l,offset;	int clusters=0;	ntfs_io io;	offset=0;	io.fn_put=ntfs_put;	io.fn_get=ntfs_get;	while(1)	{		register int i;		io.param=bits;		l=ntfs_read_attr(bitmap,AT_DATA,NULL,offset,&io,2048);		if(l==0)break;		if(l<0 || l>2048)return 0; /* something wrong here */		/* I never thought I would do loop unrolling some day */		for(i=0;i<l-8;){			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];		}		for(;i<l;){			clusters+=nc[bits[i]>>4];clusters+=nc[bits[i++] & 0xF];		}		offset+=l;	}	return clusters;}/* Insert the fixups for the record. The number and location of the fixes    is obtained from the record header */void ntfs_insert_fixups(unsigned char *rec,int secsize){	int first=NTFS_GETU16(rec+4);	int count=NTFS_GETU16(rec+6);	int offset=-2;	ntfs_u16 fix=NTFS_GETU16(rec+first);	fix=fix+1;	NTFS_PUTU16(rec+first,fix);	count--;	while(count--){		first+=2;		offset+=secsize;		NTFS_PUTU16(rec+first,NTFS_GETU16(rec+offset));		NTFS_PUTU16(rec+offset,fix);	};}/* search the bitmap bits of l bytes for *cnt zero bits. Return the bit   number in *loc, which is initially set to the number of the first bit.   Return the largest block found in *cnt. Return 0 on success, ENOSPC if   all bits are used */static int search_bits(unsigned char* bits,int *loc,int *cnt,int l){	unsigned char c=0;	int bc=0;	int bstart=0,bstop=0,found=0;	int start,stop=0,in=0;	/* special case searching for a single block */	if(*cnt==1){		while(l && *cnt==0xFF){			bits++;			*loc+=8;			l--;		}		if(!l)return ENOSPC;		for(c=*bits;c & 1;c>>=1)			(*loc)++;		return 0;	}	start=*loc;	while(l || bc){		if(bc==0){			c=*bits;			if(l){				l--;bits++;			}			bc=8;		}		if(in){			if((c&1)==0)				stop++;			else{ /* end of sequence of zeroes */				in=0;				if(!found || bstop-bstart<stop-start){					bstop=stop;bstart=start;found=1;					if(bstop-bstart>*cnt)						break;				}				start=stop+1;			}		}else{			if(c&1)				start++;			else{ /*start of sequence*/				in=1;				stop=start+1;			}		}		bc--;		c>>=1;	}	if(!found)return ENOSPC;	*loc=bstart;	if(*cnt>bstop-bstart)		*cnt=bstop-bstart;	return 0;}int ntfs_set_bitrange(ntfs_inode* bitmap,int loc,int cnt,int bit){	int bsize,locit;	unsigned char *bits,*it;	ntfs_io io;	int l;	io.fn_put=ntfs_put;	io.fn_get=ntfs_get;	bsize=(cnt+loc%8+7)/8; /* round up */	bits=ntfs_malloc(bsize);	io.param=bits;	if(!bits)		return ENOMEM;	l=ntfs_read_attr(bitmap,AT_DATA,NULL,loc/8,&io,bsize);	if(l!=bsize){		ntfs_free(bits);		return EIO;	}	/* now set the bits */	it=bits;	locit=loc;	while(locit%8 && cnt){ /* process first byte */		if(bit)			*it |= 1<<(locit%8);		else			*it &= ~(1<<(locit%8));		cnt--;locit++;		if(locit%8==7)			it++;	}	while(cnt>8){ /*process full bytes */		*it= bit ? 0xFF : 0;		cnt-=8;		locit+=8;		it++;	}	while(cnt){ /*process last byte */		if(bit)			*it |= 1<<(locit%8);		else			*it &= ~(1<<(locit%8));		cnt--;locit++;	}	/* reset to start */	io.param=bits;	l=ntfs_write_attr(bitmap,AT_DATA,NULL,loc/8,&io,bsize);	ntfs_free(bits);	if(l!=bsize)		return EIO;	return 0;}    	/* allocate count clusters around location. If location is -1,   it does not matter where the clusters are. Result is 0 if   success, in which case location and count says what they really got */int ntfs_search_bits(ntfs_inode* bitmap, int *location, int *count){	unsigned char *bits;	ntfs_io io;	int error,found=0;	int loc,cnt,bloc=-1,bcnt=0;	int start,l;	bits=ntfs_malloc(2048);	io.fn_put=ntfs_put;	io.fn_get=ntfs_get;	io.param=bits;	/* first search within +/- 8192 clusters */	start=*location/8;	start= start>1024 ? start-1024 : 0;	l=ntfs_read_attr(bitmap,AT_DATA,NULL,start,&io,2048);	if(l<0 || l>2048){		error=EIO;		goto fail;	}	loc=start*8;	cnt=*count;	error=search_bits(bits,&loc,&cnt,l);	if(error)		goto fail;	if(*count==cnt){		bloc=loc;		bcnt=cnt;		goto success;	}	/* now search from the beginning */	for(start=0;1;start+=2048)	{		l=ntfs_read_attr(bitmap,AT_DATA,NULL,start,&io,2048);		if(l<0 || l>2048){			error=EIO;			goto fail;		}				if(l==0)			if(found)				goto success;			else{				error=ENOSPC;				goto fail;			}		loc=start*8;		cnt=*count;		error=search_bits(bits,&loc,&cnt,l);		if(error)			goto fail;		if(*count==cnt)			goto success;		if(bcnt<cnt){			bcnt=cnt;			bloc=loc;			found=1;		}	} success:	ntfs_free(bits);	ntfs_set_bitrange(bitmap,bloc,bcnt,1);	*location=bloc;	*count=bcnt;	return 0; fail:	ntfs_free(bits);	return error;}int ntfs_allocate_clusters(ntfs_volume *vol,int *location,int *count){	ntfs_inode bitmap;	int error;	ntfs_init_inode(&bitmap,vol,FILE_BITMAP);	error=ntfs_search_bits(&bitmap,location,count);	ntfs_clear_inode(&bitmap);	return error;}int ntfs_deallocate_clusters(ntfs_volume *vol,int location,int count){	ntfs_inode bitmap;	int error;	ntfs_init_inode(&bitmap,vol,FILE_BITMAP);	error=ntfs_set_bitrange(&bitmap,location,count,0);	ntfs_clear_inode(&bitmap);	return error;}/* Helper functions */void ntfs_put(ntfs_io *dest,void *src,ntfs_size_t n){	ntfs_memcpy(dest->param,src,n);	dest->param+=n;}void ntfs_get(void* dest,ntfs_io *src,ntfs_size_t n){	ntfs_memcpy(dest,src->param,n);	src->param+=n;}/* * Local variables: * c-file-style: "linux" * End: */

⌨️ 快捷键说明

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