📄 mkfs.c
字号:
/* initial guess for cgsize, in blocks */ mincgsize = mult * align; cguess = (good_cg_size(blocks, iblocks, align) / mincgsize) * mincgsize; if (cguess == 0) cguess = mincgsize; savecgisize = align * (cguess / mincgsize); for (i = 0; i < cguess/5; i += align) { cgs = blocks / (cguess + i); waste = blocks % (cguess + i); if (waste < prevwaste) { prevwaste = waste; savecgs = cgs; savecgsize = cguess + i; } cgs = blocks / (cguess - i); waste = blocks % (cguess - i); if (waste < prevwaste) { prevwaste = waste; savecgs = cgs; savecgsize = cguess - i; } } *addr_ncg = savecgs; *addr_cg_fsize = savecgsize; *addr_cg_isize = savecgisize;}/* * Initialize the superblock */voidinit_sb(){ fs = &sblock.fs; bzero(fs, sizeof(*fs)); fs->fs_size = start_blocks + (ncg * cg_fsize); fs->fs_firstcg = firstcg; fs->fs_cgfsize = cg_fsize; fs->fs_cgisize = cg_isize; fs->fs_sectors = fs_sectors; fs->fs_ncg = ncg; time(&fs->fs_time); fs->fs_magic = EFS_MAGIC; fs->fs_bmblock = 0; /* to force 3.2 defaults... */ fs->fs_heads = 10; /* BOGUS: but 3.2 mount expects nonzero... */ if (short_form) fs->fs_replsb = dev_blocks - 1; else { /* If long form invocation, put in a replicate superblock only if * the given size parameter is "close" to the actual device size. * "Close" is arbitrarily defined as less than cgfsize... * Of course, if we're working on a file not a device (eg miniroot * construction) we don't have a dev size so never put in a replsb! */ if (!dev_blocks || ((dev_blocks - fs_blocks) >= cg_fsize)) fs->fs_replsb = 0; else fs->fs_replsb = dev_blocks - 1; } fs->fs_bmsize = (fs->fs_size + BITSPERBYTE - 1) / BITSPERBYTE; fs->fs_tfree = ncg * (fs->fs_cgfsize - fs->fs_cgisize); strncpy(fs->fs_fpack, "nopack", sizeof(fs->fs_fpack)); strncpy(fs->fs_fname, "noname", sizeof(fs->fs_fname)); /* subtract 2 for inodes 0 & 1 which are never used */ fs->fs_tinode = ncg * fs->fs_cgisize * EFS_INOPBB - 2; /* If this is recovery-option, mark the superblock dirty to * force an fsck before it can be mounted. */ if (recover_option) fs->fs_dirty = EFS_DIRTY; EFS_SETUP_SUPERB(fs);}/* * Clear out the inodes */voidclear_inodes(){ register struct efs_dinode *di; register char *cp; register int ilist_bytes; register int i; unsigned long igen; ilist_bytes = BBTOB(cg_isize); cp = calloc(1, ilist_bytes); if (!cp) { fprintf(stderr, "%s: can't initialize inodes - out of memory\n", progname); exit(-1); } /* * Construct generation number based on current time to avoid * generation number collisions when a server recreates an * exported file system. */ time(&igen); di = (struct efs_dinode *)cp; for (i = EFS_INOPBB * cg_isize; i > 0; i-- ) { di->di_gen = igen; di++; } for (i = 0; i < ncg; i++) { if (c_writeb(fs_fd, cp, EFS_CGIMIN(fs, i), cg_isize) != cg_isize) { fprintf(stderr, "%s: inode write failed\n", progname); exit(-1); } } free(cp);}/* * Fill bootblock with zeros */voidclear_bootblock(){ long buf[BBSIZE / sizeof(long)]; bzero(buf, sizeof(buf)); if (c_writeb(fs_fd, buf, 0, 1) != 1) { fprintf(stderr, "%s: boot block write failed\n", progname); exit(-1); }}/* * Initialize the bitmap */voidinit_bitmap(){ register int i, j; register daddr_t bn; bitmap = malloc(BBTOB(bitmap_blocks)); if (!bitmap) { fprintf(stderr, "%s: can't initialize bitmap - out of memory\n", progname); exit(-1); } /* * Start the bitmap out as entirely used. Then clear out * the regions that are allocatable. */ bzero(bitmap, BBTOB(bitmap_blocks)); for (i = 0; i < ncg; i++) { bn = EFS_CGIMIN(fs, i) + fs->fs_cgisize; for (j = fs->fs_cgisize; j < fs->fs_cgfsize; j++) { bset(bitmap, bn); bn++; } }}error(){ int old_errno; old_errno = errno; fprintf(stderr, "%s: i/o error\n", progname); errno = old_errno; perror(progname); exit(-1);}/* * Get a character from the canned string or from the input file */getch(){ if (charp) return (*charp++); return (getc(fproto));}/* * Get a string from the input file. Gleefully stolen from system V mkfs. */voidgetstr(f) FILE *f;{ register int i, c;loop: switch(c = getch()) { case ' ': case '\t': case '\n': goto loop; case '\0': fprintf(stderr, "%s: premature EOF on %s\n", progname, proto); exit(-1); case ':': while (getch() != '\n') ; goto loop; } i = 0; do { string[i++] = c; c = getch(); } while((c != ' ') && (c != '\t') && (c != '\n') && (c != '\0')) ; string[i] = '\0';/* printf("getstr: %s\n", string); */}/* * Convert a string into a decimal number. */long getnum(){ register int i, c; register long n; getstr(); n = 0; for (i = 0; c = string[i]; i++) { if ((c < '0') || (c > '9')) { fprintf(stderr, "%s: %s is a bad number\n", progname, string); exit(-1); } n = n * 10 + (c - '0'); } return n;}/* * Parse the proto file */parseproto(parent, child) ino_t parent, child;{ struct efs_dinode *di; int val; int i; int fd; int nb; int majdev, mindev; char buf[16384]; int fmt, mode, uid, gid; ino_t newino; int islostfound; /* get first word */ getstr(); /* decode mode spec */ switch (string[0]) { case '-': fmt = IFREG; break; case 'b': fmt = IFBLK; break; case 'c': fmt = IFCHR; break; case 'd': fmt = IFDIR; break; case 'p': fmt = IFIFO; break; case 'l': fmt = IFLNK; break; default: fprintf(stderr, "%s: got unknown mode spec %c\n", progname, string[0]); fprintf(stderr, "ABORTING!\n"); exit(-1); } mode = 0; if (string[1] == 'u') mode |= ISUID; if (string[2] == 'g') mode |= ISGID; val = 0; for (i = 3; i < 6; i++) { if ((string[i] < '0') || (string[i] > '7')) { fprintf(stderr, "%s: %c/%s: bad octal mode digit\n", progname, string[i], string); exit(-1); } val = (val * 8) + (string[i] - '0'); } mode |= val; /* decode uid & gid */ uid = getnum(); gid = getnum(); /* initialize an inode */ efs_mknod(child, mode | fmt, uid, gid); /* now create the requested file */ switch (fmt) { case IFREG: /* regular file */ getstr(); if (debug) printf("Creating %s\n", string); efs_newregfile(child, string); break; case IFBLK: /* block device special */ case IFCHR: /* character device special */ majdev = getnum() & L_MAXMAJ; mindev = getnum() & L_MAXMIN; di = efs_iget(child); efs_putdev(makedev(majdev, mindev), &di->di_u); efs_iput(di, child); break; case IFIFO: /* fifo */ break; case IFLNK: /* symbolic link */ /* * Get contents of link from proto and write it to the * link file. */ getstr(); if (debug) printf("Creating link to %s\n", string); efs_write(child, string, strlen(string)); break; case IFDIR: /* directory */ if (child == EFS_ROOTINO) { /* * For the root inode, we just need to set its * link count to two to get things going. */ di = efs_iget(parent); di->di_nlink = 2; efs_iput(di, parent); } else { /* increment link count of parent inode */ di = efs_iget(parent); di->di_nlink++; efs_iput(di, parent); /* increment link count of new directory */ di = efs_iget(child); di->di_nlink++; efs_iput(di, child); } /* put "." and ".." entries into new directory */ efs_enter(child, child, "."); efs_enter(child, parent, ".."); /* now read in the directories contents and install them */ for (;;) { getstr(); if ((string[0] == '$') && (string[1] == '\0')) { break; } /* * Allocate a new inode for the file in the current * directory. Then parse its attributes by recursing. */ newino = efs_allocino(); efs_enter(child, newino, string); islostfound = strcmp(string, "lost+found") == 0; parseproto(child, newino); /* * If inode is the lost+found inode, make it a big * file so that fsck will work well. We do this * after recursing to allow for the lost+found "." * and ".." directories to be entered first. */ if (islostfound) { efs_mklostandfound(newino); } } break; }}be_verbose(){ printf("%s: %s: blocks=%d inodes=%d\n", progname, special, fs_blocks, ncg * cg_isize * EFS_INOPBB); printf("%s: %s: sectors=%d cgfsize=%d\n", progname, special, fs_sectors, cg_fsize); printf("%s: %s: cgalign=%d ialign=%d ncg=%d\n", progname, special, cg_align, i_align, ncg); printf("%s: %s: firstcg=%d cgisize=%d\n", progname, special, firstcg, cg_isize); printf("%s: %s: bitmap blocks=%d\n", progname, special, bitmap_blocks);}buildfs(){char *realpath; if (rawpath) realpath = rawpath; else realpath = special; if(interact || !quiet) be_verbose(); if (interact) ask_confirm(); /* Added 2/14/90: the "recover" option just puts the superblock * on disk without touching the rest of the space. This allows * a last-ditch attempt to salvage a filesystem with fsck. */ if (!recover_option) clear_other_sb(); init_sb(); /* allocate root inode */ fs->fs_tinode--; if (!recover_option) { clear_inodes(); clear_bootblock(); init_bitmap(); /* finally, parse proto file and build fs */ parseproto(EFS_ROOTINO, EFS_ROOTINO); /* sync to disk: updated superblock, its replica, & the bitmap. */ printf("Updating superblock, etc...\n"); if (c_writeb(fs_fd, bitmap, EFS_BITMAPBB, bitmap_blocks) != bitmap_blocks) { fprintf(stderr,"%s: Can't write to %s\n", progname, realpath); exit(-1); } } printf("Computing checksum.\n"); efs_checksum(); /* libefs relies on global fs, yucko!! */ printf("Writing to superblock again.\n"); if (c_writeb(fs_fd, &sblock, EFS_SUPERBB , 1) != 1) { fprintf(stderr,"%s: Can't write to %s\n", progname, realpath); exit(-1); } /* We write the replicated superblock only if its pointer is * present in the superblock. * Also not written if it's recover_option. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -