📄 mkdosfs.c
字号:
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(hidden_sectors); else { /* In Atari format, hidden is a 16 bit field */ __u16 hidden = CT_LE_W(hidden_sectors); if (hidden_sectors & ~0xffff) die("#hidden doesn't fit in 16bit field of Atari format\n"); memcpy( &bs.hidden, &hidden, 2 ); } num_sectors = (long long)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*((long long) 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 = ((long long) 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, * not really present cluster. */ clust16 = (fatdata - nr_fats*fatlength16)/bs.cluster_size; maxclust16 = (fatlength16 * sector_size) / 2; if (maxclust16 > MAX_CLUST_16) maxclust16 = MAX_CLUST_16; if (verbose >= 2) printf( "FAT16: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n", clust16, fatlength16, maxclust16, MAX_CLUST_16 ); if (clust16 > maxclust16-2) { if (verbose >= 2) printf( "FAT16: too much clusters\n" ); clust16 = 0; } /* The < 4078 avoids that the filesystem will be misdetected as having a * 12 bit FAT. */ if (clust16 < FAT12_THRESHOLD && !(size_fat_by_user && size_fat == 16)) { if (verbose >= 2) printf( clust16 < FAT12_THRESHOLD ? "FAT16: would be misdetected as FAT12\n" : "FAT16: too much clusters\n" ); clust16 = 0; } clust32 = ((long long) fatdata *sector_size + nr_fats*8) / ((int) bs.cluster_size * sector_size + nr_fats*4); fatlength32 = cdiv ((clust32+2) * 4, 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. */ clust32 = (fatdata - nr_fats*fatlength32)/bs.cluster_size; maxclust32 = (fatlength32 * sector_size) / 4; if (maxclust32 > MAX_CLUST_32) maxclust32 = MAX_CLUST_32; if (clust32 && clust32 < MIN_CLUST_32 && !(size_fat_by_user && size_fat == 32)) { clust32 = 0; if (verbose >= 2) printf( "FAT32: not enough clusters (%d)\n", MIN_CLUST_32); } if (verbose >= 2) printf( "FAT32: #clu=%u, fatlen=%u, maxclu=%u, limit=%u\n", clust32, fatlength32, maxclust32, MAX_CLUST_32 ); if (clust32 > maxclust32) { clust32 = 0; if (verbose >= 2) printf( "FAT32: too much clusters\n" ); } if ((clust12 && (size_fat == 0 || size_fat == 12)) || (clust16 && (size_fat == 0 || size_fat == 16)) || (clust32 && size_fat == 32)) break; bs.cluster_size <<= 1; } while (bs.cluster_size && bs.cluster_size <= maxclustsize); /* Use the optimal FAT size if not specified; * FAT32 is (not yet) choosen automatically */ if (!size_fat) { size_fat = (clust16 > clust12) ? 16 : 12; if (verbose >= 2) printf( "Choosing %d bits for FAT\n", size_fat ); } switch (size_fat) { case 12: cluster_count = clust12; fat_length = fatlength12; bs.fat_length = CT_LE_W(fatlength12); memcpy(vi->fs_type, MSDOS_FAT12_SIGN, 8); break; case 16: if (clust16 < FAT12_THRESHOLD) { if (size_fat_by_user) { fprintf( stderr, "WARNING: Not enough clusters for a " "16 bit FAT! The filesystem will be\n" "misinterpreted as having a 12 bit FAT without " "mount option \"fat=16\".\n" ); } else { fprintf( stderr, "This filesystem has an unfortunate size. " "A 12 bit FAT cannot provide\n" "enough clusters, but a 16 bit FAT takes up a little " "bit more space so that\n" "the total number of clusters becomes less than the " "threshold value for\n" "distinction between 12 and 16 bit FATs.\n" ); die( "Make the file system a bit smaller manually." ); } } cluster_count = clust16; fat_length = fatlength16; bs.fat_length = CT_LE_W(fatlength16); memcpy(vi->fs_type, MSDOS_FAT16_SIGN, 8); break; case 32: cluster_count = clust32; fat_length = fatlength32; bs.fat_length = CT_LE_W(0); bs.fat32.fat32_length = CT_LE_L(fatlength32); memcpy(vi->fs_type, MSDOS_FAT32_SIGN, 8); break; default: die("FAT not 12, 16 or 32 bits"); } } else { unsigned clusters, maxclust; /* GEMDOS always uses a 12 bit FAT on floppies, and always a 16 bit FAT on * hard disks. So use 12 bit if the size of the file system suggests that * this fs is for a floppy disk, if the user hasn't explicitly requested a * size. */ if (!size_fat) size_fat = (num_sectors == 1440 || num_sectors == 2400 || num_sectors == 2880 || num_sectors == 5760) ? 12 : 16; if (verbose >= 2) printf( "Choosing %d bits for FAT\n", size_fat ); /* Atari format: cluster size should be 2, except explicitly requested by * the user, since GEMDOS doesn't like other cluster sizes very much. * Instead, tune the sector size for the FS to fit. */ bs.cluster_size = sectors_per_cluster ? sectors_per_cluster : 2; if (!sector_size_set) { while( num_sectors > GEMDOS_MAX_SECTORS ) { num_sectors >>= 1; sector_size <<= 1; } } if (verbose >= 2) printf( "Sector size must be %d to have less than %d log. sectors\n", sector_size, GEMDOS_MAX_SECTORS ); /* Check if there are enough FAT indices for how much clusters we have */ do { fatdata = num_sectors - cdiv (root_dir_entries * 32, sector_size) - reserved_sectors; /* The factor 2 below avoids cut-off errors for nr_fats == 1 and * size_fat == 12 * The "2*nr_fats*size_fat/8" is for the reserved first two FAT entries */ clusters = (2*((long long)fatdata*sector_size - 2*nr_fats*size_fat/8)) / (2*((int)bs.cluster_size*sector_size + nr_fats*size_fat/8)); fat_length = cdiv( (clusters+2)*size_fat/8, 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. */ clusters = (fatdata - nr_fats*fat_length)/bs.cluster_size; maxclust = (fat_length*sector_size*8)/size_fat; if (verbose >= 2) printf( "ss=%d: #clu=%d, fat_len=%d, maxclu=%d\n", sector_size, clusters, fat_length, maxclust ); /* last 10 cluster numbers are special (except FAT32: 4 high bits rsvd); * first two numbers are reserved */ if (maxclust <= (size_fat == 32 ? MAX_CLUST_32 : (1<<size_fat)-0x10) && clusters <= maxclust-2) break; if (verbose >= 2) printf( clusters > maxclust-2 ? "Too many clusters\n" : "FAT too big\n" ); /* need to increment sector_size once more to */ if (sector_size_set) die( "With this sector size, the maximum number of FAT entries " "would be exceeded." ); num_sectors >>= 1; sector_size <<= 1; } while( sector_size <= GEMDOS_MAX_SECTOR_SIZE ); if (sector_size > GEMDOS_MAX_SECTOR_SIZE) die( "Would need a sector size > 16k, which GEMDOS can't work with"); cluster_count = clusters; if (size_fat != 32) bs.fat_length = CT_LE_W(fat_length); else { bs.fat_length = 0; bs.fat32.fat32_length = CT_LE_L(fat_length); } } bs.sector_size[0] = (char) (sector_size & 0x00ff); bs.sector_size[1] = (char) ((sector_size & 0xff00) >> 8); if (size_fat == 32) { /* set up additional FAT32 fields */ bs.fat32.flags = CT_LE_W(0); bs.fat32.version[0] = 0; bs.fat32.version[1] = 0; bs.fat32.root_cluster = CT_LE_L(2); bs.fat32.info_sector = CT_LE_W(1); if (!backup_boot) backup_boot = (reserved_sectors >= 7) ? 6 : (reserved_sectors >= 2) ? reserved_sectors-1 : 0; else { if (backup_boot == 1) die("Backup boot sector must be after sector 1"); else if (backup_boot >= reserved_sectors) die("Backup boot sector must be a reserved sector"); } if (verbose >= 2) printf( "Using sector %d as backup boot sector (0 = none)\n", backup_boot ); bs.fat32.backup_boot = CT_LE_W(backup_boot); memset( &bs.fat32.reserved2, 0, sizeof(bs.fat32.reserved2) ); } if (atari_format) { /* Just some consistency checks */ if (num_sectors >= GEMDOS_MAX_SECTORS) die( "GEMDOS can't handle more than 65531 sectors" ); else if (num_sectors >= OLDGEMDOS_MAX_SECTORS) printf( "Warning: More than 32765 sector need TOS 1.04 " "or higher.\n" ); } if (num_sectors >= 65536) { bs.sectors[0] = (char) 0; bs.sectors[1] = (char) 0; bs.total_sect = CT_LE_L(num_sectors); } else { bs.sectors[0] = (char) (num_sectors & 0x00ff); bs.sectors[1] = (char) ((num_sectors & 0xff00) >> 8); if (!atari_format) bs.total_sect = CT_LE_L(0); } if (!atari_format) vi->ext_boot_sign = MSDOS_EXT_SIGN; if (!cluster_count) { if (sectors_per_cluster) /* If yes, die if we'd spec'd sectors per cluster */ die ("Too many clusters for file system - try more sectors per cluster"); else die ("Attempting to create a too large file system"); } /* The two following vars are in hard sectors, i.e. 512 byte sectors! */ start_data_sector = (reserved_sectors + nr_fats * fat_length) * (sector_size/HARD_SECTOR_SIZE); start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) / SECTORS_PER_BLOCK; if (blocks < start_data_block + 32) /* Arbitrary undersize file system! */ die ("Too few blocks for viable file system"); if (verbose) { printf("%s has %d head%s and %d sector%s per track,\n", device_name, CF_LE_W(bs.heads), (CF_LE_W(bs.heads) != 1) ? "s" : "", CF_LE_W(bs.secs_track), (CF_LE_W(bs.secs_track) != 1) ? "s" : ""); printf("logical sector size is %d,\n",sector_size); printf("using 0x%02x media descriptor, with %d sectors;\n", (int) (bs.media), num_sectors); printf("file system has %d %d-bit FAT%s and %d sector%s per cluster.\n", (int) (bs.fats), size_fat, (bs.fats != 1) ? "s" : "", (int) (bs.cluster_size), (bs.cluster_size != 1) ? "s" : ""); printf ("FAT size is %d sector%s, and provides %d cluster%s.\n", fat_length, (fat_length != 1) ? "s" : "", cluster_count, (cluster_count != 1) ? "s" : ""); if (size_fat != 32) printf ("Root directory contains %d slots.\n", (int) (bs.dir_entries[0]) + (int) (bs.dir_entries[1]) * 256); printf ("Volume ID is %08lx, ", volume_id & (atari_format ? 0x00ffffff : 0xffffffff)); if ( strcmp(volume_name, " ") ) printf("volume label %s.\n", volume_name); else printf("no volume label.\n"); } /* Make the file allocation tables! */ if ((fat = (unsigned char *) malloc (fat_length * sector_size)) == NULL) die ("unable to allocate space for FAT image in memory"); memset( fat, 0, fat_length * sector_size ); mark_FAT_cluster (0, 0xffffffff); /* Initial fat entries */ mark_FAT_cluster (1, 0xffffffff); fat[0] = (unsigned char) bs.media; /* Put media type in first byte! */ if (size_fat == 32) { /* Mark cluster 2 as EOF (used for root dir) */ mark_FAT_cluster (2, FAT_EOF); } /* Make the root directory entries */ size_root_dir = (size_fat == 32) ? bs.cluster_size*sector_size : (((int)bs.dir_entries[1]*256+(int)bs.dir_entries[0]) * sizeof (struct msdos_dir_entry)); if ((root_dir = (struct msdos_dir_entry *) malloc (size_root_dir)) == NULL) { free (fat); /* Tidy up before we die! */ die ("unable to allocate space for root directory in memory"); } memset(root_dir, 0, size_root_dir); if ( memcmp(volume_name, " ", 11) ) { struct msdos_dir_entry *de = &root_dir[0]; memcpy(de->name, volume_name, 11); de->attr = ATTR_VOLUME; ctime = localtime(&create_time); de->time = CT_LE_W((unsigned short)((ctime->tm_sec >> 1) + (ctime->tm_min << 5) + (ctime->tm_hour << 11))); de->date = CT_LE_W((unsigned short)(ctime->tm_mday + ((ctime->tm_mon+1) << 5) + ((ctime->tm_year-80) << 9))); de->ctime_ms = 0; de->ctime = de->time; de->cdate = de->date; de->adate = de->date; de->starthi = CT_LE_W(0); de->start = CT_LE_W(0); de->size = CT_LE_L(0); } if (size_fat == 32) { /* For FAT32, create an info sector */ struct fat32_fsinfo *info; if (!(info_sector = malloc( sector_size ))) die("Out of memory"); memset(info_sector, 0, sector_size); /* fsinfo structure is at offset 0x1e0 in info sector by observation */ info = (struct fat32_fsinfo *)(info_sector + 0x1e0); /* Info sector magic */ info_sector[0] = 'R'; info_sector[1] = 'R'; info_sector[2] = 'a'; info_sector[3] = 'A'; /* Magic for fsinfo structure */ info->signature = CT_LE_L(0x61417272); /* We've allocated cluster 2 for the root dir. */ info->free_clusters = CT_LE_L(cluster_count - 1); info->next_cluster = CT_LE_L(2); /* Info sector also must have boot sign */ *(__u16 *)(info_sector + 0x1fe) = CT_LE_W(BOOT_SIGN); } if (!(blank_sector = malloc( sector_size ))) die( "Out of memory" ); memset(blank_sector, 0, sector_size);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -