Commit 0063d2c4 authored by Mike Hibler's avatar Mike Hibler

Introducing imagezip redux!

Ok, not really any fundamental changes, mostly a source reorganization,
but some new features as well:

1. Split off FS specific code for all FS types into subdirectories.
   imagezip.c was just getting unwieldy.  You can now (in theory, I
   haven't enabled this in any easy way) build a version of imagezip
   with only the FSes you care about.

2. As part of the above, localize the filesystem specific headers in
   the subdirs instead of relying on the installed system headers.
   This allows easy building of, for example, BSD FS support under
   Linux.

3. Hacked up the GNUmakefiles some so that imagezip with all FS support
   will build (in the Emulab context) under Linux and FreeBSD 5.1 as
   well as FreeBSD 4.x.  Still a hack, for Linux you need to first do:
	setenv LINUX 1
	setenv HAVE_GCC3 1
	setenv HAVE_LOCALE 1
   and for FreeBSD 5.x:
	setenv HAVE_GCC3 1
	setenv HAVE_LOCALE 1
   these trigger ifdefs in some of the Makefiles to DTRT.  Imagezip
   and frisbee still need a standalone configure...

4. Added support for UFS2 (aka FreeBSD 5.x default filesystems).

5. Added "-S dos-type" option to imagezip.  This is the general form
   of the -b, -l, and -n options to force imagezip to treat the device
   as though it contains a filesystem of the indicated type.
parent ccf23ccb
......@@ -14,50 +14,73 @@ DISTFILES = ext2_fs.h imagehdr.h linux_types.h queue.h \
imageunzip.c crc.c imageunzip.8
EXPANDCOPYRIGHT = /usr/site/lib/copyright/expand-copyr
WITH_FFS = 1
WITH_EXTFS = 1
WITH_NTFS = @WINSUPPORT@
WITH_FAT = @WINSUPPORT@
include $(OBJDIR)/Makeconf
SUBDIRCFLAGS = -Wall -O2 -g -I$(SRCDIR)
ifdef LINUX
SUBDIRCFLAGS += -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_THREAD_SAFE -pthread
else
PTHREADCFLAGS = -D_THREAD_SAFE \
-I/usr/local/include/pthread/linuxthreads
SUBDIRCFLAGS +=
PTHREADLIBS = -L/usr/local/lib -llthread -llgcc_r
endif
# Define this if you implementation of cond_vars works well
# They don't with linuxthreads under FreeBSD: wakeups take longer than
# Necessary sometimes.
#PTHREADCFLAGS += -DCONDVARS_WORK
CFLAGS = -Wall -O2 -g -static
CFLAGS = $(SUBDIRCFLAGS) -static
LIBS = -lz $(PTHREADLIBS)
UNZIPCFLAGS = $(CFLAGS) $(PTHREADCFLAGS) -Wall
UNZIPLIBS = $(LIBS) $(PTHREADLIBS)
# UFS/UFS2
ifeq ($(WITH_FFS),1)
CFLAGS += -DWITH_FFS
SUBDIRS += ffs
FSLIBS += ffs/libffs.a
endif
# EXT2/EXT3
ifeq ($(WITH_EXTFS),1)
CFLAGS += -DWITH_EXTFS
SUBDIRS += extfs
FSLIBS += extfs/libextfs.a
endif
# with NTFS
ifeq ($(WITH_NTFS),1)
ifndef HAVE_GCC3
CC = gcc30
INCS = -I$(SRCDIR)/ntfs/extra_bsd_includes \
-I$(SRCDIR)/liblocale/include \
-Intfs/libntfs/ntfsprogs/include \
-I$(SRCDIR)
CFLAGS += -DWITH_NTFS $(INCS)
LIBS += -Lntfs -lntfs -llocale
NTFSDIR = ntfs
endif
CFLAGS += -DWITH_NTFS
SUBDIRS += ntfs
FSLIBS += ntfs/libntfs.a
ifndef HAVE_LOCALE
FSLIBS += ntfs/liblocale.a
endif
endif
# with FAT
ifeq ($(WITH_FAT),1)
CFLAGS += -DWITH_FAT
FSOBJS += fat_boot.o fat_fat.o fat_glue.o
MOSTLY_SRCDIRS += $(SRCDIR)/fat
SUBDIRS += fat
FSLIBS += fat/libfat.a
endif
all: imagezip imageunzip imagedump
all: $(SUBDIRS) imagezip imageunzip imagedump
include $(TESTBED_SRCDIR)/GNUmakerules
imagezip: $(NTFSDIR) imagezip.o version.o $(FSOBJS)
$(CC) $(CFLAGS) imagezip.o version.o $(FSOBJS) $(LIBS) -o imagezip
imagezip: imagezip.o version.o $(FSLIBS)
$(CC) $(CFLAGS) imagezip.o version.o $(LIBS) $(FSLIBS) -o imagezip
imageunzip: imageunzip.o crc.o version.o
$(CC) $(CFLAGS) imageunzip.o crc.o version.o $(UNZIPLIBS) -o imageunzip
......@@ -68,10 +91,11 @@ imageunzip.o: imageunzip.c
imagedump: imagedump.o version.o
$(CC) $(CFLAGS) imagedump.o version.o $(LIBS) -o imagedump
fat_boot.o fat_fat.o fat_glue.o: $(SRCDIR)/fat/fat_glue.h
ffs extfs ntfs fat:
@$(MAKE) SUBDIRCFLAGS="$(SUBDIRCFLAGS)" -C $@ all
ntfs:
@$(MAKE) -C ntfs all
imagezip.o: sliceinfo.h imagehdr.h global.h
imageunzip.o: imagehdr.h
version.c: imagezip.c imageunzip.c imagedump.c
echo >$@ "char build_info[] = \"Built `date +%d-%b-%Y` by `id -nu`@`hostname | sed 's/\..*//'`:`pwd`\";"
......@@ -84,13 +108,16 @@ client-install:
$(INSTALL_PROGRAM) imageunzip $(DESTDIR)/usr/local/bin/imageunzip
$(INSTALL_PROGRAM) imagedump $(DESTDIR)/usr/local/bin/imagedump
clean:
@if [ -d ntfs ]; then \
$(MAKE) -C ntfs clean; \
fi;
clean: subdir-clean
/bin/rm -f *.o imagezip imageunzip imagedump version.c
/bin/rm -f imagezip.tar imagezip.tar.gz
subdir-clean:
@$(MAKE) -C ffs clean
@$(MAKE) -C extfs clean
@$(MAKE) -C ntfs clean
@$(MAKE) -C fat clean
imagezip.tar.gz: imagezip.tar
gzip -c imagezip.tar > imagezip.tar.gz
......@@ -105,4 +132,4 @@ imagezip.tar: Makefile.sa Makefile-linux.sa $(DISTFILES)
tar cf imagezip.tar imagezip-dist
rm -rf imagezip-dist
.PHONY: $(NTFSDIR)
.PHONY: $(SUBDIRS)
......@@ -13,6 +13,7 @@ Things to do for image*:
for doing output.
3. In imagezip, split out the FS-specific code into subdirectories.
[DONE]
4. Write an imageconvert so that we can convert old version images into
new ones and maybe change the compression level used in an image.
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../../..
SUBDIR = os/imagezip/extfs
MAINDIR = $(SRCDIR)/..
include $(OBJDIR)/Makeconf
CFLAGS += $(SUBDIRCFLAGS) -I$(SRCDIR)
all: libextfs.a
include $(TESTBED_SRCDIR)/GNUmakerules
OBJS = extfs.o
extfs.o: $(MAINDIR)/sliceinfo.h $(MAINDIR)/global.h
libextfs.a: $(OBJS)
$(AR) $(ARFLAGS) $@ $?
$(RANLIB) $@
install:
clean:
rm -f libextfs.a $(OBJS)
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2003 University of Utah and the Flux Group.
* All rights reserved.
*/
#include <stdio.h>
#include <err.h>
#include <assert.h>
#include <sys/param.h>
#include <ext2_fs.h>
#include "sliceinfo.h"
#include "global.h"
static int read_linuxgroup(struct ext2_super_block *super,
struct ext2_group_desc *group, int index,
u_int32_t sliceoffset, int infd);
/*
* Operate on a linux slice. I actually don't have a clue what a linux
* slice looks like. I just know that in our images, the linux slice
* has the boot block in the first sector, part of the boot in the
* second sector, and then the superblock for the one big filesystem
* in the 3rd sector. Just start there and move on.
*
* Unlike BSD partitions, linux block offsets are from the start of the
* slice, so we have to add the starting sector to everything.
*/
int
read_linuxslice(int slice, int stype, u_int32_t start, u_int32_t size,
char *sname, int infd)
{
#define LINUX_SUPERBLOCK_OFFSET 1024
#define LINUX_SUPERBLOCK_SIZE 1024
#define LINUX_MAXGRPSPERBLK \
(EXT2_MAX_BLOCK_SIZE/sizeof(struct ext2_group_desc))
int cc, i, numgroups, rval = 0;
struct ext2_super_block fs;
struct ext2_group_desc groups[LINUX_MAXGRPSPERBLK];
int dosslice = slice + 1; /* DOS Numbering */
off_t soff;
assert((sizeof(fs) & ~LINUX_SUPERBLOCK_SIZE) == 0);
assert((sizeof(groups) & ~EXT2_MAX_BLOCK_SIZE) == 0);
if (debug)
fprintf(stderr, " P%d (Linux Slice)\n", dosslice);
/*
* Skip ahead to the superblock.
*/
if (devlseek(infd, sectobytes(start) + LINUX_SUPERBLOCK_OFFSET,
SEEK_SET) < 0) {
warnx("Linux Slice %d: Could not seek to superblock",
dosslice);
return 1;
}
if ((cc = devread(infd, &fs, LINUX_SUPERBLOCK_SIZE)) < 0) {
warn("Linux Slice %d: Could not read superblock", dosslice);
return 1;
}
if (cc != LINUX_SUPERBLOCK_SIZE) {
warnx("Linux Slice %d: Truncated superblock", dosslice);
return 1;
}
if (fs.s_magic != EXT2_SUPER_MAGIC) {
warnx("Linux Slice %d: Bad magic number in superblock",
dosslice);
return (1);
}
if (EXT2_BLOCK_SIZE(&fs) < EXT2_MIN_BLOCK_SIZE ||
EXT2_BLOCK_SIZE(&fs) > EXT2_MAX_BLOCK_SIZE) {
warnx("Linux Slice %d: Block size not what I expect it to be: %d!",
dosslice, EXT2_BLOCK_SIZE(&fs));
return 1;
}
numgroups = ((fs.s_blocks_count - fs.s_first_data_block)
+ (fs.s_blocks_per_group - 1))
/ fs.s_blocks_per_group;
if (debug) {
fprintf(stderr, " %s\n",
(fs.s_feature_compat & 4) ? "EXT3" : "EXT2");
fprintf(stderr, " count %9u, size %9d, pergroup %9d\n",
fs.s_blocks_count, EXT2_BLOCK_SIZE(&fs),
fs.s_blocks_per_group);
fprintf(stderr, " bfree %9u, first %9u, groups %9d\n",
fs.s_free_blocks_count, fs.s_first_data_block,
numgroups);
}
/*
* Read each group descriptor. It says where the free block bitmap
* lives. The absolute block numbers a group descriptor refers to
* is determined by its index * s_blocks_per_group. Once we know where
* the bitmap lives, we can go out to the bitmap and see what blocks
* are free.
*
* Group descriptors are in the blocks right after the superblock.
*/
assert(LINUX_SUPERBLOCK_SIZE <= EXT2_BLOCK_SIZE(&fs));
assert(EXT2_DESC_PER_BLOCK(&fs) * sizeof(struct ext2_group_desc)
== EXT2_BLOCK_SIZE(&fs));
soff = sectobytes(start) +
(fs.s_first_data_block + 1) * EXT2_BLOCK_SIZE(&fs);
for (i = 0; i < numgroups; i++) {
int gix;
/*
* Read the group descriptors in groups since they are
* smaller than a sector size, packed into EXT2_BLOCK_SIZE
* blocks right after the superblock.
*/
gix = (i % EXT2_DESC_PER_BLOCK(&fs));
if (gix == 0) {
if (devlseek(infd, soff, SEEK_SET) < 0) {
warnx("Linux Slice %d: "
"Could not seek to Group %d",
dosslice, i);
return 1;
}
if ((cc = devread(infd, groups, sizeof(groups))) < 0) {
warn("Linux Slice %d: "
"Could not read Group %d",
dosslice, i);
return 1;
}
if (cc != sizeof(groups)) {
warnx("Linux Slice %d: "
"Truncated Group %d", dosslice, i);
return 1;
}
soff += EXT2_BLOCK_SIZE(&fs);
}
if (debug) {
fprintf(stderr,
" Group:%-2d\tBitmap %9u, bfree %9d\n",
i, groups[gix].bg_block_bitmap,
groups[gix].bg_free_blocks_count);
}
if ((rval = read_linuxgroup(&fs, &groups[gix], i, start, infd)))
return rval;
}
return 0;
}
/*
* A group descriptor says where on the disk the block bitmap is. Its
* a 1bit per block map, where each bit is a FS block (instead of a
* fragment like in BSD). Since linux offsets are relative to the start
* of the slice, need to adjust the numbers using the slice offset.
*/
static int
read_linuxgroup(struct ext2_super_block *super,
struct ext2_group_desc *group,
int index,
u_int32_t sliceoffset /* Sector offset of slice */,
int infd)
{
char *p, bitmap[EXT2_MAX_BLOCK_SIZE];
int i, cc, max;
int count, j, freecount;
off_t offset;
unsigned long block;
block = super->s_first_data_block +
(index * super->s_blocks_per_group);
/*
* Sanity check the bitmap block numbers
*/
if (group->bg_block_bitmap < block ||
group->bg_block_bitmap >= block + super->s_blocks_per_group) {
warnx("Linux Group %d: "
"Group bitmap block (%d) out of range [%lu-%lu]",
index, group->bg_block_bitmap,
block, block + super->s_blocks_per_group - 1);
return 1;
}
offset = sectobytes(sliceoffset);
offset += (off_t)EXT2_BLOCK_SIZE(super) * group->bg_block_bitmap;
if (devlseek(infd, offset, SEEK_SET) < 0) {
warn("Linux Group %d: "
"Could not seek to Group bitmap block %d",
index, group->bg_block_bitmap);
return 1;
}
/*
* Sanity check this number since it the number of blocks in
* the group (bitmap size) is dependent on the block size.
*/
if (super->s_blocks_per_group > (EXT2_BLOCK_SIZE(super) * 8)) {
warnx("Linux Group %d: "
"Block count not what I expect it to be: %d!",
index, super->s_blocks_per_group);
return 1;
}
if ((cc = devread(infd, bitmap, EXT2_BLOCK_SIZE(super))) < 0) {
warn("Linux Group %d: "
"Could not read Group bitmap", index);
return 1;
}
if (cc != EXT2_BLOCK_SIZE(super)) {
warnx("Linux Group %d: Truncated Group bitmap", index);
return 1;
}
/*
* The final group may have fewer than s_blocks_per_group
*/
max = super->s_blocks_count - block;
if (max > super->s_blocks_per_group)
max = super->s_blocks_per_group;
else if (debug && max != super->s_blocks_per_group)
fprintf(stderr,
" Linux Group %d: only %d blocks\n", index, max);
p = bitmap;
freecount = 0;
/*
* XXX The bitmap is FS blocks.
* The bitmap is an "inuse" map, not a free map.
*/
#define LINUX_FSBTODB(count) \
((EXT2_BLOCK_SIZE(super) / secsize) * (count))
if (debug > 2)
fprintf(stderr, " ");
for (freecount = count = i = 0; i < max; i++)
if (!isset(p, i)) {
unsigned long dboff;
int dbcount;
j = i;
while ((i+1)<max && !isset(p, i+1))
i++;
/*
* The offset of this free range, relative
* to the start of the disk, is: the slice
* offset, plus the offset of the group itself,
* plus the index of the first free block in
* the current range, plus the offset of the
* first data block in the filesystem.
*/
dboff = sliceoffset +
LINUX_FSBTODB(index*super->s_blocks_per_group) +
LINUX_FSBTODB(j) +
LINUX_FSBTODB(super->s_first_data_block);
dbcount = LINUX_FSBTODB((i-j) + 1);
if (debug > 2) {
if (count)
fprintf(stderr, ",%s",
count % 4 ?
" " : "\n ");
fprintf(stderr, "%lu:%d %d:%d",
dboff, dbcount, j, i);
count++;
}
addskip(dboff, dbcount);
freecount += dbcount;
}
if (debug > 2)
fprintf(stderr, "\n");
if (freecount != LINUX_FSBTODB(group->bg_free_blocks_count)) {
warnx("Linux Group %d: "
"computed free count (%d) != expected free count (%d)",
index, freecount, group->bg_free_blocks_count);
}
return 0;
}
/*
* For a linux swap partition, all that matters is the first little
* bit of it. The rest of it does not need to be written to disk.
*/
int
read_linuxswap(int slice, int stype, u_int32_t start, u_int32_t size,
char *sname, int infd)
{
if (debug) {
fprintf(stderr,
" P%d (Linux Swap)\n", slice + 1 /* DOS Numbering */);
fprintf(stderr,
" start %12d, size %9d\n",
start, size);
}
start += bytestosec(0x8000);
size -= bytestosec(0x8000);
addskip(start, size);
return 0;
}
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
#include<sys/types.h>
#include <sys/types.h>
typedef u_int8_t __u8;
typedef u_int16_t __u16;
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../../..
SUBDIR = os/imagezip/fat
MAINDIR = $(SRCDIR)/..
include $(OBJDIR)/Makeconf
CFLAGS += $(SUBDIRCFLAGS) -I$(SRCDIR)
all: libfat.a
include $(TESTBED_SRCDIR)/GNUmakerules
OBJS = fat_glue.o fat_boot.o fat_fat.o
fat_glue.o: fat_glue.h $(MAINDIR)/sliceinfo.h $(MAINDIR)/global.h
libfat.a: $(OBJS)
$(AR) $(ARFLAGS) $@ $?
$(RANLIB) $@
install:
clean:
rm -f libfat.a $(OBJS)
/*
* Hacked from...
* Hacked from BSD fsck_msdosfs.
*/
#ifndef __RCSID
#define __RCSID(s)
#endif
/*
* Copyright (C) 1995, 1997 Wolfgang Solfrank
......
/*
* Hacked from...
* Hacked from BSD fsck_msdosfs.
*/
#ifndef __RCSID
#define __RCSID(s)
#endif
/*
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
......
......@@ -14,6 +14,8 @@
#include <unistd.h>
#include <sys/param.h>
#include "sliceinfo.h"
#include "global.h"
#include "fat_glue.h"
/* XXX */
......@@ -27,7 +29,8 @@ static u_int32_t fat_offset, fat_limit;
static int fatsecpersec;
int
read_fatslice(int slice, u_int32_t start, u_int32_t size, int infd)
read_fatslice(int slice, int stype, u_int32_t start, u_int32_t size,
char *sfilename, int infd)
{
struct bootblock boot;
struct fatEntry *fat = NULL;
......
......@@ -9,6 +9,7 @@
*/
#include <err.h>
#include <sys/types.h>
#include "dosfs.h"
#define FSOK 0 /* Check was OK */
......@@ -30,3 +31,7 @@ ssize_t devread(int fd, void *buf, size_t nbytes);
#define read(f,b,s) devread((f), (b), (s))
#define pfatal warnx
#define pwarn warnx
#ifndef __RCSID
#define __RCSID(s)
#endif
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../../..
SUBDIR = os/imagezip/ffs
MAINDIR = $(SRCDIR)/..
include $(OBJDIR)/Makeconf
CFLAGS += $(SUBDIRCFLAGS)
all: libffs.a
include $(TESTBED_SRCDIR)/GNUmakerules
OBJS = ffs.o
ffs.o: ffs.h fs.h disklabel.h
ffs.o: $(MAINDIR)/global.h $(MAINDIR)/sliceinfo.h $(MAINDIR)/imagehdr.h
libffs.a: $(OBJS)
$(AR) $(ARFLAGS) $@ $?
$(RANLIB) $@
install:
clean:
rm -f libffs.a $(OBJS)
/*
* Copyright (c) 1987, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the