mkfs.mfs -I: insert fs at offset feature

. use it in x86_hdimage.sh:
	  avoid copying big FS images into iso & hd images each time

Change-Id: I0775f43cd1821ea7be2fec5b96d107a68afb96d6
This commit is contained in:
Ben Gras 2013-11-07 08:33:39 +01:00
parent 09143af258
commit 8dbe32610b
3 changed files with 121 additions and 104 deletions

View file

@ -28,12 +28,6 @@ fi
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
#
# Artifacts from this script are stored in the IMG_DIR
#
rm -rf $IMG_DIR $IMG
mkdir -p $IMG_DIR $CDFILES
while getopts "i" c
do
case "$c" in
@ -45,6 +39,12 @@ done
: ${IMG=minix_x86.img}
#
# Artifacts from this script are stored in the IMG_DIR
#
rm -rf $IMG_DIR $IMG
mkdir -p $IMG_DIR $CDFILES
#
# Call build.sh using a sloppy file list so we don't need to remove the installed /etc/fstag
#
@ -56,24 +56,13 @@ then cp ${DESTDIR}/usr/mdec/boot_monitor $CDFILES/boot
cp ${MODDIR}/* $CDFILES/
. ./releasetools/release.functions
cd_root_changes # uses $CDFILES and writes $CDFILES/boot.cfg
${CROSS_TOOLS}/nbwriteisofs -s0x0 -l MINIX -B ${DESTDIR}/usr/mdec/bootxx_cd9660 -n $CDFILES ${IMG_DIR}/iso.img
ISO_SIZE=$((`stat -c %s ${IMG_DIR}/iso.img` / 512))
# start the image off with the iso image; reduce root size to reserve
${CROSS_TOOLS}/nbwriteisofs -s0x0 -l MINIX -B ${DESTDIR}/usr/mdec/bootxx_cd9660 -n $CDFILES $IMG
ISO_SIZE=$((`stat -c %s $IMG` / 512))
else # just make an empty iso partition
ISO_SIZE=8
fi
# This script creates a bootable image and should at some point in the future
# be replaced by makefs.
#
# All sized are written in 512 byte blocks
#
# we create a disk image of about 2 gig's
# for alignment reasons, prefer sizes which are multiples of 4096 bytes
#
: ${ROOT_SIZE=$(( 64*(2**20) / 512))}
: ${HOME_SIZE=$(( 128*(2**20) / 512))}
: ${USR_SIZE=$((1536*(2**20) / 512))}
#
# create a fstab entry in /etc this is normally done during the
# setup phase on x86
@ -87,15 +76,6 @@ rm -f ${DESTDIR}/SETS.*
${CROSS_TOOLS}/nbpwd_mkdb -V 0 -p -d ${DESTDIR} ${DESTDIR}/etc/master.passwd
#
# Now given the sizes above use DD to create separate files representing
# the partitions we are going to use.
#
dd if=/dev/zero of=${IMG_DIR}/iso.img bs=512 count=1 seek=$(($ISO_SIZE -1)) 2>/dev/null
dd if=/dev/zero of=${IMG_DIR}/root.img bs=512 count=1 seek=$(($ROOT_SIZE -1)) 2>/dev/null
dd if=/dev/zero of=${IMG_DIR}/home.img bs=512 count=1 seek=$(($HOME_SIZE -1)) 2>/dev/null
dd if=/dev/zero of=${IMG_DIR}/usr.img bs=512 count=1 seek=$(($USR_SIZE -1)) 2>/dev/null
# make the different file system. this part is *also* hacky. We first convert
# the METALOG.sanitised using mtree into a input METALOG containing uids and
# gids.
@ -133,54 +113,48 @@ rm ${IMG_DIR}/root.in
cat ${IMG_DIR}/input | grep "^\./usr/\|^. " | sed "s,\./usr,\.,g" | ${CROSS_TOOLS}/nbtoproto -b ${DESTDIR}/usr -o ${IMG_DIR}/usr.proto
cat ${IMG_DIR}/input | grep "^\./home/\|^. " | sed "s,\./home,\.,g" | ${CROSS_TOOLS}/nbtoproto -b ${DESTDIR}/home -o ${IMG_DIR}/home.proto
# If in ISO mode, fit the FSes
# This script creates a bootable image and should at some point in the future
# be replaced by makefs.
#
# All sized are written in 512 byte blocks
#
# we create a disk image of about 2 gig's
# for alignment reasons, prefer sizes which are multiples of 4096 bytes
#
: ${ROOT_SIZE=$(( 64*(2**20) / 512))}
: ${HOME_SIZE=$(( 128*(2**20) / 512))}
: ${USR_SIZE=$(( 1536*(2**20) / 512))}
if [ "$ISOMODE" ]
then ROOTSIZEARG="-x 5" # give root fs a little breathing room on the CD
else # give args with the right sizes
then
# In iso mode, make all FSes fit (i.e. as small as possible), but
# leave some space on /
ROOTSIZEARG="-x 5"
else
# In hd image mode, FSes have fixed sizes
ROOTSIZEARG="-b $((${ROOT_SIZE} / 8))"
USRSIZEARG="-b $((${USR_SIZE} / 8))"
HOMESIZEARG="-b $((${HOME_SIZE} / 8))"
fi
#
# Generate /root, /usr and /home partition images.
#
echo "Writing Minix filesystem images"
echo " - ROOT"
${CROSS_TOOLS}/nbmkfs.mfs $ROOTSIZEARG ${IMG_DIR}/root.img ${IMG_DIR}/root.proto
echo " - USR"
${CROSS_TOOLS}/nbmkfs.mfs $USRSIZEARG ${IMG_DIR}/usr.img ${IMG_DIR}/usr.proto
echo " - HOME"
${CROSS_TOOLS}/nbmkfs.mfs $HOMESIZEARG ${IMG_DIR}/home.img ${IMG_DIR}/home.proto
# Set the sizes based on what was just generated - should change nothing if sizes
# were specified
echo "$ROOT_SIZE $USR_SIZE $HOME_SIZE"
ROOT_SIZE=$((`stat -c %s ${IMG_DIR}/root.img` / 512))
USR_SIZE=$((`stat -c %s ${IMG_DIR}/usr.img` / 512))
HOME_SIZE=$((`stat -c %s ${IMG_DIR}/home.img` / 512))
echo "$ROOT_SIZE $USR_SIZE $HOME_SIZE"
# Do some math to determine the start addresses of the partitions.
# Ensure the start of the partitions are always aligned, the end will
# always be as we assume the sizes are multiples of 4096 bytes, which
# is always true as soon as you have an integer multiple of 1MB.
#
ISO_START=0
ROOT_START=$(($ISO_START + $ISO_SIZE))
ROOT_START=$ISO_SIZE
echo " - ROOT"
ROOT_SIZE=$((`${CROSS_TOOLS}/nbmkfs.mfs -d $ROOTSIZEARG -I $(($ROOT_START*512)) $IMG ${IMG_DIR}/root.proto`/512))
USR_START=$(($ROOT_START + $ROOT_SIZE))
echo " - USR"
USR_SIZE=$((`${CROSS_TOOLS}/nbmkfs.mfs -d $USRSIZEARG -I $(($USR_START*512)) $IMG ${IMG_DIR}/usr.proto`/512))
HOME_START=$(($USR_START + $USR_SIZE))
echo " - HOME"
HOME_SIZE=$((`${CROSS_TOOLS}/nbmkfs.mfs -d $HOMESIZEARG -I $(($HOME_START*512)) $IMG ${IMG_DIR}/home.proto`/512))
#
# Merge the partitions into a single image.
#
echo "Merging file systems"
dd if=${IMG_DIR}/iso.img of=${IMG} seek=$ISO_START conv=notrunc
dd if=${IMG_DIR}/root.img of=${IMG} seek=$ROOT_START conv=notrunc
dd if=${IMG_DIR}/usr.img of=${IMG} seek=$USR_START conv=notrunc
dd if=${IMG_DIR}/home.img of=${IMG} seek=$HOME_START conv=notrunc
${CROSS_TOOLS}/nbpartition -m ${IMG} ${ISO_START} 81:${ISO_SIZE} 81:${ROOT_SIZE} 81:${USR_SIZE} 81:${HOME_SIZE}
${CROSS_TOOLS}/nbpartition -m ${IMG} 0 81:${ISO_SIZE} 81:${ROOT_SIZE} 81:${USR_SIZE} 81:${HOME_SIZE}
mods="`( cd $MODDIR; echo mod* | tr ' ' ',' )`"
if [ "$ISOMODE" ]

View file

@ -52,7 +52,6 @@
#if !defined(__minix)
#define mul64u(a,b) ((uint64_t)(a) * (b))
#define lseek64(a,b,c,d) lseek(a,b,c)
#endif
/* some Minix specific types that do not conflict with Posix */
@ -88,6 +87,7 @@ int lct = 0, fd, print = 0;
int simple = 0, dflag = 0, verbose = 0;
int donttest; /* skip test if it fits on medium */
char *progname;
uint64_t fs_offset_bytes, fs_offset_blocks, written_fs_size = 0;
time_t current_time;
char *zero;
@ -128,11 +128,13 @@ __dead void pexit(char const *s, ...) __printflike(1,2);
void *alloc_block(void);
void print_fs(void);
int read_and_set(block_t n);
void special(char *string);
void special(char *string, int insertmode);
__dead void usage(void);
void get_block(block_t n, void *buf);
void get_super_block(void *buf);
void put_block(block_t n, void *buf);
static uint64_t mkfs_seek(uint64_t pos, int whence);
static ssize_t mkfs_write(void * buf, size_t count);
/*================================================================
* mkfs - make filesystem
@ -145,6 +147,7 @@ main(int argc, char *argv[])
ino_t inodes, root_inum;
char *token[MAX_TOKENS], line[LINE_LEN], *sfx;
struct fs_size fssize;
int insertmode = 0;
progname = argv[0];
@ -157,7 +160,7 @@ main(int argc, char *argv[])
#endif
zone_shift = 0;
extra_space_percent = 0;
while ((ch = getopt(argc, argv, "B:b:di:ltvx:z:")) != EOF)
while ((ch = getopt(argc, argv, "B:b:di:ltvx:z:I:")) != EOF)
switch (ch) {
#ifndef MFS_STATIC_BLOCK_SIZE
case 'B':
@ -179,6 +182,10 @@ main(int argc, char *argv[])
break;
(void)sfx; /* shut up warnings about unused variable...*/
#endif
case 'I':
fs_offset_bytes = strtoul(optarg, (char **) NULL, 0);
insertmode = 1;
break;
case 'b':
blocks = bblocks = strtoul(optarg, (char **) NULL, 0);
break;
@ -253,9 +260,11 @@ main(int argc, char *argv[])
*/
zero = alloc_block();
fs_offset_blocks = roundup(fs_offset_bytes, block_size) / block_size;
/* Determine the size of the device if not specified as -b or proto. */
maxblocks = sizeup(argv[optind]);
if (bblocks != 0 && bblocks > maxblocks){
if (bblocks != 0 && bblocks + fs_offset_blocks > maxblocks && !insertmode) {
errx(4, "Given size -b %d exeeds device capacity(%d)\n", bblocks, maxblocks);
}
@ -274,7 +283,7 @@ main(int argc, char *argv[])
*/
if (argc - optind != 2 && (argc - optind != 1 || blocks == 0)) usage();
if (maxblocks && blocks > maxblocks) {
if (maxblocks && blocks > maxblocks && !insertmode) {
errx(1, "%s: number of blocks too large for device.", argv[optind]);
}
@ -315,7 +324,7 @@ main(int argc, char *argv[])
blocks += blocks*extra_space_percent/100;
inodes += inodes*extra_space_percent/100;
/* XXX is it OK to write on stdout? Use warn() instead? Also consider using verbose */
printf("dynamically sized filesystem: %u blocks, %u inodes\n",
fprintf(stderr, "dynamically sized filesystem: %u blocks, %u inodes\n",
(unsigned int) blocks, (unsigned int) inodes);
}
} else {
@ -362,7 +371,7 @@ main(int argc, char *argv[])
(unsigned)umap_array_elements);
/* Open special. */
special(argv[--optind]);
special(argv[--optind], insertmode);
if (!donttest) {
uint16_t *testb;
@ -371,19 +380,13 @@ main(int argc, char *argv[])
testb = alloc_block();
/* Try writing the last block of partition or diskette. */
if(lseek64(fd, mul64u(blocks - 1, block_size), SEEK_SET, NULL) < 0) {
err(1, "couldn't seek to last block to test size (1)");
}
mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET);
testb[0] = 0x3245;
testb[1] = 0x11FF;
testb[block_size/2-1] = 0x1F2F;
if ((w=write(fd, testb, block_size)) != block_size)
err(1, "File system is too big for minor device (write1 %d/%u)",
w, block_size);
w=mkfs_write(testb, block_size);
sync(); /* flush write, so if error next read fails */
if(lseek64(fd, mul64u(blocks - 1, block_size), SEEK_SET, NULL) < 0) {
err(1, "couldn't seek to last block to test size (2)");
}
mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET);
testb[0] = 0;
testb[1] = 0;
testb[block_size/2-1] = 0;
@ -395,13 +398,12 @@ main(int argc, char *argv[])
testb[0], testb[1], testb[block_size-1]);
errx(1, "File system is too big for minor device (read)");
}
lseek64(fd, mul64u(blocks - 1, block_size), SEEK_SET, NULL);
mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET);
testb[0] = 0;
testb[1] = 0;
testb[block_size/2-1] = 0;
if (write(fd, testb, block_size) != block_size)
err(1, "File system is too big for minor device (write2)");
lseek(fd, 0L, SEEK_SET);
mkfs_write(testb, block_size);
mkfs_seek(0L, SEEK_SET);
free(testb);
}
@ -426,6 +428,8 @@ main(int argc, char *argv[])
(int)next_inode-1, next_zone);
}
if(insertmode) printf("%ld\n", written_fs_size);
return(0);
/* NOTREACHED */
@ -560,9 +564,7 @@ sizeup(char * device)
progname, (unsigned long)d);
}
#else
size = lseek(fd, 0, SEEK_END);
if (size == (off_t) -1)
err(1, "cannot get device size fd=%d: %s", fd, device);
size = mkfs_seek(0, SEEK_END);
/* Assume block_t is unsigned */
if (size / block_size > (block_t)(-1ul)) {
d = (block_t)(-1ul);
@ -691,10 +693,8 @@ super(zone_t zones, ino_t inodes)
#endif
}
if (lseek(fd, (off_t) SUPER_BLOCK_BYTES, SEEK_SET) == (off_t) -1)
err(1, "super() couldn't seek");
if (write(fd, buf, SUPER_BLOCK_BYTES) != SUPER_BLOCK_BYTES)
err(1, "super() couldn't write");
mkfs_seek((off_t) SUPER_BLOCK_BYTES, SEEK_SET);
mkfs_write(buf, SUPER_BLOCK_BYTES);
/* Clear maps and inodes. */
for (i = START_BLOCK; i < initblks; i++) put_block((block_t) i, zero);
@ -1541,19 +1541,20 @@ read_and_set(block_t n)
__dead void
usage(void)
{
fprintf(stderr, "Usage: %s [-dltv] [-b blocks] [-i inodes] [-z zone_shift]\n"
"\t[-x extra] [-B blocksize] special [proto]\n",
fprintf(stderr, "Usage: %s [-dltv] [-b blocks] [-i inodes]\n"
"\t[-z zone_shift] [-I offset] [-x extra] [-B blocksize] special [proto]\n",
progname);
exit(4);
}
void
special(char * string)
special(char * string, int insertmode)
{
fd = creat(string, 0777);
close(fd);
fd = open(string, O_RDWR);
int openmode = O_RDWR;
if(!insertmode) openmode |= O_TRUNC;
fd = open(string, O_RDWR | O_CREAT, 0644);
if (fd < 0) err(1, "Can't open special file %s", string);
mkfs_seek(0, SEEK_SET);
}
@ -1569,8 +1570,7 @@ get_block(block_t n, void *buf)
memcpy(buf, zero, block_size);
return;
}
if (lseek64(fd, mul64u(n, block_size), SEEK_SET, NULL) == (off_t)(-1))
pexit("get_block couldn't seek");
mkfs_seek(mul64u(n, block_size), SEEK_SET);
k = read(fd, buf, block_size);
if (k != block_size)
pexit("get_block couldn't read block #%u", (unsigned)n);
@ -1582,8 +1582,7 @@ get_super_block(void *buf)
{
ssize_t k;
if(lseek(fd, (off_t) SUPER_BLOCK_BYTES, SEEK_SET) == (off_t) -1)
err(1, "seek for superblock failed");
mkfs_seek((off_t) SUPER_BLOCK_BYTES, SEEK_SET);
k = read(fd, buf, SUPER_BLOCK_BYTES);
if (k != SUPER_BLOCK_BYTES)
err(1, "get_super_block couldn't read super block");
@ -1596,8 +1595,49 @@ put_block(block_t n, void *buf)
(void) read_and_set(n);
if (lseek64(fd, mul64u(n, block_size), SEEK_SET, NULL) == (off_t) -1)
pexit("put_block couldn't seek");
if (write(fd, buf, block_size)!= block_size)
pexit("put_block couldn't write block #%u", (unsigned)n);
mkfs_seek(mul64u(n, block_size), SEEK_SET);
mkfs_write(buf, block_size);
}
static ssize_t
mkfs_write(void * buf, size_t count)
{
uint64_t fssize;
ssize_t w;
/* Perform & check write */
w = write(fd, buf, count);
if(w < 0)
err(1, "mkfs_write: write failed");
if(w != count)
errx(1, "mkfs_write: short write: %ld != %ld", w, count);
/* Check if this has made the FS any bigger; count bytes after offset */
fssize = mkfs_seek(0, SEEK_CUR);
assert(fssize >= fs_offset_bytes);
fssize -= fs_offset_bytes;
fssize = roundup(fssize, block_size);
if(fssize > written_fs_size)
written_fs_size = fssize;
return w;
}
/* Seek to position in FS we're creating. */
static uint64_t
mkfs_seek(uint64_t pos, int whence)
{
if(whence == SEEK_SET) pos += fs_offset_bytes;
#ifdef __minix
uint64_t newpos;
if((lseek64(fd, pos, whence, &newpos)) < 0)
err(1, "mkfs_seek: lseek64 failed");
return newpos;
#else
off_t newpos;
if((newpos=lseek(fd, pos, whence)) == (off_t) -1)
err(1, "mkfs_seek: lseek failed");
return newpos;
#endif
}

View file

@ -12,6 +12,7 @@
.Op Fl b Ar blocks
.Op Fl z Ar zone_shift
.Op Fl x Ar extra_space
.Op Fl I Ar fs_offset
.Ar special
.Op Ar prototype
.Sh OPTIONS
@ -35,6 +36,8 @@ Number of i-nodes (files)
Filesystem block size (in bytes)
.It Fl b Ar blocks
Filesystem size (in blocks)
.It Fl I Ar fs_offset
Write filesystem starting at offset (in bytes)
.It Fl x Ar extra_space
Extra space after dynamic sizing (blocks and inodes)
.It Fl z Ar zone_shift
@ -118,4 +121,4 @@ For special files, the major and minor devices are needed.
The
.Nm
utility was written by
.An Andy Tanenbaum, Paul Ogilvie, Frans Meulenbroeks, Bruce Evans
.An Andy Tanenbaum, Paul Ogilvie, Frans Meulenbroeks, Bruce Evans