diff --git a/commands/writeisofs/writeisofs.c b/commands/writeisofs/writeisofs.c index a5cefc557..b6d50b0cd 100644 --- a/commands/writeisofs/writeisofs.c +++ b/commands/writeisofs/writeisofs.c @@ -1,6 +1,7 @@ /* writeisofs - simple ISO9660-format-image writing utility */ +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include @@ -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; diff --git a/include/minix/minlib.h b/include/minix/minlib.h index 52059eb5a..4772bfed3 100644 --- a/include/minix/minlib.h +++ b/include/minix/minlib.h @@ -1,7 +1,10 @@ #ifndef _MINLIB #define _MINLIB +#if defined(_NETBSD_SOURCE) + #include +#include /* 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 diff --git a/lib/libminixfs/cache.c b/lib/libminixfs/cache.c index 02d496aa9..b7af1bdbb 100644 --- a/lib/libminixfs/cache.c +++ b/lib/libminixfs/cache.c @@ -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; diff --git a/lib/libminlib/fslib.c b/lib/libminlib/fslib.c index 899f35c95..fa0e48759 100644 --- a/lib/libminlib/fslib.c +++ b/lib/libminlib/fslib.c @@ -3,6 +3,9 @@ #include /* for unused stuff in :-( */ #include #include +#include +#include +#include #include #include #include /* for unshort :-( */ @@ -11,6 +14,7 @@ #include "mfs/inode.h" /* ditto */ #include "mfs/super.h" #include +#include /* 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); +} diff --git a/servers/iso9660fs/read.c b/servers/iso9660fs/read.c index 045fddfe3..44886be7a 100644 --- a/servers/iso9660fs/read.c +++ b/servers/iso9660fs/read.c @@ -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"); } diff --git a/test/Makefile b/test/Makefile index fccab7e9e..809dc3fde 100644 --- a/test/Makefile +++ b/test/Makefile @@ -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 diff --git a/test/run b/test/run index ba57609dc..aa5d51650 100755 --- a/test/run +++ b/test/run @@ -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 diff --git a/test/testisofs.sh b/test/testisofs.sh new file mode 100644 index 000000000..7f36b15bc --- /dev/null +++ b/test/testisofs.sh @@ -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 + diff --git a/usr.sbin/mkproto/Makefile b/usr.sbin/mkproto/Makefile index baa5da16c..8b569e047 100644 --- a/usr.sbin/mkproto/Makefile +++ b/usr.sbin/mkproto/Makefile @@ -1,4 +1,7 @@ PROG= mkproto MAN= +LDADD+= -lminlib +DPADD+= ${LIBMINLIB} + .include diff --git a/usr.sbin/mkproto/mkproto.c b/usr.sbin/mkproto/mkproto.c index a0b5e9ba3..eb95370ce 100644 --- a/usr.sbin/mkproto/mkproto.c +++ b/usr.sbin/mkproto/mkproto.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -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--; }