mkfs.minix.c代码解析

本文详细解析了mkfs.minix.c代码,涉及setlocale()、bindtextdomain()、getopt_long()用于参数处理,特别是格式化分区功能。接着介绍如何分离参数中的字符和数字部分,处理fs_namelen和fs_dirsize的设定,以及检查minix v1文件系统的魔数。此外,还讨论了is_mounted函数检查设备是否已挂载,stat函数获取设备属性,以及设备的锁定、打开、计算fs_block数量等步骤。最后展示了设置超级块结构体和位图的代码段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

int main(int argc, char ** argv)
{
	struct fs_control ctl = {
		.fs_namelen = 30,	/* keep in sync with DEFAULT_FS_VERSION */
		0
	};
	int i;
	struct stat statbuf;
	char * listfile = NULL;
	enum {
		OPT_LOCK = CHAR_MAX + 1
	};
	static const struct option longopts[] = {
		{"namelength", required_argument, NULL, 'n'},
		{"inodes", required_argument, NULL, 'i'},
		{"check", no_argument, NULL, 'c'},
		{"badblocks", required_argument, NULL, 'l'},
		{"version", no_argument, NULL, 'V'},
		{"help", no_argument, NULL, 'h'},
		{"lock",optional_argument, NULL, OPT_LOCK},
		{NULL, 0, NULL, 0}
	};

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	close_stdout_atexit();

	strutils_set_exitcode(MKFS_EX_USAGE);

	while ((i = getopt_long(argc, argv, "1v23n:i:cl:Vh", longopts, NULL)) != -1)
		switch (i) {
		case '1':
			fs_version = 1;
			break;
		case 'v': /* kept for backwards compatibility */
			warnx(_("-v is ambiguous, use '-2' instead"));
			/* fallthrough */
		case '2':
			fs_version = 2;
			break;
		case '3':
			fs_version = 3;
			ctl.fs_namelen = 60;
			break;
		case 'n':
			ctl.fs_namelen = strtou16_or_err(optarg,
					_("failed to parse maximum length of filenames"));
			break;
		case 'i':
			ctl.fs_inodes = strtoul_or_err(optarg,
					_("failed to parse number of inodes"));
			break;
		case 'c':
			ctl.check_blocks = 1;
			break;
		case 'l':
			listfile = optarg;
			break;
		case OPT_LOCK:
			ctl.lockmode = "1";
			if (optarg) {
				if (*optarg == '=')
					optarg++;
				ctl.lockmode = optarg;
			}
			break;
		case 'V':
			print_version(MKFS_EX_OK);
		case 'h':
			usage();
		default:
			errtryhelp(MKFS_EX_USAGE);
		}
	argc -= optind;
	argv += optind;
	if (argc > 0) {
		ctl.device_name = argv[0];
		argc--;
		argv++;
	}
	if (argc > 0)
		ctl.fs_blocks = strtoul_or_err(argv[0], _("failed to parse number of blocks"));

	if (!ctl.device_name) {
		warnx(_("no device specified"));
		errtryhelp(MKFS_EX_USAGE);
	}
	check_user_instructions(&ctl);
	if (is_mounted(ctl.device_name))
		errx(MKFS_EX_ERROR, _("%s is mounted; will not make a filesystem here!"),
			ctl.device_name);
	if (stat(ctl.device_name, &statbuf) < 0)
		err(MKFS_EX_ERROR, _("stat of %s failed"), ctl.device_name);
	ctl.device_fd = open_blkdev_or_file(&statbuf, ctl.device_name, O_RDWR);
	if (ctl.device_fd < 0)
		err(MKFS_EX_ERROR, _("cannot open %s"), ctl.device_name);
	if (blkdev_lock(ctl.device_fd, ctl.device_name, ctl.lockmode) != 0)
		exit(MKFS_EX_ERROR);
	determine_device_blocks(&ctl, &statbuf);
	setup_tables(&ctl);
	if (ctl.check_blocks)
		check_blocks(&ctl);
	else if (listfile)
		get_list_blocks(&ctl, listfile);

	make_root_inode(&ctl);
	make_bad_inode(&ctl);

	mark_good_blocks(&ctl);
	write_tables(&ctl);
	if (close_fd(ctl.device_fd) != 0)
		err(MKFS_EX_ERROR, _("write failed"));

	return MKFS_EX_OK;
}

1.setlocale(): 设置或读取地域化信息

2.bindtextdomain() 用来设置文本域目录.

3.getopt_long循环部分。
获取主函数传参的功能。 根据参数部署相应的功能。
目前主要看格式化分区功能。

4.ctl.fs_blocks = strtoul_or_err(argv[0], _("failed to parse number of blocks"));
分开参数中的字符部分, 和数字部分 , 并返回数字部分给ctl.fs_blocks。
没有传参的话,就返回0.

5.check_user_instructions(&ctl);

static void check_user_instructions(struct fs_control *ctl)
{
	switch (fs_version) {
	case 1:
	case 2:
		if (ctl->fs_namelen == 14 || ctl->fs_namelen == 30)
			ctl->fs_dirsize = ctl->fs_namelen + 2;
		else
			errx(MKFS_EX_ERROR, _("unsupported name length: %d"), ctl->fs_namelen);
		break;
	case 3:
		if (ctl->fs_namelen == 60)
			ctl->fs_dirsize = ctl->fs_namelen + 4;
		else
			errx(MKFS_EX_ERROR, _("unsupported name length: %d"), ctl->fs_namelen);
		break;
	default:
		errx(MKFS_EX_ERROR, _("unsupported minix file system version: %d"), fs_version);
	}
	ctl->fs_magic = find_super_magic(ctl);
}

fs_namelen :在初始化时为30,如果没有传参改变它的值,那它还是30, 则进入到case2:中,fs_dirsize = 32;

然后通过ctl->fs_magic = find_super_magic(ctl);返回minix v1版本文件系统魔数。

6.is_mounted(ctl.device_name)
通过is_mounted判断,要格式化的该分区或者文件是否已经被挂载。

7.stat(ctl.device_name, &statbuf)
通过stat函数进行获取该设备或者文件的属性信息,并放入到statbuf中。

8.ctl.device_fd = open_blkdev_or_file(&statbuf, ctl.device_name, O_RDWR);
打开该设备,或者文件, 并返回文件描述符。

9.blkdev_lock(ctl.device_fd, ctl.device_name, ctl.lockmode)
对该打开的设备进行加锁,防止其他进程访问。

10.determine_device_blocks(&ctl, &statbuf);
获取该设备的存储大小,并计算有多少fs_block,并赋值给ctl.fs_blocks。

static void determine_device_blocks(struct fs_control *ctl, const struct stat *statbuf)
{
	unsigned long long dev_blocks = 0;

	if (S_ISBLK(statbuf->st_mode)) { //判断该文件是否为一个块设备
		int sectorsize;

		if (blkdev_get_sector_size(ctl->device_fd, &sectorsize) == -1)//得到扇区大小
			sectorsize = DEFAULT_SECTOR_SIZE;	/* kernel < 2.3.3 */
		if (MINIX_BLOCK_SIZE < sectorsize) //1024
			errx(MKFS_EX_ERROR, _("block size smaller than physical "
					      "sector size of %s"), ctl->device_name);
		if (blkdev_get_size(ctl->device_fd, &dev_blocks) == -1)
			errx(MKFS_EX_ERROR, _("cannot determine size of %s"), ctl->device_name);
		dev_blocks /= MINIX_BLOCK_SIZE;
	} else if (!S_ISBLK(statbuf->st_mode))
		dev_blocks = statbuf->st_size / MINIX_BLOCK_SIZE;
	//不是块设备时获取文件大小,  块总数 = 总字节数 / 1024   一个块的大小。
	if (!ctl->fs_blocks)
		ctl->fs_blocks = dev_blocks;
	else if (dev_blocks < ctl->fs_blocks)
		errx(MKFS_EX_ERROR,
		     _("%s: requested blocks (%llu) exceeds available (%llu) blocks\n"),
		     ctl->device_name, ctl->fs_blocks, dev_blocks);
	if (ctl->fs_blocks < 10)
		errx(MKFS_EX_ERROR, _("%s: number of blocks too small"), ctl->device_name);
	if (fs_version == 1 && ctl->fs_blocks > MINIX_MAX_INODES)
		ctl->fs_blocks = MINIX_MAX_INODES;
	if (ctl->fs_blocks > (4 + ((MINIX_MAX_INODES - 4) * BITS_PER_BLOCK)))
		ctl->fs_blocks = 4 + ((MINIX_MAX_INODES - 4) * BITS_PER_BLOCK);	/* Utter maximum: Clip. */
}

11.setup_tables(&ctl);
设置要写入的超级块的结构体。
设置超级块的位表。
代码如下:

static void setup_tables(const struct fs_control *ctl) {
	unsigned long inodes, zmaps, imaps, zones, i;

	super_block_buffer = xcalloc(1, MINIX_BLOCK_SIZE);

	memset(boot_block_buffer,0,512);
	super_set_magic(ctl);

	if (fs_version == 3) {
		Super3.s_log_zone_size = 0;
		Super3.s_blocksize = MINIX_BLOCK_SIZE;
	}
	else {
		Super.s_log_zone_size = 0;
	}

	super_init_maxsize();
	super_set_nzones(ctl);
	zones = get_nzones();

	/* some magic nrs: 1 inode / 3 blocks for smaller filesystems,
	 * for one inode / 16 blocks for large ones. mkfs will eventually
	 * crab about too far when getting close to the maximum size. */
	if (ctl->fs_inodes == 0)
		if (2048 * 1024 < ctl->fs_blocks)	/* 2GB */
			inodes = ctl->fs_blocks / 16;
		else if (512 * 1024 < ctl->fs_blocks)	/* 0.5GB */
			inodes = ctl->fs_blocks / 8;
		else
			inodes = ctl->fs_blocks / 3;
	else
		inodes = ctl->fs_inodes;
	/* Round up inode count to fill block size */
	if (fs_version == 2 || fs_version == 3)
		inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) &
			  ~(MINIX2_INODES_PER_BLOCK - 1));
	else
		inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) &
			  ~(MINIX_INODES_PER_BLOCK - 1));

	if (fs_version == 3)
		Super3.s_ninodes = inodes;
	else {
		if (inodes > MINIX_MAX_INODES)
			inodes = MINIX_MAX_INODES;
		Super.s_ninodes = inodes;
	}
	super_set_map_blocks(ctl, inodes);
	if (MINIX_MAX_INODES < first_zone_data())
		errx(MKFS_EX_ERROR,
		     _("First data block at %jd, which is too far (max %d).\n"
		       "Try specifying fewer inodes by passing --inodes <num>"),
		     (intmax_t)first_zone_data(),
		     MINIX_MAX_INODES);
	imaps = get_nimaps();
	zmaps = get_nzmaps();

	inode_map = xmalloc(imaps * MINIX_BLOCK_SIZE);
	zone_map = xmalloc(zmaps * MINIX_BLOCK_SIZE);
	memset(inode_map,0xff,imaps * MINIX_BLOCK_SIZE);
	memset(zone_map,0xff,zmaps * MINIX_BLOCK_SIZE);

	for (i = get_first_zone() ; i<zones ; i++)
		unmark_zone(i);
	for (i = MINIX_ROOT_INO ; i<=inodes; i++)
		unmark_inode(i);

	inode_buffer = xmalloc(get_inode_buffer_size());
	memset(inode_buffer,0, get_inode_buffer_size());

	printf(P_("%lu inode\n", "%lu inodes\n", inodes), inodes);
	printf(P_("%lu block\n", "%lu blocks\n", zones), zones);
	printf(_("Firstdatazone=%jd (%jd)\n"),
		(intmax_t)get_first_zone(), (intmax_t)first_zone_data());
	printf(_("Zonesize=%zu\n"), (size_t) MINIX_BLOCK_SIZE << get_zone_size());
	printf(_("Maxsize=%zu\n\n"),get_max_size());
}
	make_root_inode(&ctl);
	make_bad_inode(&ctl);
	mark_good_blocks(&ctl);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘仕豪

IT发展快就是因为有开源精神

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值