www.pudn.com > truecrypt.zip > FAT.C


/* Copyright (C) 2004 TrueCrypt Team, truecrypt.org 
   This product uses components written by Paul Le Roux  */ 
 
#include "TCdefs.h" 
 
#include "crypto.h" 
#include "random.h" 
#include "fat.h" 
#include "progress.h" 
 
 
#include  
 
#define WRITE_BUF_SIZE 65536 
 
void 
GetFatParams (fatparams * ft) 
{ 
	int fatsecs; 
 
	if(ft->cluster_size == 0) 
	{ 
		if (ft->num_sectors >= 1024I64 *1024*1024*2) 
			ft->cluster_size = 128; 
		else if (ft->num_sectors >= 256*1024*1024*2) 
			ft->cluster_size = 64; 
		else if (ft->num_sectors >= 32*1024*1024*2) 
			ft->cluster_size = 32; 
		else if (ft->num_sectors >= 8*1024*1024*2) 
			ft->cluster_size = 16; 
		else if (ft->num_sectors >= 512*1024*2) 
			ft->cluster_size = 8; 
		else if (ft->num_sectors >= 64*1024*2) 
			ft->cluster_size = 4; 
		else if (ft->num_sectors >= 66600) 
			ft->cluster_size = 2; 
		else 
			ft->cluster_size = 1; 
	} 
 
/*	for (j = 2;; j = j << 1) 
	{ 
		if ((ft->num_sectors * SECTOR_SIZE) / SECTOR_SIZE / j < 65536) 
			break; 
	} 
 
	ft->secs_track = (ft->num_sectors * SECTOR_SIZE) / SECTOR_SIZE / j; 
	ft->heads = j; 
*/ 
 
	// Geometry always set to SECTORS/1/1 
	ft->secs_track = 1;  
	ft->heads = 1;  
 
	ft->dir_entries = 512; 
	ft->fats = 2; 
	ft->create_time = (long) time (NULL); 
	ft->media = 0xf8; 
	ft->sector_size = SECTOR_SIZE; 
	ft->hidden = 0; 
 
	ft->size_root_dir = ft->dir_entries * 32; 
	fatsecs = ft->num_sectors - (ft->size_root_dir + SECTOR_SIZE + 1) / SECTOR_SIZE - 1; 
 
	ft->size_fat = 12; 
	ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / 
	    (ft->cluster_size * SECTOR_SIZE + 3)); 
	ft->fat_length = (((ft->cluster_count * 3 + 1) >> 1) + SECTOR_SIZE + 1) / 
	    SECTOR_SIZE; 
 
	if (ft->cluster_count >= 4085) //FAT16 
	{ 
		ft->size_fat = 16; 
		ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / 
		    (ft->cluster_size * SECTOR_SIZE + 4)); 
		ft->fat_length = (ft->cluster_count * 2 + SECTOR_SIZE + 1) / 
		    SECTOR_SIZE; 
	} 
	if(ft->cluster_count >= 65525) //FAT32 
	{ 
		ft->size_fat = 32; 
		fatsecs = ft->num_sectors - 32 - ft->cluster_size * SECTOR_SIZE; 
		ft->size_root_dir = ft->cluster_size * SECTOR_SIZE; 
		ft->cluster_count = (int) (((__int64) fatsecs * SECTOR_SIZE) / 
		    (ft->cluster_size * SECTOR_SIZE + 4)); 
		ft->fat_length = (ft->cluster_count * 4 + SECTOR_SIZE + 1) / 
		    SECTOR_SIZE; 
	} 
 
	/* MS recommended cut-over safety net for buggy code out there */ 
	#define UNSAFE_AREA 32 
	if(ft->cluster_count > 4085-UNSAFE_AREA  &&  ft->cluster_count < 4085) 
		ft->cluster_count = 4085-UNSAFE_AREA; 
 
	if(ft->cluster_count > 65525-UNSAFE_AREA  &&  ft->cluster_count < 65525) 
		ft->cluster_count = 65525-UNSAFE_AREA; 
 
 
	if (ft->num_sectors >= 65536 || ft->size_fat == 32) 
	{ 
		ft->sectors = 0; 
		ft->total_sect = ft->num_sectors; 
	} 
	else 
	{ 
		ft->sectors = ft->num_sectors; 
		ft->total_sect = 0; 
	} 
 
 
} 
 
void 
PutBoot (fatparams * ft, unsigned char *boot) 
{ 
	int cnt = 0; 
 
	boot[cnt++] = 0xeb;	/* boot jump */ 
	boot[cnt++] = 0x3c; 
	boot[cnt++] = 0x90; 
	memcpy (boot + cnt, "MSWIN4.1", 8); /* system id */ 
	cnt += 8; 
	memcpy (boot + cnt, (short *) &ft->sector_size, 2);	/* bytes per sector */ 
	cnt += 2; 
	memcpy (boot + cnt, (char *) &ft->cluster_size, 1);	/* sectors per cluster */ 
	cnt++; 
	boot[cnt++] = ft->size_fat == 32 ? 32 : 1;	/* reserved sectors */ 
	boot[cnt++] = 0x00; 
	memcpy (boot + cnt, (char *) &ft->fats, 1);	/* 2 fats */ 
	cnt++; 
 
	if(ft->size_fat == 32) 
	{ 
		boot[cnt++] = 0x00; 
		boot[cnt++] = 0x00; 
	} 
	else 
	{ 
		memcpy (boot + cnt, (short *) &ft->dir_entries, 2);	/* 512 root entries */ 
		cnt += 2; 
	} 
 
	memcpy (boot + cnt, (short *) &ft->sectors, 2);	/* # sectors */ 
	cnt += 2; 
	memcpy (boot + cnt, (char *) &ft->media, 1);	/* media byte */ 
	cnt++; 
 
	if(ft->size_fat == 32)	 
	{ 
		boot[cnt++] = 0x00; 
		boot[cnt++] = 0x00; 
	} 
	else  
	{  
		memcpy (boot + cnt, (short *) &ft->fat_length, 2);	/* fat size */ 
		cnt += 2; 
	} 
 
	memcpy (boot + cnt, (short *) &ft->secs_track, 2);	/* # sectors per track */ 
	cnt += 2; 
	memcpy (boot + cnt, (short *) &ft->heads, 2);	/* # heads */ 
	cnt += 2; 
	boot[cnt++] = 0x00;	/* 0 hidden sectors */ 
	boot[cnt++] = 0x00; 
	boot[cnt++] = 0x00; 
	boot[cnt++] = 0x00; 
	memcpy (boot + cnt, (long *) &ft->total_sect, 4);	/* # huge sectors */ 
 
	cnt += 4; 
 
	if(ft->size_fat == 32) 
	{ 
		memcpy (boot + cnt, &ft->fat_length, 4); cnt += 4;	/* fat size 32 */ 
		boot[cnt++] = 0x01;	/* ExtFlags */ 
		boot[cnt++] = 0x00; 
		boot[cnt++] = 0x00;	/* FSVer */ 
		boot[cnt++] = 0x00; 
		boot[cnt++] = 0x02;	/* RootClus */ 
		boot[cnt++] = 0x00; 
		boot[cnt++] = 0x00; 
		boot[cnt++] = 0x00; 
		boot[cnt++] = 0x01;	/* FSInfo */ 
		boot[cnt++] = 0x00; 
		boot[cnt++] = 0x06;	/* BkBootSec */ 
		boot[cnt++] = 0x00; 
		memset(boot+cnt, 0, 12); cnt+=12;	/* Reserved */ 
		 
	} 
 
	boot[cnt++] = 0x80;	/* drive number */   // FIXED 80 > 00 
	boot[cnt++] = 0x00;	/* reserved */ 
	boot[cnt++] = 0x29;	/* boot sig */ 
	memcpy (boot + cnt, (long *) &ft->create_time, 4);	/* vol id */ 
	cnt += 4; 
	memcpy (boot + cnt, (char *) ft->volume_name, 11);	/* vol title */ 
	cnt += 11; 
 
	switch(ft->size_fat) /* filesystem type */ 
	{ 
		case 12: memcpy (boot + cnt, "FAT12   ", 8); break; 
		case 16: memcpy (boot + cnt, "FAT16   ", 8); break; 
		case 32: memcpy (boot + cnt, "FAT32   ", 8); break; 
	} 
	cnt += 8; 
 
	memset (boot + cnt, 0, ft->size_fat==32 ? 420:448);	/* boot code */ 
	cnt += ft->size_fat==32 ? 420:448; 
	boot[cnt++] = 0x55; 
	boot[cnt++] = 0xaa;	/* boot sig */ 
} 
 
/* FAT32 FSInfo */ 
PutFSInfo (unsigned char *sector) 
{ 
 
		memset (sector, 0, 512); 
		sector[3]=0x41; /* LeadSig */ 
		sector[2]=0x61;  
		sector[1]=0x52;  
		sector[0]=0x52;  
		sector[484+3]=0x61; /* StrucSig */ 
		sector[484+2]=0x41;  
		sector[484+1]=0x72;  
		sector[484+0]=0x72;  
		sector[488+3]=0xff; /* Free_Count */ 
		sector[488+2]=0xff; 
		sector[488+1]=0xff; 
		sector[488+0]=0xff; 
		sector[492+3]=0xff; /* Nxt_Free */ 
		sector[492+2]=0xff; 
		sector[492+1]=0xff; 
		sector[492+0]=0xff; 
		sector[508+3]=0xaa; /* TrailSig */ 
		sector[508+2]=0x55; 
		sector[508+1]=0x00; 
		sector[508+0]=0x00; 
} 
 
BOOL 
WriteSector (HFILE dev, char *sector, 
	     char *write_buf, int *write_buf_cnt, 
	     __int64 *nSecNo, int *progress, PCRYPTO_INFO cryptoInfo, 
	     int nFrequency, diskio_f write) 
{ 
	(*cryptoInfo->encrypt_sector) ((unsigned long *) sector, 
	(*nSecNo)++, 1, cryptoInfo->ks, cryptoInfo->iv, cryptoInfo->cipher); 
	memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE); 
	(*write_buf_cnt) += SECTOR_SIZE; 
 
 
	if (*write_buf_cnt == WRITE_BUF_SIZE) 
	{ 
		if ((*write) (dev, write_buf, WRITE_BUF_SIZE) == HFILE_ERROR) 
			return FALSE; 
		else 
			*write_buf_cnt = 0; 
	} 
 
	if (++(*progress) == nFrequency) 
	{ 
		if (UpdateProgressBar (*nSecNo) == TRUE) 
			return FALSE; 
		*progress = 0; 
	} 
 
	return TRUE; 
 
} 
 
int 
Format (fatparams * ft, HFILE dev, PCRYPTO_INFO cryptoInfo, int nFrequency, diskio_f write, BOOL quickFormat) 
{ 
	int write_buf_cnt = 0; 
	char sector[SECTOR_SIZE], *write_buf; 
	int progress = 0; 
	unsigned __int64 nSecNo = 1; 
	int x, n; 
 
	if ((*write) (dev, (char *) &ft->header, SECTOR_SIZE) == HFILE_ERROR) 
		return ERR_OS_ERROR; 
 
	write_buf = TCalloc (WRITE_BUF_SIZE); 
 
	memset (sector, 0, sizeof (sector)); 
 
	PutBoot (ft, (unsigned char *) sector); 
	if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
		cryptoInfo, nFrequency, write) == FALSE) 
		goto fail; 
 
	/* fat32 boot area */ 
	if (ft->size_fat == 32)				 
	{ 
		/* fsinfo */ 
		PutFSInfo((unsigned char *) sector); 
		if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
			cryptoInfo, nFrequency, write) == FALSE) 
			goto fail; 
 
		/* reserved */ 
		while (nSecNo<=6) 
		{ 
			memset (sector, 0, sizeof (sector)); 
			sector[508+3]=0xaa; /* TrailSig */ 
			sector[508+2]=0x55; 
			if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
				cryptoInfo, nFrequency, write) == FALSE) 
				goto fail; 
		} 
		 
		/* bootsector backup */ 
		memset (sector, 0, sizeof (sector)); 
		PutBoot (ft, (unsigned char *) sector); 
		if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
				 cryptoInfo, nFrequency, write) == FALSE) 
			goto fail; 
 
		PutFSInfo((unsigned char *) sector); 
		if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
			cryptoInfo, nFrequency, write) == FALSE) 
			goto fail; 
 
		/* reserved */ 
		while (nSecNo<=32) 
		{ 
			memset (sector, 0, sizeof (sector)); 
			if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
				cryptoInfo, nFrequency, write) == FALSE) 
				goto fail; 
		} 
	} 
 
 
	/* write fat */ 
	for (x = 1; x <= ft->fats; x++) 
	{ 
		for (n = 0; n < ft->fat_length; n++) 
		{ 
			memset (sector, 0, SECTOR_SIZE); 
 
			if (n == 0) 
			{ 
				unsigned char fat_sig[12]; 
				if (ft->size_fat == 32) 
				{ 
					fat_sig[0] = (unsigned char) ft->media; 
					fat_sig[1] = fat_sig[2] = 0xff; 
					fat_sig[3] = 0x0f; 
					fat_sig[4] = fat_sig[5] = fat_sig[6] = 0xff; 
					fat_sig[7] = 0x0f; 
					fat_sig[8] = fat_sig[9] = fat_sig[10] = 0xff; 
					fat_sig[11] = 0x0f; 
					memcpy (sector, fat_sig, 12); 
				}				 
				else if (ft->size_fat == 16) 
				{ 
					fat_sig[0] = (unsigned char) ft->media; 
					fat_sig[1] = 0xff; 
					fat_sig[2] = 0xff; 
					fat_sig[3] = 0xff; 
					memcpy (sector, fat_sig, 4); 
				} 
				else if (ft->size_fat == 12) 
				{ 
					fat_sig[0] = (unsigned char) ft->media; 
					fat_sig[1] = 0xff; 
					fat_sig[2] = 0xff; 
					fat_sig[3] = 0x00; 
					memcpy (sector, fat_sig, 4); 
				} 
			} 
 
			if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
				    cryptoInfo, nFrequency, write) == FALSE) 
				goto fail; 
		} 
	} 
 
 
	/* write rootdir */ 
	for (x = 0; x < ft->size_root_dir / SECTOR_SIZE; x++) 
	{ 
		memset (sector, 0, SECTOR_SIZE); 
		if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
				 cryptoInfo, nFrequency, write) == FALSE) 
			goto fail; 
 
	} 
 
	/* write data area */ 
	if(!quickFormat) 
	{ 
		char key[MAX_CIPHER_KEY]; 
 
		// Generate a random key and IV to randomize data area 
		// and support a possible hidden volume 
		RandgetBytes (key, MAX_CIPHER_KEY);  
		RandgetBytes (cryptoInfo->iv, sizeof cryptoInfo->iv);  
		init_cipher (cryptoInfo->cipher, key, cryptoInfo->ks); 
		ZeroMemory (sector, 512);  
 
		x = ft->num_sectors - (ft->size_fat==32 ? 32 : 1) - ft->size_root_dir / SECTOR_SIZE - ft->fat_length * 2; 
		while (x--) 
		{ 
			if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo, &progress, 
				cryptoInfo, nFrequency, write) == FALSE) 
				goto fail; 
		} 
	} 
 
	if (write_buf_cnt != 0 && (*write) (dev, write_buf, write_buf_cnt) == HFILE_ERROR) 
		goto fail; 
 
	UpdateProgressBar (nSecNo); 
 
	TCfree (write_buf); 
	return 0; 
 
      fail: 
 
	TCfree (write_buf); 
	return ERR_OS_ERROR; 
}