testfs: test MFS format doesn't change, using mkfs
This test tests mkfs.mfs will generate the same FS image given the same input files. mkproto creates a proto file (normalizing directory entry order). The assumption is that a change in the output flags a tacit change in FS format, and that a FS format change will cause the image to change. . Changes to mkfs.mfs that innocently change the format can change the sha1 output in the script along with it. . The assumption is that corresponding versions of mkfs.mfs and MFS will always work together; otherwise a lot breaks (ramdisk etc.) . Therefore, as long as a generated FS image stays the same with the same input now, incompatible MFS changes will still be flagged, even if they work together with the current mkfs.mfs. Change-Id: I120cd1d9347aedaf438c8847f0e7b8eccf086e9d
This commit is contained in:
parent
4a70ffda08
commit
2e9ab96380
|
|
@ -74,7 +74,7 @@ PROGS+= test${t}
|
||||||
PROGS+= t10a t11a t11b t40a t40b t40c t40d t40e t40f t60a t60b \
|
PROGS+= t10a t11a t11b t40a t40b t40c t40d t40e t40f t60a t60b \
|
||||||
t67a t67b t68a t68b
|
t67a t67b t68a t68b
|
||||||
|
|
||||||
SCRIPTS+= run testinterp.sh testsh1.sh testsh2.sh
|
SCRIPTS+= run testinterp.sh testsh1.sh testsh2.sh testfs.sh
|
||||||
|
|
||||||
.if ${MKPIC} == "yes"
|
.if ${MKPIC} == "yes"
|
||||||
# Build them as dynamic executables by default if shared libraries
|
# Build them as dynamic executables by default if shared libraries
|
||||||
|
|
|
||||||
2
test/run
2
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 \
|
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 \
|
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 \
|
61 62 63 64 65 66 67 68 69 70 71 72 75 \
|
||||||
sh1.sh sh2.sh interp.sh"
|
sh1.sh sh2.sh interp.sh fs.sh"
|
||||||
tests_no=`expr 0`
|
tests_no=`expr 0`
|
||||||
|
|
||||||
# test mmap only if enabled in sysenv
|
# test mmap only if enabled in sysenv
|
||||||
|
|
|
||||||
73
test/testfs.sh
Executable file
73
test/testfs.sh
Executable file
|
|
@ -0,0 +1,73 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# expected sha1sum of the FS image
|
||||||
|
expect=2544d27de0e45dbbaf5fd273cc746b3c03be3e51
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo -n "mkfs test "
|
||||||
|
|
||||||
|
testdir=fstest
|
||||||
|
protofile=proto
|
||||||
|
fsimage=fsimage
|
||||||
|
rm -rf $testdir $protofile $fsimage
|
||||||
|
|
||||||
|
if [ -d $testdir ]
|
||||||
|
then echo "dir?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p $testdir $testdir/contents $testdir/modes
|
||||||
|
|
||||||
|
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 some files with various modes & mtimes
|
||||||
|
|
||||||
|
for many in 0 1 2 3 4 5 6 7 8 9
|
||||||
|
do for m1 in 0 1 2 3 4 5 6 7
|
||||||
|
do for m2 in 0 1 2 3 4 5 6 7
|
||||||
|
do for m3 in 0 1 2 3 4 5 6 7
|
||||||
|
do
|
||||||
|
mode=${m1}${m2}${m3}
|
||||||
|
fn=$testdir/modes/m${mode}${many}
|
||||||
|
echo "$many $m1 $m2 $m3 $mode" > $fn
|
||||||
|
chmod $mode $fn
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# Make an MFS filesystem image out of it
|
||||||
|
|
||||||
|
BS=4096
|
||||||
|
BLOCKS=15000
|
||||||
|
INODES=6000
|
||||||
|
dd if=/dev/zero seek=$BLOCKS of=$fsimage count=1 bs=$BS >/dev/null 2>&1
|
||||||
|
|
||||||
|
# -s keeps modes
|
||||||
|
mkproto -s -b $BLOCKS -i $INODES $testdir >$protofile
|
||||||
|
|
||||||
|
mkfs.mfs -T 1 -b $BLOCKS -i $INODES $fsimage $protofile >/dev/null 2>&1
|
||||||
|
sum="`sha1 $fsimage | awk '{ print $4 }'`"
|
||||||
|
if [ $sum != $expect ]
|
||||||
|
then echo sum $sum is not expected $expect
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ok
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
|
@ -142,7 +142,7 @@ static ssize_t mkfs_write(void * buf, size_t count);
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int nread, mode, usrid, grpid, ch, extra_space_percent;
|
int nread, mode, usrid, grpid, ch, extra_space_percent, Tflag = 0;
|
||||||
block_t blocks, maxblocks, bblocks;
|
block_t blocks, maxblocks, bblocks;
|
||||||
ino_t inodes, root_inum;
|
ino_t inodes, root_inum;
|
||||||
char *token[MAX_TOKENS], line[LINE_LEN], *sfx;
|
char *token[MAX_TOKENS], line[LINE_LEN], *sfx;
|
||||||
|
|
@ -160,7 +160,7 @@ main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
zone_shift = 0;
|
zone_shift = 0;
|
||||||
extra_space_percent = 0;
|
extra_space_percent = 0;
|
||||||
while ((ch = getopt(argc, argv, "B:b:di:ltvx:z:I:")) != EOF)
|
while ((ch = getopt(argc, argv, "B:b:di:ltvx:z:I:T:")) != EOF)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
#ifndef MFS_STATIC_BLOCK_SIZE
|
#ifndef MFS_STATIC_BLOCK_SIZE
|
||||||
case 'B':
|
case 'B':
|
||||||
|
|
@ -189,6 +189,10 @@ main(int argc, char *argv[])
|
||||||
case 'b':
|
case 'b':
|
||||||
blocks = bblocks = strtoul(optarg, (char **) NULL, 0);
|
blocks = bblocks = strtoul(optarg, (char **) NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
Tflag = 1;
|
||||||
|
current_time = strtoul(optarg, (char **) NULL, 0);
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
dflag = 1;
|
dflag = 1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -212,12 +216,17 @@ main(int argc, char *argv[])
|
||||||
* identical. First you set the time of the mkfs binary to what you
|
* identical. First you set the time of the mkfs binary to what you
|
||||||
* want, then go.
|
* want, then go.
|
||||||
*/
|
*/
|
||||||
current_time = time((time_t *) 0); /* time mkfs is being run */
|
if(Tflag) {
|
||||||
if(dflag) {
|
if(dflag)
|
||||||
|
errx(1, "-T and -d both specify a time and so are mutually exclusive");
|
||||||
|
} else if(dflag) {
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
if (stat(progname, &statbuf)) {
|
if (stat(progname, &statbuf)) {
|
||||||
perror("stat of itself");
|
err(1, "stat of itself");
|
||||||
} else current_time = statbuf.st_mtime;
|
}
|
||||||
|
current_time = statbuf.st_mtime;
|
||||||
|
} else {
|
||||||
|
current_time = time((time_t *) 0); /* time mkfs is being run */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Percentage of extra size must be nonnegative.
|
/* Percentage of extra size must be nonnegative.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
.Op Fl z Ar zone_shift
|
.Op Fl z Ar zone_shift
|
||||||
.Op Fl x Ar extra_space
|
.Op Fl x Ar extra_space
|
||||||
.Op Fl I Ar fs_offset
|
.Op Fl I Ar fs_offset
|
||||||
|
.Op Fl T Ar timestamp
|
||||||
.Ar special
|
.Ar special
|
||||||
.Op Ar prototype
|
.Op Ar prototype
|
||||||
.Sh OPTIONS
|
.Sh OPTIONS
|
||||||
|
|
@ -38,6 +39,8 @@ Filesystem block size (in bytes)
|
||||||
Filesystem size (in blocks)
|
Filesystem size (in blocks)
|
||||||
.It Fl I Ar fs_offset
|
.It Fl I Ar fs_offset
|
||||||
Write filesystem starting at offset (in bytes)
|
Write filesystem starting at offset (in bytes)
|
||||||
|
.It Fl T Ar timestamp
|
||||||
|
Use timestamp for inode times
|
||||||
.It Fl x Ar extra_space
|
.It Fl x Ar extra_space
|
||||||
Extra space after dynamic sizing (blocks and inodes)
|
Extra space after dynamic sizing (blocks and inodes)
|
||||||
.It Fl z Ar zone_shift
|
.It Fl z Ar zone_shift
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
/* The default values for the prototype file */
|
/* The default values for the prototype file */
|
||||||
#define DEF_UID 2 /* bin */
|
#define DEF_UID 2 /* bin */
|
||||||
|
|
@ -41,6 +43,12 @@ void display_attrib(const char *name, struct stat *st);
|
||||||
void usage(char *binname);
|
void usage(char *binname);
|
||||||
void open_outfile(void);
|
void open_outfile(void);
|
||||||
|
|
||||||
|
#define MAXNAME 256
|
||||||
|
|
||||||
|
struct mkproto_dirent {
|
||||||
|
char d_name[MAXNAME];
|
||||||
|
};
|
||||||
|
|
||||||
int main(argc, argv)
|
int main(argc, argv)
|
||||||
int argc;
|
int argc;
|
||||||
char *argv[];
|
char *argv[];
|
||||||
|
|
@ -127,16 +135,27 @@ char *argv[];
|
||||||
return(0);
|
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. */
|
/* Output the prototype spec for this directory. */
|
||||||
void descend(dirname)
|
void descend(dirname)
|
||||||
char *dirname;
|
char *dirname;
|
||||||
{
|
{
|
||||||
struct dirent *dp;
|
struct dirent *rdp;
|
||||||
|
struct mkproto_dirent *dirents = NULL, *dp;
|
||||||
|
int reserved_dirents = 0;
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
char *name, *temp, *tempend;
|
char *name, *temp, *tempend;
|
||||||
int i;
|
int i;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
|
int entries = 0;
|
||||||
|
|
||||||
dirp = opendir(dirname);
|
dirp = opendir(dirname);
|
||||||
if (dirp == NULL) {
|
if (dirp == NULL) {
|
||||||
|
|
@ -149,7 +168,28 @@ char *dirname;
|
||||||
strcat(temp, "/");
|
strcat(temp, "/");
|
||||||
tempend = &temp[strlen(temp)];
|
tempend = &temp[strlen(temp)];
|
||||||
|
|
||||||
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
|
/* 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++;
|
||||||
|
}
|
||||||
|
closedir(dirp);
|
||||||
|
|
||||||
|
/* normalize (sort) them */
|
||||||
|
qsort(dirents, entries, sizeof(*dp), cmp_dirent);
|
||||||
|
|
||||||
|
for (dp = dirents; entries > 0; dp++, entries--) {
|
||||||
name = dp->d_name;
|
name = dp->d_name;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
@ -202,8 +242,8 @@ char *dirname;
|
||||||
fprintf(outfile, " /dev/null");
|
fprintf(outfile, " /dev/null");
|
||||||
fprintf(stderr,"File\n\t%s\n has an invalid mode, made empty.\n",temp);
|
fprintf(stderr,"File\n\t%s\n has an invalid mode, made empty.\n",temp);
|
||||||
}
|
}
|
||||||
closedir(dirp);
|
|
||||||
free(temp);
|
free(temp);
|
||||||
|
free(dirents);
|
||||||
tabs--;
|
tabs--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,7 +261,7 @@ struct stat *st;
|
||||||
if (same_prot)
|
if (same_prot)
|
||||||
prot = st->st_mode & 0777; /***** This one is a bit shady *****/
|
prot = st->st_mode & 0777; /***** This one is a bit shady *****/
|
||||||
for (i = 0; i < tabs; i++) fprintf(outfile, "%s", indentstr);
|
for (i = 0; i < tabs; i++) fprintf(outfile, "%s", indentstr);
|
||||||
fprintf(outfile, "%s%s%c%c%c%3o %d %d",
|
fprintf(outfile, "%s%s%c%c%c%03o %d %d",
|
||||||
name,
|
name,
|
||||||
*name == '\0' ? "" : indentstr, /* stop the tab for a null name */
|
*name == '\0' ? "" : indentstr, /* stop the tab for a null name */
|
||||||
(st->st_mode & S_IFMT) == S_IFDIR ? 'd' :
|
(st->st_mode & S_IFMT) == S_IFDIR ? 'd' :
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user