📄 mkdosfs.c
字号:
if (valid_offset (fd, mid))
low = mid;
else
high = mid;
}
valid_offset (fd, 0);
close (fd);
return (low + 1) / BLOCK_SIZE;
#endif
}
/* Check to see if the specified device is currently mounted - abort if it is */
static void
check_mount (char *device_name)
{
#ifndef _WIN32
FILE *f;
struct mntent *mnt;
if ((f = setmntent (MOUNTED, "r")) == NULL)
return;
while ((mnt = getmntent (f)) != NULL)
if (strcmp (device_name, mnt->mnt_fsname) == 0)
die ("%s contains a mounted file system.");
endmntent (f);
#endif
}
/* Establish the geometry and media parameters for the device */
#ifdef _WIN32
static void
establish_params (void)
{
DISK_GEOMETRY geometry;
DWORD ret;
if (!is_device) {
bs.media = (char) 0xf8; /* Set up the media descriptor for a hard drive */
bs.dir_entries[0] = (char) 0;
bs.dir_entries[1] = (char) 2;
/* For FAT32, use 4k clusters on sufficiently large file systems,
* otherwise 1 sector per cluster. This is also what M$'s format
* command does for FAT32. */
bs.cluster_size = (char)
(size_fat == 32 ?
((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) :
4); /* FAT12 and FAT16: start at 4 sectors per cluster */
return;
}
if (!DeviceIoControl((HANDLE)dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geometry, sizeof(geometry), &ret, NULL)) {
errno = GetLastError();
die ("unable to get geometry for '%s'");
}
bs.secs_track = geometry.SectorsPerTrack;
bs.heads = geometry.TracksPerCylinder;
switch (geometry.MediaType) {
case F3_1Pt44_512:
bs.media = (char) 0xf9;
bs.cluster_size = (char) 2;
bs.dir_entries[0] = (char) 112;
bs.dir_entries[1] = (char) 0;
break;
case F3_2Pt88_512:
bs.media = (char) 0xf0;
bs.cluster_size = (char)(atari_format ? 2 : 1);
bs.dir_entries[0] = (char) 224;
bs.dir_entries[1] = (char) 0;
break;
case F3_720_512:
bs.media = (char) 0xfd;
bs.cluster_size = (char) 2;
bs.dir_entries[0] = (char) 112;
bs.dir_entries[1] = (char) 0;
break;
default:
bs.media = (char) 0xf8; /* Set up the media descriptor for a hard drive */
bs.dir_entries[0] = (char) 0;
bs.dir_entries[1] = (char) 2;
/* For FAT32, use 4k clusters on sufficiently large file systems,
* otherwise 1 sector per cluster. This is also what M$'s format
* command does for FAT32. */
bs.cluster_size = (char)
(size_fat == 32 ?
((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) :
4); /* FAT12 and FAT16: start at 4 sectors per cluster */
}
}
#else
static void
establish_params (int device_num,int size)
{
long loop_size;
struct hd_geometry geometry;
struct floppy_struct param;
if ((0 == device_num) || ((device_num & 0xff00) == 0x0200))
/* file image or floppy disk */
{
if (0 == device_num)
{
param.size = size/512;
switch(param.size)
{
case 720:
param.sect = 9 ;
param.head = 2;
break;
case 1440:
param.sect = 9;
param.head = 2;
break;
case 2400:
param.sect = 15;
param.head = 2;
break;
case 2880:
param.sect = 18;
param.head = 2;
break;
case 5760:
param.sect = 36;
param.head = 2;
break;
default:
/* fake values */
param.sect = 32;
param.head = 64;
break;
}
}
else /* is a floppy diskette */
{
if (ioctl (dev, FDGETPRM, ¶m)) /* Can we get the diskette geometry? */
die ("unable to get diskette geometry for '%s'");
}
bs.secs_track = CT_LE_W(param.sect); /* Set up the geometry information */
bs.heads = CT_LE_W(param.head);
switch (param.size) /* Set up the media descriptor byte */
{
case 720: /* 5.25", 2, 9, 40 - 360K */
bs.media = (char) 0xfd;
bs.cluster_size = (char) 2;
bs.dir_entries[0] = (char) 112;
bs.dir_entries[1] = (char) 0;
break;
case 1440: /* 3.5", 2, 9, 80 - 720K */
bs.media = (char) 0xf9;
bs.cluster_size = (char) 2;
bs.dir_entries[0] = (char) 112;
bs.dir_entries[1] = (char) 0;
break;
case 2400: /* 5.25", 2, 15, 80 - 1200K */
bs.media = (char) 0xf9;
bs.cluster_size = (char)(atari_format ? 2 : 1);
bs.dir_entries[0] = (char) 224;
bs.dir_entries[1] = (char) 0;
break;
case 5760: /* 3.5", 2, 36, 80 - 2880K */
bs.media = (char) 0xf0;
bs.cluster_size = (char) 2;
bs.dir_entries[0] = (char) 224;
bs.dir_entries[1] = (char) 0;
break;
case 2880: /* 3.5", 2, 18, 80 - 1440K */
floppy_default:
bs.media = (char) 0xf0;
bs.cluster_size = (char)(atari_format ? 2 : 1);
bs.dir_entries[0] = (char) 224;
bs.dir_entries[1] = (char) 0;
break;
default: /* Anything else */
if (0 == device_num)
goto def_hd_params;
else
goto floppy_default;
}
}
else if ((device_num & 0xff00) == 0x0700) /* This is a loop device */
{
/* Can we get the loop geometry? This is in 512 byte blocks, always? */
if (ioctl (dev, BLKGETSIZE, &loop_size))
die ("unable to get loop geometry for '%s'");
loop_size = loop_size >> 1;
switch (loop_size) /* Assuming the loop device -> floppy later */
{
case 720: /* 5.25", 2, 9, 40 - 360K */
bs.secs_track = CF_LE_W(9);
bs.heads = CF_LE_W(2);
bs.media = (char) 0xfd;
bs.cluster_size = (char) 2;
bs.dir_entries[0] = (char) 112;
bs.dir_entries[1] = (char) 0;
break;
case 1440: /* 3.5", 2, 9, 80 - 720K */
bs.secs_track = CF_LE_W(9);
bs.heads = CF_LE_W(2);
bs.media = (char) 0xf9;
bs.cluster_size = (char) 2;
bs.dir_entries[0] = (char) 112;
bs.dir_entries[1] = (char) 0;
break;
case 2400: /* 5.25", 2, 15, 80 - 1200K */
bs.secs_track = CF_LE_W(15);
bs.heads = CF_LE_W(2);
bs.media = (char) 0xf9;
bs.cluster_size = (char)(atari_format ? 2 : 1);
bs.dir_entries[0] = (char) 224;
bs.dir_entries[1] = (char) 0;
break;
case 5760: /* 3.5", 2, 36, 80 - 2880K */
bs.secs_track = CF_LE_W(36);
bs.heads = CF_LE_W(2);
bs.media = (char) 0xf0;
bs.cluster_size = (char) 2;
bs.dir_entries[0] = (char) 224;
bs.dir_entries[1] = (char) 0;
break;
case 2880: /* 3.5", 2, 18, 80 - 1440K */
bs.secs_track = CF_LE_W(18);
bs.heads = CF_LE_W(2);
bs.media = (char) 0xf0;
bs.cluster_size = (char)(atari_format ? 2 : 1);
bs.dir_entries[0] = (char) 224;
bs.dir_entries[1] = (char) 0;
break;
default: /* Anything else: default hd setup */
printf("Loop device does not match a floppy size, using "
"default hd params\n");
bs.secs_track = CT_LE_W(32); /* these are fake values... */
bs.heads = CT_LE_W(64);
goto def_hd_params;
}
}
else
/* Must be a hard disk then! */
{
/* Can we get the drive geometry? (Note I'm not too sure about */
/* whether to use HDIO_GETGEO or HDIO_REQ) */
if (ioctl (dev, HDIO_GETGEO, &geometry))
die ("unable to get drive geometry for '%s'");
bs.secs_track = CT_LE_W(geometry.sectors); /* Set up the geometry information */
bs.heads = CT_LE_W(geometry.heads);
def_hd_params:
bs.media = (char) 0xf8; /* Set up the media descriptor for a hard drive */
bs.dir_entries[0] = (char) 0; /* Default to 512 entries */
bs.dir_entries[1] = (char) 2;
/* For FAT32, use 4k clusters on sufficiently large file systems,
* otherwise 1 sector per cluster. This is also what M$'s format
* command does for FAT32. */
bs.cluster_size = (char)
(size_fat == 32 ?
((ll_t)blocks*SECTORS_PER_BLOCK >= 512*1024 ? 8 : 1) :
4); /* FAT12 and FAT16: start at 4 sectors per cluster */
}
}
#endif
/* Create the filesystem data tables */
static void
setup_tables (void)
{
unsigned num_sectors;
unsigned cluster_count = 0, fat_length;
unsigned fatdata; /* Sectors for FATs + data area */
struct tm *ctime;
struct msdos_volume_info *vi = (size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);
if (atari_format)
/* On Atari, the first few bytes of the boot sector are assigned
* differently: The jump code is only 2 bytes (and m68k machine code
* :-), then 6 bytes filler (ignored), then 3 byte serial number. */
strncpy( bs.system_id-1, "mkdosf", 6 );
else
strcpy (bs.system_id, "mkdosfs");
if (sectors_per_cluster)
bs.cluster_size = (char) sectors_per_cluster;
if (size_fat == 32)
{
/* Under FAT32, the root dir is in a cluster chain, and this is
* signalled by bs.dir_entries being 0. */
bs.dir_entries[0] = bs.dir_entries[1] = (char) 0;
root_dir_entries = 0;
}
else if (root_dir_entries)
{
/* Override default from establish_params() */
bs.dir_entries[0] = (char) (root_dir_entries & 0x00ff);
bs.dir_entries[1] = (char) ((root_dir_entries & 0xff00) >> 8);
}
else
root_dir_entries = bs.dir_entries[0] + (bs.dir_entries[1] << 8);
if (atari_format) {
bs.system_id[5] = (unsigned char) (volume_id & 0x000000ff);
bs.system_id[6] = (unsigned char) ((volume_id & 0x0000ff00) >> 8);
bs.system_id[7] = (unsigned char) ((volume_id & 0x00ff0000) >> 16);
}
else {
vi->volume_id[0] = (unsigned char) (volume_id & 0x000000ff);
vi->volume_id[1] = (unsigned char) ((volume_id & 0x0000ff00) >> 8);
vi->volume_id[2] = (unsigned char) ((volume_id & 0x00ff0000) >> 16);
vi->volume_id[3] = (unsigned char) (volume_id >> 24);
}
if (!atari_format) {
memcpy(vi->volume_label, volume_name, 11);
memcpy(bs.boot_jump, dummy_boot_jump, 3);
/* Patch in the correct offset to the boot code */
bs.boot_jump[1] = ((size_fat == 32 ?
(char *)&bs.fat32.boot_code :
(char *)&bs.oldfat.boot_code) -
(char *)&bs) - 2;
if (size_fat == 32) {
if (dummy_boot_code[BOOTCODE_FAT32_SIZE-1])
printf ("Warning: message too long; truncated\n");
dummy_boot_code[BOOTCODE_FAT32_SIZE-1] = 0;
memcpy(bs.fat32.boot_code, dummy_boot_code, BOOTCODE_FAT32_SIZE);
}
else {
memcpy(bs.oldfat.boot_code, dummy_boot_code, BOOTCODE_SIZE);
}
bs.boot_sign = CT_LE_W(BOOT_SIGN);
}
else {
memcpy(bs.boot_jump, dummy_boot_jump_m68k, 2);
}
if (verbose >= 2)
printf( "Boot jump code is %02x %02x\n",
bs.boot_jump[0], bs.boot_jump[1] );
if (!reserved_sectors)
reserved_sectors = (size_fat == 32) ? 32 : 1;
else {
if (size_fat == 32 && reserved_sectors < 2)
die("On FAT32 at least 2 reserved sectors are needed.");
}
bs.reserved = CT_LE_W(reserved_sectors);
if (verbose >= 2)
printf( "Using %d reserved sectors\n", reserved_sectors );
bs.fats = (char) nr_fats;
if (!atari_format || size_fat == 32)
bs.hidden = CT_LE_L(0);
else
/* In Atari format, hidden is a 16 bit field */
memset( &bs.hidden, 0, 2 );
num_sectors = (ll_t)blocks*BLOCK_SIZE/sector_size;
if (!atari_format) {
unsigned fatlength12, fatlength16, fatlength32;
unsigned maxclust12, maxclust16, maxclust32;
unsigned clust12, clust16, clust32;
int maxclustsize;
fatdata = num_sectors - cdiv (root_dir_entries * 32, sector_size) -
reserved_sectors;
if (sectors_per_cluster)
bs.cluster_size = maxclustsize = sectors_per_cluster;
else
/* An initial guess for bs.cluster_size should already be set */
maxclustsize = 128;
if (verbose >= 2)
printf( "%d sectors for FAT+data, starting with %d sectors/cluster\n",
fatdata, bs.cluster_size );
do {
if (verbose >= 2)
printf( "Trying with %d sectors/cluster:\n", bs.cluster_size );
/* The factor 2 below avoids cut-off errors for nr_fats == 1.
* The "nr_fats*3" is for the reserved first two FAT entries */
clust12 = 2*((ll_t) fatdata *sector_size + nr_fats*3) /
(2*(int) bs.cluster_size * sector_size + nr_fats*3);
fatlength12 = cdiv (((clust12+2) * 3 + 1) >> 1, sector_size);
/* Need to recalculate number of clusters, since the unused parts of the
* FATS and data area together could make up space for an additional,
* not really present cluster. */
clust12 = (fatdata - nr_fats*fatlength12)/bs.cluster_size;
maxclust12 = (fatlength12 * 2 * sector_size) / 3;
if (maxclust12 > MAX_CLUST_12)
maxclust12 = MAX_CLUST_12;
if (verbose >= 2)
printf( "FAT12: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n",
clust12, fatlength12, maxclust12, MAX_CLUST_12 );
if (clust12 > maxclust12-2) {
clust12 = 0;
if (verbose >= 2)
printf( "FAT12: too much clusters\n" );
}
clust16 = ((ll_t) fatdata *sector_size + nr_fats*4) /
((int) bs.cluster_size * sector_size + nr_fats*2);
fatlength16 = cdiv ((clust16+2) * 2, sector_size);
/* Need to recalculate number of clusters, since the unused parts of the
* FATS and data area together could make up space for an additional,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -