testisofs: restore & test ISO filesystem

. to restore isofs: fix a bug in isofs, allow non-pagesize-multiple
	  blocksizes (but disable peek, i.e. mmap, functionality in that case).
	. to test isofs: prepare an ISO FS image using writeisofs, copy it
	  to a RAM device, mount it using the iso9660fs server, compare the
	  SHA1 contents of the files on the ISO with the inputs.
	. use su to run certain commands in the script as root

Change-Id: I81c5c64a0073410197f3e442e23f8ddc1f9d216c
This commit is contained in:
Ben Gras 2013-11-18 14:08:00 +00:00
parent 8704807cb3
commit 48be52fddd
10 changed files with 187 additions and 56 deletions

View File

@ -1,6 +1,7 @@
/* writeisofs - simple ISO9660-format-image writing utility */
#include <sys/cdefs.h>
#include <errno.h>
#include <stdio.h>
#include <time.h>
@ -12,6 +13,7 @@
#include <assert.h>
#include <ctype.h>
#include <partition.h>
#include <minix/minlib.h>
#include <sys/stat.h>
@ -277,10 +279,10 @@ void
maketree(struct node *thisdir, char *name, int level)
{
DIR *dir;
struct dirent *e;
struct node *dirnodes = NULL;
int reserved_dirnodes = 0, used_dirnodes = 0;
int reserved_dirnodes = 0, used_dirnodes = 0, nentries;
struct node *child;
struct me_dirent *entries, *e;
thisdir->firstchild = NULL;
thisdir->isdir = 1;
@ -298,11 +300,11 @@ maketree(struct node *thisdir, char *name, int level)
}
/* how many entries do we need to allocate? */
while(readdir(dir)) reserved_dirnodes++;
if(!reserved_dirnodes) {
if(!(entries = minix_readdir(dir, &reserved_dirnodes))) {
closedir(dir);
return;
}
nentries = reserved_dirnodes;
if(!(dirnodes = malloc(sizeof(*dirnodes)*reserved_dirnodes))) {
fprintf(stderr, "couldn't allocate dirnodes (%d bytes)\n",
@ -315,7 +317,7 @@ maketree(struct node *thisdir, char *name, int level)
rewinddir(dir);
child = dirnodes;
while((e=readdir(dir))) {
for(e = entries; nentries--; e++) {
struct stat st;
mode_t type;
if(!strcmp(e->d_name, CURRENTDIR) || !strcmp(e->d_name, PARENTDIR))
@ -328,10 +330,6 @@ maketree(struct node *thisdir, char *name, int level)
type = st.st_mode & S_IFMT;
/*
printf("%s type: %x dir: %x file: %x\n",
e->d_name, type, S_IFDIR, S_IFREG);
*/
if(type != S_IFDIR && type != S_IFREG)
continue;

View File

@ -1,7 +1,10 @@
#ifndef _MINLIB
#define _MINLIB
#if defined(_NETBSD_SOURCE)
#include <sys/mount.h>
#include <dirent.h>
/* Miscellaneous BSD. */
char *itoa(int _n);
@ -16,6 +19,15 @@ int load_mtab(char *_prog_name);
int get_mtab_entry(char dev[PATH_MAX], char mount_point[PATH_MAX],
char type[MNTNAMELEN], char flags[MNTFLAGLEN]);
/* Returned by minix_readdir */
#define ME_MAXNAME 256
struct me_dirent {
char d_name[ME_MAXNAME];
};
struct me_dirent *minix_readdir(DIR *, int *n);
void minix_free_readdir(struct me_dirent *md, int n);
/* read_tsc() and friends */
void read_tsc(u32_t *hi, u32_t *lo);
void read_tsc_64(u64_t *t);
@ -27,3 +39,5 @@ void read_tsc_64(u64_t *t);
#define FSVERSION_EXT2 0x10002
#endif
#endif

View File

@ -161,8 +161,12 @@ free_unused_blocks(void)
static void
lmfs_alloc_block(struct buf *bp)
{
int len;
ASSERT(!bp->data);
ASSERT(bp->lmfs_bytes == 0);
len = roundup(fs_block_size, PAGE_SIZE);
if((bp->data = minix_mmap(0, fs_block_size,
PROT_READ|PROT_WRITE, MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
free_unused_blocks();
@ -191,9 +195,12 @@ void minix_munmap_t(void *a, int len)
assert(a);
assert(a != MAP_FAILED);
assert(len > 0);
assert(!(len % PAGE_SIZE));
assert(!(av % PAGE_SIZE));
len = roundup(len, PAGE_SIZE);
assert(!(len % PAGE_SIZE));
if(minix_munmap(a, len) < 0)
panic("libminixfs cache: munmap failed");
}
@ -638,9 +645,8 @@ void lmfs_rw_scattered(
}
assert(dev != NO_DEV);
assert(!(fs_block_size % PAGE_SIZE));
assert(fs_block_size > 0);
iov_per_block = fs_block_size / PAGE_SIZE;
iov_per_block = roundup(fs_block_size, PAGE_SIZE) / PAGE_SIZE;
/* (Shell) sort buffers on lmfs_blocknr. */
gap = 1;
@ -669,19 +675,24 @@ void lmfs_rw_scattered(
int r;
for (iop = iovec; nblocks < bufqsize; nblocks++) {
int p;
vir_bytes vdata;
vir_bytes vdata, blockrem;
bp = bufq[nblocks];
if (bp->lmfs_blocknr != (block_t) bufq[0]->lmfs_blocknr + nblocks)
break;
if(niovecs >= NR_IOREQS-iov_per_block) break;
vdata = (vir_bytes) bp->data;
blockrem = fs_block_size;
for(p = 0; p < iov_per_block; p++) {
vir_bytes chunk = blockrem < PAGE_SIZE ? blockrem : PAGE_SIZE;
iop->iov_addr = vdata;
iop->iov_size = PAGE_SIZE;
iop->iov_size = chunk;
vdata += PAGE_SIZE;
blockrem -= chunk;
iop++;
niovecs++;
}
assert(p == iov_per_block);
assert(blockrem == 0);
}
assert(nblocks > 0);
@ -825,7 +836,7 @@ void lmfs_set_blocksize(int new_block_size, int major)
vmcache = 0;
if(may_use_vmcache)
if(may_use_vmcache && !(new_block_size % PAGE_SIZE))
vmcache = 1;
}
@ -932,6 +943,10 @@ int lmfs_do_bpeek(message *m)
assert(fs_block_size > 0);
assert(dev != NO_DEV);
if(!vmcache) { return ENXIO; }
assert(!(fs_block_size % PAGE_SIZE));
if((extra=(pos % fs_block_size))) {
pos -= extra;
len += extra;

View File

@ -3,6 +3,9 @@
#include <minix/config.h> /* for unused stuff in <minix/type.h> :-( */
#include <limits.h>
#include <dirent.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <minix/const.h>
#include <minix/type.h> /* for unshort :-( */
@ -11,6 +14,7 @@
#include "mfs/inode.h" /* ditto */
#include "mfs/super.h"
#include <minix/fslib.h>
#include <minix/minlib.h>
/* The next routine is copied from fsck.c and mkfs.c... (Re)define some
* things for consistency. Some things should be done better.
@ -188,3 +192,61 @@ int norm; /* TRUE = do not swap bytes; FALSE = swap */
dip->d2_zone[i] = conv4(norm, (long) rip->i_zone[i]);
}
}
/* Compare dirent objects for order */
static int cmp_dirent(const void *d1, const void *d2)
{
struct me_dirent *dp1 = (struct me_dirent *) d1,
*dp2 = (struct me_dirent *) d2;
return strcmp(dp1->d_name, dp2->d_name);
}
/* Return array of me_dirents. */
struct me_dirent *minix_readdir(DIR *dirp, int *n)
{
struct dirent *rdp;
struct me_dirent *dp;
struct me_dirent *dirents = NULL;
int reserved_dirents = 0;
int entries = 0;
while((rdp = readdir(dirp)) != NULL) {
if(entries >= reserved_dirents) {
struct me_dirent *newdirents;
int newreserved = (2*(reserved_dirents+1));
if(!(newdirents = realloc(dirents, newreserved *
sizeof(*dirents)))) {
free(dirents);
return NULL;
}
dirents = newdirents;
reserved_dirents = newreserved;
}
assert(entries < reserved_dirents);
assert(strlen(rdp->d_name) < sizeof(dp->d_name));
dp = &dirents[entries];
memset(dp, 0, sizeof(*dp));
strcpy(dp->d_name, rdp->d_name);
entries++;
}
/* Assume directories contain at least "." and "..", and
* therefore the array exists.
*/
assert(entries > 0);
assert(dirents);
/* normalize (sort) them */
qsort(dirents, entries, sizeof(*dp), cmp_dirent);
/* Return no. of entries. */
*n = entries;
return dirents;
}
void minix_free_readdir(struct me_dirent *md, int n)
{
free(md);
}

View File

@ -22,8 +22,8 @@ int fs_read(void) {
int rw;
switch(fs_m_in.m_type) {
case REQ_READ: rw = READING;
case REQ_PEEK: rw = PEEKING;
case REQ_READ: rw = READING; break;
case REQ_PEEK: rw = PEEKING; break;
default: panic("odd m_type");
}

View File

@ -74,7 +74,7 @@ PROGS+= test${t}
PROGS+= t10a t11a t11b t40a t40b t40c t40d t40e t40f t60a t60b \
t67a t67b t68a t68b
SCRIPTS+= run testinterp.sh testsh1.sh testsh2.sh testfs.sh
SCRIPTS+= run testinterp.sh testsh1.sh testsh2.sh testfs.sh testisofs.sh
.if ${MKPIC} == "yes"
# Build them as dynamic executables by default if shared libraries

View File

@ -25,7 +25,7 @@ alltests=" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 75 \
sh1.sh sh2.sh interp.sh fs.sh"
sh1.sh sh2.sh interp.sh fs.sh isofs.sh"
tests_no=`expr 0`
# test mmap only if enabled in sysenv

68
test/testisofs.sh Normal file
View File

@ -0,0 +1,68 @@
# Create and verify a simple ISO filesystem
#
#!/bin/sh
set -x
set -e
echo -n "isofs test "
ramdev=/dev/ram
mp=/mnt
testdir=isofstest
fsimage=isofsimage
contents=CONTENTS
out1=v1
out2=v2
rm -rf $testdir $fsimage $out1 $out2
if [ -d $testdir ]
then echo "dir?"
exit 1
fi
mkdir -p $testdir $testdir/$contents
if [ ! -d $testdir ]
then echo "no dir?"
exit 1
fi
# Make some small & big & bigger files
prevf=$testdir/$contents/FILE
echo "Test contents 123" >$prevf
for double in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
do fn=$testdir/$contents/FN.$double
cat $prevf $prevf >$fn
prevf=$fn
done
# Make an ISO filesystem image out of it
writeisofs -s0x0 -l MINIX $testdir $fsimage >/dev/null 2>&1
# umount previous things
su root -c "umount $ramdev 2>/dev/null || true"
su root -c "umount $mp 2>/dev/null || true"
# Mount it on a RAM disk
su root -c "ramdisk 50000 $ramdev >/dev/null 2>&1"
su root -c "cp $fsimage $ramdev"
su root -c "mount -t isofs $ramdev $mp >/dev/null 2>&1"
# compare contents
(cd $testdir/$contents && sha1 * | sort) >$out1
(cd $mp/$contents && sha1 * | sort) >$out2
diff -u v1 v2
echo ok
su root -c 'umount $ramdev >/dev/null 2>&1'
# cleanup
rm -rf $testdir $fsimage $out1 $out2
exit 0

View File

@ -1,4 +1,7 @@
PROG= mkproto
MAN=
LDADD+= -lminlib
DPADD+= ${LIBMINLIB}
.include <bsd.prog.mk>

View File

@ -4,6 +4,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <minix/minlib.h>
#include <limits.h>
#include <dirent.h>
#include <stdlib.h>
@ -43,12 +44,6 @@ void display_attrib(const char *name, struct stat *st);
void usage(char *binname);
void open_outfile(void);
#define MAXNAME 256
struct mkproto_dirent {
char d_name[MAXNAME];
};
int main(argc, argv)
int argc;
char *argv[];
@ -135,27 +130,18 @@ char *argv[];
return(0);
}
/* Compare dirent objects for order */
static int cmp_dirent(const void *d1, const void *d2)
{
struct mkproto_dirent *dp1 = (struct mkproto_dirent *) d1,
*dp2 = (struct mkproto_dirent *) d2;
return strcmp(dp1->d_name, dp2->d_name);
}
/* Output the prototype spec for this directory. */
void descend(dirname)
char *dirname;
{
struct dirent *rdp;
struct mkproto_dirent *dirents = NULL, *dp;
int reserved_dirents = 0;
struct me_dirent *dirents;
DIR *dirp;
char *name, *temp, *tempend;
int i;
struct stat st;
mode_t mode;
int entries = 0;
int entries = 0, orig_entries;
struct me_dirent *dp;
dirp = opendir(dirname);
if (dirp == NULL) {
@ -169,26 +155,11 @@ char *dirname;
tempend = &temp[strlen(temp)];
/* read all directory entries */
for (rdp = readdir(dirp); rdp != NULL; rdp = readdir(dirp)) {
if(entries >= reserved_dirents) {
int newreserved = (2*(reserved_dirents+1));
if(!(dirents = realloc(dirents, newreserved *
sizeof(*dirents)))) {
errx(1, "realloc failed on dirents");
}
reserved_dirents = newreserved;
}
assert(entries < reserved_dirents);
assert(strlen(rdp->d_name) < sizeof(dp->d_name));
dp = &dirents[entries];
strcpy(dp->d_name, rdp->d_name);
entries++;
}
if(!(dirents = minix_readdir(dirp, &entries)))
errx(1, "minix_readdir failed");
orig_entries = entries;
closedir(dirp);
/* normalize (sort) them */
qsort(dirents, entries, sizeof(*dp), cmp_dirent);
for (dp = dirents; entries > 0; dp++, entries--) {
name = dp->d_name;
@ -243,7 +214,7 @@ char *dirname;
fprintf(stderr,"File\n\t%s\n has an invalid mode, made empty.\n",temp);
}
free(temp);
free(dirents);
minix_free_readdir(dirents, orig_entries);
tabs--;
}