#include <stdlib.h>
#include <termios.h>
#include <sys/stat.h>
-#include <mntent.h>
#include <getopt.h>
#include <err.h>
#include "closestream.h"
#include "ismounted.h"
+#define XALLOC_EXIT_CODE MKFS_EX_ERROR
+#include "xalloc.h"
+
#define MINIX_ROOT_INO 1
#define MINIX_BAD_INO 2
#define DEFAULT_FS_VERSION 1
/*
- * Global variables used in minix_programs.h inline fuctions
+ * Global variables used in minix_programs.h inline functions
*/
int fs_version = DEFAULT_FS_VERSION;
char *super_block_buffer;
#define mark_zone(x) (setbit(zone_map,(x)-get_first_zone()+1))
#define unmark_zone(x) (clrbit(zone_map,(x)-get_first_zone()+1))
-static void __attribute__((__noreturn__)) usage(FILE *out)
+static void __attribute__((__noreturn__)) usage(void)
{
+ FILE *out = stdout;
fputs(USAGE_HEADER, out);
fprintf(out, _(" %s [options] /dev/name [blocks]\n"), program_invocation_short_name);
fputs(USAGE_OPTIONS, out);
fputs(_(" -c, --check check the device for bad blocks\n"), out);
fputs(_(" -l, --badblocks <file> list of bad blocks from file\n"), out);
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
- fprintf(out, USAGE_MAN_TAIL("mkfs.minix(8)"));
- exit(out == stderr ? MKFS_EX_USAGE : MKFS_EX_OK);
+ printf(USAGE_HELP_OPTIONS(25));
+ printf(USAGE_MAN_TAIL("mkfs.minix(8)"));
+ exit(MKFS_EX_OK);
}
+#ifdef TEST_SCRIPT
+static inline time_t mkfs_minix_time(time_t *t)
+{
+ const char *str = getenv("MKFS_MINIX_TEST_SECOND_SINCE_EPOCH");
+ time_t sec;
+
+ if (str && sscanf(str, "%ld", &sec) == 1)
+ return sec;
+ return time(t);
+}
+#else /* !TEST_SCRIPT */
+# define mkfs_minix_time(x) time(x)
+#endif
+
static void super_set_state(void)
{
switch (fs_version) {
return;
mark_inode(MINIX_BAD_INO);
inode->i_nlinks = 1;
- inode->i_time = time(NULL);
+ inode->i_time = mkfs_minix_time(NULL);
inode->i_mode = S_IFREG + 0000;
inode->i_size = ctl->fs_bad_blocks * MINIX_BLOCK_SIZE;
zone = next(0);
return;
mark_inode (MINIX_BAD_INO);
inode->i_nlinks = 1;
- inode->i_atime = inode->i_mtime = inode->i_ctime = time (NULL);
+ inode->i_atime = inode->i_mtime = inode->i_ctime = mkfs_minix_time(NULL);
inode->i_mode = S_IFREG + 0000;
inode->i_size = ctl->fs_bad_blocks * MINIX_BLOCK_SIZE;
zone = next (0);
mark_inode(MINIX_ROOT_INO);
inode->i_zone[0] = get_free_block(ctl);
inode->i_nlinks = 2;
- inode->i_time = time(NULL);
+ inode->i_time = mkfs_minix_time(NULL);
if (ctl->fs_bad_blocks)
inode->i_size = 3 * ctl->fs_dirsize;
else {
- root_block[2 * ctl->fs_dirsize] = '\0';
- root_block[2 * ctl->fs_dirsize + 1] = '\0';
+ memset(&root_block[2 * ctl->fs_dirsize], 0, ctl->fs_dirsize);
inode->i_size = 2 * ctl->fs_dirsize;
}
inode->i_mode = S_IFDIR + 0755;
mark_inode (MINIX_ROOT_INO);
inode->i_zone[0] = get_free_block (ctl);
inode->i_nlinks = 2;
- inode->i_atime = inode->i_mtime = inode->i_ctime = time (NULL);
+ inode->i_atime = inode->i_mtime = inode->i_ctime = mkfs_minix_time(NULL);
if (ctl->fs_bad_blocks)
inode->i_size = 3 * ctl->fs_dirsize;
else {
- root_block[2 * ctl->fs_dirsize] = '\0';
+ memset(&root_block[2 * ctl->fs_dirsize], 0, ctl->fs_dirsize);
inode->i_size = 2 * ctl->fs_dirsize;
}
static void make_root_inode(struct fs_control *ctl)
{
+ char *tmp = root_block;
+
+ if (fs_version == 3) {
+ *(uint32_t *) tmp = 1;
+ strcpy(tmp + 4, ".");
+ tmp += ctl->fs_dirsize;
+ *(uint32_t *) tmp = 1;
+ strcpy(tmp + 4, "..");
+ tmp += ctl->fs_dirsize;
+ *(uint32_t *) tmp = 2;
+ strcpy(tmp + 4, ".badblocks");
+ } else {
+ *(uint16_t *) tmp = 1;
+ strcpy(tmp + 2, ".");
+ tmp += ctl->fs_dirsize;
+ *(uint16_t *) tmp = 1;
+ strcpy(tmp + 2, "..");
+ tmp += ctl->fs_dirsize;
+ *(uint16_t *) tmp = 2;
+ strcpy(tmp + 2, ".badblocks");
+ }
if (fs_version < 2) {
make_root_inode_v1(ctl);
return;
static void setup_tables(const struct fs_control *ctl) {
unsigned long inodes, zmaps, imaps, zones, i;
- super_block_buffer = calloc(1, MINIX_BLOCK_SIZE);
- if (!super_block_buffer)
- err(MKFS_EX_ERROR, _("%s: unable to allocate buffer for superblock"),
- ctl->device_name);
+ super_block_buffer = xcalloc(1, MINIX_BLOCK_SIZE);
memset(boot_block_buffer,0,512);
super_set_magic(ctl);
if (fs_version == 3)
Super3.s_ninodes = inodes;
else {
- Super.s_ninodes = inodes;
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>"),
- first_zone_data(),
+ (intmax_t)first_zone_data(),
MINIX_MAX_INODES);
imaps = get_nimaps();
zmaps = get_nzmaps();
- inode_map = malloc(imaps * MINIX_BLOCK_SIZE);
- zone_map = malloc(zmaps * MINIX_BLOCK_SIZE);
- if (!inode_map || !zone_map)
- err(MKFS_EX_ERROR, _("%s: unable to allocate buffers for maps"),
- ctl->device_name);
+ 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 = malloc(get_inode_buffer_size());
- if (!inode_buffer)
- err(MKFS_EX_ERROR, _("%s: unable to allocate buffer for inodes"),
- ctl->device_name);
+
+ 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"), get_first_zone(), first_zone_data());
+ 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());
}
/*
* Perform a test of a block; return the number of
- * blocks readable/writeable.
+ * blocks readable/writable.
*/
static size_t do_check(const struct fs_control *ctl, char * buffer, int try, unsigned int current_block) {
ssize_t got;
case 1:
if (ctl->fs_namelen == 14)
return MINIX_SUPER_MAGIC;
- else
- return MINIX_SUPER_MAGIC2;
- break;
+ return MINIX_SUPER_MAGIC2;
case 2:
if (ctl->fs_namelen == 14)
return MINIX2_SUPER_MAGIC;
- else
- return MINIX2_SUPER_MAGIC2;
- break;
+ return MINIX2_SUPER_MAGIC2;
case 3:
return MINIX3_SUPER_MAGIC;
default:
static void determine_device_blocks(struct fs_control *ctl, const struct stat *statbuf)
{
- unsigned long long dev_blocks;
+ unsigned long long dev_blocks = 0;
if (S_ISBLK(statbuf->st_mode)) {
int sectorsize;
if (blkdev_get_sector_size(ctl->device_fd, §orsize) == -1)
sectorsize = DEFAULT_SECTOR_SIZE; /* kernel < 2.3.3 */
- if (blkdev_is_misaligned(ctl->device_fd))
- warnx(_("%s: device is misaligned"), ctl->device_name);
if (MINIX_BLOCK_SIZE < sectorsize)
errx(MKFS_EX_ERROR, _("block size smaller than physical "
"sector size of %s"), ctl->device_name);
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 > MINIX_MAX_INODES * BITS_PER_BLOCK)
- ctl->fs_blocks = MINIX_MAX_INODES * BITS_PER_BLOCK; /* Utter maximum: Clip. */
+ 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. */
}
static void check_user_instructions(struct fs_control *ctl)
0
};
int i;
- char * tmp;
struct stat statbuf;
char * listfile = NULL;
static const struct option longopts[] = {
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ 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 compatiblitly */
+ case 'v': /* kept for backwards compatibility */
warnx(_("-v is ambiguous, use '-2' instead"));
+ /* fallthrough */
case '2':
fs_version = 2;
break;
listfile = optarg;
break;
case 'V':
- printf(UTIL_LINUX_VERSION);
- return MKFS_EX_OK;
+ print_version(MKFS_EX_OK);
case 'h':
- usage(stdout);
+ usage();
default:
- usage(stderr);
+ errtryhelp(MKFS_EX_USAGE);
}
argc -= optind;
argv += optind;
ctl.fs_blocks = strtoul_or_err(argv[0], _("failed to parse number of blocks"));
if (!ctl.device_name) {
- usage(stderr);
+ 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);
- tmp = root_block;
- if (fs_version == 3) {
- *(uint32_t *)tmp = 1;
- strcpy(tmp+4,".");
- tmp += ctl.fs_dirsize;
- *(uint32_t *)tmp = 1;
- strcpy(tmp+4,"..");
- tmp += ctl.fs_dirsize;
- *(uint32_t *)tmp = 2;
- strcpy(tmp+4, ".badblocks");
- } else {
- *(uint16_t *)tmp = 1;
- strcpy(tmp+2,".");
- tmp += ctl.fs_dirsize;
- *(uint16_t *)tmp = 1;
- strcpy(tmp+2,"..");
- tmp += ctl.fs_dirsize;
- *(uint16_t *)tmp = 2;
- strcpy(tmp+2, ".badblocks");
- }
if (stat(ctl.device_name, &statbuf) < 0)
err(MKFS_EX_ERROR, _("stat of %s failed"), ctl.device_name);
- if (S_ISBLK(statbuf.st_mode))
- ctl.device_fd = open(ctl.device_name, O_RDWR | O_EXCL);
- else
- ctl.device_fd = open(ctl.device_name, O_RDWR);
+ 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);
determine_device_blocks(&ctl, &statbuf);