📄 mke2fs.c
字号:
/* vi: set sw=4 ts=4: *//* * mke2fs.c - Make a ext2fs filesystem. * * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, * 2003, 2004, 2005 by Theodore Ts'o. * * This file may be redistributed under the terms of the GNU Public * License. *//* Usage: mke2fs [options] device * * The device may be a block device or a image of one, but this isn't * enforced (but it's not much fun on a character device :-). */#include <stdio.h>#include <string.h>#include <fcntl.h>#include <ctype.h>#include <time.h>#include <getopt.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <mntent.h>#include <sys/ioctl.h>#include <sys/types.h>#include "e2fsbb.h"#include "ext2fs/ext2_fs.h"#include "uuid/uuid.h"#include "e2p/e2p.h"#include "ext2fs/ext2fs.h"#include "util.h"#define STRIDE_LENGTH 8#ifndef __sparc__#define ZAP_BOOTBLOCK#endifstatic const char * device_name;/* Command line options */static int cflag;static int quiet;static int super_only;static int force;static int noaction;static int journal_size;static int journal_flags;static const char *bad_blocks_filename;static __u32 fs_stride;static struct ext2_super_block param;static char *creator_os;static char *volume_label;static char *mount_dir;static char *journal_device = NULL;static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */static int sys_page_size = 4096;static int linux_version_code = 0;static int int_log2(int arg){ int l = 0; arg >>= 1; while (arg) { l++; arg >>= 1; } return l;}static int int_log10(unsigned int arg){ int l; for (l = 0; arg; l++) arg = arg / 10; return l;}/* * This function sets the default parameters for a filesystem * * The type is specified by the user. The size is the maximum size * (in megabytes) for which a set of parameters applies, with a size * of zero meaning that it is the default parameter for the type. * Note that order is important in the table below. */#define DEF_MAX_BLOCKSIZE -1static const char default_str[] = "default";struct mke2fs_defaults { const char *type; int size; int blocksize; int inode_ratio;};static const struct mke2fs_defaults settings[] = { { default_str, 0, 4096, 8192 }, { default_str, 512, 1024, 4096 }, { default_str, 3, 1024, 8192 }, { "journal", 0, 4096, 8192 }, { "news", 0, 4096, 4096 }, { "largefile", 0, 4096, 1024 * 1024 }, { "largefile4", 0, 4096, 4096 * 1024 }, { 0, 0, 0, 0},};static void set_fs_defaults(const char *fs_type, struct ext2_super_block *super, int blocksize, int sector_size, int *inode_ratio){ int megs; int ratio = 0; const struct mke2fs_defaults *p; int use_bsize = 1024; megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024; if (inode_ratio) ratio = *inode_ratio; if (!fs_type) fs_type = default_str; for (p = settings; p->type; p++) { if ((strcmp(p->type, fs_type) != 0) && (strcmp(p->type, default_str) != 0)) continue; if ((p->size != 0) && (megs > p->size)) continue; if (ratio == 0) *inode_ratio = p->inode_ratio < blocksize ? blocksize : p->inode_ratio; use_bsize = p->blocksize; } if (blocksize <= 0) { if (use_bsize == DEF_MAX_BLOCKSIZE) { use_bsize = sys_page_size; if ((linux_version_code < (2*65536 + 6*256)) && (use_bsize > 4096)) use_bsize = 4096; } if (sector_size && use_bsize < sector_size) use_bsize = sector_size; if ((blocksize < 0) && (use_bsize < (-blocksize))) use_bsize = -blocksize; blocksize = use_bsize; super->s_blocks_count /= blocksize / 1024; } super->s_log_frag_size = super->s_log_block_size = int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);}/* * Helper function for read_bb_file and test_disk */static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk){ bb_error_msg("Bad block %u out of range; ignored", blk);}/* * Busybox stuff */static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...){ va_list ap; if (retval) { va_start(ap, fmt); fprintf(stderr,"\nCould not "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); exit(EXIT_FAILURE); }}static void mke2fs_verbose(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));static void mke2fs_verbose(const char *fmt, ...){ va_list ap; if (!quiet) { va_start(ap, fmt); vfprintf(stdout, fmt, ap); fflush(stdout); va_end(ap); }}static void mke2fs_verbose_done(void){ mke2fs_verbose("done\n");}static void mke2fs_warning_msg(int retval, char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));static void mke2fs_warning_msg(int retval, char *fmt, ... ){ va_list ap; if (retval) { va_start(ap, fmt); fprintf(stderr,"\nWarning: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); }}/* * Reads the bad blocks list from a file */static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list, const char *bad_blocks_file){ FILE *f; errcode_t retval; f = xfopen(bad_blocks_file, "r"); retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block); fclose (f); mke2fs_error_msg_and_die(retval, "read bad blocks from list");}/* * Runs the badblocks program to test the disk */static void test_disk(ext2_filsys fs, badblocks_list *bb_list){ FILE *f; errcode_t retval; char buf[1024]; sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize, quiet ? "" : "-s ", (cflag > 1) ? "-w " : "", fs->device_name, fs->super->s_blocks_count); mke2fs_verbose("Running command: %s\n", buf); f = popen(buf, "r"); if (!f) { bb_perror_msg_and_die("cannot run '%s'", buf); } retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block); pclose(f); mke2fs_error_msg_and_die(retval, "read bad blocks from program");}static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list){ dgrp_t i; blk_t j; unsigned must_be_good; blk_t blk; badblocks_iterate bb_iter; errcode_t retval; blk_t group_block; int group; int group_bad; if (!bb_list) return; /* * The primary superblock and group descriptors *must* be * good; if not, abort. */ must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks; for (i = fs->super->s_first_data_block; i <= must_be_good; i++) { if (ext2fs_badblocks_list_test(bb_list, i)) { bb_error_msg_and_die( "Block %d in primary superblock/group descriptor area bad\n" "Blocks %d through %d must be good in order to build a filesystem\n" "Aborting ...", i, fs->super->s_first_data_block, must_be_good); } } /* * See if any of the bad blocks are showing up in the backup * superblocks and/or group descriptors. If so, issue a * warning and adjust the block counts appropriately. */ group_block = fs->super->s_first_data_block + fs->super->s_blocks_per_group; for (i = 1; i < fs->group_desc_count; i++) { group_bad = 0; for (j=0; j < fs->desc_blocks+1; j++) { if (ext2fs_badblocks_list_test(bb_list, group_block + j)) { mke2fs_warning_msg(!group_bad, "the backup superblock/group descriptors at block %d contain\n" "bad blocks\n", group_block); group_bad++; group = ext2fs_group_of_blk(fs, group_block+j); fs->group_desc[group].bg_free_blocks_count++; fs->super->s_free_blocks_count++; } } group_block += fs->super->s_blocks_per_group; } /* * Mark all the bad blocks as used... */ retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); mke2fs_error_msg_and_die(retval, "mark bad blocks as used"); while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) ext2fs_mark_block_bitmap(fs->block_map, blk); ext2fs_badblocks_list_iterate_end(bb_iter);}/* * These functions implement a generalized progress meter. */struct progress_struct { char format[20]; char backup[80]; __u32 max; int skip_progress;};static void progress_init(struct progress_struct *progress, const char *label,__u32 max){ int i; memset(progress, 0, sizeof(struct progress_struct)); if (quiet) return; /* * Figure out how many digits we need */ i = int_log10(max); sprintf(progress->format, "%%%dd/%%%dld", i, i); memset(progress->backup, '\b', sizeof(progress->backup)-1); progress->backup[sizeof(progress->backup)-1] = 0; if ((2*i)+1 < (int) sizeof(progress->backup)) progress->backup[(2*i)+1] = 0; progress->max = max; progress->skip_progress = 0; if (getenv("MKE2FS_SKIP_PROGRESS")) progress->skip_progress++; fputs(label, stdout); fflush(stdout);}static void progress_update(struct progress_struct *progress, __u32 val){ if ((progress->format[0] == 0) || progress->skip_progress) return; printf(progress->format, val, progress->max); fputs(progress->backup, stdout);}static void progress_close(struct progress_struct *progress){ if (progress->format[0] == 0) return; printf("%-28s\n", "done");}/* * Helper function which zeros out _num_ blocks starting at _blk_. In * case of an error, the details of the error is returned via _ret_blk_ * and _ret_count_ if they are non-NULL pointers. Returns 0 on * success, and an error code on an error. * * As a special case, if the first argument is NULL, then it will * attempt to free the static zeroizing buffer. (This is to keep * programs that check for memory leaks happy.) */static errcode_t zero_blocks(ext2_filsys fs, blk_t blk, int num, struct progress_struct *progress, blk_t *ret_blk, int *ret_count){ int j, count, next_update, next_update_incr; static char *buf; errcode_t retval; /* If fs is null, clean up the static buffer and return */ if (!fs) { if (buf) { free(buf); buf = 0; } return 0; } /* Allocate the zeroizing buffer if necessary */ if (!buf) { buf = xzalloc(fs->blocksize * STRIDE_LENGTH); } /* OK, do the write loop */ next_update = 0; next_update_incr = num / 100; if (next_update_incr < 1) next_update_incr = 1; for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) { count = num - j; if (count > STRIDE_LENGTH) count = STRIDE_LENGTH; retval = io_channel_write_blk(fs->io, blk, count, buf); if (retval) { if (ret_count) *ret_count = count; if (ret_blk) *ret_blk = blk; return retval; } if (progress && j > next_update) { next_update += num / 100; progress_update(progress, blk); } } return 0;}static void write_inode_tables(ext2_filsys fs){ errcode_t retval; blk_t blk; dgrp_t i; int num; struct progress_struct progress; if (quiet) memset(&progress, 0, sizeof(progress)); else progress_init(&progress, "Writing inode tables: ", fs->group_desc_count); for (i = 0; i < fs->group_desc_count; i++) { progress_update(&progress, i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -