⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkdosfs.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
      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, &param))	/*  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 + -