?? mkntfs.c
字號:
/* 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 + -