📄 mkdosfs.c
字号:
/* Write the new filesystem's data tables to wherever they're going to end up! */#define error(str) \ do { \ free (fat); \ if (info_sector) free (info_sector); \ free (root_dir); \ die (str); \ } while(0)#define seekto(pos,errstr) \ do { \ loff_t __pos = (pos); \ if (llseek (dev, __pos, SEEK_SET) != __pos) \ error ("seek to " errstr " failed whilst writing tables"); \ } while(0)#define writebuf(buf,size,errstr) \ do { \ int __size = (size); \ if (write (dev, buf, __size) != __size) \ error ("failed whilst writing " errstr); \ } while(0)static voidwrite_tables (void){ int x; int fat_length; fat_length = (size_fat == 32) ? CF_LE_L(bs.fat32.fat32_length) : CF_LE_W(bs.fat_length); seekto( 0, "start of device" ); /* clear all reserved sectors */ for( x = 0; x < reserved_sectors; ++x ) writebuf( blank_sector, sector_size, "reserved sector" ); /* seek back to sector 0 and write the boot sector */ seekto( 0, "boot sector" ); writebuf( (char *) &bs, sizeof (struct msdos_boot_sector), "boot sector" ); /* on FAT32, write the info sector and backup boot sector */ if (size_fat == 32) { seekto( CF_LE_W(bs.fat32.info_sector)*sector_size, "info sector" ); writebuf( info_sector, 512, "info sector" ); if (backup_boot != 0) { seekto( backup_boot*sector_size, "backup boot sector" ); writebuf( (char *) &bs, sizeof (struct msdos_boot_sector), "backup boot sector" ); } } /* seek to start of FATS and write them all */ seekto( reserved_sectors*sector_size, "first FAT" ); for (x = 1; x <= nr_fats; x++) writebuf( fat, fat_length * sector_size, "FAT" ); /* Write the root directory directly after the last FAT. This is the root * dir area on FAT12/16, and the first cluster on FAT32. */ writebuf( (char *) root_dir, size_root_dir, "root directory" ); if (blank_sector) free( blank_sector ); if (info_sector) free( info_sector ); free (root_dir); /* Free up the root directory space from setup_tables */ free (fat); /* Free up the fat table space reserved during setup_tables */}/* Report the command usage and return a failure error code */voidusage (void){ fatal_error("\Usage: mkdosfs [-A] [-c] [-C] [-v] [-I] [-l bad-block-file] [-b backup-boot-sector]\n\ [-m boot-msg-file] [-n volume-name] [-i volume-id]\n\ [-s sectors-per-cluster] [-S logical-sector-size] [-f number-of-FATs]\n\ [-h hidden-sectors] [-F fat-size] [-r root-dir-entries] [-R reserved-sectors]\n\ /dev/name [blocks]\n");}/* * ++roman: On m68k, check if this is an Atari; if yes, turn on Atari variant * of MS-DOS filesystem by default. */static void check_atari( void ){#ifdef __mc68000__ FILE *f; char line[128], *p; if (!(f = fopen( "/proc/hardware", "r" ))) { perror( "/proc/hardware" ); return; } while( fgets( line, sizeof(line), f ) ) { if (strncmp( line, "Model:", 6 ) == 0) { p = line + 6; p += strspn( p, " \t" ); if (strncmp( p, "Atari ", 6 ) == 0) atari_format = 1; break; } } fclose( f );#endif}/* The "main" entry point into the utility - we pick up the options and attempt to process them in some sort of sensible way. In the event that some/all of the options are invalid we need to tell the user so that something can be done! */intmain (int argc, char **argv){ int c; char *tmp; char *listfile = NULL; FILE *msgfile; struct stat statbuf; int i = 0, pos, ch; int create = 0; unsigned long long cblocks; if (argc && *argv) { /* What's the program name? */ char *p; program_name = *argv; if ((p = strrchr( program_name, '/' ))) program_name = p+1; } time(&create_time); volume_id = (long)create_time; /* Default volume ID = creation time */ check_atari(); printf ("%s " VERSION " (" VERSION_DATE ")\n", program_name); while ((c = getopt (argc, argv, "AbcCf:F:Ii:l:m:n:r:R:s:S:h:v")) != EOF) /* Scan the command line for options */ switch (c) { case 'A': /* toggle Atari format */ atari_format = !atari_format; break; case 'b': /* b : location of backup boot sector */ backup_boot = (int) strtol (optarg, &tmp, 0); if (*tmp || backup_boot < 2 || backup_boot > 0xffff) { printf ("Bad location for backup boot sector : %s\n", optarg); usage (); } break; case 'c': /* c : Check FS as we build it */ check = TRUE; break; case 'C': /* C : Create a new file */ create = TRUE; break; case 'f': /* f : Choose number of FATs */ nr_fats = (int) strtol (optarg, &tmp, 0); if (*tmp || nr_fats < 1 || nr_fats > 4) { printf ("Bad number of FATs : %s\n", optarg); usage (); } break; case 'F': /* F : Choose FAT size */ size_fat = (int) strtol (optarg, &tmp, 0); if (*tmp || (size_fat != 12 && size_fat != 16 && size_fat != 32)) { printf ("Bad FAT type : %s\n", optarg); usage (); } size_fat_by_user = 1; break; case 'h': /* h : number of hidden sectors */ hidden_sectors = (int) strtol (optarg, &tmp, 0); if ( *tmp || hidden_sectors < 0 ) { printf("Bad number of hidden sectors : %s\n", optarg); usage (); } break; case 'I': ignore_full_disk = 1; break; case 'i': /* i : specify volume ID */ volume_id = strtoul(optarg, &tmp, 16); if ( *tmp ) { printf("Volume ID must be a hexadecimal number\n"); usage(); } break; case 'l': /* l : Bad block filename */ listfile = optarg; break; case 'm': /* m : Set boot message */ if ( strcmp(optarg, "-") ) { msgfile = fopen(optarg, "r"); if ( !msgfile ) perror(optarg); } else msgfile = stdin; if ( msgfile ) { /* The boot code ends at offset 448 and needs a null terminator */ i = MESSAGE_OFFSET; pos = 0; /* We are at beginning of line */ do { ch = getc(msgfile); switch (ch) { case '\r': /* Ignore CRs */ case '\0': /* and nulls */ break; case '\n': /* LF -> CR+LF if necessary */ if ( pos ) /* If not at beginning of line */ { dummy_boot_code[i++] = '\r'; pos = 0; } dummy_boot_code[i++] = '\n'; break; case '\t': /* Expand tabs */ do { dummy_boot_code[i++] = ' '; pos++; } while ( pos % 8 && i < BOOTCODE_SIZE-1 ); break; case EOF: dummy_boot_code[i++] = '\0'; /* Null terminator */ break; default: dummy_boot_code[i++] = ch; /* Store character */ pos++; /* Advance position */ break; } } while ( ch != EOF && i < BOOTCODE_SIZE-1 ); /* Fill up with zeros */ while( i < BOOTCODE_SIZE-1 ) dummy_boot_code[i++] = '\0'; dummy_boot_code[BOOTCODE_SIZE-1] = '\0'; /* Just in case */ if ( ch != EOF ) printf ("Warning: message too long; truncated\n"); if ( msgfile != stdin ) fclose(msgfile); } break; case 'n': /* n : Volume name */ sprintf(volume_name, "%-11.11s", optarg); break; case 'r': /* r : Root directory entries */ root_dir_entries = (int) strtol (optarg, &tmp, 0); if (*tmp || root_dir_entries < 16 || root_dir_entries > 32768) { printf ("Bad number of root directory entries : %s\n", optarg); usage (); } break; case 'R': /* R : number of reserved sectors */ reserved_sectors = (int) strtol (optarg, &tmp, 0); if (*tmp || reserved_sectors < 1 || reserved_sectors > 0xffff) { printf ("Bad number of reserved sectors : %s\n", optarg); usage (); } break; case 's': /* s : Sectors per cluster */ sectors_per_cluster = (int) strtol (optarg, &tmp, 0); if (*tmp || (sectors_per_cluster != 1 && sectors_per_cluster != 2 && sectors_per_cluster != 4 && sectors_per_cluster != 8 && sectors_per_cluster != 16 && sectors_per_cluster != 32 && sectors_per_cluster != 64 && sectors_per_cluster != 128)) { printf ("Bad number of sectors per cluster : %s\n", optarg); usage (); } break; case 'S': /* S : Sector size */ sector_size = (int) strtol (optarg, &tmp, 0); if (*tmp || (sector_size != 512 && sector_size != 1024 && sector_size != 2048 && sector_size != 4096 && sector_size != 8192 && sector_size != 16384 && sector_size != 32768)) { printf ("Bad logical sector size : %s\n", optarg); usage (); } sector_size_set = 1; break; case 'v': /* v : Verbose execution */ ++verbose; break; default: printf( "Unknown option: %c\n", c ); usage (); } if (optind < argc) { device_name = argv[optind]; /* Determine the number of blocks in the FS */ if (!create) cblocks = count_blocks (device_name); /* Have a look and see! */ } if (optind == argc - 2) /* Either check the user specified number */ { blocks = strtoull (argv[optind + 1], &tmp, 0); if (!create && blocks != cblocks) { fprintf (stderr, "Warning: block count mismatch: "); fprintf (stderr, "found %llu but assuming %llu.\n",cblocks,blocks); } } else if (optind == argc - 1) /* Or use value found */ { if (create) die( "Need intended size with -C." ); blocks = cblocks; tmp = ""; } else { fprintf (stderr, "No device specified!\n"); usage (); } if (*tmp) { printf ("Bad block count : %s\n", argv[optind + 1]); usage (); } if (check && listfile) /* Auto and specified bad block handling are mutually */ die ("-c and -l are incompatible"); /* exclusive of each other! */ if (!create) { check_mount (device_name); /* Is the device already mounted? */ dev = open (device_name, O_RDWR); /* Is it a suitable device to build the FS on? */ if (dev < 0) die ("unable to open %s"); } else { off_t offset = blocks*BLOCK_SIZE - 1; char null = 0; /* create the file */ dev = open( device_name, O_RDWR|O_CREAT|O_TRUNC, 0666 ); if (dev < 0) die("unable to create %s"); /* seek to the intended end-1, and write one byte. this creates a * sparse-as-possible file of appropriate size. */ if (llseek( dev, offset, SEEK_SET ) != offset) die( "seek failed" ); if (write( dev, &null, 1 ) < 0) die( "write failed" ); if (llseek( dev, 0, SEEK_SET ) != 0) die( "seek failed" ); } if (fstat (dev, &statbuf) < 0) die ("unable to stat %s"); if (!S_ISBLK (statbuf.st_mode)) { statbuf.st_rdev = 0; check = 0; } else /* * Ignore any 'full' fixed disk devices, if -I is not given. * On a MO-disk one doesn't need partitions. The filesytem can go * directly to the whole disk. Under other OSes this is known as * the 'superfloppy' format. As I don't know how to find out if * this is a MO disk I introduce a -I (ignore) switch. -Joey */ if (!ignore_full_disk && ( (statbuf.st_rdev & 0xff3f) == 0x0300 || /* hda, hdb */ (statbuf.st_rdev & 0xff0f) == 0x0800 || /* sd */ (statbuf.st_rdev & 0xff3f) == 0x0d00 || /* xd */ (statbuf.st_rdev & 0xff3f) == 0x1600 ) /* hdc, hdd */ ) die ("Will not try to make filesystem on full-disk device '%s' (use -I if wanted)"); establish_params (statbuf.st_rdev,statbuf.st_size); /* Establish the media parameters */ setup_tables (); /* Establish the file system tables */ if (check) /* Determine any bad block locations and mark them */ check_blocks (); else if (listfile) get_list_blocks (listfile); write_tables (); /* Write the file system tables away! */ exit (0); /* Terminate with no errors! */}/* That's All Folks *//* Local Variables: *//* tab-width: 8 *//* End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -