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

📄 mkntfs.c

📁 NTFS(NT文件系统) for Linux的一个实现源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  mkntfs - create NTFS format filesystems on block devices    Copyright 1999 by Steve Dodd <dirk@loth.demon.co.uk>    This program is free software; you can redistribute it and/or modify    it under the terms of version 2 of the GNU General Public License as    published by the Free Software Foundation.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See version 2    of the GNU General Public License for more details.    You should have received a copy of version 2 of the GNU General    Public License along with this program; if not, write to the    Free Software Foundation, Inc., 675 Mass Ave, Cambridge,    MA 02139, USA.    Version: $Id: mkntfs.c,v 1.1 1999/04/11 18:32:49 martin Exp $*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <ctype.h>#ifdef HAVE_GETOPT_H#include <getopt.h>#else#define getopt_long(a,v,o,ol,x)        getopt(a,v,o)#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <fcntl.h>#include <errno.h>#include "ntfstypes.h"#include "struct.h"#include "macros.h"#include "support.h"#include "util.h"#include "attr.h"#include "inode.h"#include "super.h"#include "dir.h"#include "attrtypes.h"#include <sys/ioctl.h>#include <linux/hdreg.h>#include <linux/fs.h>int verbose_flag = 0;	/* verbose mode defaults to off */int fd;			/* file descriptor of block device */int cluster_size = 0;	/* cluster size in bytes */int sector_size = 512;	/* sector size in bytes */long sect_per_trk = 0;	/* sectors per track */int heads = 0;		/* heads */long dev_size;		/* size of device in 512 byte blocks */long max_lcn;		/* largest LCN */long mft_lcn = 1;	/* LCN of MFT */long mftmirr_lcn;	/* LCN of MFT mirror */int file_rec_size;	/* FILE record size in clusters */int indx_buf_size;	/* index buffer size in clusters */char *vol_label="";	/* volume label */ntfs_volume *vol;	/* structure representing volume */ntfs_inode *mft_ino;	/* inode struct for $MFT */ntfs_inode *root_ino;	/* inode struct for root */ntfs_inode *boot_ino;	/* inode struct for $Boot */void verbose( const char *fmt, ... ){	va_list args;	if( verbose_flag ) {		va_start( args, fmt );		vprintf( fmt, args );		fflush( stdout );		va_end( args );	}}void iso8859_2_uni( char *dest, const char *src ){	int i, len;	len = strlen( src );	for( i = 0; i < len; i++ ) {		*dest++ = *src++;		*dest++ = '\0';	}}void get_blkdev_info( void ){	if( ioctl( fd, BLKGETSIZE, &dev_size ) ) {		fprintf( stderr, "Couldn't get device size: %s\n",			strerror( errno ) );	}		if( !cluster_size ) {		if( dev_size ) {			if( dev_size < 512 * 1024 * 2 )				cluster_size = sector_size;			else if( dev_size < 1024 * 1024 * 2 )				cluster_size = 1024;			else if( dev_size < 2048 * 1024 * 2 )				cluster_size = 2048;			else				cluster_size = 4096;		} else			cluster_size = 1024;	}	if( cluster_size < sector_size )		cluster_size = sector_size;	printf( "Sector size:\t\t\t%d\n", sector_size );	printf( "Cluster size:\t\t\t%d\n", cluster_size );	if( cluster_size > 4096 )		printf( "Warning: large cluster sizes may cause problems with			compression.\n" );	printf( "Device size:\t\t\t%ld sectors (%ld clusters)\n", dev_size			* ( sector_size / 512 ), dev_size *			( cluster_size / 512 ) );	file_rec_size = max( 1024 / cluster_size, 1 );	printf( "FILE record size:\t\t%d clusters (%ld bytes)\n", file_rec_size,		(long)file_rec_size * (long)cluster_size );	indx_buf_size = max( 2048 / cluster_size, 1 );	verbose( "INDX buffer size:\t\t%d clusters (%ld bytes)\n", indx_buf_size,		(long)indx_buf_size * (long)cluster_size );	max_lcn = ( dev_size / ( cluster_size / 512 ) ) - 1;	verbose( "Maximum cluster number:\t\t%ld\n", max_lcn );	printf( "MFT starts at cluster:\t\t%ld\n", mft_lcn );	mftmirr_lcn = max_lcn - ( file_rec_size * 4 ) + 1;		printf( "Mirror of MFT at cluster:\t%ld\n", mftmirr_lcn );	printf( "\n" );}ntfs_inode *add_mft_entry( int ino ){	char *mftent;	ntfs_inode *new_ino;	/* allocate mem for MFT entry */	mftent = calloc( file_rec_size, cluster_size );	ntfs_fill_mft_header( (ntfs_u8 *)mftent, file_rec_size * cluster_size,		cluster_size, 0 );	/* insert fix ups */	ntfs_insert_fixups( (unsigned char *)mftent, sector_size );	/* move to correct position in MFT */	lseek( fd, ( mft_lcn * cluster_size ) + ( ino * file_rec_size *		cluster_size ), SEEK_SET );	/* write it */	write( fd, mftent, file_rec_size * cluster_size );	free( mftent );	/* read it back */	new_ino = (ntfs_inode *)ntfs_malloc( sizeof( ntfs_inode ) );	ntfs_init_inode( new_ino, vol, ino );	return new_ino;}void add_boot_file( void ){	ntfs_attribute *attr;	ntfs_runlist *rl;	boot_ino = add_mft_entry( FILE_BOOT );	ntfs_create_attr( boot_ino, ATTR_DATA, NULL, NULL, 0, &attr );	rl = ntfs_malloc( sizeof( ntfs_runlist ) );	attr->resident = 0;	attr->allocated = attr->initialized = attr->size = 1 * cluster_size;	rl->len = 1;	rl->cluster = 0;			/* boot cluster at LCN 0 */	attr->d.r.runlist = rl; attr->d.r.len = 1;	/* flush to disk */	verbose( "Writing MFT entry for $Boot (%d)...", FILE_BOOT );	ntfs_update_inode( boot_ino );	verbose( "done.\n" );}ntfs_attribute *create_name_attr( char *name, int hidden ){	ntfs_attribute *attr;	char *data;	attr = calloc( sizeof( ntfs_attribute ), 1 );	data = calloc( 0x42 + strlen( name ) * 2, 1 );	attr->d.data = data; attr->size = 0x42 + strlen( name ) * 2;	iso8859_2_uni( data+0x42, name );	NTFS_PUTU8( data + 0x40, strlen( name ) );	/* file name len */		NTFS_PUTU8( data + 0x41, 0 );			/* POSIX name space */	NTFS_PUTU64( data + 0x38, 0x20 |		( hidden ? 0x02 : 0 ) );		/* Arch + maybe hidden */	/* times */	NTFS_PUTU64( data + 0x8, ntfs_unixutc2ntutc( time( NULL ) ) );	NTFS_PUTU64( data + 0x10, ntfs_unixutc2ntutc( time( NULL ) ) );	NTFS_PUTU64( data + 0x18, ntfs_unixutc2ntutc( time( NULL ) ) );	NTFS_PUTU64( data + 0x20, ntfs_unixutc2ntutc( time( NULL ) ) );	return attr;}	void dispose_temp_name( ntfs_attribute *attr ){	free( attr->d.data );	free( attr );}	void add_root_ent( char *name, ntfs_inode *ino ){	ntfs_attribute *attr = create_name_attr( name, 1 );	verbose( "Adding root entry `%s' for inode %d...", name, ino->i_number );		ntfs_dir_add( root_ino, ino, attr );	ntfs_update_inode( root_ino );	dispose_temp_name( attr );	verbose( "done.\n" );}void init_volume( void ){	ntfs_attribute *attr;	ntfs_inode *vol_ino;	char *vol_label_uni;	char vol_info[0xb];	vol_ino = add_mft_entry( FILE_VOLUME );	/* add volume label */	vol_label_uni = malloc( strlen( vol_label ) * 2 );	iso8859_2_uni( vol_label_uni, vol_label );	ntfs_create_attr( vol_ino, ATTR_VOLUME_NAME, NULL, vol_label_uni,		strlen( vol_label ) * 2, &attr );	/* add volume information */	ntfs_create_attr( vol_ino, ATTR_VOLUME_INFORMATION, NULL, vol_info,		0xb, &attr );		ntfs_update_inode( vol_ino );	add_root_ent( "$Volume", vol_ino );	free( vol_label_uni );	free( vol_ino );}struct attrdef {	const char *label;	ntfs_u64 type, flags;	ntfs_u64 min_size, max_size;};struct attrdef attrdefs[] = {	{ "$STANDARD_INFORMATION", ATTR_STANDARD_INFORMATION, AFLAG_INDEXABLE |		AFLAG_NONRESIDENT, ASIZE_MIN, ASIZE_MAX }, 	{ "$ATTRIBUTE_LIST", ATTR_ATTRIBUTE_LIST, AFLAG_INDEXABLE |		AFLAG_NONRESIDENT, ASIZE_MIN, ASIZE_MAX }, 	{ "$FILE_NAME", ATTR_FILE_NAME, AFLAG_INDEXABLE | AFLAG_NONRESIDENT,		ASIZE_MIN, ASIZE_MAX }, 	{ "$VOLUME_VERSION", ATTR_VOLUME_VERSION, AFLAG_INDEXABLE |		AFLAG_NONRESIDENT, ASIZE_MIN, ASIZE_MAX }, 	{ "$SECURITY_DESCRIPTOR", ATTR_SECURITY_DESCRIPTOR, AFLAG_INDEXABLE |		AFLAG_NONRESIDENT, ASIZE_MIN, ASIZE_MAX }, 	{ "$VOLUME_NAME", ATTR_VOLUME_NAME, AFLAG_INDEXABLE | AFLAG_NONRESIDENT,		ASIZE_MIN, ASIZE_MAX }, 	{ "$VOLUME_INFORMATION", ATTR_VOLUME_INFORMATION, AFLAG_INDEXABLE |		AFLAG_NONRESIDENT, ASIZE_MIN, ASIZE_MAX }, 	{ "$DATA", ATTR_DATA, AFLAG_INDEXABLE | AFLAG_NONRESIDENT, ASIZE_MIN,		ASIZE_MAX} , 	{ "$INDEX_ROOT", ATTR_INDEX_ROOT, AFLAG_INDEXABLE | AFLAG_NONRESIDENT,		ASIZE_MIN, ASIZE_MAX }, 	{ "$INDEX_ALLOCATION", ATTR_INDEX_ALLOCATION, AFLAG_INDEXABLE |		AFLAG_NONRESIDENT, ASIZE_MIN, ASIZE_MAX }, 	{ "$BITMAP", ATTR_BITMAP, AFLAG_INDEXABLE | AFLAG_NONRESIDENT, ASIZE_MIN,		 ASIZE_MAX }, 	{ "$SYMBOLIC_LINK", ATTR_SYMBOLIC_LINK, AFLAG_INDEXABLE |		AFLAG_NONRESIDENT, ASIZE_MIN, ASIZE_MAX }, 	{ "$EA_INFORMATION", ATTR_EA_INFORMATION, AFLAG_INDEXABLE |		AFLAG_NONRESIDENT, ASIZE_MIN, ASIZE_MAX }, 	{ "$EA", ATTR_EA, AFLAG_INDEXABLE | AFLAG_NONRESIDENT, ASIZE_MIN,		ASIZE_MAX }};int num_attrdefs = sizeof( attrdefs ) / sizeof( struct attrdef );void init_attrdef( void ){	ntfs_attribute *attr;	ntfs_inode *attr_ino;	char *attr_rec;	int i;	ntfs_io io;	attr_ino = add_mft_entry( FILE_ATTRDEF );	ntfs_create_attr( attr_ino, ATTR_DATA, NULL, NULL, 0, &attr );	/* we seem to need to do this before adding data to the inode?	   do we still need to do it after we finish writing the data? */	ntfs_update_inode( attr_ino );	attr_rec = malloc( 0xa0 );	io.fn_get = ntfs_get; io.fn_put = ntfs_put;	for( i = 0; i < num_attrdefs; i++ ) {		/* probably not needed, but filesystem dumps are easier to			read if unused space isn't full of crap */		memset( attr_rec, 0, 0xa0 );		iso8859_2_uni( attr_rec, attrdefs[i].label );		NTFS_PUTU16( attr_rec + strlen( attrdefs[i].label )			* 2, 0x0000 ); /* null-terminate */		NTFS_PUTU64( attr_rec + 0x80, attrdefs[i].type );		NTFS_PUTU64( attr_rec + 0x88, attrdefs[i].flags );		NTFS_PUTU64( attr_rec + 0x90, attrdefs[i].min_size );		NTFS_PUTU64( attr_rec + 0x98, attrdefs[i].max_size );					io.size = 0xa0; io.param = attr_rec;		verbose( "Adding attribute `%s', type 0x%Lx, flags 0x%Lx...",			attrdefs[i].label, attrdefs[i].type, attrdefs[i].flags );		ntfs_write_attr( attr_ino, ATTR_DATA, NULL, i * 0xa0, &io );		verbose( "done.\n" );	}	ntfs_update_inode( attr_ino );	add_root_ent( "$AttrDef", attr_ino );	free( attr_rec );	free( attr_ino );}void init_mftmirr( void ){	ntfs_attribute *attr;	ntfs_inode *mirr_ino;	char *mirror_data;	ntfs_io io;	ntfs_runlist rl;	mirr_ino = add_mft_entry( FILE_MFTMIRR );	ntfs_create_attr( mirr_ino, ATTR_DATA, NULL, NULL, 0, &attr );	/* force attribute to allocated area */	attr->resident = 0; attr->allocated = cluster_size * file_rec_size * 4;	attr->size = attr->initialized = 0; attr->d.r.runlist = &rl;	attr->d.r.len = 1;	rl.cluster = mftmirr_lcn; rl.len = attr->allocated / cluster_size;

⌨️ 快捷键说明

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