Fix - in makefile var bug reported by Jim.
Make pintos util able to format and put in one step.
SRCDIR = ../../src
SINGLETONS = \
+ $(addprefix args-, argc argv0 argvn single multiple dbl-space) \
+ $(addprefix sc-, bad-sp bad-arg boundary) \
+ halt exit \
$(addprefix create-, normal empty null bad-ptr long exists bound) \
- $(addprefix args-, argc argv0 argvn single multiple dbl-space)
+ $(addprefix open-, normal missing boundary empty null bad-ptr twice) \
+ $(addprefix close-, normal twice stdin stdout bad-fd) \
+ $(addprefix read-, normal bad-ptr boundary zero stdout bad-fd)
define SINGLETON_PROG
PROGS += $(1)
-$(1)_SRC = $(1).c
+$(subst -,_,$(1))_SRC = $(1).c
endef
$(foreach prog,$(SINGLETONS),$(eval $(call SINGLETON_PROG,$(prog))))
disks: $(DISKS)
-PINTOS = ../../src/utils/pintos
-OS_DISK = ../../src/userprog/build/os.dsk
%.dsk: %
- rm -f $@.tmp
- $(PINTOS) make-disk $@.tmp 2
- $(PINTOS) -v --os-disk=$(OS_DISK) --fs-disk=$@.tmp run -f -q
- $(PINTOS) -v --os-disk=$(OS_DISK) --fs-disk=$@.tmp put $<
- mv $@.tmp $@
+ ./prep-disk $<
clean::
rm -f $(DISKS)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(close-bad-fd) begin\n");
+ close (0xc0101234);
+ printf ("(close-bad-fd) end\n");
+ return 0;
+}
--- /dev/null
+(close-bad-fd) begin
+(close-bad-fd) end
+close-bad-fd: exit(0)
+--OR--
+(close-bad-fd) begin
+close-bad-fd: exit(-1)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ int handle;
+ printf ("(close-normal) begin\n");
+ handle = open ("sample.txt");
+ if (handle < 2)
+ printf ("(close-normal) fail: open() returned %d\n", handle);
+ close (handle);
+ printf ("(close-normal) end\n");
+ return 0;
+}
--- /dev/null
+(close-normal) begin
+(close-normal) end
+close-normal: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(close-stdin) begin\n");
+ close (0);
+ printf ("(close-stdin) end\n");
+ return 0;
+}
--- /dev/null
+(close-stdin) begin
+(close-stdin) end
+close-stdin: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(close-stdout) begin\n");
+ close (1);
+ printf ("(close-stdout) end\n");
+ return 0;
+}
--- /dev/null
+(close-stdout) begin
+(close-stdout) end
+close-stdout: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ int handle;
+ printf ("(close-twice) begin\n");
+ handle = open ("sample.txt");
+ if (handle < 2)
+ printf ("(close-twice) fail: open() returned %d\n", handle);
+ close (handle);
+ close (handle);
+ printf ("(close-twice) end\n");
+ return 0;
+}
--- /dev/null
+(close-twice) begin
+(close-twice) end
+close-twice: exit(0)
+--OR--
+(close-twice) begin
+close-twice: exit(-1)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(exit) begin\n");
+ exit (57);
+ printf ("(exit) fail\n");
+ return 0;
+}
--- /dev/null
+(exit) begin
+exit: exit(57)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(halt) begin\n");
+ halt ();
+ printf ("(halt) fail\n");
+ return 0;
+}
--- /dev/null
+(halt) begin
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(open-bad-ptr) begin\n");
+ open ((char *) 0xc0101234);
+ printf ("(open-bad-ptr) end\n");
+ return 0;
+}
--- /dev/null
+(open-bad-ptr) begin
+(open-bad-ptr) end
+open-bad-ptr: exit(0)
+--OR--
+(open-bad-ptr) begin
+open-bad-ptr: exit(-1)
--- /dev/null
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+
+static char *
+mk_boundary_string (const char *src)
+{
+ static char dst[8192];
+ char *p = dst + (4096 - (uintptr_t) dst % 4096 - strlen (src) / 2);
+ strlcpy (p, src, 4096);
+ return p;
+}
+
+int
+main (void)
+{
+ int handle;
+
+ printf ("(open-boundary) begin\n");
+ handle = open (mk_boundary_string ("sample.txt"));
+ if (handle < 2)
+ printf ("(open-boundary) fail: open() returned %d\n", handle);
+ printf ("(open-boundary) end\n");
+ return 0;
+}
--- /dev/null
+(open-boundary) begin
+(open-boundary) end
+open-boundary: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ int handle;
+ printf ("(open-empty) begin\n");
+ handle = open ("");
+ if (handle != -1)
+ printf ("(open-empty) fail: open() returned %d\n", handle);
+ printf ("(open-empty) end\n");
+ return 0;
+}
--- /dev/null
+(open-empty) begin
+(open-empty) end
+open-empty: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ int handle;
+ printf ("(open-missing) begin\n");
+ handle = open ("no-such-file");
+ if (handle != -1)
+ printf ("(open-missing) fail: open() returned %d\n", handle);
+ printf ("(open-missing) end\n");
+ return 0;
+}
--- /dev/null
+(open-missing) begin
+(open-missing) end
+open-missing: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ int handle;
+ printf ("(open-normal) begin\n");
+ handle = open ("sample.txt");
+ if (handle < 2)
+ printf ("(open-normal) fail: open() returned %d\n", handle);
+ printf ("(open-normal) end\n");
+ return 0;
+}
--- /dev/null
+(open-normal) begin
+(open-normal) end
+open-normal: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(open-null) begin\n");
+ open (NULL);
+ printf ("(open-null) end\n");
+ return 0;
+}
--- /dev/null
+(open-null) begin
+(open-null) end
+open-null: exit(0)
+--OR--
+(open-null) begin
+open-null: exit(-1)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ int h1, h2;
+ printf ("(open-twice) begin\n");
+
+ h1 = open ("sample.txt");
+ if (h1 < 2)
+ printf ("(open-twice) fail: open() returned %d first time\n", h1);
+
+ h2 = open ("sample.txt");
+ if (h2 < 2)
+ printf ("(open-twice) fail: open() returned %d second time\n", h2);
+ if (h1 == h2)
+ printf ("(open-twice) fail: open() returned %d both times\n", h1);
+
+ printf ("(open-twice) end\n");
+ return 0;
+}
--- /dev/null
+(open-twice) begin
+(open-twice) end
+open-twice: exit(0)
--- /dev/null
+#! /usr/bin/perl -w
+
+use strict;
+use Getopt::Long;
+
+my ($pintos) = "pintos";
+my ($os_disk) = "../../src/userprog/build/os.dsk";
+my ($fs_disk);
+my ($test);
+
+GetOptions ("os-disk=s" => \$os_disk,
+ "fs-disk=s" => \$fs_disk,
+ "test=s" => \$test,
+ "help" => sub { usage (0) })
+ or die "option parsing failed; use --help for help\n";
+
+if (!defined ($test)) {
+ die "test name expected; use --help for help\n"
+ if @ARGV != 1;
+ $test = shift @ARGV;
+} elsif (@ARGV != 0) {
+ die "can't have non-option arg with --test\n";
+}
+
+$fs_disk = "$test.dsk" if !defined $fs_disk;
+
+if (! -e $os_disk) {
+ print STDERR "$os_disk: stat: $!\n";
+ print STDERR "perhaps you should `make' in ../../src/userprog?\n";
+ exit 1;
+}
+
+our ($formatted) = 0;
+
+unlink $fs_disk;
+xsystem ("$pintos make-disk '$fs_disk' 2");
+put_file ("$test");
+put_file ("sample.txt")
+ if grep ($_ eq $test,
+ qw (open-normal open-boundary open-twice
+ close-normal close-twice
+ read-normal read-bad-ptr read-boundary read-zero
+ write-normal write-boundary write-zero));
+
+sub put_file {
+ my ($fn) = @_;
+ my ($cmd) = "$pintos -v --os-disk='$os_disk' --fs-disk='$fs_disk' put";
+ $cmd .= " -f", $formatted = 1 if !$formatted;
+ $cmd .= " '$fn'";
+ xsystem ($cmd);
+}
+
+sub xsystem {
+ my ($cmd) = @_;
+ print "$cmd\n";
+ system ($cmd) == 0 || die "command failed\n";
+}
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ char buf;
+ printf ("(read-bad-fd) begin\n");
+ read (0xc0101234, &buf, 1);
+ printf ("(read-bad-fd) end\n");
+ return 0;
+}
--- /dev/null
+(read-bad-fd) begin
+(read-bad-fd) end
+read-bad-fd: exit(0)
+--OR--
+(read-bad-fd) begin
+read-bad-fd: exit(-1)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ int handle;
+ printf ("(read-bad-ptr) begin\n");
+
+ handle = open ("sample.txt");
+ if (handle < 2)
+ printf ("(read-bad-ptr) fail: open() returned %d\n", handle);
+
+ read (handle, (char *) 0xc0101234, 123);
+
+ printf ("(read-bad-ptr) end\n");
+ return 0;
+}
--- /dev/null
+(read-bad-ptr) begin
+(read-bad-ptr) end
+read-bad-ptr: exit(0)
+--OR--
+(read-bad-ptr) begin
+read-bad-ptr: exit(-1)
--- /dev/null
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+
+char expected[] = {
+ "Amazing Electronic Fact: If you scuffed your feet long enough without\n"
+ "touching anything, you would build up so many electrons that your\n"
+ "finger would explode! But this is nothing to worry about unless you\n"
+ "have carpeting.\n"
+};
+
+
+
+static char *
+mk_boundary_string (const char *src)
+{
+ static char dst[8192];
+ char *p = dst + (4096 - (uintptr_t) dst % 4096 - strlen (src) / 2);
+ strlcpy (p, src, 4096);
+ return p;
+}
+
+int
+main (void)
+{
+ int handle;
+ int byte_cnt;
+ char *actual_p;
+
+ actual_p = mk_boundary_string (expected);
+
+ printf ("(read-boundary) begin\n");
+
+ handle = open ("sample.txt");
+ if (handle < 2)
+ printf ("(read-boundary) fail: open() returned %d\n", handle);
+
+ byte_cnt = read (handle, actual_p, sizeof expected - 1);
+ if (byte_cnt != sizeof expected - 1)
+ printf ("(read-boundary) fail: read() returned %d instead of %d\n",
+ byte_cnt, sizeof expected - 1);
+ else if (strcmp (expected, actual_p))
+ printf ("(read-boundary) fail: expected text differs from actual:\n%s",
+ actual_p);
+
+ printf ("(read-boundary) end\n");
+ return 0;
+}
--- /dev/null
+(read-boundary) begin
+(read-boundary) end
+read-boundary: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+
+char expected[] = {
+ "Amazing Electronic Fact: If you scuffed your feet long enough without\n"
+ "touching anything, you would build up so many electrons that your\n"
+ "finger would explode! But this is nothing to worry about unless you\n"
+ "have carpeting.\n"
+};
+
+char actual[sizeof expected];
+
+int
+main (void)
+{
+ int handle, byte_cnt;
+ printf ("(read-normal) begin\n");
+
+ handle = open ("sample.txt");
+ if (handle < 2)
+ printf ("(read-normal) fail: open() returned %d\n", handle);
+
+ byte_cnt = read (handle, actual, sizeof actual - 1);
+ if (byte_cnt != sizeof actual - 1)
+ printf ("(read-normal) fail: read() returned %d instead of %d\n",
+ byte_cnt, sizeof actual - 1);
+ else if (strcmp (expected, actual))
+ printf ("(read-normal) fail: expected text differs from actual:\n%s",
+ actual);
+
+ printf ("(read-normal) end\n");
+ return 0;
+}
--- /dev/null
+(read-normal) begin
+(read-normal) end
+read-normal: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ char buf;
+ printf ("(read-stdout) begin\n");
+ read (1, &buf, 1);
+ printf ("(read-stdout) end\n");
+ return 0;
+}
--- /dev/null
+(read-stdout) begin
+(read-stdout) end
+read-stdout: exit(0)
+--OR--
+(read-stdout) begin
+read-stdout: exit(-1)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ int handle, byte_cnt;
+ char buf;
+ printf ("(read-zero) begin\n");
+
+ handle = open ("sample.txt");
+ if (handle < 2)
+ printf ("(read-zero) fail: open() returned %d\n", handle);
+
+ buf = 123;
+ byte_cnt = read (handle, &buf, 0);
+ if (byte_cnt != 0)
+ printf ("(read-zero) fail: read() returned %d instead of 0\n", byte_cnt);
+ else if (buf != 123)
+ printf ("(read-zero) fail: 0-byte read() modified buffer\n");
+
+ printf ("(read-zero) end\n");
+ return 0;
+}
--- /dev/null
+(read-zero) begin
+(read-zero) end
+read-zero: exit(0)
}
# Default set of tests.
-@TESTS = qw (create-normal create-empty create-null create-bad-ptr
+@TESTS = qw (args-argc args-argv0 args-argvn args-single args-multiple
+ args-dbl-space
+ sc-bad-sp sc-bad-arg sc-boundary
+ halt exit
+ create-normal create-empty create-null create-bad-ptr
create-long create-exists create-bound
- args-argc args-argv0 args-argvn args-single args-multiple
- args-dbl-space)
- unless @TESTS > 0;
+ open-normal open-missing open-boundary open-empty open-null
+ open-bad-ptr open-twice
+ close-normal close-twice close-stdin close-stdout close-bad-fd
+ read-normal read-bad-ptr read-boundary read-zero read-stdout
+ read-bad-fd
+ ) unless @TESTS > 0;
our (%args);
for my $key ('args-argc', 'args-argv0', 'args-argvn', 'args-multiple') {
# They differ. Output a diff.
my (@diff) = "";
my ($d) = Algorithm::Diff->new (\@expected, \@actual);
- my ($all_additions) = 1;
+ my ($not_fuzzy_match) = 0;
while ($d->Next ()) {
my ($ef, $el, $af, $al) = $d->Get (qw (min1 max1 min2 max2));
if ($d->Same ()) {
} else {
push (@diff, map ("- $_", $d->Items (1))) if $d->Items (1);
push (@diff, map ("+ $_", $d->Items (2))) if $d->Items (2);
- $all_additions = 0 if $d->Items (1);
+ if ($d->Items (1)
+ || grep (/\($test\)|exit\(-?\d+\)/, $d->Items (2))) {
+ $not_fuzzy_match = 1;
+ }
}
}
-
- $fuzzy_match = 1 if $all_additions;
+ $fuzzy_match = 1 if !$not_fuzzy_match;
$details .= "Differences in `diff -u' format:\n";
$details .= join ('', @diff);
--- /dev/null
+Amazing Electronic Fact: If you scuffed your feet long enough without
+touching anything, you would build up so many electrons that your
+finger would explode! But this is nothing to worry about unless you
+have carpeting.
main (void)
{
printf ("(sc-bad-arg) begin\n");
- asm volatile ("mov $0xbffffffc, %%esp; movl $%0, (%%esp); int $0x30"
+ asm volatile ("mov $0xbffffffc, %%esp; movl %0, (%%esp); int $0x30"
:
: "i" (SYS_exit));
printf ("(sc-bad-arg) end\n");
main (void)
{
printf ("(sc-bad-sp) begin\n");
- asm volatile ("mov $0xc0101234, %%esp; int $0x30");
+ asm volatile ("mov $0xc0101234, %esp; int $0x30");
printf ("(sc-bad-sp) end\n");
return 0;
}
--- /dev/null
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <syscall-nr.h>
+
+static void *
+mk_boundary_array (void)
+{
+ static char dst[8192];
+ return dst + (4096 - (uintptr_t) dst % 4096);
+}
+
+int
+main (void)
+{
+ int *p;
+
+ printf ("(sc-boundary) begin\n");
+ p = mk_boundary_array ();
+ p--;
+ p[0] = SYS_exit;
+ p[1] = 42;
+ asm volatile ("mov %0, %%esp; int $0x30"
+ :
+ : "g" (p));
+ printf ("(sc-boundary) failed\n");
+ return 1;
+}
--- /dev/null
+(sc-boundary) begin
+sc-boundary: exit(42)
-2 open-boundary: pass name of file crossing page boundary
-1 open-empty: pass empty string to open system call
-1 open-null: pass null pointer to open system call
+ -1 open-bad-ptr: pass invalid pointer to open system call
-1 open-twice: open the same file twice
-Score: /9
+Score: /10
System calls: close
-2 close-normal: close an open file in the most normal way
LIB_DEP = $(patsubst %.o,%.d,$(LIB_OBJ))
LIB = lib/user/entry.o libc.a
-PROGS_SRC = $(foreach prog,$(PROGS),$($(prog)_SRC))
+PROGS_SRC = $(foreach prog,$(PROGS),$($(subst -,_,$(prog))_SRC))
PROGS_OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(PROGS_SRC)))
PROGS_DEP = $(patsubst %.o,%.d,$(PROGS_OBJ))
all: $(PROGS)
define TEMPLATE
-$(1)_OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$($(1)_SRC)))
-$(1): $$($(1)_OBJ) $$(LIB)
+$(2)_OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$($(2)_SRC)))
+$(1): $$($(2)_OBJ) $$(LIB)
+ $$(CC) $$(LDFLAGS) $$^ $$(LDLIBS) -o $$@
endef
-$(foreach prog,$(PROGS),$(eval $(call TEMPLATE,$(prog))))
+$(foreach prog,$(PROGS),$(eval $(call TEMPLATE,$(prog),$(subst -,_,$(prog)))))
$(PROGS): $(LIB)
our ($jitter);
use Getopt::Long qw(:config require_order bundling);
-GetOptions ("bochs|qemu|gsx" => \&set_sim,
- "no-debug|monitor|gdb" => \&set_debug,
+GetOptions ("sim=s" => sub { set_sim (@_) },
+ "bochs" => sub { set_sim ("bochs") },
+ "qemu" => sub { set_sim ("qemu") },
+ "gsx" => sub { set_sim ("gsx") },
+
+ "debug=s" => sub { set_debug (@_) },
+ "no-debug" => sub { set_debug ("no-debug") },
+ "monitor" => sub { set_debug ("monitor") },
+ "gdb" => sub { set_debug ("gdb") },
+
"run|get|put|make-disk" => \&cmd_option,
+
"m|memory=i" => \$mem,
"j|jitter=i" => \$jitter,
+
"v|no-vga" => sub { set_vga ('none'); },
"s|no-serial" => sub { $serial_out = 0; },
"t|terminal" => sub { set_vga ('terminal'); },
+
"h|help" => sub { usage (0); },
+
"0|os-disk|disk-0|hda=s" => \$disks[0],
"1|fs-disk|disk-1|hdb=s" => \$disks[1],
"2|scratch-disk|disk-2|hdc=s" => \$disks[2],
$vga = "window" if !defined $vga;
sub set_sim {
- my ($option) = @_;
- die "--$option conflicts with --$sim\n" if defined $sim;
- our ($sim) = $option;
+ my ($new_sim) = @_;
+ die "--$new_sim conflicts with --$sim\n"
+ if defined ($sim) && $sim ne $new_sim;
+ $sim = $new_sim;
}
sub set_debug {
- my ($option) = @_;
- die "--$option conflicts with --$debug\n" if defined $debug;
- our ($debug) = $option;
+ my ($new_debug) = @_;
+ die "--$new_debug conflicts with --$debug\n"
+ if defined ($debug) && $debug ne $new_debug;
+ $debug = $new_debug;
}
sub set_vga {
if (defined ($vga) && $vga ne $new_vga) {
print "warning: conflicting vga display options\n";
}
- our ($vga) = $new_vga;
+ $vga = $new_vga;
}
sub cmd_option {
- our ($cmd) = @_;
-
# Force an end to option processing, as with --.
die ("!FINISH");
}
create_disk ($file, int ($mb * 1008));
} elsif ($cmd eq 'put') {
+ # Take a -f option to combine formatting with putting.
+ my ($format) = 0;
+ if (@ARGV > 0 && $ARGV[0] eq '-f') {
+ shift @ARGV;
+ $format = 1;
+ }
+
usage () if @ARGV != 1 && @ARGV != 2;
my ($hostfn, $guestfn) = @ARGV;
$guestfn = $hostfn if !defined $guestfn;
copy_pad ($hostfn, "scratch.dsk", 512);
# Do copy.
- run_vm ("-ci", $guestfn, $size, "-q");
+ my (@cmd) = ("-ci", $guestfn, $size, "-q");
+ unshift (@cmd, "-f") if $format;
+ run_vm (@cmd);
} elsif ($cmd eq 'get') {
usage () if @ARGV != 1 && @ARGV != 2;
my ($guestfn, $hostfn) = @ARGV;