| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: mke2fs.c,v 1.14 2010/09/10 15:51:20 tsutsui Exp $ */ | | 1 | /* $NetBSD: mke2fs.c,v 1.14.8.1 2012/03/09 16:51:04 sborrill Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2007 Izumi Tsutsui. All rights reserved. | | 4 | * Copyright (c) 2007 Izumi Tsutsui. All rights reserved. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -90,51 +90,51 @@ | | | @@ -90,51 +90,51 @@ |
90 | * - Ext2fs Home Page | | 90 | * - Ext2fs Home Page |
91 | * http://e2fsprogs.sourceforge.net/ext2.html | | 91 | * http://e2fsprogs.sourceforge.net/ext2.html |
92 | * - Design and Implementation of the Second Extended Filesystem | | 92 | * - Design and Implementation of the Second Extended Filesystem |
93 | * http://e2fsprogs.sourceforge.net/ext2intro.html | | 93 | * http://e2fsprogs.sourceforge.net/ext2intro.html |
94 | * - Linux Documentation "The Second Extended Filesystem" | | 94 | * - Linux Documentation "The Second Extended Filesystem" |
95 | * http://www.kernel.org/doc/Documentation/filesystems/ext2.txt | | 95 | * http://www.kernel.org/doc/Documentation/filesystems/ext2.txt |
96 | */ | | 96 | */ |
97 | | | 97 | |
98 | #include <sys/cdefs.h> | | 98 | #include <sys/cdefs.h> |
99 | #ifndef lint | | 99 | #ifndef lint |
100 | #if 0 | | 100 | #if 0 |
101 | static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; | | 101 | static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; |
102 | #else | | 102 | #else |
103 | __RCSID("$NetBSD: mke2fs.c,v 1.14 2010/09/10 15:51:20 tsutsui Exp $"); | | 103 | __RCSID("$NetBSD: mke2fs.c,v 1.14.8.1 2012/03/09 16:51:04 sborrill Exp $"); |
104 | #endif | | 104 | #endif |
105 | #endif /* not lint */ | | 105 | #endif /* not lint */ |
106 | | | 106 | |
107 | #include <sys/param.h> | | 107 | #include <sys/param.h> |
108 | #include <sys/mman.h> | | 108 | #include <sys/mman.h> |
109 | #include <sys/time.h> | | 109 | #include <sys/time.h> |
110 | #include <ufs/ext2fs/ext2fs_dinode.h> | | 110 | #include <ufs/ext2fs/ext2fs_dinode.h> |
111 | #include <ufs/ext2fs/ext2fs_dir.h> | | 111 | #include <ufs/ext2fs/ext2fs_dir.h> |
112 | #include <ufs/ext2fs/ext2fs.h> | | 112 | #include <ufs/ext2fs/ext2fs.h> |
113 | #include <sys/ioctl.h> | | 113 | #include <sys/ioctl.h> |
114 | | | 114 | |
115 | #include <err.h> | | 115 | #include <err.h> |
116 | #include <errno.h> | | 116 | #include <errno.h> |
117 | #include <string.h> | | 117 | #include <string.h> |
118 | #include <unistd.h> | | 118 | #include <unistd.h> |
119 | #include <stdlib.h> | | 119 | #include <stdlib.h> |
120 | #include <stddef.h> | | 120 | #include <stddef.h> |
121 | #include <stdio.h> | | 121 | #include <stdio.h> |
122 | #include <uuid.h> | | 122 | #include <uuid.h> |
123 | | | 123 | |
124 | #include "extern.h" | | 124 | #include "extern.h" |
125 | | | 125 | |
126 | static void initcg(uint); | | 126 | static void initcg(uint); |
127 | static void zap_old_sblock(daddr_t); | | 127 | static void zap_old_sblock(int); |
128 | static uint cgoverhead(uint); | | 128 | static uint cgoverhead(uint); |
129 | static int fsinit(const struct timeval *); | | 129 | static int fsinit(const struct timeval *); |
130 | static int makedir(struct ext2fs_direct *, int); | | 130 | static int makedir(struct ext2fs_direct *, int); |
131 | static void copy_dir(struct ext2fs_direct *, struct ext2fs_direct *); | | 131 | static void copy_dir(struct ext2fs_direct *, struct ext2fs_direct *); |
132 | static void init_resizeino(const struct timeval *); | | 132 | static void init_resizeino(const struct timeval *); |
133 | static uint32_t alloc(uint32_t, uint16_t); | | 133 | static uint32_t alloc(uint32_t, uint16_t); |
134 | static void iput(struct ext2fs_dinode *, ino_t); | | 134 | static void iput(struct ext2fs_dinode *, ino_t); |
135 | static void rdfs(daddr_t, int, void *); | | 135 | static void rdfs(daddr_t, int, void *); |
136 | static void wtfs(daddr_t, int, void *); | | 136 | static void wtfs(daddr_t, int, void *); |
137 | static int ilog2(uint); | | 137 | static int ilog2(uint); |
138 | static int skpc(int, size_t, uint8_t *); | | 138 | static int skpc(int, size_t, uint8_t *); |
139 | | | 139 | |
140 | /* XXX: some of these macro should be into <ufs/ext2fs/ext2fs.h>? */ | | 140 | /* XXX: some of these macro should be into <ufs/ext2fs/ext2fs.h>? */ |
| @@ -542,53 +542,57 @@ mke2fs(const char *fsys, int fi, int fo) | | | @@ -542,53 +542,57 @@ mke2fs(const char *fsys, int fi, int fo) |
542 | iobufsize = (NBLOCK_SUPERBLOCK + sblock.e2fs_ngdb) * sblock.e2fs_bsize; | | 542 | iobufsize = (NBLOCK_SUPERBLOCK + sblock.e2fs_ngdb) * sblock.e2fs_bsize; |
543 | iobuf = mmap(0, iobufsize, PROT_READ|PROT_WRITE, | | 543 | iobuf = mmap(0, iobufsize, PROT_READ|PROT_WRITE, |
544 | MAP_ANON|MAP_PRIVATE, -1, 0); | | 544 | MAP_ANON|MAP_PRIVATE, -1, 0); |
545 | if (iobuf == NULL) | | 545 | if (iobuf == NULL) |
546 | errx(EXIT_FAILURE, "Cannot allocate I/O buffer\n"); | | 546 | errx(EXIT_FAILURE, "Cannot allocate I/O buffer\n"); |
547 | memset(iobuf, 0, iobufsize); | | 547 | memset(iobuf, 0, iobufsize); |
548 | | | 548 | |
549 | /* | | 549 | /* |
550 | * We now start writing to the filesystem | | 550 | * We now start writing to the filesystem |
551 | */ | | 551 | */ |
552 | | | 552 | |
553 | if (!Nflag) { | | 553 | if (!Nflag) { |
554 | static const uint pbsize[] = { 1024, 2048, 4096, 0 }; | | 554 | static const uint pbsize[] = { 1024, 2048, 4096, 0 }; |
555 | uint pblock, epblock; | | 555 | uint pblock; |
556 | /* | | 556 | /* |
557 | * Validate the given file system size. | | 557 | * Validate the given file system size. |
558 | * Verify that its last block can actually be accessed. | | 558 | * Verify that its last block can actually be accessed. |
559 | * Convert to file system fragment sized units. | | 559 | * Convert to file system fragment sized units. |
560 | */ | | 560 | */ |
561 | if (fssize <= 0) | | 561 | if (fssize <= 0) |
562 | errx(EXIT_FAILURE, "Preposterous size %" PRId64 "\n", | | 562 | errx(EXIT_FAILURE, "Preposterous size %" PRId64 "\n", |
563 | fssize); | | 563 | fssize); |
564 | wtfs(fssize - 1, sectorsize, iobuf); | | 564 | wtfs(fssize - 1, sectorsize, iobuf); |
565 | | | 565 | |
566 | /* | | 566 | /* |
567 | * Ensure there is nothing that looks like a filesystem | | 567 | * Ensure there is nothing that looks like a filesystem |
568 | * superblock anywhere other than where ours will be. | | 568 | * superblock anywhere other than where ours will be. |
569 | * If fsck_ext2fs finds the wrong one all hell breaks loose! | | | |
570 | * | | 569 | * |
571 | * XXX: needs to check how fsck_ext2fs programs even | | 570 | * Ext2fs superblock is always placed at the same SBOFF, |
572 | * on other OSes determine alternate superblocks | | 571 | * so we just zap possible first backups. |
573 | */ | | 572 | */ |
574 | for (i = 0; pbsize[i] != 0; i++) { | | 573 | for (i = 0; pbsize[i] != 0; i++) { |
575 | epblock = (uint64_t)bcount * bsize / pbsize[i]; | | 574 | pblock = (pbsize[i] > BBSIZE) ? 0 : 1; /* 1st dblk */ |
576 | for (pblock = ((pbsize[i] == SBSIZE) ? 1 : 0); | | 575 | pblock += pbsize[i] * NBBY; /* next bg */ |
577 | pblock < epblock; | | 576 | /* zap first backup */ |
578 | pblock += pbsize[i] * NBBY /* bpg */) | | 577 | zap_old_sblock(pblock * pbsize[i]); |
579 | zap_old_sblock((daddr_t)pblock * | | | |
580 | pbsize[i] / sectorsize); | | | |
581 | } | | 578 | } |
| | | 579 | /* |
| | | 580 | * Also zap possbile FFS magic leftover to prevent |
| | | 581 | * kernel vfs_mountroot() and bootloadres from mis-recognizing |
| | | 582 | * this file system as FFS. |
| | | 583 | */ |
| | | 584 | zap_old_sblock(8192); /* SBLOCK_UFS1 */ |
| | | 585 | zap_old_sblock(65536); /* SBLOCK_UFS2 */ |
582 | } | | 586 | } |
583 | | | 587 | |
584 | if (verbosity >= 3) | | 588 | if (verbosity >= 3) |
585 | printf("super-block backups (for fsck_ext2fs -b #) at:\n"); | | 589 | printf("super-block backups (for fsck_ext2fs -b #) at:\n"); |
586 | /* If we are printing more than one line of numbers, line up columns */ | | 590 | /* If we are printing more than one line of numbers, line up columns */ |
587 | fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64, | | 591 | fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64, |
588 | (uint64_t)cgbase(&sblock, ncg - 1)); | | 592 | (uint64_t)cgbase(&sblock, ncg - 1)); |
589 | /* Get terminal width */ | | 593 | /* Get terminal width */ |
590 | if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0) | | 594 | if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0) |
591 | max_cols = winsize.ws_col; | | 595 | max_cols = winsize.ws_col; |
592 | else | | 596 | else |
593 | max_cols = 80; | | 597 | max_cols = 80; |
594 | if (Nflag && verbosity == 3) | | 598 | if (Nflag && verbosity == 3) |
| @@ -759,91 +763,92 @@ initcg(uint cylno) | | | @@ -759,91 +763,92 @@ initcg(uint cylno) |
759 | dp = (struct ext2fs_dinode *)(buf + inodesize * j); | | 763 | dp = (struct ext2fs_dinode *)(buf + inodesize * j); |
760 | /* h2fs32() just for consistency */ | | 764 | /* h2fs32() just for consistency */ |
761 | dp->e2di_gen = h2fs32(arc4random()); | | 765 | dp->e2di_gen = h2fs32(arc4random()); |
762 | } | | 766 | } |
763 | wtfs(fsbtodb(&sblock, gd[cylno].ext2bgd_i_tables + i), | | 767 | wtfs(fsbtodb(&sblock, gd[cylno].ext2bgd_i_tables + i), |
764 | sblock.e2fs_bsize, buf); | | 768 | sblock.e2fs_bsize, buf); |
765 | } | | 769 | } |
766 | } | | 770 | } |
767 | | | 771 | |
768 | /* | | 772 | /* |
769 | * Zap possible lingering old superblock data | | 773 | * Zap possible lingering old superblock data |
770 | */ | | 774 | */ |
771 | static void | | 775 | static void |
772 | zap_old_sblock(daddr_t sec) | | 776 | zap_old_sblock(int sblkoff) |
773 | { | | 777 | { |
774 | static daddr_t cg0_data; | | 778 | static int cg0_data; |
775 | uint32_t oldfs[SBSIZE / sizeof(uint32_t)]; | | 779 | uint32_t oldfs[SBSIZE / sizeof(uint32_t)]; |
776 | static const struct fsm { | | 780 | static const struct fsm { |
777 | uint32_t offset; | | 781 | uint32_t offset; |
778 | uint32_t magic; | | 782 | uint32_t magic; |
779 | uint32_t mask; | | 783 | uint32_t mask; |
780 | } fs_magics[] = { | | 784 | } fs_magics[] = { |
781 | {offsetof(struct ext2fs, e2fs_magic) / 4, E2FS_MAGIC, 0xffff}, | | 785 | {offsetof(struct ext2fs, e2fs_magic) / 4, E2FS_MAGIC, 0xffff}, |
782 | {offsetof(struct ext2fs, e2fs_magic) / 4, | | 786 | {offsetof(struct ext2fs, e2fs_magic) / 4, |
783 | E2FS_MAGIC << 16, 0xffff0000}, | | 787 | E2FS_MAGIC << 16, 0xffff0000}, |
784 | {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */ | | 788 | {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */ |
785 | {0x55c / 4, 0x00011954, ~0U}, /* FS_UFS1_MAGIC */ | | 789 | {0x55c / 4, 0x00011954, ~0U}, /* FS_UFS1_MAGIC */ |
786 | {0x55c / 4, 0x19540119, ~0U}, /* FS_UFS2_MAGIC */ | | 790 | {0x55c / 4, 0x19540119, ~0U}, /* FS_UFS2_MAGIC */ |
787 | {0, 0x70162, ~0U}, /* LFS_MAGIC */ | | 791 | {0, 0x70162, ~0U}, /* LFS_MAGIC */ |
788 | {.offset = ~0U}, | | 792 | {.offset = ~0U}, |
789 | }; | | 793 | }; |
790 | const struct fsm *fsm; | | 794 | const struct fsm *fsm; |
791 | | | 795 | |
792 | if (Nflag) | | 796 | if (Nflag) |
793 | return; | | 797 | return; |
794 | | | 798 | |
795 | /* don't override data before superblock */ | | 799 | /* don't override data before superblock */ |
796 | if (sec < SBOFF / sectorsize) | | 800 | if (sblkoff < SBOFF) |
797 | return; | | 801 | return; |
798 | | | 802 | |
799 | if (cg0_data == 0) { | | 803 | if (cg0_data == 0) { |
800 | cg0_data = | | 804 | cg0_data = |
801 | ((daddr_t)sblock.e2fs.e2fs_first_dblock + cgoverhead(0)) * | | 805 | ((daddr_t)sblock.e2fs.e2fs_first_dblock + cgoverhead(0)) * |
802 | sblock.e2fs_bsize / sectorsize; | | 806 | sblock.e2fs_bsize; |
803 | } | | 807 | } |
804 | | | 808 | |
805 | /* Ignore anything that is beyond our filesystem */ | | 809 | /* Ignore anything that is beyond our filesystem */ |
806 | if (sec >= fssize) | | 810 | if (sblkoff / sectorsize >= fssize) |
807 | return; | | 811 | return; |
808 | /* Zero anything inside our filesystem... */ | | 812 | /* Zero anything inside our filesystem... */ |
809 | if (sec >= sblock.e2fs.e2fs_first_dblock * bsize / sectorsize) { | | 813 | if (sblkoff >= sblock.e2fs.e2fs_first_dblock * bsize) { |
810 | /* ...unless we will write that area anyway */ | | 814 | /* ...unless we will write that area anyway */ |
811 | if (sec >= cg0_data) | | 815 | if (sblkoff >= cg0_data) |
812 | /* assume iobuf is zero'ed here */ | | 816 | /* assume iobuf is zero'ed here */ |
813 | wtfs(sec, roundup(SBSIZE, sectorsize), iobuf); | | 817 | wtfs(sblkoff / sectorsize, |
| | | 818 | roundup(SBSIZE, sectorsize), iobuf); |
814 | return; | | 819 | return; |
815 | } | | 820 | } |
816 | | | 821 | |
817 | /* | | 822 | /* |
818 | * The sector might contain boot code, so we must validate it | | 823 | * The sector might contain boot code, so we must validate it |
819 | * | | 824 | * |
820 | * XXX: ext2fs won't preserve data after SBOFF, | | 825 | * XXX: ext2fs won't preserve data after SBOFF, |
821 | * but first_dblock could have a different value. | | 826 | * but first_dblock could have a different value. |
822 | */ | | 827 | */ |
823 | rdfs(sec, sizeof(oldfs), &oldfs); | | 828 | rdfs(sblkoff / sectorsize, sizeof(oldfs), &oldfs); |
824 | for (fsm = fs_magics;; fsm++) { | | 829 | for (fsm = fs_magics;; fsm++) { |
825 | uint32_t v; | | 830 | uint32_t v; |
826 | if (fsm->mask == 0) | | 831 | if (fsm->mask == 0) |
827 | return; | | 832 | return; |
828 | v = oldfs[fsm->offset]; | | 833 | v = oldfs[fsm->offset]; |
829 | if ((v & fsm->mask) == fsm->magic || | | 834 | if ((v & fsm->mask) == fsm->magic || |
830 | (bswap32(v) & fsm->mask) == fsm->magic) | | 835 | (bswap32(v) & fsm->mask) == fsm->magic) |
831 | break; | | 836 | break; |
832 | } | | 837 | } |
833 | | | 838 | |
834 | /* Just zap the magic number */ | | 839 | /* Just zap the magic number */ |
835 | oldfs[fsm->offset] = 0; | | 840 | oldfs[fsm->offset] = 0; |
836 | wtfs(sec, sizeof(oldfs), &oldfs); | | 841 | wtfs(sblkoff / sectorsize, sizeof(oldfs), &oldfs); |
837 | } | | 842 | } |
838 | | | 843 | |
839 | /* | | 844 | /* |
840 | * uint cgoverhead(uint c) | | 845 | * uint cgoverhead(uint c) |
841 | * | | 846 | * |
842 | * Return a number of reserved blocks on the specified group. | | 847 | * Return a number of reserved blocks on the specified group. |
843 | * XXX: should be shared with src/sbin/fsck_ext2fs/setup.c | | 848 | * XXX: should be shared with src/sbin/fsck_ext2fs/setup.c |
844 | */ | | 849 | */ |
845 | uint | | 850 | uint |
846 | cgoverhead(uint c) | | 851 | cgoverhead(uint c) |
847 | { | | 852 | { |
848 | uint overh; | | 853 | uint overh; |
849 | | | 854 | |