/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
* mkfs.minix.c - make a linux (minix) file-system.
*
* (C) 1991 Linus Torvalds. This file may be redistributed as per
* the Linux copyright.
- */
-
-/*
+*
* DD.MM.YY
*
* 24.11.91 - Time began. Used the fsck sources to get started.
*
* 30.10.94 - Added support for v2 filesystem
* (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
- *
+ *
* 09.11.94 - Added test to prevent overwrite of mounted fs adapted
* from Theodore Ts'o's (tytso@athena.mit.edu) mke2fs
* program. (Daniel Quinlan, quinlan@yggdrasil.com)
#include <stdlib.h>
#include <termios.h>
#include <sys/stat.h>
-#include <mntent.h>
#include <getopt.h>
#include <err.h>
#include "all-io.h"
#include "closestream.h"
#include "ismounted.h"
+
+#define XALLOC_EXIT_CODE MKFS_EX_ERROR
#include "xalloc.h"
#define MINIX_ROOT_INO 1
#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;
struct fs_control {
char *device_name; /* device on a Minix file system is created */
int device_fd; /* open file descriptor of the device */
+ char *lockmode; /* as specified by --lock */
unsigned long long fs_blocks; /* device block count for the file system */
int fs_used_blocks; /* used blocks on a device */
int fs_bad_blocks; /* number of bad blocks found from device */
#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(_(" -i, --inodes <num> number of inodes for the filesystem\n"), out);
fputs(_(" -c, --check check the device for bad blocks\n"), out);
fputs(_(" -l, --badblocks <file> list of bad blocks from file\n"), out);
+ fprintf(out, _(
+ " --lock[=<mode>] use exclusive device lock (%s, %s or %s)\n"), "yes", "no", "nonblock");
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
+ fprintf(out, USAGE_HELP_OPTIONS(25));
fprintf(out, USAGE_MAN_TAIL("mkfs.minix(8)"));
- exit(out == stderr ? MKFS_EX_USAGE : MKFS_EX_OK);
+ 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;
+ uint64_t sec;
- if (str && sscanf(str, "%ld", &sec) == 1)
+ if (str && sscanf(str, "%"SCNd64, &sec) == 1)
return sec;
return time(t);
}
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;
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;
}
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();
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;
-
+
/* Seek to the correct loc. */
if (lseek(ctl->device_fd, current_block * MINIX_BLOCK_SIZE, SEEK_SET) !=
current_block * MINIX_BLOCK_SIZE )
/* Try the read */
got = read(ctl->device_fd, buffer, try * MINIX_BLOCK_SIZE);
- if (got < 0) got = 0;
+ if (got < 0) got = 0;
if (got & (MINIX_BLOCK_SIZE - 1 )) {
printf(_("Weird values in do_check: probably bugs\n"));
}
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;
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'},
{"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);
- 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':
case 'l':
listfile = optarg;
break;
+ case OPT_LOCK:
+ ctl.lockmode = "1";
+ if (optarg) {
+ if (*optarg == '=')
+ optarg++;
+ ctl.lockmode = 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))
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)