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

📄 mkfs.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* mkfs  -  make the MINIX filesystem	Authors: Tanenbaum et al. *//*	Authors: Andy Tanenbaum, Paul Ogilvie, Frans Meulenbroeks, Bruce Evans * * This program can make both version 1 and version 2 file systems, as follows: *	mkfs /dev/fd0 1200	# Version 2 (default) *	mkfs -1 /dev/fd0 360	# Version 1 * */#include <sys/types.h>#include <sys/dir.h>#include <sys/stat.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <minix/config.h>#include <minix/const.h>#include <minix/type.h>#include <minix/minlib.h>#include "../../fs/const.h"#if (MACHINE == IBM_PC)#include <minix/partition.h>#include <sys/ioctl.h>#endif#undef EXTERN#define EXTERN			/* get rid of EXTERN by making it null */#include "../../fs/type.h"#include "../../fs/super.h"#include <minix/fslib.h>#ifndef DOS#ifndef UNIX#undef printf			/* printf is a macro for printk */#define UNIX#endif#endif#include <stdio.h>#define INODE_MAP            2#define MAX_TOKENS          10#define LINE_LEN           200#define BIN                  2#define BINGRP               2#define BIT_MAP_SHIFT       13#define N_BLOCKS         (1024L * 1024)#define N_BLOCKS16	  (128L * 1024)#define INODE_MAX       ((unsigned) 65535)/* You can make a really large file system on a 16-bit system, but the array * of bits that get_block()/putblock() needs gets a bit big, so we can only * prefill MAX_INIT blocks.  (16-bit fsck can't check a file system larger * than N_BLOCKS16 anyway.) */#define MAX_INIT	 (sizeof(char *) == 2 ? N_BLOCKS16 : N_BLOCKS)#ifdef DOSmaybedefine O_RDONLY 4		/* O_RDONLY | BINARY_BIT */ maybedefine BWRITE 5		/* O_WRONLY | BINARY_BIT */#endif#if (MACHINE == ATARI)int isdev;#endifextern char *optarg;extern int optind;int next_zone, next_inode, zone_size, zone_shift = 0, zoff;block_t nrblocks;int inode_offset, lct = 0, disk, fd, print = 0, file = 0;unsigned int nrinodes;int override = 0, simple = 0, dflag;int donttest;			/* skip test if it fits on medium */char *progname;long current_time, bin_time;char zero[BLOCK_SIZE], *lastp;char umap[MAX_INIT / 8];	/* bit map tells if block read yet */block_t zone_map;		/* where is zone map? (depends on # inodes) */int inodes_per_block;int fs_version;block_t max_nrblocks;FILE *proto;_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(block_t sizeup, (char *device));_PROTOTYPE(void super, (zone_t zones, Ino_t inodes));_PROTOTYPE(void rootdir, (Ino_t inode));_PROTOTYPE(void eat_dir, (Ino_t parent));_PROTOTYPE(void eat_file, (Ino_t inode, int f));_PROTOTYPE(void enter_dir, (Ino_t parent, char *name, Ino_t child));_PROTOTYPE(void incr_size, (Ino_t n, long count));_PROTOTYPE(PRIVATE ino_t alloc_inode, (int mode, int usrid, int grpid));_PROTOTYPE(PRIVATE zone_t alloc_zone, (void));_PROTOTYPE(void add_zone, (Ino_t n, zone_t z, long bytes, long cur_time));_PROTOTYPE(void add_z_1, (Ino_t n, zone_t z, long bytes, long cur_time));_PROTOTYPE(void add_z_2, (Ino_t n, zone_t z, long bytes, long cur_time));_PROTOTYPE(void incr_link, (Ino_t n));_PROTOTYPE(void insert_bit, (block_t block, int bit));_PROTOTYPE(int mode_con, (char *p));_PROTOTYPE(void getline, (char line[LINE_LEN], char *parse[MAX_TOKENS]));_PROTOTYPE(void check_mtab, (char *devname));_PROTOTYPE(long file_time, (int f));_PROTOTYPE(void pexit, (char *s));_PROTOTYPE(void copy, (char *from, char *to, int count));_PROTOTYPE(void print_fs, (void));_PROTOTYPE(int read_and_set, (block_t n));_PROTOTYPE(void special, (char *string));_PROTOTYPE(void get_block, (block_t n, char buf[BLOCK_SIZE]));_PROTOTYPE(void put_block, (block_t n, char buf[BLOCK_SIZE]));_PROTOTYPE(void cache_init, (void));_PROTOTYPE(void flush, (void));_PROTOTYPE(void mx_read, (int blocknr, char buf[BLOCK_SIZE]));_PROTOTYPE(void mx_write, (int blocknr, char buf[BLOCK_SIZE]));_PROTOTYPE(void dexit, (char *s, int sectnum, int err));_PROTOTYPE(void usage, (void));/*================================================================ *                    mkfs  -  make filesystem *===============================================================*/int main(argc, argv)int argc;char *argv[];{  int nread, mode, usrid, grpid, ch;  block_t blocks;  block_t i;  ino_t root_inum;  ino_t inodes;  zone_t zones;  char *token[MAX_TOKENS], line[LINE_LEN];  struct stat statbuf;  /* Get two times, the current time and the mod time of the binary of   * mkfs itself.  When the -d flag is used, the later time is put into   * the i_mtimes of all the files.  This feature is useful when   * producing a set of file systems, and one wants all the times to be   * identical. First you set the time of the mkfs binary to what you   * want, then go.   */  current_time = time((time_t *) 0);	/* time mkfs is being run */  stat(argv[0], &statbuf);  bin_time = statbuf.st_mtime;	/* time when mkfs binary was last modified */  /* Process switches. */  progname = argv[0];  blocks = 0;  i = 0;  fs_version = 2;  inodes_per_block = V2_INODES_PER_BLOCK;  max_nrblocks = N_BLOCKS;  while ((ch = getopt(argc, argv, "1b:di:lot")) != EOF)	switch (ch) {	    case '1':		fs_version = 1;		inodes_per_block = V1_INODES_PER_BLOCK;		max_nrblocks = 0xFFFF;		break;	    case 'b':		blocks = strtoul(optarg, (char **) NULL, 0);		break;	    case 'd':		dflag = 1;		current_time = bin_time;		break;	    case 'i':		i = strtoul(optarg, (char **) NULL, 0);		break;	    case 'l':	print = 1;	break;	    case 'o':	override = 1;	break;	    case 't':	donttest = 1;	break;	    default:	usage();	}  /* Determine the size of the device if not specified as -b or proto. */  if (argc - optind == 1 && blocks == 0) blocks = sizeup(argv[optind]);  /* The remaining args must be 'special proto', or just 'special' if the   * block size has already been specified.   */  if (argc - optind != 2 && (argc - optind != 1 || blocks == 0)) usage();  /* Check special. */  check_mtab(argv[optind]);  /* Check and start processing proto. */  optarg = argv[++optind];  if (optind < argc && (proto = fopen(optarg, "r")) != NULL) {	/* Prototype file is readable. */	lct = 1;	getline(line, token);	/* skip boot block info */	/* Read the line with the block and inode counts. */	getline(line, token);	blocks = atol(token[0]);	if (blocks > max_nrblocks) pexit("Block count too large");	if (sizeof(char *) == 2 && blocks > N_BLOCKS16) {		fprintf(stderr,		"%s: warning: FS is larger than the %dM that fsck can check!\n",			progname, (int) (N_BLOCKS16 / (1024L * 1024)));	}	inodes = atoi(token[1]);	/* Process mode line for root directory. */	getline(line, token);	mode = mode_con(token[0]);	usrid = atoi(token[1]);	grpid = atoi(token[2]);  } else {	lct = 0;	if (optind < argc) {		/* Maybe the prototype file is just a size.  Check. */		blocks = strtoul(optarg, (char **) NULL, 0);		if (blocks == 0) pexit("Can't open prototype file");	}	if (i == 0) {		/* The default for inodes is 3 blocks per inode, rounded up		 * to fill an inode block.  Above 20M, the average files are		 * sure to be larger because it is hard to fill up 20M with		 * tiny files, so reduce the default number of inodes.  This		 * default can always be overridden by using the -i option.		 */		i = blocks / 3;		if (blocks >= 20000) i = blocks / 4;		if (blocks >= 40000) i = blocks / 5;		if (blocks >= 60000) i = blocks / 6;		if (blocks >= 80000) i = blocks / 7;		if (blocks >= 100000) i = blocks / 8;		i += inodes_per_block - 1;		i = i / inodes_per_block * inodes_per_block;		if (i > INODE_MAX) i = INODE_MAX;	}	if (blocks < 5) pexit("Block count too small");	if (blocks > max_nrblocks) pexit("Block count too large");	if (i < 1) pexit("Inode count too small");	if (i > INODE_MAX) pexit("Inode count too large");	inodes = (ino_t) i;	/* Make simple file system of the given size, using defaults. */	mode = 040777;	usrid = BIN;	grpid = BINGRP;	simple = 1;  }  nrblocks = blocks;  nrinodes = inodes;  /* Open special. */  special(argv[--optind]);#ifdef UNIX  if (!donttest) {	static short testb[BLOCK_SIZE / sizeof(short)];	/* Try writing the last block of partition or diskette. */	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);	testb[0] = 0x3245;	testb[1] = 0x11FF;	if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)		pexit("File system is too big for minor device");	sync();			/* flush write, so if error next read fails */	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);	testb[0] = 0;	testb[1] = 0;	nread = read(fd, (char *) testb, BLOCK_SIZE);	if (nread != BLOCK_SIZE || testb[0] != 0x3245 || testb[1] != 0x11FF)		pexit("File system is too big for minor device");	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);	testb[0] = 0;	testb[1] = 0;	if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)		pexit("File system is too big for minor device");	lseek(fd, 0L, SEEK_SET);  }#endif  /* Make the file-system */  cache_init();#if (MACHINE == ATARI)  if (isdev) {	char block0[BLOCK_SIZE];	get_block((block_t) 0, block0);	/* Need to read twice; first time gets an empty block */	get_block((block_t) 0, block0);	/* Zero parts of the boot block so the disk won't be	 * recognized as a tos disk any more. */	block0[0] = block0[1] = 0;	/* branch code to boot code    */	strncpy(&block0[2], "MINIX ", (size_t) 6);	block0[16] = 0;		/* number of FATS              */	block0[17] = block0[18] = 0;	/* number of dir entries       */	block0[22] = block0[23] = 0;	/* sectors/FAT                 */	bzero(&block0[30], 480);/* boot code                   */	put_block((block_t) 0, block0);  } else#endif	put_block((block_t) 0, zero);	/* Write a null boot block. */  zone_shift = 0;		/* for future use */  zones = nrblocks >> zone_shift;  super(zones, inodes);  root_inum = alloc_inode(mode, usrid, grpid);  rootdir(root_inum);  if (simple == 0) eat_dir(root_inum);  if (print) print_fs();  flush();  return(0);  /* NOTREACHED */}				/* end main *//*================================================================ *                    sizeup  -  determine device size *===============================================================*/block_t sizeup(device)char *device;{  int fd;  struct partition entry;  if ((fd = open(device, O_RDONLY)) == -1) return 0;  if (ioctl(fd, DIOCGETP, &entry) == -1) entry.size = 0;  close(fd);  return entry.size / BLOCK_SIZE;}/*================================================================ *                 super  -  construct a superblock *===============================================================*/void super(zones, inodes)zone_t zones;ino_t inodes;{  unsigned int i;  int inodeblks;  int initblks;  zone_t initzones, nrzones, v1sq, v2sq;  zone_t zo;  struct super_block *sup;  char buf[BLOCK_SIZE], *cp;  for (cp = buf; cp < &buf[BLOCK_SIZE]; cp++) *cp = 0;  sup = (struct super_block *) buf;	/* lint - might use a union */  sup->s_ninodes = inodes;  if (fs_version == 1) {	sup->s_nzones = zones;  } else {	sup->s_nzones = 0;	/* not used in V2 - 0 forces errors early */	sup->s_zones = zones;  }  sup->s_imap_blocks = bitmapsize((bit_t) (1 + inodes));  sup->s_zmap_blocks = bitmapsize((bit_t) zones);  inode_offset = sup->s_imap_blocks + sup->s_zmap_blocks + 2;  inodeblks = (inodes + inodes_per_block - 1) / inodes_per_block;  initblks = inode_offset + inodeblks;  initzones = (initblks + (1 << zone_shift) - 1) >> zone_shift;  nrzones = nrblocks >> zone_shift;  sup->s_firstdatazone = (initblks + (1 << zone_shift) - 1) >> zone_shift;  zoff = sup->s_firstdatazone - 1;  sup->s_log_zone_size = zone_shift;  if (fs_version == 1) {	sup->s_magic = SUPER_MAGIC;	/* identify super blocks */	v1sq = (zone_t) V1_INDIRECTS * V1_INDIRECTS;	zo = V1_NR_DZONES + (long) V1_INDIRECTS + v1sq;  } else {	sup->s_magic = SUPER_V2;/* identify super blocks */	v2sq = (zone_t) V2_INDIRECTS * V2_INDIRECTS;	zo = V2_NR_DZONES + (zone_t) V2_INDIRECTS + v2sq;  }  sup->s_max_size = zo * BLOCK_SIZE;  zone_size = 1 << zone_shift;	/* nr of blocks per zone */  put_block((block_t) 1, buf);  /* Clear maps and inodes. */  for (i = 2; i < initblks; i++) put_block((block_t) i, zero);  next_zone = sup->s_firstdatazone;  next_inode = 1;  zone_map = INODE_MAP + sup->s_imap_blocks;  insert_bit(zone_map, 0);	/* bit zero must always be allocated */  insert_bit((block_t) INODE_MAP, 0);	/* inode zero not used but					 * must be allocated */}/*================================================================ *              rootdir  -  install the root directory *===============================================================*/void rootdir(inode)ino_t inode;{  zone_t z;  z = alloc_zone();  add_zone(inode, z, 32L, current_time);  enter_dir(inode, ".", inode);  enter_dir(inode, "..", inode);  incr_link(inode);  incr_link(inode);}/*================================================================ *	    eat_dir  -  recursively install directory *===============================================================*/void eat_dir(parent)ino_t parent;{  /* Read prototype lines and set up directory. Recurse if need be. */  char *token[MAX_TOKENS], *p;  char line[LINE_LEN];  int mode, usrid, grpid, maj, min, f;  ino_t n;  zone_t z;  long size;  while (1) {	getline(line, token);	p = token[0];	if (*p == '$') return;	p = token[1];	mode = mode_con(p);	usrid = atoi(token[2]);	grpid = atoi(token[3]);	if (grpid & 0200) fprintf(stderr, "A.S.Tanenbaum\n");	n = alloc_inode(mode, usrid, grpid);	/* Enter name in directory and update directory's size. */	enter_dir(parent, token[0], n);	incr_size(parent, 16L);	/* Check to see if file is directory or special. */	incr_link(n);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -