]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - disk-utils/mkfs.minix.c
whereis: use xstrncpy()
[thirdparty/util-linux.git] / disk-utils / mkfs.minix.c
index c2ab6644c686b92d222ed672353c3093e6230ad7..ed03f4a42d04a989c9a08242d7c522bc884c96ce 100644 (file)
@@ -64,7 +64,6 @@
 #include <stdlib.h>
 #include <termios.h>
 #include <sys/stat.h>
-#include <mntent.h>
 #include <getopt.h>
 #include <err.h>
 
@@ -79,6 +78,9 @@
 #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
 
@@ -90,7 +92,7 @@
 #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;
@@ -129,8 +131,9 @@ static char *zone_map;
 #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);
@@ -142,12 +145,25 @@ static void __attribute__((__noreturn__)) usage(FILE *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) {
@@ -251,7 +267,7 @@ static void make_bad_inode_v1(struct fs_control *ctl)
                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);
@@ -299,7 +315,7 @@ static void make_bad_inode_v2_v3 (struct fs_control *ctl)
                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);
@@ -351,12 +367,11 @@ static void make_root_inode_v1(struct fs_control *ctl) {
        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;
@@ -372,12 +387,12 @@ static void make_root_inode_v2_v3 (struct fs_control *ctl) {
        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;
        }
 
@@ -390,6 +405,27 @@ static void make_root_inode_v2_v3 (struct fs_control *ctl) {
 
 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;
@@ -460,10 +496,7 @@ static void super_set_magic(const struct fs_control *ctl)
 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);
@@ -503,46 +536,44 @@ static void setup_tables(const struct fs_control *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;
@@ -640,15 +671,11 @@ static int find_super_magic(const struct fs_control *ctl)
        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:
@@ -658,15 +685,13 @@ static int find_super_magic(const struct fs_control *ctl)
 
 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, &sectorsize) == -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);
@@ -685,8 +710,8 @@ static void determine_device_blocks(struct fs_control *ctl, const struct stat *s
                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)
@@ -718,7 +743,6 @@ int main(int argc, char ** argv)
                0
        };
        int i;
-       char * tmp;
        struct stat statbuf;
        char * listfile = NULL;
        static const struct option longopts[] = {
@@ -734,15 +758,18 @@ int main(int argc, char ** argv)
        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;
@@ -765,12 +792,11 @@ int main(int argc, char ** argv)
                        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;
@@ -783,38 +809,16 @@ int main(int argc, char ** argv)
                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);