From: Derrick Brashear Date: Mon, 14 Jan 2002 07:49:15 +0000 (+0000) Subject: functionality-test-suite-20020114 X-Git-Tag: openafs-devel-1_3_0~83 X-Git-Url: http://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=f1964d2cf8d4c8b0468ad59a01f68c329258b40d functionality-test-suite-20020114 Based on Arla test suite and AFSTools with some other additions; intended to set up a standalone cell, perform operations --- diff --git a/Makefile.in b/Makefile.in index 0d87d6b..364456e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -90,6 +90,9 @@ build_dirs_rx: project: cmd comerr +tests: all + ${COMPILE_PART1} tests ${COMPILE_PART2} + config: ${COMPILE_PART1} config ${COMPILE_PART2} diff --git a/configure.in b/configure.in index 1f4b000..10615e2 100644 --- a/configure.in +++ b/configure.in @@ -105,6 +105,8 @@ src/sgistuff/Makefile \ src/sia/Makefile \ src/sys/Makefile \ src/tbutc/Makefile \ +src/tests/Makefile \ +src/tests/Dirpath.pm \ src/tools/Makefile \ src/tsm41/Makefile \ src/tviced/Makefile \ diff --git a/src/tests/Auth-Heimdal.pm b/src/tests/Auth-Heimdal.pm new file mode 100644 index 0000000..f578c82 --- /dev/null +++ b/src/tests/Auth-Heimdal.pm @@ -0,0 +1,44 @@ +# This is -*- perl -*- + +package OpenAFS::Auth; +use OpenAFS::Dirpath; + +use strict; +#use vars qw( @ISA @EXPORT ); +#@ISA = qw(Exporter); +#require Exporter; +#@EXPORT = qw($openafs-authadmin $openafs-authuser); + +sub getcell { + my($cell); + open(CELL, "$openafsdirpath->{'afsconfdir'}/ThisCell") + or die "Cannot open $openafsdirpath->{'afsconfdir'}/ThisCell: $!\n"; + $cell = ; + chomp $cell; + close CELL; + return $cell; +} + +sub getrealm { + my($cell); + open(CELL, "$openafsdirpath->{'afsconfdir'}/ThisCell") + or die "Cannot open $openafsdirpath->{'afsconfdir'}/ThisCell: $!\n"; + $cell = ; + chomp $cell; + close CELL; + $cell =~ tr/a-z/A-Z/; + return $cell; +} + +sub authadmin { + my $cell = &getrealm; + my $cmd = "kinit -k -t /usr/afs/etc/krb5.keytab admin\@${cell} ; afslog"; + system($cmd); +} +sub authuser { + my $cell = &getrealm; + my $cmd = "kinit -k -t /usr/afs/etc/krb5.keytab user\@${cell} ; afslog"; + system($cmd); +} + +1; diff --git a/src/tests/CMU_copyright.pm b/src/tests/CMU_copyright.pm new file mode 100644 index 0000000..8b3b5a0 --- /dev/null +++ b/src/tests/CMU_copyright.pm @@ -0,0 +1,33 @@ +## CMUCS AFStools +## Copyright (c) 1996, 2001 Carnegie Mellon University +## All Rights Reserved. +# +# Permission to use, copy, modify and distribute this software and its +# documentation is hereby granted, provided that both the copyright +# notice and this permission notice appear in all copies of the +# software, derivative works or modified versions, and any portions +# thereof, and that both notices appear in supporting documentation. +# +# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +# CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR +# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. +# +# Carnegie Mellon requests users of this software to return to +# +# Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU +# School of Computer Science +# Carnegie Mellon University +# Pittsburgh PA 15213-3890 +# +# any improvements or extensions that they make and grant Carnegie Mellon +# the rights to redistribute these changes. +# +# CMU_copyright.pm - CMU copyright +# This isn't a real package; it merely provides a central location to keep +# information regarding redistribution of this set of modules, and to make +# sure that no one can use the modules (at least, as shipped) without also +# having a copy of these terms. + +package AFS::CMU_copyright; + +1; diff --git a/src/tests/ConfigUtils.pm b/src/tests/ConfigUtils.pm new file mode 100644 index 0000000..ca56d60 --- /dev/null +++ b/src/tests/ConfigUtils.pm @@ -0,0 +1,26 @@ +# This is -*- perl -*- + +package OpenAFS::ConfigUtils; + +use strict; +use vars qw( @ISA @EXPORT @unwinds); +@ISA = qw(Exporter); +require Exporter; +@EXPORT = qw(@unwinds run unwind); + +sub run ($) { + print join(' ', @_); + print "\n"; + system (@_) == 0 + or die "Failed: $?\n"; +} + +# This subroutine takes a command to run in case of failure. After +# each succesful step, this routine should be run with a command to +# undo the successful step. + + sub unwind($) { + push @unwinds, $_[0]; + } + +1; diff --git a/src/tests/Dirpath.pm.in b/src/tests/Dirpath.pm.in new file mode 100644 index 0000000..32c001c --- /dev/null +++ b/src/tests/Dirpath.pm.in @@ -0,0 +1,25 @@ +# This is -*- perl -*- + +package OpenAFS::Dirpath; + +use strict; +use vars qw( @ISA @EXPORT $openafsdirpath); +@ISA = qw(Exporter); +require Exporter; +@EXPORT = qw($openafsdirpath); + +# Dirpath configuration +$openafsdirpath = { + 'afsconfdir' => '@afsconfdir@', + 'viceetcdir' => '@viceetcdir@', + 'afssrvbindir' => '@afssrvbindir@', + 'afssrvsbindir' => '@afssrvsbindir@', + 'afssrvlibexecdir' => '@afssrvlibexecdir@', + 'afsdbdir' => '@afsdbdir@', + 'afslogsdir' => '@afslogsdir@', + 'afslocaldir' => '@afslocaldir@', + 'afsbackupdir' => '@afsbackupdir@', + 'afsbosconfigdir' => '@afsbosconfigdir@' +}; + +1; diff --git a/src/tests/Makefile b/src/tests/Makefile new file mode 100644 index 0000000..0ab6df3 --- /dev/null +++ b/src/tests/Makefile @@ -0,0 +1,284 @@ +# Generated automatically from Makefile.in by configure. +srcdir = . +include /usr/src/openafs/openafs/src/config/Makefile.config + +SHELL = /bin/sh + +CFLAGS = -I. -I${srcdir} ${DBG} ${OPTMZ} -I${TOP_OBJDIR}/src/config -I${TOP_INCDIR} ${XCFLAGS} +LDFLAGS=${DBG} ${OPTMZ} ${XLDFLAGS} + +SYS_LIBS = ${TOP_LIBDIR}/libsys.a ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/util.a + +AUTH_LIBS = ${TOP_LIBDIR}/libauth.a ${SYS_LIBS} + +INT_LIBS = ${TOP_LIBDIR}/libafsint.a ${TOP_LIBDIR}/libsys.a ${TOP_LIBDIR}/librxkad.a ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/libcom_err.a ${TOP_LIBDIR}/util.a + +TEST_PROGRAMS = write-ro-file hello-world read-vs-mmap read-vs-mmap2 \ + mmap-and-read large-dir large-dir2 large-dir3 mountpoint \ + test-setgroups test-setpag hardlink1 hardlink2 mkdir2 \ + create-files create-symlinks create-dirs dup2-and-unlog \ + readdir-vs-lstat read-write create-remove mkdir3 \ + symlink echo-n test-parallel1 test-parallel2 create-stat \ + kill-softly kill-softer rm-rf exit-wo-close \ + mmap-vs-read mmap-vs-read2 strange-characters-c pine \ + append-over-page write-ucc utime-dir mmap-shared-write \ + rename5 rename-under-feet write-closed write-closed2 \ + truncate fchmod make-page utime-file rename6 \ + write3 still-there-p write-large afscp hardlink4 \ + intr-read asu truncate-files mmap-cat blocks-new-file \ + fsx write-rand + +TEST_OBJS = write-ro-file.o read-vs-mmap.o read-vs-mmap2.o \ + mmap-and-read.o large-dir.o large-dir2.o large-dir3.o \ + test-setgroups.o test-setpag.o hardlink1.o hardlink2.o \ + mkdir2.o create-files.o create-symlinks.o create-dirs.o \ + dup2-and-unlog.o readdir-vs-lstat.o read-write.o \ + create-remove.o symlink.o echo-n.o test-parallel1.o \ + test-parallel1.o mkdir3.o rename6.o \ + create-stat.o kill-softly.o kill-softer.o rm-rf.o \ + exit-wo-close.o mmap-vs-read.o mmap-vs-read2.o \ + strange-characters-c.o pine.o append-over-page.o \ + write-ucc.o utime-dir.o mmap-shared-write.o rename5.o \ + rename-under-feet.o write-closed.o write-closed2.o \ + truncate.o fchmod.o make-page.o utime-file.o \ + write3.o still-there-p.o write-large.o hardlink4.o \ + intr-read.o asu.o truncate-files.o mmap-cat.o \ + blocks-new-file.o fsx.o afscp.o afscp_callback.o \ + write-rand.o + +TEST_SRCS = write-ro-file.c read-vs-mmap.c read-vs-mmap2.c \ + mmap-and-read.c large-dir.c large-dir2.c large-dir3.c \ + test-setgroups.c test-setpag.c hardlink1.c hardlink2.c \ + mkdir2.c create-files.c create-symlinks.c create-dirs.c \ + dup2-and-unlog.c readdir-vs-lstat.c read-write.c \ + create-remove.c symlink.c echo-n.c test-parallel1.c \ + test-parallel2.c mkdir3.c rename6.c \ + create-stat.c kill-softly.c kill-softer.c rm-rf.c \ + exit-wo-close.c mmap-vs-read.c mmap-vs-read2.c \ + strange-characters-c.c pine.c append-over-page.c \ + write-ucc.c utime-dir.c mmap-shared-write.c rename5.c \ + rename-under-feet.c write-closed.c write-closed2.c \ + truncate.c fchmod.c make-page.c utime-file.c \ + write3.c still-there-p.c write-large.c hardlink4.c \ + intr-read.c asu.c truncate-files.c mmap-cat.c \ + blocks-new-file.c fsx.c afscp.c afscp_callback.c \ + write-rand.c + +EXTRA_OBJS = err.o errx.o warn.o warnx.o + +all: run-tests $(TEST_PROGRAMS) OS.pm + +OS.pm: OS-$(MKAFS_OSTYPE).pm + $(CP) OS-$(MKAFS_OSTYPE).pm OS.pm + +write-rand: write-rand.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-rand.o $(EXTRA_OBJS) $(LIBS) + +write-ro-file: write-ro-file.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-ro-file.o $(EXTRA_OBJS) $(LIBS) + +write-large: write-large.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-large.o $(EXTRA_OBJS) $(LIBS) + +read-vs-mmap: read-vs-mmap.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ read-vs-mmap.o $(EXTRA_OBJS) $(LIBS) + +read-vs-mmap2: read-vs-mmap2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ read-vs-mmap2.o $(EXTRA_OBJS) $(LIBS) + +mmap-vs-read: mmap-vs-read.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-vs-read.o $(EXTRA_OBJS) $(LIBS) + +mmap-vs-read2: mmap-vs-read2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-vs-read2.o $(EXTRA_OBJS) $(LIBS) + +read-write: read-write.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ read-write.o $(EXTRA_OBJS) $(LIBS) + +mmap-and-read: mmap-and-read.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-and-read.o $(EXTRA_OBJS) $(LIBS) + +large-dir: large-dir.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ large-dir.o $(EXTRA_OBJS) $(LIBS) + +large-dir2: large-dir2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ large-dir2.o $(EXTRA_OBJS) $(LIBS) + +large-dir3: large-dir3.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ large-dir3.o $(EXTRA_OBJS) $(LIBS) + +fchmod: fchmod.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ fchmod.o $(EXTRA_OBJS) $(LIBS) + +truncate: truncate.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ truncate.o $(EXTRA_OBJS) $(LIBS) + +make-page: make-page.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ make-page.o $(EXTRA_OBJS) $(LIBS) + +still-there-p: still-there-p.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ still-there-p.o $(EXTRA_OBJS) $(LIBS) + +intr-read: intr-read.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ intr-read.o $(EXTRA_OBJS) $(LIBS) + +blocks-new-file: blocks-new-file.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ blocks-new-file.o $(EXTRA_OBJS) $(LIBS) + +asu: asu.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ asu.o $(EXTRA_OBJS) $(LIBS) + +test-setgroups: test-setgroups.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ test-setgroups.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +test-setpag: test-setpag.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ test-setpag.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +hardlink1: hardlink1.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ hardlink1.o $(EXTRA_OBJS) $(LIBS) + +hardlink2: hardlink2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ hardlink2.o $(EXTRA_OBJS) $(LIBS) + +hardlink4: hardlink4.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ hardlink4.o $(EXTRA_OBJS) $(LIBS) + +mkdir2: mkdir2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mkdir2.o $(EXTRA_OBJS) $(LIBS) + +mkdir3: mkdir3.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mkdir3.o $(EXTRA_OBJS) $(LIBS) + +create-files: create-files.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-files.o $(EXTRA_OBJS) $(LIBS) + +create-symlinks: create-symlinks.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-symlinks.o $(EXTRA_OBJS) $(LIBS) + +create-dirs: create-dirs.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-dirs.o $(EXTRA_OBJS) $(LIBS) + +create-remove: create-remove.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-remove.o $(EXTRA_OBJS) $(LIBS) + +dup2-and-unlog: dup2-and-unlog.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ dup2-and-unlog.o $(EXTRA_OBJS) $(AUTH_LIBS) $(LIBS) + +readdir-vs-lstat: readdir-vs-lstat.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ readdir-vs-lstat.o $(EXTRA_OBJS) $(LIBS) + +symlink: symlink.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ symlink.o $(EXTRA_OBJS) $(LIBS) + +echo-n: echo-n.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ echo-n.o $(EXTRA_OBJS) + +test-parallel1: test-parallel1.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ test-parallel1.o $(EXTRA_OBJS) $(LIBS) + +test-parallel2: test-parallel2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ test-parallel2.o $(EXTRA_OBJS) $(LIBS) + +create-stat: create-stat.o fs_lib.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-stat.o fs_lib.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +kill-softly: kill-softly.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ kill-softly.o $(EXTRA_OBJS) $(LIBS) + +kill-softer: kill-softer.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ kill-softer.o $(EXTRA_OBJS) $(LIBS) + +rm-rf: rm-rf.o fs_lib.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ rm-rf.o fs_lib.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +exit-wo-close: exit-wo-close.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ exit-wo-close.o $(EXTRA_OBJS) $(LIBS) + +strange-characters-c: strange-characters-c.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ strange-characters-c.o $(EXTRA_OBJS) $(LIBS) + +pine: pine.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ pine.o $(EXTRA_OBJS) $(LIBS) + +append-over-page: append-over-page.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ append-over-page.o $(EXTRA_OBJS) $(LIBS) + +write-ucc: write-ucc.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-ucc.o $(EXTRA_OBJS) $(LIBS) + +utime-dir: utime-dir.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ utime-dir.o $(EXTRA_OBJS) $(LIBS) + +utime-file: utime-file.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ utime-file.o $(EXTRA_OBJS) $(LIBS) + +mmap-shared-write: mmap-shared-write.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-shared-write.o $(EXTRA_OBJS) $(LIBS) + +rename5: rename5.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ rename5.o $(EXTRA_OBJS) $(LIBS) + +rename6: rename6.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ rename6.o $(EXTRA_OBJS) $(LIBS) + +write3: write3.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write3.o $(EXTRA_OBJS) $(LIBS) + +rename-under-feet: rename-under-feet.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ rename-under-feet.o $(EXTRA_OBJS) $(LIBS) + +write-closed: write-closed.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-closed.o $(EXTRA_OBJS) $(LIBS) + +write-closed2: write-closed2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-closed2.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +truncate-files: truncate-files.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ truncate-files.o $(EXTRA_OBJS) $(LIBS) + +mmap-cat: mmap-cat.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-cat.o $(EXTRA_OBJS) $(LIBS) + +run-tests: run-tests.in + (cd ..; CONFIG_FILES=tests/run-tests CONFIG_HEADERS= $(SHELL) /usr/src/openafs/openafs/config.status) + @chmod +x run-tests + +#.c.o: +# $(CC) -c $(CPPFLAGS) $(DEFS) -I$(srcdir) -I. $(REALCFLAGS) $< + +afscp: afscp.o afscp_callback.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ afscp.o afscp_callback.o $(EXTRA_OBJS) $(INT_LIBS) + +hello-world: hello-world.in + sed -e "s!%CC%!$(CC)!" $(srcdir)/hello-world.in > $@ + chmod +x hello-world + +mountpoint: mountpoint.in + sed -e "s!%bindir%!$(bindir)!" $(srcdir)/mountpoint.in > $@ + chmod +x mountpoint + +clean: + rm -f run-tests $(TEST_PROGRAMS) *.o *~ + +realclean: + +distclean: clean + rm -f Makefile + +mostlyclean: + +install: + +uninstall: + + +TAGS: $(TEST_SRCS) + etags $(TEST_SRCS) + +check: run-tests $(TEST_PROGRAMS) + ./run-tests -all + +check-fast: run-tests $(TEST_PROGRAMS) + ./run-tests -all -fast + +.PHONY: all install clean realclean distclean mostlyclean install uninstall check diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in new file mode 100644 index 0000000..b402189 --- /dev/null +++ b/src/tests/Makefile.in @@ -0,0 +1,276 @@ +srcdir = @srcdir@ +include @TOP_OBJDIR@/src/config/Makefile.config + +SHELL = /bin/sh + +CFLAGS = -I. -I${srcdir} ${DBG} ${OPTMZ} -I${TOP_OBJDIR}/src/config -I${TOP_INCDIR} ${XCFLAGS} +LDFLAGS=${DBG} ${OPTMZ} ${XLDFLAGS} + +SYS_LIBS = ${TOP_LIBDIR}/libsys.a ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/util.a + +AUTH_LIBS = ${TOP_LIBDIR}/libauth.a ${SYS_LIBS} + +INT_LIBS = ${TOP_LIBDIR}/libafsint.a ${TOP_LIBDIR}/libsys.a ${TOP_LIBDIR}/librxkad.a ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/libcom_err.a ${TOP_LIBDIR}/util.a + +TEST_PROGRAMS = write-ro-file hello-world read-vs-mmap read-vs-mmap2 \ + mmap-and-read large-dir large-dir2 large-dir3 mountpoint \ + test-setgroups test-setpag hardlink1 hardlink2 mkdir2 \ + create-files create-symlinks create-dirs dup2-and-unlog \ + readdir-vs-lstat read-write create-remove mkdir3 \ + symlink echo-n test-parallel1 test-parallel2 create-stat \ + kill-softly kill-softer rm-rf exit-wo-close \ + mmap-vs-read mmap-vs-read2 strange-characters-c pine \ + append-over-page write-ucc utime-dir mmap-shared-write \ + rename5 rename-under-feet write-closed write-closed2 \ + truncate fchmod make-page utime-file rename6 \ + write3 still-there-p write-large afscp hardlink4 \ + intr-read asu truncate-files mmap-cat blocks-new-file \ + fsx write-rand + +TEST_OBJS = write-ro-file.o read-vs-mmap.o read-vs-mmap2.o \ + mmap-and-read.o large-dir.o large-dir2.o large-dir3.o \ + test-setgroups.o test-setpag.o hardlink1.o hardlink2.o \ + mkdir2.o create-files.o create-symlinks.o create-dirs.o \ + dup2-and-unlog.o readdir-vs-lstat.o read-write.o \ + create-remove.o symlink.o echo-n.o test-parallel1.o \ + test-parallel1.o mkdir3.o rename6.o \ + create-stat.o kill-softly.o kill-softer.o rm-rf.o \ + exit-wo-close.o mmap-vs-read.o mmap-vs-read2.o \ + strange-characters-c.o pine.o append-over-page.o \ + write-ucc.o utime-dir.o mmap-shared-write.o rename5.o \ + rename-under-feet.o write-closed.o write-closed2.o \ + truncate.o fchmod.o make-page.o utime-file.o \ + write3.o still-there-p.o write-large.o hardlink4.o \ + intr-read.o asu.o truncate-files.o mmap-cat.o \ + blocks-new-file.o fsx.o afscp.o afscp_callback.o \ + write-rand.o + +TEST_SRCS = write-ro-file.c read-vs-mmap.c read-vs-mmap2.c \ + mmap-and-read.c large-dir.c large-dir2.c large-dir3.c \ + test-setgroups.c test-setpag.c hardlink1.c hardlink2.c \ + mkdir2.c create-files.c create-symlinks.c create-dirs.c \ + dup2-and-unlog.c readdir-vs-lstat.c read-write.c \ + create-remove.c symlink.c echo-n.c test-parallel1.c \ + test-parallel2.c mkdir3.c rename6.c \ + create-stat.c kill-softly.c kill-softer.c rm-rf.c \ + exit-wo-close.c mmap-vs-read.c mmap-vs-read2.c \ + strange-characters-c.c pine.c append-over-page.c \ + write-ucc.c utime-dir.c mmap-shared-write.c rename5.c \ + rename-under-feet.c write-closed.c write-closed2.c \ + truncate.c fchmod.c make-page.c utime-file.c \ + write3.c still-there-p.c write-large.c hardlink4.c \ + intr-read.c asu.c truncate-files.c mmap-cat.c \ + blocks-new-file.c fsx.c afscp.c afscp_callback.c \ + write-rand.c + +EXTRA_OBJS = err.o errx.o warn.o warnx.o + +all: run-tests $(TEST_PROGRAMS) OS.pm + +OS.pm: OS-$(MKAFS_OSTYPE).pm + $(CP) OS-$(MKAFS_OSTYPE).pm OS.pm + +write-rand: write-rand.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-rand.o $(EXTRA_OBJS) $(LIBS) + +write-ro-file: write-ro-file.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-ro-file.o $(EXTRA_OBJS) $(LIBS) + +write-large: write-large.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-large.o $(EXTRA_OBJS) $(LIBS) + +read-vs-mmap: read-vs-mmap.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ read-vs-mmap.o $(EXTRA_OBJS) $(LIBS) + +read-vs-mmap2: read-vs-mmap2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ read-vs-mmap2.o $(EXTRA_OBJS) $(LIBS) + +mmap-vs-read: mmap-vs-read.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-vs-read.o $(EXTRA_OBJS) $(LIBS) + +mmap-vs-read2: mmap-vs-read2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-vs-read2.o $(EXTRA_OBJS) $(LIBS) + +read-write: read-write.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ read-write.o $(EXTRA_OBJS) $(LIBS) + +mmap-and-read: mmap-and-read.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-and-read.o $(EXTRA_OBJS) $(LIBS) + +large-dir: large-dir.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ large-dir.o $(EXTRA_OBJS) $(LIBS) + +large-dir2: large-dir2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ large-dir2.o $(EXTRA_OBJS) $(LIBS) + +large-dir3: large-dir3.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ large-dir3.o $(EXTRA_OBJS) $(LIBS) + +fchmod: fchmod.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ fchmod.o $(EXTRA_OBJS) $(LIBS) + +truncate: truncate.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ truncate.o $(EXTRA_OBJS) $(LIBS) + +make-page: make-page.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ make-page.o $(EXTRA_OBJS) $(LIBS) + +still-there-p: still-there-p.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ still-there-p.o $(EXTRA_OBJS) $(LIBS) + +intr-read: intr-read.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ intr-read.o $(EXTRA_OBJS) $(LIBS) + +blocks-new-file: blocks-new-file.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ blocks-new-file.o $(EXTRA_OBJS) $(LIBS) + +asu: asu.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ asu.o $(EXTRA_OBJS) $(LIBS) + +test-setgroups: test-setgroups.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ test-setgroups.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +test-setpag: test-setpag.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ test-setpag.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +hardlink1: hardlink1.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ hardlink1.o $(EXTRA_OBJS) $(LIBS) + +hardlink2: hardlink2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ hardlink2.o $(EXTRA_OBJS) $(LIBS) + +hardlink4: hardlink4.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ hardlink4.o $(EXTRA_OBJS) $(LIBS) + +mkdir2: mkdir2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mkdir2.o $(EXTRA_OBJS) $(LIBS) + +mkdir3: mkdir3.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mkdir3.o $(EXTRA_OBJS) $(LIBS) + +create-files: create-files.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-files.o $(EXTRA_OBJS) $(LIBS) + +create-symlinks: create-symlinks.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-symlinks.o $(EXTRA_OBJS) $(LIBS) + +create-dirs: create-dirs.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-dirs.o $(EXTRA_OBJS) $(LIBS) + +create-remove: create-remove.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-remove.o $(EXTRA_OBJS) $(LIBS) + +dup2-and-unlog: dup2-and-unlog.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ dup2-and-unlog.o $(EXTRA_OBJS) $(AUTH_LIBS) $(LIBS) + +readdir-vs-lstat: readdir-vs-lstat.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ readdir-vs-lstat.o $(EXTRA_OBJS) $(LIBS) + +symlink: symlink.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ symlink.o $(EXTRA_OBJS) $(LIBS) + +echo-n: echo-n.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ echo-n.o $(EXTRA_OBJS) + +test-parallel1: test-parallel1.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ test-parallel1.o $(EXTRA_OBJS) $(LIBS) + +test-parallel2: test-parallel2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ test-parallel2.o $(EXTRA_OBJS) $(LIBS) + +create-stat: create-stat.o fs_lib.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ create-stat.o fs_lib.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +kill-softly: kill-softly.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ kill-softly.o $(EXTRA_OBJS) $(LIBS) + +kill-softer: kill-softer.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ kill-softer.o $(EXTRA_OBJS) $(LIBS) + +rm-rf: rm-rf.o fs_lib.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ rm-rf.o fs_lib.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +exit-wo-close: exit-wo-close.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ exit-wo-close.o $(EXTRA_OBJS) $(LIBS) + +strange-characters-c: strange-characters-c.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ strange-characters-c.o $(EXTRA_OBJS) $(LIBS) + +pine: pine.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ pine.o $(EXTRA_OBJS) $(LIBS) + +append-over-page: append-over-page.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ append-over-page.o $(EXTRA_OBJS) $(LIBS) + +write-ucc: write-ucc.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-ucc.o $(EXTRA_OBJS) $(LIBS) + +utime-dir: utime-dir.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ utime-dir.o $(EXTRA_OBJS) $(LIBS) + +utime-file: utime-file.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ utime-file.o $(EXTRA_OBJS) $(LIBS) + +mmap-shared-write: mmap-shared-write.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-shared-write.o $(EXTRA_OBJS) $(LIBS) + +rename5: rename5.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ rename5.o $(EXTRA_OBJS) $(LIBS) + +rename6: rename6.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ rename6.o $(EXTRA_OBJS) $(LIBS) + +write3: write3.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write3.o $(EXTRA_OBJS) $(LIBS) + +rename-under-feet: rename-under-feet.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ rename-under-feet.o $(EXTRA_OBJS) $(LIBS) + +write-closed: write-closed.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-closed.o $(EXTRA_OBJS) $(LIBS) + +write-closed2: write-closed2.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ write-closed2.o $(EXTRA_OBJS) $(SYS_LIBS) $(LIBS) + +truncate-files: truncate-files.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ truncate-files.o $(EXTRA_OBJS) $(LIBS) + +mmap-cat: mmap-cat.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ mmap-cat.o $(EXTRA_OBJS) $(LIBS) + +run-tests: run-tests.in + (cd ..; CONFIG_FILES=tests/run-tests CONFIG_HEADERS= $(SHELL) @TOP_OBJDIR@/config.status) + @chmod +x run-tests + +#.c.o: +# $(CC) -c $(CPPFLAGS) $(DEFS) -I$(srcdir) -I. $(REALCFLAGS) $< + +afscp: afscp.o afscp_callback.o $(EXTRA_OBJS) + $(CC) $(LDFLAGS) -o $@ afscp.o afscp_callback.o $(EXTRA_OBJS) $(INT_LIBS) + +hello-world: hello-world.in + sed -e "s!%CC%!$(CC)!" $(srcdir)/hello-world.in > $@ + chmod +x hello-world + +mountpoint: mountpoint.in + sed -e "s!%bindir%!$(bindir)!" $(srcdir)/mountpoint.in > $@ + chmod +x mountpoint + +clean: + rm -f run-tests $(TEST_PROGRAMS) *.o *~ OS.pm + +install: + +uninstall: + + +TAGS: $(TEST_SRCS) + etags $(TEST_SRCS) + +check: run-tests $(TEST_PROGRAMS) + ./run-tests -all + +check-fast: run-tests $(TEST_PROGRAMS) + ./run-tests -all -fast + +.PHONY: all install clean realclean distclean mostlyclean install uninstall check diff --git a/src/tests/OS-LINUX.pm b/src/tests/OS-LINUX.pm new file mode 100644 index 0000000..70c7d38 --- /dev/null +++ b/src/tests/OS-LINUX.pm @@ -0,0 +1,23 @@ +# This is -*- perl -*- + +package OpenAFS::OS; + +use strict; +use vars qw( @ISA @EXPORT $openafsinitcmd); +@ISA = qw(Exporter); +require Exporter; +@EXPORT = qw($openafsinitcmd); + +# OS-specific configuration +$openafsinitcmd = { + 'client-start' => '/etc/init.d/openafs-client start', + 'client-stop' => '/etc/init.d/openafs-client stop', + 'client-forcestart' => '/etc/init.d/openafs-client force-start', + 'client-restart' => '/etc/init.d/openafs-client restart', + 'filesrv-start' => '/etc/init.d/openafs-fileserver start', + 'filesrv-stop' => '/etc/init.d/openafs-fileserver stop', + 'filesrv-forcestart'=> '/etc/init.d/openafs-fileserver force-start', + 'filesrv-restart' => '/etc/init.d/openafs-fileserver restart', +}; + +1; diff --git a/src/tests/OS-SOLARIS.pm b/src/tests/OS-SOLARIS.pm new file mode 100644 index 0000000..3ba2645 --- /dev/null +++ b/src/tests/OS-SOLARIS.pm @@ -0,0 +1,23 @@ +# This is -*- perl -*- + +package OpenAFS::OS; + +use strict; +use vars qw( @ISA @EXPORT $openafsinitcmd); +@ISA = qw(Exporter); +require Exporter; +@EXPORT = qw($openafsinitcmd); + +# OS-specific configuration +$openafsinitcmd = { + 'client-start' => 'modload /usr/vice/etc/modload/libafs.nonfs.o; /usr/vice/etc/afsd -nosettime', + 'client-stop' => 'echo Solaris client cannot be stopped', + 'client-forcestart' => 'modload /usr/vice/etc/modload/libafs.nonfs.o; /usr/vice/etc/afsd -nosettime', + 'client-restart' => 'echo Solaris client cannot be restarted', + 'filesrv-start' => '/usr/afs/bin/bosserver', + 'filesrv-stop' => '/usr/afs/bin/bos shutdown localhost -local -wait; pkill /usr/afs/bin/bosserver', + 'filesrv-forcestart'=> '/usr/afs/bin/bosserver', + 'filesrv-restart' => '/usr/afs/bin/bos shutdown localhost -local -wait; pkill /usr/afs/bin/bosserver; sleep 1; /usr/afs/bin/bosserver', +}; + +1; diff --git a/src/tests/README b/src/tests/README new file mode 100644 index 0000000..49d10ba --- /dev/null +++ b/src/tests/README @@ -0,0 +1,239 @@ +AFS verification suite +14 Jan 2002 + +Prerequisites + +1) A Kerberos KDC should already be configured +2) An afs key should be in the KeyFile the AFS binaries will use + (/usr/afs/etc/KeyFile in an IBM-style installation; bos_util can be used + to set it up) +3) 2 srvtabs or keytabs with user keys, one for the user "admin" + and one for the user "user" that can be used for authenticated testing + of the AFS installation +4) The necessary tools for getting an AFS token from the installed Kerberos + (typically aklog) should be available. +5) Ability to run as root on the "test" node. +6) If the AFS to be tested is not OpenAFS, pt_util from OpenAFS should be + built and installed. +7) Volume dump test tools included in new versions of OpenAFS. +8) The "test" node should have partitions mounted as /vicepa and /vicepb +9) perl5 +10) wget (should be configurable to use curl; what else?) + +(*) This is not yet true but will be by the time the suite is delivered. + +Setup +1) Scripts provided bootstrap and populate a "test cell". (afs-newcell) + +Tests + +A) Simple tests +10) Create a file. (creat1) +20) Create a directory. (mkdir1/mkdir2) +30) Create a symlink. (symlink) +40) Create a in-same-directory hardlink. (hardlink1) +50) Create a hardlink to a different-directory-same-volume file. (hardlink4) +60) Create a hardlink to a directory. (hardlink2) +70) Create a cross-volume hardlink. (hardlink5) +80) Touch a file. (touch1) +90) Write a simple file. (write1) +100) Rewrite a file. (write3) +110) Rename a file. (rename1) + +B) Basic functionality +10) Stat multiple hardlinked files. (hardlink3) +20) Write, truncate, rewrite a file. (write2) +30) Append to a file. (append1) +40) Rename a file over another file. (rename2) +50) Rename a file into a same-volume directory. (rename4) +60) Rename a file into another-volume directory. (rename6) +70) Rename an open directory. (rename-under-feet) +80) Create a file with a large filename. (large-filename) +90) Chmod a file by descriptor. (fchmod) +100) Utimes a file. (utime-file) +110) Utimes a directory. (utime-dir) +120) Test directory "link count" increasing/decreasing appropriately. (mkdir3) + +C) Mountpoint tests +10) Create and remove a good mountpoint. (mkm-rmm) +20) Create a mountpoint to a nonexistant volume. (mountpoint) + +D) ACL tests +10) Add a valid PTS user to an ACL. (acladduser) +20) Add a valid PTS group to an ACL. (acladdgroup) +30) Add ACL rights for a PTS user. (acladdrights) +40) Add negative ACL rights for a PTS user. (acladdnegrights) +50) Clear negative ACL rights for a PTS user. (aclclearnegrights) +60) Remove a valid PTS user from an ACL. (aclremoveuser) +70) Remove a valid PTS group from an ACL. (aclremovegroup) +80) Copy an ACL. (aclcopy) + +E) Executable tests +10) Write and execute a script in a directory. (exec) +20) Download and build http://www.openafs.org/dl/openafs/1.2.2/openafs-1.2.2-src.tar.gz, then run something from it. (build-openafs) + +F) mmap tests +10) Append over a mapped page. (append-over-page) +20) Write via mmap to a shared-mapped file. (mmap-shared-write) +30) Compare a file being read via mmap private and read (mmap-vs-read2) +40) Compare a file being read via mmap shared and read (mmap-vs-read) +50) Compare a file being read via read and mmap shared (read-vs-mmap2) +60) Compare a file being read via read and mmap private (read-vs-mmap) + +G) Filesystem Semantics tests +10) Create a file with 8 bit characters in its name. (strange-characters) +20) Test pine lockfile semantics. (pine) +30) Create and remove a single file in parallel. (parallel1) +40) Create a >2gb file (write-large) + +H) AFS behavior tests +10) Write a file in a readonly volume. (write-ro) +20) Create 31707 entries in a directory. (too-many-files) +30) Test setpag(). (setpag) +40) Test setgroups(). (setgroups) + +I) Remote operation tests +10) Write a file locally and read it in a foreign cache manager. (extcopyin) +20) Write a file in a foreign cache manager and read it locally. (extcopyout) + +K) Client abuse tests +10) Write a file, read, rewrite and reread a file with the same open descriptor. (read-write) +20) Populate and clean up a directory tree. (create-remove-files) +30) FSX file system stresser (fsx) + +L) Fileserver tests + +M) Ptserver tests +10) Create a user (ptscreateuser) +20) Create a group (ptscreategroup) +30) Add a user to a group (ptsadduser) +40) Chown a group (ptschown) +50) Get user membership (ptsmembersuser) +60) Get group membership (ptsmembersgroup) +70) Examine a user (ptsexamineuser) +80) Examine a group (ptsexaminegroup) +90) Remove a user from a group (ptsremove) +100) List groups a user owns (ptslistown) +100) Set maxuser (ptssetmax) +110) List maxuser (ptslistmax) +130) Set fields on a user (ptssetf) +140) Delete a group (ptsdeletegroup) +150) Delete a user (ptsdeleteuser) +160) pt_util exercising (?) + +N) Volserver/vlserver tests +10) Create a volume (voscreate) +20) Move a volume (vosmove) +30) Add a replication site (vosaddsite) +40) Release a volume (vosrelease) +50) Remove a replication site (vosremsite) +70) Remove a volume (vosremove) +80) Delete a VLDB entry (vosdelentry) +90) Synchronize vldb to volumes (vossyncvldb) +100) Zap a volume (voszap) +110) Synchronize volumes to vldb (vossyncserv) +120) Lock a VLDB entry (voslock) +130) Unlock a VLDB entry (vosunlock) +140) Unlock all VLDB entries after locking one or more (vosunlockall) +150) Rename a volume. (vosrename) +160) List all volumes on a partition. (voslistvol) +170) List vldb (voslistvldb) +180) Get partition info. (vospartinfo) +190) List partitions (voslistpart) +200) Backup a volume (vosbackup) +210) Examine a volume (vosexamine) +220) Dump a volume (vosdump) +230) Restore a volume (vosrestore) +240) Verify a volume dump (?) + +O) Bosserver tests +10) Add a bosserver host (bosaddhost) +20) List server hosts (bostlisthosts) +30) Remove a server host (bosremovehost) +40) Add a superuser (bosadduser) +50) List superusers (boslistusers) +60) Remove a superuser (bosremoveuser) +70) Install an executable shell script (bosinstall) +80) Execute something via the bosserver (bosexec) +80) Create a bos bnode (boscreate) +90) Delete a running bnode (bosdeleterunning) +100) Get a bnode status (bosstatus) +110) Stop a bos bnode (bosstop) +120) Restart a bos bnode (bosrestartstopped) +130) Start a bos bnode (bosstart) +140) Shutdown a bnode (bosshutdown) +150) Delete a stopped bnode (bosdelete) +160) Add a key (bosaddkey) +170) List keys (boslistkeys) +180) Remove a key (bosremovekey) +180) Salvage a volume (bossalvagevolume) +190) Salvage a partition (bossalvagepart) +200) Salvage a server (bossalvageserver) + +P) Regression +10) Restore volume with a bad uniquifier in it, salvage, check. (?) +20) Check for bad dentry caching on Linux taking advantage of last test. (?) +30) Write a file larger than the cache. (fcachesize-write-file) +40) Read a file larger than the cache. (fcachesize-read-file) + +--- +Copyright information + +The AFStools perl modules are: + +## Copyright (c) 1996, 2001 Carnegie Mellon University +## All Rights Reserved. +# +# Permission to use, copy, modify and distribute this software and its +# documentation is hereby granted, provided that both the copyright +# notice and this permission notice appear in all copies of the +# software, derivative works or modified versions, and any portions +# thereof, and that both notices appear in supporting documentation. +# +# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +# CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR +# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. +# +# Carnegie Mellon requests users of this software to return to +# +# Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU +# School of Computer Science +# Carnegie Mellon University +# Pittsburgh PA 15213-3890 +# +# any improvements or extensions that they make and grant Carnegie Mellon +# the rights to redistribute these changes. + +Some tests as noted are: +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ diff --git a/src/tests/README.afstools b/src/tests/README.afstools new file mode 100644 index 0000000..d9f5c7f --- /dev/null +++ b/src/tests/README.afstools @@ -0,0 +1,2 @@ +This is a (potentially) modified verion of the AFSTools perl suite. +You should visit grand.central.org for the official version. diff --git a/src/tests/acladdgroup.pl b/src/tests/acladdgroup.pl new file mode 100755 index 0000000..8259c6f --- /dev/null +++ b/src/tests/acladdgroup.pl @@ -0,0 +1,41 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($wscell, $path, @pos1, @pos2, @neg1, @neg2, $ret, @tmp, @tmp2, @tmp3, $found); +&AFS_Init(); +$wscell = &AFS_fs_wscell(); +$found = 0; + +eval { &AFS_pts_creategroup(group1,,,); }; +$path = "/afs/${wscell}/service/acltest"; +mkdir $path, 0777; +($pos1, $neg1) = &AFS_fs_getacl($path); +$ret = &AFS_fs_setacl([$path],[["group1", "rl"]],,); +($pos2, $neg2) = &AFS_fs_getacl($path); +while ($ret = pop(@$pos2)) { + @tmp2=@$ret; + if ($tmp2[0] eq "group1") { + $found++; + } else { + unshift @tmp, @$ret; + } +} + +@tmp2=(); +while ($ret = pop(@$pos1)) { + unshift @tmp2, @$ret; +} + +if ($found != 1) { + exit(1); +} +exit(0); + + + diff --git a/src/tests/acladdnegrights.pl b/src/tests/acladdnegrights.pl new file mode 100755 index 0000000..d18db57 --- /dev/null +++ b/src/tests/acladdnegrights.pl @@ -0,0 +1,42 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($wscell, $path, @pos1, @pos2, @neg1, @neg2, $ret, @tmp, @tmp2, @tmp3, $found); +&AFS_Init(); +$wscell = &AFS_fs_wscell(); +$found = 0; + +eval { &AFS_pts_createuser(user1,,); }; +$path = "/afs/${wscell}/service/acltest"; +mkdir $path, 0777; +($pos1, $neg1) = &AFS_fs_getacl($path); +$ret = &AFS_fs_setacl([$path],[],[["user1", "rl"]],); +($pos2, $neg2) = &AFS_fs_getacl($path); +while ($ret = pop(@$neg2)) { + @tmp2=@$ret; + if ($tmp2[0] eq "user1") { + $found++; + } else { + unshift @tmp, @$ret; + } +} + +if ($found != 1) { + exit(1); +} + +@tmp2=(); +while ($ret = pop(@$neg1)) { + unshift @tmp2, @$ret; +} + +exit(0); + + + diff --git a/src/tests/acladdrights.pl b/src/tests/acladdrights.pl new file mode 100755 index 0000000..a37a210 --- /dev/null +++ b/src/tests/acladdrights.pl @@ -0,0 +1,42 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($wscell, $path, @pos1, @pos2, @neg1, @neg2, $ret, @tmp, @tmp2, @tmp3, $found); +&AFS_Init(); +$wscell = &AFS_fs_wscell(); +$found = 0; + +eval { &AFS_pts_createuser(user1,,); }; +$path = "/afs/${wscell}/service/acltest"; +mkdir $path, 0777; +($pos1, $neg1) = &AFS_fs_getacl($path); +$ret = &AFS_fs_setacl([$path],[["user1", "rlidw"]],,); +($pos2, $neg2) = &AFS_fs_getacl($path); +while ($ret = pop(@$pos2)) { + @tmp2=@$ret; + if ($tmp2[0] eq "user1") { + if ($tmp2[1] ne "rlidw") { + exit (1); + } + $tmp2[1] = "rl"; + unshift @tmp, @tmp2; + } else { + unshift @tmp, @$ret; + } +} + +@tmp2=(); +while ($ret = pop(@$pos1)) { + unshift @tmp2, @$ret; +} + +exit(0); + + + diff --git a/src/tests/acladduser.pl b/src/tests/acladduser.pl new file mode 100755 index 0000000..7e29fa4 --- /dev/null +++ b/src/tests/acladduser.pl @@ -0,0 +1,41 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($wscell, $path, @pos1, @pos2, @neg1, @neg2, $ret, @tmp, @tmp2, @tmp3, $found); +&AFS_Init(); +$wscell = &AFS_fs_wscell(); +$found = 0; + +eval { &AFS_pts_createuser(user1,,); }; +$path = "/afs/${wscell}/service/acltest"; +mkdir $path, 0777; +($pos1, $neg1) = &AFS_fs_getacl($path); +$ret = &AFS_fs_setacl([$path],[["user1", "rl"]],,); +($pos2, $neg2) = &AFS_fs_getacl($path); +while ($ret = pop(@$pos2)) { + @tmp2=@$ret; + if ($tmp2[0] eq "user1") { + $found++; + } else { + unshift @tmp, @$ret; + } +} + +@tmp2=(); +while ($ret = pop(@$pos1)) { + unshift @tmp2, @$ret; +} + +if ($found != 1) { + exit(1); +} +exit(0); + + + diff --git a/src/tests/aclclearnegrights.pl b/src/tests/aclclearnegrights.pl new file mode 100755 index 0000000..738001f --- /dev/null +++ b/src/tests/aclclearnegrights.pl @@ -0,0 +1,48 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($wscell, $path, @pos1, @pos2, @neg1, @neg2, $ret, @tmp, @tmp2, @tmp3, $found); +&AFS_Init(); +$wscell = &AFS_fs_wscell(); +$found = 0; + +eval { &AFS_pts_createuser(user1,,); }; +$path = "/afs/${wscell}/service/acltest"; +mkdir $path, 0777; +($pos1, $neg1) = &AFS_fs_getacl($path); +$ret = &AFS_fs_setacl([$path],[],[["user1", "r"]],); +($pos2, $neg2) = &AFS_fs_getacl($path); +while ($ret = pop(@$neg2)) { + @tmp2=@$ret; + if ($tmp2[0] eq "user1") { + if ($tmp2[1] ne "r") { + exit 1; + } + $tmp2[1] = "rl"; + unshift @tmp, @tmp2; + } else { + unshift @tmp, @$ret; + } +} + +@tmp2=(); +while ($ret = pop(@$neg1)) { + unshift @tmp2, @$ret; +} + +if (@tmp != @tmp2) { + exit(1); +} +if (@pos1 != @pos2) { + exit(1); +} +exit(0); + + + diff --git a/src/tests/aclcopy.pl b/src/tests/aclcopy.pl new file mode 100755 index 0000000..dce2f54 --- /dev/null +++ b/src/tests/aclcopy.pl @@ -0,0 +1,32 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($wscell, $path, @pos1, @pos2, @neg1, @neg2, $ret, @tmp, @tmp2, @tmp3, $found, $path2); +&AFS_Init(); +$wscell = &AFS_fs_wscell(); +$found = 0; + +eval { &AFS_pts_createuser(user1,,); }; +$path = "/afs/${wscell}/service/acltest"; +$path2 = "/afs/${wscell}/service/acltest2"; +mkdir $path, 0777; +mkdir $path2, 0777; +($pos1, $neg1) = &AFS_fs_getacl($path); +$ret = &AFS_fs_copyacl($path,[$path2],1); +($pos2, $neg2) = &AFS_fs_getacl($path2); +if (@pos1 != @pos2) { + exit(1); +} +if (@neg1 != @neg2) { + exit(1); +} +exit(0); + + + diff --git a/src/tests/aclremovegroup.pl b/src/tests/aclremovegroup.pl new file mode 100755 index 0000000..65cb0f4 --- /dev/null +++ b/src/tests/aclremovegroup.pl @@ -0,0 +1,52 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($wscell, $path, @pos1, @pos2, @neg1, @neg2, $ret, @tmp, @tmp2, @tmp3, $found, $listref, $first); +&AFS_Init(); +$wscell = &AFS_fs_wscell(); +$found = 0; +$first = 0; + +$path = "/afs/${wscell}/service/acltest"; +mkdir $path, 0777; +($pos1, $neg1) = &AFS_fs_getacl($path); +$listref = "[ "; +while ($ret = pop(@$pos1)) { + $first++; + @tmp2=@$ret; + if ($tmp2[0] eq "group1") { + $found++; + } else { + unshift @tmp, @$ret; + if ($first == 0 ) { + $listref = $listref . "[ @tmp2 ]"; + } else { + $listref = $listref . ", [ @tmp2 ]"; + } + } +} +$listref = $listref . " ]"; + +if ($found != 1) { + print "WARNING: Can't remove user not on ACL. This shouldn't happen.\n"; + exit(1); +} + +$ret = &AFS_fs_setacl([$path],$listref,,); +($pos2, $neg2) = &AFS_fs_getacl($path); + +@tmp2=(); +while ($ret = pop(@$pos1)) { + unshift @tmp2, @$ret; +} + +exit(0); + + + diff --git a/src/tests/aclremoveuser.pl b/src/tests/aclremoveuser.pl new file mode 100755 index 0000000..9124c6d --- /dev/null +++ b/src/tests/aclremoveuser.pl @@ -0,0 +1,52 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($wscell, $path, @pos1, @pos2, @neg1, @neg2, $ret, @tmp, @tmp2, @tmp3, $found, $listref, $first); +&AFS_Init(); +$wscell = &AFS_fs_wscell(); +$found = 0; +$first = 0; + +$path = "/afs/${wscell}/service/acltest"; +mkdir $path, 0777; +($pos1, $neg1) = &AFS_fs_getacl($path); +$listref = "[ "; +while ($ret = pop(@$pos1)) { + $first++; + @tmp2=@$ret; + if ($tmp2[0] eq "user1") { + $found++; + } else { + unshift @tmp, @$ret; + if ($first == 0 ) { + $listref = $listref . "[ @tmp2 ]"; + } else { + $listref = $listref . ", [ @tmp2 ]"; + } + } +} +$listref = $listref . " ]"; + +if ($found != 1) { + print "WARNING: Can't remove user not on ACL. This shouldn't happen.\n"; + exit(1); +} + +$ret = &AFS_fs_setacl([$path],$listref,,); +($pos2, $neg2) = &AFS_fs_getacl($path); + +@tmp2=(); +while ($ret = pop(@$pos1)) { + unshift @tmp2, @$ret; +} + +exit(0); + + + diff --git a/src/tests/afs-newcell.pl b/src/tests/afs-newcell.pl new file mode 100755 index 0000000..91a2428 --- /dev/null +++ b/src/tests/afs-newcell.pl @@ -0,0 +1,294 @@ +#!/usr/bin/env perl -w +# Copyright (C) 2000 by Sam Hartman +# This file may be copied either under the terms of the GNU GPL or the IBM Public License +# either version 2 or later of the GPL or version 1.0 or later of the IPL. + +use Term::ReadLine; +use strict; +use OpenAFS::ConfigUtils; +use OpenAFS::Dirpath; +use OpenAFS::OS; +use OpenAFS::Auth; +use Getopt::Long; +use vars qw($admin $server $cellname $cachesize $part + $requirements_met $shutdown_needed $csdb); +my $rl = new Term::ReadLine('afs-newcell'); + +=head1 NAME + + afs-newcell - Set up initial database server for AFS cell. + +=head1 SYNOPSIS + +B [B<--requirements-met>] [B<--admin> admin_user] [B<--cellname> cellname] [B<--cachesize> size] [B<--partition> partition-letter] + +=head1 DESCRIPTION + + +This script sets up the initial AFS database and configures the first +database/file server. It also sets up an AFS cell's root volumes. It +assumes that you already have a fileserver and database servers. The +fileserver should have an empty root.afs. This script creates root.cell, +user, service and populates root.afs. + +The B option specifies that the initial requirements +have been met and that the script can proceed without displaying the +initial banner or asking for confirmation. + +The B option specifies the name of the administrative user. +This user will be given system:administrators and susers permission in +the cell. + +The B option specifies the name of the cell. + +The B option specifies the size of the AFS cache. + +=head1 AUTHOR + +Sam Hartman + +=cut + +# main script + +# mkvol(volume, mount) +sub mkvol($$) { + my ($vol, $mnt) = @_; + run("$openafsdirpath->{'afssrvsbindir'}/vos create $server $part $vol -localauth"); + unwind("$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part $vol -localauth"); + run("$openafsdirpath->{'afssrvbindir'}/fs mkm $mnt $vol "); + run("$openafsdirpath->{'afssrvbindir'}/fs sa $mnt system:anyuser rl"); +} + +GetOptions ( + "requirements-met" => \$requirements_met, + "cellname=s" => \$cellname, + "cachesize=s" => \$cachesize, + "partition=s" => \$part, + "admin=s" => \$admin); + +unless ($requirements_met) { + print <{'afsconfdir'}/KeyFile. If your cell's name is the same as + your Kerberos realm then create a principal called afs. Otherwise, + create a principal called afs/cellname in your realm. The cell + name should be all lower case, unlike Kerberos realms which are all + upper case. You can use asetkey from the openafs-krb5 package, or + if you used AFS3 salt to create the key, the bos addkey command. + +3) This machine should have a filesystem mounted on /vicepa. If you + do not have a free partition, on Linux you can create a large file by using + dd to extract bytes from /dev/zero. Create a filesystem on this file + and mount it using -oloop. + +4) You will need an administrative principal created in a Kerberos + realm. This principal will be added to susers and + system:administrators and thus will be able to run administrative + commands. Generally the user is a root instance of some administravie + user. For example if jruser is an administrator then it would be + reasonable to create jruser/root and specify jruser/root as the user + to be added in this script. + +5) The AFS client must not be running on this workstation. It will be + at the end of this script. + +eoreqs + + $_ = $rl->readline("Do you meet these requirements? [y/n] "); + unless (/^y/i ) { + print "Run this script again when you meet the requirements\n"; + exit(1); + } + + if ($> != 0) { + die "This script should almost always be run as root. Use the --requirements-met option to run as non-root.\n"; + } +} +open(MOUNT, "mount |") or die "Failed to run mount: $!\n"; +while() { + if(m:^AFS:) { + print "The AFS client is currently running on this workstation.\n"; + print "Please restart this script after running $openafsinitcmd->{'client-stop'}\n"; + exit(1); + } + if(m:^/afs on AFS:) { + print "The AFS client is currently running on this workstation.\n"; + print "Please restart this script after running $openafsinitcmd->{'client-stop'}\n"; + exit(1); + } +} +close MOUNT; + +unless ( -f "$openafsdirpath->{'afsconfdir'}/KeyFile") { + print "You do not have an AFS keyfile. Please create this using asetkey from openafs-krb5 or +the bos addkey command"; + exit(1); +} + +print "If the fileserver is not running, this may hang for 30 seconds.\n"; +run("$openafsinitcmd->{'filesrv-stop'}"); +$server = `hostname`; +chomp $server; +$admin = $rl->readline("What administrative principal should be used? ") unless $admin; + die "Please specify an administrative user\n" unless $admin; +$admin =~ s:/:.:g; +if($admin =~ /@/) { +die "The administrative user must be in the same realm as the cell and no realm may be specified.\n"; +} + +$cellname = $rl->readline("What cellname should be used? ") unless $cellname; +die "Please specify a cellname\n" unless $cellname; + +if (! -f "$openafsdirpath->{'afsconfdir'}/ThisCell") { + open(CELL, "> $openafsdirpath->{'afsconfdir'}/ThisCell"); + print CELL "${cellname}"; + close CELL; +} + +open(CELL, "$openafsdirpath->{'afsconfdir'}/ThisCell") or + die "Cannot open $openafsdirpath->{'afsconfdir'}/ThisCell: $!\n"; + +my $lcell = ; +chomp $lcell; +close CELL; + +run( "echo \\>$lcell >$openafsdirpath->{'afsconfdir'}/CellServDB"); +$csdb = `host $server|awk '{print $4 " #" $1}'`; +run( "echo $csdb >>$openafsdirpath->{'afsconfdir'}/CellServDB"); +run("$openafsinitcmd->{'filesrv-start'}"); +unwind("$openafsinitcmd->{'filesrv-stop'}"); +$shutdown_needed = 1; +run ("$openafsdirpath->{'afssrvbindir'}/bos addhost $server $server -localauth ||true"); +run("$openafsdirpath->{'afssrvbindir'}/bos adduser $server $admin -localauth"); +unwind("$openafsdirpath->{'afssrvbindir'}/bos removeuser $server $admin -localauth"); +if ( -f "$openafsdirpath->{'afsdbdir'}/prdb.DB0" ) { + die "Protection database already exists; cell already partially created\n"; + } +open(PRDB, "|$openafsdirpath->{'afssrvsbindir'}/pt_util -p $openafsdirpath->{'afsdbdir'}/prdb.DB0 -w ") +or die "Unable to start pt_util: $!\n"; +print PRDB "$admin 128/20 1 -204 -204\n"; +print PRDB "system:administrators 130/20 -204 -204 -204\n"; +print PRDB" $admin 1\n"; +close PRDB; +unwind( "rm $openafsdirpath->{'afsdbdir'}/prdb* "); +# Start up ptserver and vlserver +run("$openafsdirpath->{'afssrvbindir'}/bos create $server ptserver simple $openafsdirpath->{'afssrvlibexecdir'}/ptserver -localauth"); +unwind("$openafsdirpath->{'afssrvbindir'}/bos delete $server ptserver -localauth"); + +run("$openafsdirpath->{'afssrvbindir'}/bos create $server vlserver simple $openafsdirpath->{'afssrvlibexecdir'}/vlserver -localauth"); +unwind("$openafsdirpath->{'afssrvbindir'}/bos delete $server vlserver -localauth"); + +run( "$openafsdirpath->{'afssrvbindir'}/bos create $server fs fs ". + "-cmd $openafsdirpath->{'afssrvlibexecdir'}/fileserver ". + "-cmd $openafsdirpath->{'afssrvlibexecdir'}/volserver ". + "-cmd $openafsdirpath->{'afssrvlibexecdir'}/salvager -localauth"); +unwind( "$openafsdirpath->{'afssrvbindir'}/bos delete $server fs -localauth "); + +print "Waiting for database elections: "; +sleep(30); +print "done.\n"; +# Past this point we want to control when bos shutdown happens +$shutdown_needed = 0; +unwind( "$openafsdirpath->{'afssrvbindir'}/bos shutdown $server -localauth "); +run("$openafsdirpath->{'afssrvsbindir'}/vos create $server a root.afs -localauth"); +# bring up client + +$cachesize = $rl->readline("What size cache (in 1k blocks)? ") unless $cachesize; +die "Please specify a cache size\n" unless $cachesize; + +run("echo $lcell >$openafsdirpath->{'viceetcdir'}/ThisCell"); +run("cp $openafsdirpath->{'afsconfdir'}/CellServDB $openafsdirpath->{'viceetcdir'}/CellServDB"); +run("echo /afs:/usr/vice/cache:${cachesize} >$openafsdirpath->{'viceetcdir'}/cacheinfo"); +run("$openafsinitcmd->{'client-forcestart'}"); +my $afs_running = 0; +open(MOUNT, "mount |") or die "Failed to run mount: $!\n"; +while() { +if(m:^AFS:) { + $afs_running = 1; +} + } +unless ($afs_running) { +print "*** The AFS client failed to start.\n"; +print "Please fix whatever problem kept it from running.\n"; + exit(1); +} +unwind("$openafsinitcmd->{'client-stop'}"); + +unless ($part) { + $part = $rl ->readline("What partition? [a] "); + $part = "a" unless $part; +} + +&OpenAFS::Auth::authadmin(); + +run("$openafsdirpath->{'afssrvbindir'}/fs sa /afs system:anyuser rl"); + +run("$openafsdirpath->{'afssrvsbindir'}/vos create $server $part root.cell -localauth"); +unwind("$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part root.cell -localauth"); +# We make root.cell s:anyuser readable after we mount in the next +# loop. +open(CELLSERVDB, "$openafsdirpath->{'viceetcdir'}/CellServDB") + or die "Unable to open $openafsdirpath->{'viceetcdir'}/CellServDB: $!\n"; +while() { + chomp; + if (/^>\s*([a-z0-9_\-.]+)/ ) { + run("$openafsdirpath->{'afssrvbindir'}/fs mkm /afs/$1 root.cell -cell $1 -fast"); + unwind ("$openafsdirpath->{'afssrvbindir'}/fs rmm /afs/$1"); + } +} + +run("$openafsdirpath->{'afssrvbindir'}/fs sa /afs/$lcell system:anyuser rl"); +run ("$openafsdirpath->{'afssrvbindir'}/fs mkm /afs/.$lcell root.cell -cell $lcell -rw"); +unwind ("$openafsdirpath->{'afssrvbindir'}/fs rmm /afs/.$lcell"); +run("$openafsdirpath->{'afssrvbindir'}/fs mkm /afs/.root.afs root.afs -rw"); +unwind ("$openafsdirpath->{'afssrvbindir'}/fs rmm /afs/.root.afs"); + +mkvol( "user", "/afs/$lcell/user" ); +unwind( "$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part user -localauth "); + +mkvol( "service", "/afs/$lcell/service" ); +unwind( "$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part service -localauth "); + +mkvol( "rep", "/afs/$lcell/.replicated" ); +unwind( "$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part rep -localauth "); +run( "$openafsdirpath->{'afssrvbindir'}/fs mkm /afs/$lcell/replicated rep.readonly " ); + +run( "$openafsdirpath->{'afssrvsbindir'}/vos addsite $server $part rep -localauth" ); +run( "$openafsdirpath->{'afssrvsbindir'}/vos release rep -localauth" ); +unwind( "$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part rep.readonly -localauth "); + +mkvol( "unrep", "/afs/$lcell/unreplicated" ); +unwind( "$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part unrep -localauth "); + +$lcell =~ /^([^.]*)/; +my $cellpart = $1; +run("ln -s /afs/$lcell /afs/$cellpart"); +unwind ("rm /afs/$cellpart"); +run( "ln -s /afs/.$lcell /afs/.$cellpart" ); +unwind ("rm /afs/.$cellpart"); + +run( "$openafsdirpath->{'afssrvsbindir'}/vos addsite $server $part root.afs -localauth" ); +run( "$openafsdirpath->{'afssrvsbindir'}/vos addsite $server $part root.cell -localauth" ); +run( "$openafsdirpath->{'afssrvsbindir'}/vos release root.afs -localauth" ); +run( "$openafsdirpath->{'afssrvsbindir'}/vos release root.cell -localauth" ); +unwind( "$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part root.cell.readonly -localauth "); +unwind( "$openafsdirpath->{'afssrvsbindir'}/vos remove $server $part root.afs.readonly -localauth "); + + + +@unwinds = (); +END { +# If we fail before all the instances are created, we need to perform +# our own bos shutdown + system("$openafsdirpath->{'afssrvbindir'}/bos shutdown $server -localauth") if $shutdown_needed; + run(pop @unwinds) while @unwinds; + } diff --git a/src/tests/afs-rmcell.sh b/src/tests/afs-rmcell.sh new file mode 100755 index 0000000..53f5958 --- /dev/null +++ b/src/tests/afs-rmcell.sh @@ -0,0 +1,7 @@ +#!/bin/sh +/bin/rm -rf /usr/afs/db/prdb.DB0 /usr/afs/db/prdb.DBSYS1 /usr/afs/db/vldb.DB0 /usr/afs/db/vldb.DBSYS1 /usr/afs/local/BosConfig /usr/afs/etc/UserList /usr/afs/etc/ThisCell /usr/afs/etc/CellServDB +/bin/rm -rf /vicepa/AFSIDat +/bin/rm -rf /vicepb/AFSIDat +/bin/rm -rf /vicepa/V*.vol +/bin/rm -rf /vicepb/V*.vol +exit 0 diff --git a/src/tests/afsconf.pm b/src/tests/afsconf.pm new file mode 100644 index 0000000..86db460 --- /dev/null +++ b/src/tests/afsconf.pm @@ -0,0 +1,234 @@ +# CMUCS AFStools +# Copyright (c) 1996, Carnegie Mellon University +# All rights reserved. +# +# See CMUCS/CMU_copyright.pm for use and distribution information + +package OpenAFS::afsconf; + +=head1 NAME + +OpenAFS::afsconf - Access to AFS config info + +=head1 SYNOPSIS + + use OpenAFS::afsconf; + + $cell = AFS_conf_localcell(); + $cell = AFS_conf_canoncell($cellname); + @servers = AFS_conf_cellservers($cellname); + @cells = AFS_conf_listcells(); + %info = AFS_conf_cacheinfo(); + +=head1 DESCRIPTION + +This module provides access to information about the local workstation's +AFS configuration. This includes information like the name of the +local cell, where AFS is mounted, and access to information in the +F. All information returned by this module is based on the +configuration files, and does not necessarily reflect changes made +on the afsd command line or using B commands. + +=cut + +use OpenAFS::CMU_copyright; +use OpenAFS::config; +use OpenAFS::util qw(:DEFAULT :afs_internal); +use Exporter; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&AFS_conf_localcell + &AFS_conf_canoncell + &AFS_conf_listcells + &AFS_conf_cellservers + &AFS_conf_cacheinfo); + + +# _confpath($file) - Return path to a configuration file +sub _confpath { + my($file) = @_; + + if ($conf_paths{$file}) { + $conf_paths{$file}; + } elsif ($AFS_Parms{confdir} && -r "$AFS_Parms{confdir}/$file") { + $conf_paths{$file} = "$AFS_Parms{confdir}/$file"; + } elsif (-r "$def_ConfDir/$file") { + $conf_paths{$file} = "$def_ConfDir/$file"; + } else { + die "Unable to locate $file\n"; + } +} + +=head2 AFS_conf_localcell() + +Return the canonical name of the local cell. This depends on the contents +of the F file in the AFS configuration directory. + +=cut + +$AFS_Help{conf_localcell} = '=> $lclcell'; +sub AFS_conf_localcell { + my($path) = _confpath(ThisCell); + my($result); + + return '' if (!$path); + if (open(THISCELL, $path)) { + chomp($result = ); + close(THISCELL); + $result; + } else { + die "Unable to open $path: $!\n"; + } +} + +=head2 AFS_conf_canoncell($cellname) + +Return the canonical name of the specified cell, as found in F. +I<$cellname> may be any unique prefix of a cell name, as with various AFS +commands that take cell names as arguments. + +=head2 AFS_conf_cellservers($cellname) + +Return a list of servers in the specified cell. As with B, +I<$cellname> may be any unique prefix of a cell name. The resulting list +contains server hostnames, as found in F. + +=cut + +$AFS_Help{conf_canoncell} = '$cellname => $canon'; +$AFS_Help{conf_cellservers} = '$cellname => @servers'; + +sub AFS_conf_canoncell { &_findcell($_[0], 0); } +sub AFS_conf_cellservers { &_findcell($_[0], 1); } + +sub _findcell { + my($cellname, $doservers) = @_; + my($path, $found, @servers, $looking); + + return $canon_name{$cellname} if (!$doservers && $canon_name{$cellname}); + $path = _confpath(CellServDB) || die "Unable to locate CellServDB\n"; + + if (open(CELLSERVDB, $path)) { + my($cellpat) = $cellname; + $cellpat =~ s/(\W)/\\$1/g; + while () { + $looking = 0 if (/^\>/); + if (/^\>$cellpat/) { + if ($found) { + close(CELLSERVDB); + die "Cell name $cellname is not unique\n"; + } else { + chop($found = $_); + $found =~ s/^\>(\S+).*/$1/; + $looking = 1 if ($doservers); + } + } elsif ($looking && (/^[\.\d]+\s*\#\s*(.*\S+)/ || /^([\.\d]+)/)) { + push(@servers, $1); + } + } + close(CELLSERVDB); + if ($found) { + $canon_name{$cellname} = $found; + $doservers ? @servers : ($found); + } else { + die "Cell $cellname not in CellServDB\n"; + } + } else { + die "Unable to open $path: $!\n"; + } +} + +=head2 AFS_conf_listcells() + +Return a list of canonical names (as found in F) of all +known AFS cells. + +=cut + +$AFS_Help{conf_listcells} = '=> @cells'; +sub AFS_conf_listcells { + my($path, @cells); + + $path = _confpath(CellServDB) || die "Unable to locate CellServDB!\n"; + + if (open(CELLSERVDB, $path)) { + while () { + if (/^\>(\S+)/) { + push(@cells, $1); + } + } + close(CELLSERVDB); + @cells; + } else { + die "Unable to open $path: $!\n"; + } +} + +=head2 AFS_conf_cacheinfo() + +Return a table of information about the local workstation's cache +configuration. This table may contain any or all of the following elements: + +=over 14 + +=item afsroot + +Mount point for the AFS root volume + +=item cachedir + +Location of the AFS cache directory + +=item cachesize + +AFS cache size + +=item hardcachesize + +Hard limit on AFS cache size (if specified; probably Mach-specific) + +=item translator + +Name of AFS/NFS translator server (if set) + +=back + +=cut + +$AFS_Help{conf_cacheinfo} = '=> %info'; +sub AFS_conf_cacheinfo { + my($path) = _confpath('cacheinfo'); + my(%result, $line, $hcs); + + if ($path) { + if (open(CACHEINFO, $path)) { + chop($line = ); + close(CACHEINFO); + (@result{'afsroot', 'cachedir', 'cachesize'} , $hcs) = split(/:/, $line); + $result{'hardcachesize'} = $hcs if ($hcs); + } else { + die "Unable to open $path: $!\n"; + } + } + if ($ENV{'AFSSERVER'}) { + $result{'translator'} = $ENV{'AFSSERVER'}; + } elsif (open(SRVFILE, "$ENV{HOME}/.AFSSERVER") + || open(SRVFILE, "/.AFSSERVER")) { + $result{'translator'} = ; + close(SRVFILE); + } + %result; +} + + +1; + +=head1 COPYRIGHT + +The CMUCS AFStools, including this module are +Copyright (c) 1996, Carnegie Mellon University. All rights reserved. +For use and redistribution information, see CMUCS/CMU_copyright.pm + +=cut diff --git a/src/tests/afscp.c b/src/tests/afscp.c new file mode 100644 index 0000000..4bf5ce2 --- /dev/null +++ b/src/tests/afscp.c @@ -0,0 +1,500 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/*#include */ +#include + +/*#include */ +#include + +struct VenusFid { + afs_int32 Cell; + struct AFSFid Fid; +}; + +int statfile(char *path, char *cellname, afs_uint32 *server, + struct AFSFid *f) +{ + + struct ViceIoctl v; + struct VenusFid vf; + afs_int32 srvbuf[MAXHOSTS]; + int code; + + v.in=0; + v.in_size=0; + v.out=cellname; + v.out_size=MAXCELLCHARS; + if ((code=pioctl(path, VIOC_FILE_CELL_NAME, &v, 1))) + return code; + + v.out=(char *)&vf; + v.out_size=sizeof(struct VenusFid); + if ((code=pioctl(path, VIOCGETFID, &v, 1))) + return code; + memcpy(f,&vf.Fid, sizeof(struct AFSFid)); + + v.out=(char *)srvbuf; + v.out_size=sizeof(srvbuf); + if ((code=pioctl(path, VIOCWHEREIS, &v, 1))) + return code; + if (v.out_size <= sizeof(afs_int32)) + return EINVAL; + + memcpy(server, srvbuf, sizeof(afs_int32)); + return 0; +} + + +extern int RXAFSCB_ExecuteRequest(); +struct rx_securityClass *sc; + +extern int start_cb_server() +{ + struct rx_service *s; + + sc=rxnull_NewServerSecurityObject(); + s=rx_NewService(0,1,"afs", &sc, 1, RXAFSCB_ExecuteRequest); + if (!s) + return 1; + rx_StartServer(0); + return 0; +} + + +/*extern int rx_socket;*/ +extern unsigned short rx_port; +int do_rx_Init(void) +{ + struct sockaddr_in s; + int len; + + if (rx_Init(0)) { + fprintf(stderr, "Cannot initialize rx\n"); + return 1; + } + + len=sizeof(struct sockaddr_in); + if (getsockname(rx_socket, &s, &len)) { + perror("getsockname"); + return 1; + } + rx_port=ntohs(s.sin_port); + + return 0; +} + +struct rx_securityClass *get_sc(char * cellname) +{ +#if 0 + char realm[REALM_SZ]; + CREDENTIALS c; +#endif + + return rxnull_NewClientSecurityObject(); +#if 0 + + ucstring(realm, cellname, REALM_SZ); + + if (krb_get_cred("afs", "", realm, &c)) { + if (get_ad_tkt("afs","",realm, DEFAULT_TKT_LIFE)) { + return NULL; + } else { + if (krb_get_cred("afs", "", realm, &c)) { + return NULL; + } + } + } + + return rxkad_NewClientSecurityObject(rxkad_clear, c.session, c.kvno, + c.ticket_st.length, c.ticket_st.dat); +#endif +} + +#define scindex_NULL 0 +#define scindex_RXKAD 2 + +#define scindex scindex_RXKAD +int main(int argc, char **argv) +{ + char scell[MAXCELLCHARS], dcell[MAXCELLCHARS]; + afs_uint32 ssrv, dsrv; + char *databuffer,*srcf,*destd,*destf,*destpath; + struct stat statbuf; + + struct AFSStoreStatus sst; + struct AFSFetchStatus fst,dfst; + struct AFSVolSync vs; + struct AFSCallBack scb,dcb; + struct AFSFid sf, dd, df; + + int filesz; + int ch, blksize, bytesremaining, bytes; + struct timeval start, finish; + struct timezone tz; + struct rx_securityClass *ssc = 0, *dsc = 0; + int sscindex, dscindex; + struct rx_connection *sconn,*dconn; + struct rx_call *scall, *dcall; + int code,fetchcode,storecode,printcallerrs; + int slcl = 0, dlcl = 0; + int sfd, dfd, unauth = 0; + + struct AFSCBFids theFids; + struct AFSCBs theCBs; + + + blksize=8*1024; + + while ((ch=getopt(argc, argv, "ioub:")) != -1) { + switch(ch) + { + case 'b': + blksize=atoi(optarg); + break; + case 'i': + slcl=1; + break; + case 'o': + dlcl=1; + break; + case 'a': + unauth=1; + break; + default: + exit(1); + } + } + + + if (argc - optind < 2) { + fprintf(stderr, "Usage: afscp [-i|-o]] [-b xfersz] [-u] source dest\n"); + fprintf(stderr, " -b Set block size\n"); + fprintf(stderr, " -i Source is local (copy into AFS)\n"); + fprintf(stderr, " -o Dest is local (copy out of AFS)\n"); + fprintf(stderr, " -u Run unauthenticated\n"); + exit(1); + } + srcf=argv[optind++]; + destpath=argv[optind++]; + destd=strdup(destpath); + if (!destd) { + perror("strdup"); + exit(1); + } + if ((destf=strrchr(destd, '/'))) { + *destf++=0; + } else { + destf=destd; + destd="."; + } + + + if (!slcl && statfile(srcf, scell, &ssrv, &sf)) { + fprintf(stderr, "Cannot get attributes of %s\n", srcf); + exit(1); + } + if (!dlcl && statfile(destd, dcell, &dsrv, &dd)) { + fprintf(stderr, "Cannot get attributes of %s\n", destd); + exit(1); + } + + if ((databuffer=malloc(blksize)) == NULL) { + perror("malloc"); + exit(1); + } + + if (do_rx_Init()) + exit(1); + + if (start_cb_server()) { + printf("Cannot start callback service\n"); + goto Fail_rx; + } + + if (!slcl) { + sscindex=scindex_RXKAD; + if (unauth || (ssc=get_sc(scell)) == NULL) { + ssc=rxnull_NewClientSecurityObject(); + sscindex=scindex_NULL; + /*printf("Cannot get authentication for cell %s; running unauthenticated\n", scell);*/ + } + sscindex=scindex_NULL; + + if ((sconn=rx_NewConnection(ssrv, htons(AFSCONF_FILEPORT), 1, ssc, + sscindex)) + ==NULL) { + struct in_addr s; + s.s_addr=ssrv; + printf("Cannot initialize rx connection to source server (%s)\n", + inet_ntoa(s)); + goto Fail_sc; + } + } + + if (!dlcl) { + if (!slcl && ssrv == dsrv) { + dconn=sconn; + dsc=NULL; + } else { + if (slcl || strcmp(scell, dcell)){ + dscindex=scindex_RXKAD; + if (unauth || (dsc=get_sc(dcell)) == NULL) { + dsc=rxnull_NewClientSecurityObject(); + dscindex=scindex_NULL; + /*printf("Cannot get authentication for cell %s; running unauthenticated\n", dcell);*/ + } + dscindex=scindex_NULL; + } else { + dsc=ssc; + dscindex=sscindex; + } + + if ((dconn=rx_NewConnection(dsrv, htons(AFSCONF_FILEPORT), 1, dsc, + dscindex)) + ==NULL) { + struct in_addr s; + s.s_addr=dsrv; + printf("Cannot initialize rx connection to dest server (%s)\n", + inet_ntoa(s)); + goto Fail_sconn; + } + } + } + + + memset(&sst, 0, sizeof(struct AFSStoreStatus)); + + if (dlcl) { + dfd = open(destpath, O_RDWR|O_CREAT|O_EXCL, 0666); + if (dfd < 0 && errno == EEXIST) { + printf("%s already exists, overwriting\n", destpath); + dfd = open(destpath, O_RDWR|O_TRUNC, 0666); + if (dfd < 0) { + fprintf(stderr, "Cannot open %s (%s)\n", destpath, + error_message(errno)); + goto Fail_dconn; + } + } else if (dfd < 0) { + fprintf(stderr, "Cannot open %s (%s)\n", destpath, + error_message(errno)); + goto Fail_dconn; + } + } else { + if ((code=RXAFS_CreateFile(dconn, &dd, destf, &sst, &df, &fst, + &dfst, &dcb, &vs))) { + if (code == EEXIST) { + printf("%s already exits, overwriting\n", destpath); + if (statfile(destpath, dcell, &dsrv, &df)) + fprintf(stderr, "Cannot get attributes of %s\n", + destpath); + else + code=0; + } else { + printf("Cannot create %s (%s)\n", destpath, + error_message(code)); + if (code) + goto Fail_dconn; + } + } + } + + if (slcl) { + sfd = open(srcf, O_RDONLY, 0); + if (sfd < 0) { + fprintf(stderr, "Cannot open %s (%s)\n", srcf, + error_message(errno)); + goto Fail_dconn; + } + if (fstat(sfd, &statbuf) < 0) { + fprintf(stderr, "Cannot stat %s (%s)\n", srcf, + error_message(errno)); + close(sfd); + goto Fail_dconn; + } + } else { + if ((code=RXAFS_FetchStatus(sconn, &sf, &fst, &scb, &vs))) { + printf("Cannot fetchstatus of %d.%d (%s)\n", sf.Volume, sf.Vnode, + error_message(code)); + goto Fail_dconn; + } + } + + + + if (slcl) { + filesz=statbuf.st_size; + } else { + filesz=fst.Length; + } + + printcallerrs=0; + fetchcode=0; + storecode=0; + if (!slcl) scall=rx_NewCall(sconn); + if (!dlcl) dcall=rx_NewCall(dconn); + gettimeofday(&start, &tz); + + if (!slcl) { + if ((code = StartRXAFS_FetchData(scall, &sf, 0, filesz))) { + printf("Unable to fetch data from %s (%s)\n", srcf, + error_message(code)); + goto Fail_call; + } + } + + if (!dlcl) { + if (slcl) { + sst.Mask=AFS_SETMODTIME|AFS_SETMODE; + sst.ClientModTime=statbuf.st_mtime; + sst.UnixModeBits=statbuf.st_mode & ~(S_IFMT|S_ISUID|S_ISGID); + } else { + sst.Mask=AFS_SETMODTIME|AFS_SETMODE; + sst.ClientModTime=fst.ClientModTime; + sst.UnixModeBits=fst.UnixModeBits & ~(S_IFMT|S_ISUID|S_ISGID); + } + + if ((code = StartRXAFS_StoreData(dcall, &df, &sst, 0, filesz, filesz))) { + printf("Unable to store data to %s (%s)\n", destpath, + error_message(code)); + goto Fail_call; + } + } + + if (slcl) { + bytesremaining=statbuf.st_size; + } else { + rx_Read(scall,&bytesremaining,sizeof(afs_int32)); + bytesremaining=ntohl(bytesremaining); + } + + while (bytesremaining >0) { + /*printf("%d bytes remaining\n",bytesremaining);*/ + if (slcl) { + if ((bytes=read(sfd, databuffer, + min(blksize,bytesremaining)))<= 0) { + fetchcode=errno; + break; + } + } else { + if ((bytes=rx_Read(scall, databuffer, + min(blksize,bytesremaining)))<= 0) + break; + } + if (dlcl) { + if (write(dfd, databuffer, bytes) != bytes) { + storecode=errno; + break; + } + } else { + if (rx_Write(dcall, databuffer, bytes) != bytes) + break; + } + bytesremaining -= bytes; + /*printf("%d bytes copied\n",bytes);*/ + } + + + if (bytesremaining > 0) { + printf("Some network error occured while copying data\n"); + goto Fail_call; + } + + if (!slcl) fetchcode = EndRXAFS_FetchData(scall, &fst, &scb, &vs); + if (!dlcl) storecode = EndRXAFS_StoreData(dcall, &fst, &vs); + printcallerrs=1; + Fail_call: + + if (slcl) { + if (close(sfd) && !fetchcode) fetchcode = errno; + } else { + fetchcode = rx_EndCall(scall, fetchcode); + } + if (fetchcode && printcallerrs) + printf("Error returned from fetch: %s\n", error_message(fetchcode)); + + if (dlcl) { + if (close(dfd) && !storecode) storecode = errno; + } else { + storecode = rx_EndCall(dcall, storecode); + } + if (storecode && printcallerrs) + printf("Error returned from store: %s\n", error_message(storecode)); + + gettimeofday(&finish, &tz); + + if (!slcl) { + theFids.AFSCBFids_len=1; + theFids.AFSCBFids_val=&sf; + theCBs.AFSCBs_len=1; + theCBs.AFSCBs_val=&scb; + scb.CallBackType = CB_DROPPED; + if ((code=RXAFS_GiveUpCallBacks(sconn, &theFids, &theCBs))) + printf("Could not give up source callback: %s\n", + error_message(code)); + } + + if (!dlcl) { + theFids.AFSCBFids_len=1; + theFids.AFSCBFids_val=&df; + theCBs.AFSCBs_len=1; + theCBs.AFSCBs_val=&dcb; + dcb.CallBackType = CB_DROPPED; + if ((code=RXAFS_GiveUpCallBacks(dconn, &theFids, &theCBs))) + printf("Could not give up target callback: %s\n", + error_message(code)); + } + + if (code==0) + code=storecode; + if (code==0) + code=fetchcode; + + Fail_dconn: + if (!dlcl && (slcl || dconn != sconn)) + rx_DestroyConnection(dconn); + Fail_sconn: + if (!slcl) rx_DestroyConnection(sconn); + Fail_sc: + if (dsc && dsc != ssc) + RXS_Close(dsc); + if (ssc) RXS_Close(ssc); + Fail_rx: + rx_Finalize(); + + free(databuffer); + if (printcallerrs) { + double rate,size,time; + if (finish.tv_sec == start.tv_sec) { + printf("Copied %d bytes in %d microseconds\n", filesz, finish.tv_usec + -start.tv_usec); + } else { + printf("Copied %d bytes in %d seconds\n", filesz, finish.tv_sec + -start.tv_sec); + } + + size=filesz/1024.0; + time=finish.tv_sec-start.tv_sec + (finish.tv_usec-start.tv_usec)/1e+06; + rate=size/time; + printf("Transfer rate %g Kbytes/sec\n", rate); + + } + + exit(code != 0); +} diff --git a/src/tests/afscp_callback.c b/src/tests/afscp_callback.c new file mode 100644 index 0000000..6d2549d --- /dev/null +++ b/src/tests/afscp_callback.c @@ -0,0 +1,156 @@ +#include +#include /*Callback interface defs*/ +int afs_cb_inited = 0; +struct interfaceAddr afs_cb_interface; +static int init_afs_cb() { + int count; + + afs_uuid_create(&afs_cb_interface.uuid); + count = rx_getAllAddr(&afs_cb_interface.addr_in, AFS_MAX_INTERFACE_ADDR); + if ( count <= 0 ) + afs_cb_interface.numberOfInterfaces = 0; + else + afs_cb_interface.numberOfInterfaces = count; + afs_cb_inited = 1; + return 0; +} +afs_int32 SRXAFSCB_CallBack(rxcall, Fids_Array, CallBack_Array) + struct rx_call *rxcall; + AFSCBFids *Fids_Array; + AFSCBs *CallBack_Array; + +{ /*SRXAFSCB_CallBack*/ + return(0); + +} /*SRXAFSCB_CallBack*/ + + +afs_int32 SRXAFSCB_InitCallBackState(rxcall) + struct rx_call *rxcall; + +{ /*SRXAFSCB_InitCallBackState*/ + return(0); + +} /*SRXAFSCB_InitCallBackState*/ + +afs_int32 SRXAFSCB_Probe(rxcall) + struct rx_call *rxcall; + +{ /*SRXAFSCB_Probe*/ + return(0); + +} /*SRXAFSCB_Probe*/ + + +afs_int32 SRXAFSCB_GetCE(rxcall) + struct rx_call *rxcall; + +{ /*SRXAFSCB_GetCE*/ + return(0); +} /*SRXAFSCB_GetCE*/ + + +afs_int32 SRXAFSCB_GetCE64(rxcall) + struct rx_call *rxcall; + +{ /*SRXAFSCB_GetCE64*/ + return(0); +} /*SRXAFSCB_GetCE64*/ + + +afs_int32 SRXAFSCB_GetLock(rxcall) + struct rx_call *rxcall; + +{ /*SRXAFSCB_GetLock*/ + return(0); + +} /*SRXAFSCB_GetLock*/ +afs_int32 SRXAFSCB_XStatsVersion(rxcall) + struct rx_call *rxcall; + +{ /*SRXAFSCB_XStatsVersion*/ + return(0); + +} /*SRXAFSCB_XStatsVersion*/ + +afs_int32 SRXAFSCB_GetXStats(rxcall) + struct rx_call *rxcall; + +{ /*SRXAFSCB_GetXStats*/ + return(0); +} /*SRXAFSCB_GetXStats*/ + +int SRXAFSCB_InitCallBackState2(rxcall, addr) +struct rx_call *rxcall; +struct interfaceAddr * addr; +{ + return RXGEN_OPCODE; +} + +int SRXAFSCB_WhoAreYou(rxcall, addr) +struct rx_call *rxcall; +struct interfaceAddr *addr; +{ + if ( rxcall && addr ) + { + if (!afs_cb_inited) init_afs_cb(); + *addr = afs_cb_interface; + } + return(0); +} + +int SRXAFSCB_InitCallBackState3(rxcall, uuidp) +struct rx_call *rxcall; +afsUUID *uuidp; +{ + return(0); +} +int SRXAFSCB_ProbeUuid(rxcall, uuidp) +struct rx_call *rxcall; +afsUUID *uuidp; +{ + int code = 0; + if (!afs_cb_inited) init_afs_cb(); + if (!afs_uuid_equal(uuidp, &afs_cb_interface.uuid)) + code = 1; /* failure */ + return code; +} + +afs_int32 SRXAFSCB_GetServerPrefs(rxcall, serverIndex, srvrAddr, srvrRank) +struct rx_call *rxcall; +afs_int32 serverIndex; +afs_int32 *srvrAddr; +afs_int32 *srvrRank; +{ + return RXGEN_OPCODE; +} + + +afs_int32 SRXAFSCB_GetCellServDB(rxcall, cellIndex, cellName, cellHosts) +struct rx_call *rxcall; +afs_int32 cellIndex; +char *cellName; +afs_int32 *cellHosts; +{ + return RXGEN_OPCODE; +} + + +afs_int32 SRXAFSCB_GetLocalCell(rxcall, cellName) +struct rx_call *rxcall; +char *cellName; +{ + return RXGEN_OPCODE; +} + + +afs_int32 SRXAFSCB_GetCacheConfig(rxcall, callerVersion, serverVersion, + configCount, config) +struct rx_call *rxcall; +afs_uint32 callerVersion; +afs_uint32 *serverVersion; +afs_uint32 *configCount; +cacheConfig *config; +{ + return RXGEN_OPCODE; +} diff --git a/src/tests/append-over-page.c b/src/tests/append-over-page.c new file mode 100644 index 0000000..6b875a9 --- /dev/null +++ b/src/tests/append-over-page.c @@ -0,0 +1,977 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static char long_buf[] = +"1000\n" +"1001\n" +"1002\n" +"1003\n" +"1004\n" +"1005\n" +"1006\n" +"1007\n" +"1008\n" +"1009\n" +"1010\n" +"1011\n" +"1012\n" +"1013\n" +"1014\n" +"1015\n" +"1016\n" +"1017\n" +"1018\n" +"1019\n" +"1020\n" +"1021\n" +"1022\n" +"1023\n" +"1024\n" +"1025\n" +"1026\n" +"1027\n" +"1028\n" +"1029\n" +"1030\n" +"1031\n" +"1032\n" +"1033\n" +"1034\n" +"1035\n" +"1036\n" +"1037\n" +"1038\n" +"1039\n" +"1040\n" +"1041\n" +"1042\n" +"1043\n" +"1044\n" +"1045\n" +"1046\n" +"1047\n" +"1048\n" +"1049\n" +"1050\n" +"1051\n" +"1052\n" +"1053\n" +"1054\n" +"1055\n" +"1056\n" +"1057\n" +"1058\n" +"1059\n" +"1060\n" +"1061\n" +"1062\n" +"1063\n" +"1064\n" +"1065\n" +"1066\n" +"1067\n" +"1068\n" +"1069\n" +"1070\n" +"1071\n" +"1072\n" +"1073\n" +"1074\n" +"1075\n" +"1076\n" +"1077\n" +"1078\n" +"1079\n" +"1080\n" +"1081\n" +"1082\n" +"1083\n" +"1084\n" +"1085\n" +"1086\n" +"1087\n" +"1088\n" +"1089\n" +"1090\n" +"1091\n" +"1092\n" +"1093\n" +"1094\n" +"1095\n" +"1096\n" +"1097\n" +"1098\n" +"1099\n" +"1100\n" +"1101\n" +"1102\n" +"1103\n" +"1104\n" +"1105\n" +"1106\n" +"1107\n" +"1108\n" +"1109\n" +"1110\n" +"1111\n" +"1112\n" +"1113\n" +"1114\n" +"1115\n" +"1116\n" +"1117\n" +"1118\n" +"1119\n" +"1120\n" +"1121\n" +"1122\n" +"1123\n" +"1124\n" +"1125\n" +"1126\n" +"1127\n" +"1128\n" +"1129\n" +"1130\n" +"1131\n" +"1132\n" +"1133\n" +"1134\n" +"1135\n" +"1136\n" +"1137\n" +"1138\n" +"1139\n" +"1140\n" +"1141\n" +"1142\n" +"1143\n" +"1144\n" +"1145\n" +"1146\n" +"1147\n" +"1148\n" +"1149\n" +"1150\n" +"1151\n" +"1152\n" +"1153\n" +"1154\n" +"1155\n" +"1156\n" +"1157\n" +"1158\n" +"1159\n" +"1160\n" +"1161\n" +"1162\n" +"1163\n" +"1164\n" +"1165\n" +"1166\n" +"1167\n" +"1168\n" +"1169\n" +"1170\n" +"1171\n" +"1172\n" +"1173\n" +"1174\n" +"1175\n" +"1176\n" +"1177\n" +"1178\n" +"1179\n" +"1180\n" +"1181\n" +"1182\n" +"1183\n" +"1184\n" +"1185\n" +"1186\n" +"1187\n" +"1188\n" +"1189\n" +"1190\n" +"1191\n" +"1192\n" +"1193\n" +"1194\n" +"1195\n" +"1196\n" +"1197\n" +"1198\n" +"1199\n" +"1200\n" +"1201\n" +"1202\n" +"1203\n" +"1204\n" +"1205\n" +"1206\n" +"1207\n" +"1208\n" +"1209\n" +"1210\n" +"1211\n" +"1212\n" +"1213\n" +"1214\n" +"1215\n" +"1216\n" +"1217\n" +"1218\n" +"1219\n" +"1220\n" +"1221\n" +"1222\n" +"1223\n" +"1224\n" +"1225\n" +"1226\n" +"1227\n" +"1228\n" +"1229\n" +"1230\n" +"1231\n" +"1232\n" +"1233\n" +"1234\n" +"1235\n" +"1236\n" +"1237\n" +"1238\n" +"1239\n" +"1240\n" +"1241\n" +"1242\n" +"1243\n" +"1244\n" +"1245\n" +"1246\n" +"1247\n" +"1248\n" +"1249\n" +"1250\n" +"1251\n" +"1252\n" +"1253\n" +"1254\n" +"1255\n" +"1256\n" +"1257\n" +"1258\n" +"1259\n" +"1260\n" +"1261\n" +"1262\n" +"1263\n" +"1264\n" +"1265\n" +"1266\n" +"1267\n" +"1268\n" +"1269\n" +"1270\n" +"1271\n" +"1272\n" +"1273\n" +"1274\n" +"1275\n" +"1276\n" +"1277\n" +"1278\n" +"1279\n" +"1280\n" +"1281\n" +"1282\n" +"1283\n" +"1284\n" +"1285\n" +"1286\n" +"1287\n" +"1288\n" +"1289\n" +"1290\n" +"1291\n" +"1292\n" +"1293\n" +"1294\n" +"1295\n" +"1296\n" +"1297\n" +"1298\n" +"1299\n" +"1300\n" +"1301\n" +"1302\n" +"1303\n" +"1304\n" +"1305\n" +"1306\n" +"1307\n" +"1308\n" +"1309\n" +"1310\n" +"1311\n" +"1312\n" +"1313\n" +"1314\n" +"1315\n" +"1316\n" +"1317\n" +"1318\n" +"1319\n" +"1320\n" +"1321\n" +"1322\n" +"1323\n" +"1324\n" +"1325\n" +"1326\n" +"1327\n" +"1328\n" +"1329\n" +"1330\n" +"1331\n" +"1332\n" +"1333\n" +"1334\n" +"1335\n" +"1336\n" +"1337\n" +"1338\n" +"1339\n" +"1340\n" +"1341\n" +"1342\n" +"1343\n" +"1344\n" +"1345\n" +"1346\n" +"1347\n" +"1348\n" +"1349\n" +"1350\n" +"1351\n" +"1352\n" +"1353\n" +"1354\n" +"1355\n" +"1356\n" +"1357\n" +"1358\n" +"1359\n" +"1360\n" +"1361\n" +"1362\n" +"1363\n" +"1364\n" +"1365\n" +"1366\n" +"1367\n" +"1368\n" +"1369\n" +"1370\n" +"1371\n" +"1372\n" +"1373\n" +"1374\n" +"1375\n" +"1376\n" +"1377\n" +"1378\n" +"1379\n" +"1380\n" +"1381\n" +"1382\n" +"1383\n" +"1384\n" +"1385\n" +"1386\n" +"1387\n" +"1388\n" +"1389\n" +"1390\n" +"1391\n" +"1392\n" +"1393\n" +"1394\n" +"1395\n" +"1396\n" +"1397\n" +"1398\n" +"1399\n" +"1400\n" +"1401\n" +"1402\n" +"1403\n" +"1404\n" +"1405\n" +"1406\n" +"1407\n" +"1408\n" +"1409\n" +"1410\n" +"1411\n" +"1412\n" +"1413\n" +"1414\n" +"1415\n" +"1416\n" +"1417\n" +"1418\n" +"1419\n" +"1420\n" +"1421\n" +"1422\n" +"1423\n" +"1424\n" +"1425\n" +"1426\n" +"1427\n" +"1428\n" +"1429\n" +"1430\n" +"1431\n" +"1432\n" +"1433\n" +"1434\n" +"1435\n" +"1436\n" +"1437\n" +"1438\n" +"1439\n" +"1440\n" +"1441\n" +"1442\n" +"1443\n" +"1444\n" +"1445\n" +"1446\n" +"1447\n" +"1448\n" +"1449\n" +"1450\n" +"1451\n" +"1452\n" +"1453\n" +"1454\n" +"1455\n" +"1456\n" +"1457\n" +"1458\n" +"1459\n" +"1460\n" +"1461\n" +"1462\n" +"1463\n" +"1464\n" +"1465\n" +"1466\n" +"1467\n" +"1468\n" +"1469\n" +"1470\n" +"1471\n" +"1472\n" +"1473\n" +"1474\n" +"1475\n" +"1476\n" +"1477\n" +"1478\n" +"1479\n" +"1480\n" +"1481\n" +"1482\n" +"1483\n" +"1484\n" +"1485\n" +"1486\n" +"1487\n" +"1488\n" +"1489\n" +"1490\n" +"1491\n" +"1492\n" +"1493\n" +"1494\n" +"1495\n" +"1496\n" +"1497\n" +"1498\n" +"1499\n" +"1500\n" +"1501\n" +"1502\n" +"1503\n" +"1504\n" +"1505\n" +"1506\n" +"1507\n" +"1508\n" +"1509\n" +"1510\n" +"1511\n" +"1512\n" +"1513\n" +"1514\n" +"1515\n" +"1516\n" +"1517\n" +"1518\n" +"1519\n" +"1520\n" +"1521\n" +"1522\n" +"1523\n" +"1524\n" +"1525\n" +"1526\n" +"1527\n" +"1528\n" +"1529\n" +"1530\n" +"1531\n" +"1532\n" +"1533\n" +"1534\n" +"1535\n" +"1536\n" +"1537\n" +"1538\n" +"1539\n" +"1540\n" +"1541\n" +"1542\n" +"1543\n" +"1544\n" +"1545\n" +"1546\n" +"1547\n" +"1548\n" +"1549\n" +"1550\n" +"1551\n" +"1552\n" +"1553\n" +"1554\n" +"1555\n" +"1556\n" +"1557\n" +"1558\n" +"1559\n" +"1560\n" +"1561\n" +"1562\n" +"1563\n" +"1564\n" +"1565\n" +"1566\n" +"1567\n" +"1568\n" +"1569\n" +"1570\n" +"1571\n" +"1572\n" +"1573\n" +"1574\n" +"1575\n" +"1576\n" +"1577\n" +"1578\n" +"1579\n" +"1580\n" +"1581\n" +"1582\n" +"1583\n" +"1584\n" +"1585\n" +"1586\n" +"1587\n" +"1588\n" +"1589\n" +"1590\n" +"1591\n" +"1592\n" +"1593\n" +"1594\n" +"1595\n" +"1596\n" +"1597\n" +"1598\n" +"1599\n" +"1600\n" +"1601\n" +"1602\n" +"1603\n" +"1604\n" +"1605\n" +"1606\n" +"1607\n" +"1608\n" +"1609\n" +"1610\n" +"1611\n" +"1612\n" +"1613\n" +"1614\n" +"1615\n" +"1616\n" +"1617\n" +"1618\n" +"1619\n" +"1620\n" +"1621\n" +"1622\n" +"1623\n" +"1624\n" +"1625\n" +"1626\n" +"1627\n" +"1628\n" +"1629\n" +"1630\n" +"1631\n" +"1632\n" +"1633\n" +"1634\n" +"1635\n" +"1636\n" +"1637\n" +"1638\n" +"1639\n" +"1640\n" +"1641\n" +"1642\n" +"1643\n" +"1644\n" +"1645\n" +"1646\n" +"1647\n" +"1648\n" +"1649\n" +"1650\n" +"1651\n" +"1652\n" +"1653\n" +"1654\n" +"1655\n" +"1656\n" +"1657\n" +"1658\n" +"1659\n" +"1660\n" +"1661\n" +"1662\n" +"1663\n" +"1664\n" +"1665\n" +"1666\n" +"1667\n" +"1668\n" +"1669\n" +"1670\n" +"1671\n" +"1672\n" +"1673\n" +"1674\n" +"1675\n" +"1676\n" +"1677\n" +"1678\n" +"1679\n" +"1680\n" +"1681\n" +"1682\n" +"1683\n" +"1684\n" +"1685\n" +"1686\n" +"1687\n" +"1688\n" +"1689\n" +"1690\n" +"1691\n" +"1692\n" +"1693\n" +"1694\n" +"1695\n" +"1696\n" +"1697\n" +"1698\n" +"1699\n" +"1700\n" +"1701\n" +"1702\n" +"1703\n" +"1704\n" +"1705\n" +"1706\n" +"1707\n" +"1708\n" +"1709\n" +"1710\n" +"1711\n" +"1712\n" +"1713\n" +"1714\n" +"1715\n" +"1716\n" +"1717\n" +"1718\n" +"1719\n" +"1720\n" +"1721\n" +"1722\n" +"1723\n" +"1724\n" +"1725\n" +"1726\n" +"1727\n" +"1728\n" +"1729\n" +"1730\n" +"1731\n" +"1732\n" +"1733\n" +"1734\n" +"1735\n" +"1736\n" +"1737\n" +"1738\n" +"1739\n" +"1740\n" +"1741\n" +"1742\n" +"1743\n" +"1744\n" +"1745\n" +"1746\n" +"1747\n" +"1748\n" +"1749\n" +"1750\n" +"1751\n" +"1752\n" +"1753\n" +"1754\n" +"1755\n" +"1756\n" +"1757\n" +"1758\n" +"1759\n" +"1760\n" +"1761\n" +"1762\n" +"1763\n" +"1764\n" +"1765\n" +"1766\n" +"1767\n" +"1768\n" +"1769\n" +"1770\n" +"1771\n" +"1772\n" +"1773\n" +"1774\n" +"1775\n" +"1776\n" +"1777\n" +"1778\n" +"1779\n" +"1780\n" +"1781\n" +"1782\n" +"1783\n" +"1784\n" +"1785\n" +"1786\n" +"1787\n" +"1788\n" +"1789\n" +"1790\n" +"1791\n" +"1792\n" +"1793\n" +"1794\n" +"1795\n" +"1796\n" +"1797\n" +"1798\n" +"1799\n" +"1800\n" +"1801\n" +"1802\n" +"1803\n" +"1804\n" +"1805\n" +"1806\n" +"1807\n" +"1808\n" +"1809\n" +"1810\n" +"1811\n" +"1812\n" +"1813\n" +"1814\n" +"1815\n" +"1816\n" +"1817\n" +"1818\n" +"1819\n" +"1820\n" +"1821\n" +"1822\n" +"1823\n" +"1824\n" +"1825\n" +"1826\n"; + +/* + * compare this file with read and mmap. + * return 0 iff identical. + */ + +static int +compare_file (const char *filename) +{ + struct stat sb; + int fd; + int ret; + void *read_buf; + void *mmap_buf; + + fd = open (filename, O_RDONLY); + if (fd < 0) + err(1, "open %s", filename); + ret = fstat (fd, &sb); + if (ret < 0) + err (1, "stat %s", filename); + read_buf = malloc (sb.st_size); + if (read_buf == NULL) + err (1, "malloc %u", (unsigned)sb.st_size); + ret = read (fd, read_buf, sb.st_size); + if (ret < 0) + err (1, "read %s", filename); + if (ret != sb.st_size) + errx (1, "short read from %s", filename); + mmap_buf = mmap (NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mmap_buf == (void *)MAP_FAILED) + err (1, "mmap %s", filename); + ret = memcmp (read_buf, mmap_buf, sb.st_size); + close (fd); + free (read_buf); + return ret; +} + +static void +doit (const char *filename) +{ + int fd; + int ret; + + fd = open (filename, O_WRONLY | O_APPEND | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + err (1, "open %s", filename); + ret = close (fd); + if (ret < 0) + err (1, "close %s", filename); + fd = open (filename, O_WRONLY | O_APPEND); + if (fd < 0) + err (1, "open %s", filename); + ret = write (fd, "foobar\n", 7); + if (ret < 0) + err (1, "write %s", filename); + if (ret != 7) + errx (1, "short write to %s", filename); + ret = close (fd); + if (ret < 0) + err(1, "close %s", filename); + + if(compare_file (filename)) + errx (1, "compare 1 failed"); + + fd = open (filename, O_WRONLY | O_APPEND); + if (fd < 0) + err (1, "open %s", filename); + ret = write (fd, long_buf, strlen(long_buf)); + if (ret < 0) + err (1, "write %s", filename); + if (ret != strlen(long_buf)) + errx (1, "short write to %s", filename); + ret = close (fd); + if (ret < 0) + err(1, "close %s", filename); + + if(compare_file (filename)) + errx (1, "compare 2 failed"); +} + +int +main(int argc, char **argv) +{ + const char *file = "blaha"; + + if (argc != 1 && argc != 2) + errx (1, "usage: %s [file]", argv[0]); + if (argc == 2) + file = argv[1]; + doit (file); + return 0; +} diff --git a/src/tests/append1 b/src/tests/append1 new file mode 100644 index 0000000..c7dc373 --- /dev/null +++ b/src/tests/append1 @@ -0,0 +1,6 @@ +#!/bin/sh +$objdir/echo-n hej > foo || exit 1 +if test `cat foo` != "hej"; then exit 1; fi +$objdir/echo-n hopp >> foo || exit 1 +if test `cat foo` != "hejhopp"; then exit 1; fi +rm foo || exit 1 diff --git a/src/tests/apwd.c b/src/tests/apwd.c new file mode 100644 index 0000000..82335ec --- /dev/null +++ b/src/tests/apwd.c @@ -0,0 +1,472 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifndef MAXPATHLEN +#ifdef PATH_MAX +#define MAXPATHLEN PATH_MAX +#else +#define MAXPATHLEN 4096 +#endif +#endif + +RCSID("$Id$"); + +static int verbose_flag; +static FILE *verbose_fp = NULL; + +static int +initial_string (char **buf, size_t *size, size_t new_size) +{ + char *tmp = malloc (new_size); + + if (tmp == NULL) + return -1; + *buf = tmp; + *size = new_size; + return 0; +} + +static int +expand_string (char **buf, size_t *size, size_t new_size) +{ + char *tmp = realloc (*buf, new_size); + + if (tmp == NULL) + return -1; + *buf = tmp; + *size = new_size; + return 0; +} + +/* + * Verify that the dynamically allocated string `buf' of length + * `size', has room for `len' bytes. Returns -1 if realloc fails. + */ + +static int +guarantee_room (char **buf, size_t *size, size_t len) +{ + if (*size > len) + return 0; + + return expand_string (buf, size, min(*size * 2, len)); +} + +static char * +getcwd_classic (char *buf, size_t size) +{ + int dynamic_buf = 0; + struct stat root_sb, dot_sb, dotdot_sb; + char *work_string; + size_t work_length; + char slash_dot_dot[] = "/.."; + char *curp; + char *endp; + DIR *dir = NULL; + + if (initial_string (&work_string, &work_length, MAXPATHLEN) < 0) + return NULL; + + if (buf == NULL) { + dynamic_buf = 1; + if (initial_string (&buf, &size, MAXPATHLEN) < 0) { + free (work_string); + return NULL; + } + } + + endp = curp = buf + size - 1; + + if (lstat (".", &dot_sb) < 0) + goto err_ret; + if (lstat ("/", &root_sb) < 0) + goto err_ret; + strcpy (work_string, ".."); + fprintf (verbose_fp, "\".\" is (%u, %u), \"/\" is (%u, %u)\n", + (unsigned)dot_sb.st_dev, (unsigned)dot_sb.st_ino, + (unsigned)root_sb.st_dev, (unsigned)root_sb.st_ino); + + while (dot_sb.st_dev != root_sb.st_dev + || dot_sb.st_ino != root_sb.st_ino) { + struct dirent *dp; + int found = 0; + int change_dev = 0; + int pattern_len = strlen (work_string); + + if (lstat (work_string, &dotdot_sb) < 0) + goto err_ret; + fprintf (verbose_fp, "\"..\" is (%u, %u)\n", + (unsigned)dotdot_sb.st_dev, (unsigned)dotdot_sb.st_ino); + if (dot_sb.st_dev != dotdot_sb.st_dev) + change_dev = 1; + dir = opendir (work_string); + if (dir == NULL) + goto err_ret; + while ((dp = readdir (dir)) != NULL) { + size_t name_len = strlen (dp->d_name); + + if (change_dev) { + struct stat sb; + + if (guarantee_room (&work_string, &work_length, + pattern_len + name_len + 2) < 0) { + goto err_ret; + } + + strcat (work_string, "/"); + strcat (work_string, dp->d_name); + + if (lstat (work_string, &sb) < 0) { + goto err_ret; + } + if (sb.st_dev == dot_sb.st_dev + && sb.st_ino == dot_sb.st_ino) { + fprintf (verbose_fp, "\"%s\" found\n", work_string); + found = 1; + } + work_string[pattern_len] = '\0'; + } else if (dp->d_ino == dot_sb.st_ino) { + fprintf (verbose_fp, "\"%s\" found\n", dp->d_name); + found = 1; + } + + if (found) { + while (buf + name_len >= curp) { + size_t old_len; + + if (!dynamic_buf) { + errno = ERANGE; + goto err_ret; + } + old_len = endp - curp + 1; + if (expand_string (&buf, &size, size * 2) < 0) + goto err_ret; + memmove (buf + size - old_len, + buf + size / 2 - old_len, + old_len); + endp = buf + size - 1; + curp = endp - old_len + 1; + } + memcpy (curp - name_len, dp->d_name, name_len); + curp[-(name_len + 1)] = '/'; + curp -= name_len + 1; + break; + } + } + closedir (dir); + dir = NULL; + + if (!found) + goto err_ret; + + dot_sb = dotdot_sb; + if (guarantee_room (&work_string, &work_length, + pattern_len + strlen(slash_dot_dot) + 1) < 0) + goto err_ret; + strcat (work_string, slash_dot_dot); + } + if (curp == endp) { + while (buf >= curp) { + if (!dynamic_buf) { + errno = ERANGE; + goto err_ret; + } + if (expand_string (&buf, &size, size * 2) < 0) + goto err_ret; + } + *--curp = '/'; + } + *endp = '\0'; + memmove (buf, curp, endp - curp + 1); + free (work_string); + return buf; + +err_ret: + if (dir) + closedir (dir); + if (dynamic_buf) + free (buf); + free (work_string); + return NULL; +} + +#if linux + +static char * +getcwd_proc (char *buf, size_t size) +{ + int dynamic_buf = 0; + + if (buf == NULL) { + dynamic_buf = 1; + if (initial_string (&buf, &size, MAXPATHLEN) < 0) + return NULL; + } else if (size <= 1) { + errno = ERANGE; + return NULL; + } + + for (;;) { + int ret; + + ret = readlink ("/proc/self/cwd", buf, size); + if (ret == -1) + goto err_ret; + if (buf[0] != '/') { + errno = EINVAL; + goto err_ret; + } + if (buf[ret-1] != '\0' && ret >= size) { + if (!dynamic_buf) { + errno = ERANGE; + goto err_ret; + } + if (expand_string (&buf, &size, size * 2) < 0) + goto err_ret; + } else { + if (buf[ret - 1] != '\0') + buf[ret] = '\0'; + return buf; + } + } +err_ret: + if (dynamic_buf) + free (buf); + return NULL; +} + +#endif /* linux */ + +static int +test_1(char *(*func)(char *, size_t), const char *func_name, int init_size) +{ + char real_buf[2048]; + char buf[2048], *buf2, buf3[4711]; + int i; + int ret = 0; + int three_done = 1; + + if (getcwd (real_buf, sizeof(real_buf)) == NULL) { + fprintf (verbose_fp, "getcwd(buf, %u) failed\n", + (unsigned)sizeof(real_buf)); + ret = 1; + } + if (func (buf, sizeof(buf)) == NULL) { + fprintf (verbose_fp, "%s(buf, %u) failed\n", func_name, + (unsigned)sizeof(buf)); + ret = 1; + } else { + fprintf (verbose_fp, "first *%s*\n", buf); + if (strcmp (real_buf, buf) != 0) { + fprintf (verbose_fp, "first comparison failed: *%s* != *%s*\n", + real_buf, buf); + ret = 1; + } + } + + buf2 = func (NULL, 0); + if (buf2 == NULL) { + fprintf (verbose_fp, "%s(NULL, 0) failed\n", func_name); + ret = 1; + } else { + fprintf (verbose_fp, "second *%s*\n", buf2); + if (strcmp (real_buf, buf2) != 0) { + fprintf (verbose_fp, "second comparison failed: *%s* != *%s*\n", + real_buf, buf2); + ret = 1; + } + free (buf2); + } + + for (i = init_size; i < sizeof(buf3); ++i) { + memset (buf3, '\x01', sizeof(buf3)); + if (func (buf3, i) == NULL) { + if (errno != ERANGE) { + fprintf (verbose_fp, "%s(buf,%u) call failed\n", func_name, i); + three_done = 0; + break; + } + } else { + int j; + + for (j = i; j < sizeof(buf3); ++j) + if (buf3[j] != '\x01') { + fprintf (verbose_fp, "buffer was overwritten at %d\n", j); + three_done = 0; + break; + } + break; + } + } + + if (three_done) { + fprintf (verbose_fp, "third *%s*\n", buf3); + if (strcmp (real_buf, buf3) != 0) { + fprintf (verbose_fp, "third comparison failed: *%s* != *%s*\n", + real_buf, buf3); + ret = 1; + } else if (strlen (buf3) + 1 != i + && strlen (buf3) + 1 >= init_size) { + fprintf (verbose_fp, "wrong len in third call: %d != %d\n", + (unsigned)strlen(buf3) + 1, i); + ret = 1; + } + } else { + ret = 1; + } + + return ret; +} + +static int +test_it(char *(*func)(char *, size_t), const char *name, int init_size) +{ + int ret; + + fprintf (verbose_fp, "testing %s (initial size %d)\n", name, init_size); + ret = test_1 (func, name, init_size); + if (ret) + fprintf (verbose_fp, "FAILED!\n"); + else + fprintf (verbose_fp, "passed\n"); + return ret; +} + +#ifdef linux +#include +#endif + +#ifdef __NR_getcwd + +#define __NR_sys_getcwd __NR_getcwd + +static +_syscall2(int, sys_getcwd, char *, buf, size_t, size) + +static char * +getcwd_syscall (char *buf, size_t size) +{ + int dynamic_buf = 0; + + if (buf == NULL) { + dynamic_buf = 1; + if (initial_string (&buf, &size, MAXPATHLEN) < 0) + return NULL; + } + + for (;;) { + int ret; + + ret = sys_getcwd (buf, size); + if (ret >= 0) + return buf; + else if (errno == ERANGE) { + if (!dynamic_buf) + return NULL; + if (expand_string (&buf, &size, size * 2) < 0) + return NULL; + } else + return NULL; + } +} + +#endif + +static int help_flag; + +static struct agetargs args[] = { + {"verbose", 'v', aarg_flag, &verbose_flag, "verbose", NULL}, + {"help", 0, aarg_flag, &help_flag, NULL, NULL}, + {NULL, 0, aarg_end, NULL, NULL, NULL} +}; + +static void +usage (int exit_val) +{ + aarg_printusage (args, NULL, "", AARG_GNUSTYLE); +} + +int +main(int argc, char **argv) +{ + int ret = 0; + int optind = 0; + + + verbose_flag = getenv ("VERBOSE") != NULL; + + if (agetarg (args, argc, argv, &optind, AARG_GNUSTYLE)) + usage (1); + + argc -= optind; + argv += optind; + + if (argc != 0) + usage (1); + if (help_flag) + usage (0); + + verbose_fp = fdopen (4, "w"); + if (verbose_fp == NULL) { + verbose_fp = fopen ("/dev/null", "w"); + if (verbose_fp == NULL) + err (1, "fopen"); + } + + ret += test_it (getcwd, "getcwd", 3); +#ifdef __NR_getcwd + ret += test_it (getcwd_syscall, "getcwd_syscall", 3); +#endif + ret += test_it (getcwd_classic, "getcwd_classic", 0); +#if linux + ret += test_it (getcwd_proc, "getcwd_proc", 0); +#endif + return ret; +} diff --git a/src/tests/asu.c b/src/tests/asu.c new file mode 100644 index 0000000..d69650d --- /dev/null +++ b/src/tests/asu.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +RCSID("$Id$"); +#endif + +#include +#include +#include +#include +#include +#include + + +#include + +static void +usage(int exit_val) +{ + fprintf(stderr, "asu user program [arguments ...]\n"); + exit(exit_val); +} + +int +main(int argc, char **argv) +{ + const char *user, *prog; + + + if (argc < 3) + usage(1); + + user = argv[1]; + prog = argv[2]; + + if (getuid() == 0) { + struct passwd *pw; + gid_t groups[1]; + uid_t uid; + gid_t gid; + + pw = getpwnam(user); + if(pw == NULL) + errx(1, "no such user %s", user); + + uid = pw->pw_uid; + gid = pw->pw_gid; + groups[0] = gid; + + if (setgroups(1, groups)) + errx(1, "setgroups failed"); + + setgid(gid); + setuid(uid); + setegid(gid); + seteuid(uid); + } + +#if 0 + if (k_hasafs()) { + int ret = k_setpag(); + if (ret < 0) + warn("k_setpag"); + } +#endif + + execvp(prog, &argv[2]); + + return 0; +} diff --git a/src/tests/blocks-new-file.c b/src/tests/blocks-new-file.c new file mode 100644 index 0000000..d04a519 --- /dev/null +++ b/src/tests/blocks-new-file.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +static void +doit (const char *filename) +{ + int fd; + struct stat sb; + + fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, 0666); + if (fd < 0) + err (1, "open %s", filename); + if (lseek (fd, (off_t)(1024*1024), SEEK_SET) != 1024*1024) + err (1, "lseek %s", filename); + if (write (fd, "hej", 3) != 3) + err (1, "write to %s", filename); + if (close (fd) < 0) + err (1, "close %s", filename); + if (stat (filename, &sb) < 0) + err (1, "stat %s", filename); + if (unlink (filename) < 0) + err (1, "unlink %s", filename); + if (sb.st_blocks == 0) + errx (1, "st_blocks == 0"); +} + +int +main(int argc, char **argv) +{ + + if (argc == 1) + doit ("foo"); + else if (argc == 2) + doit (argv[1]); + else + errx (1, "usage: %s [filename]", argv[0]); + return 0; +} diff --git a/src/tests/boot-strap-arla b/src/tests/boot-strap-arla new file mode 100644 index 0000000..beba197 --- /dev/null +++ b/src/tests/boot-strap-arla @@ -0,0 +1,17 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ;exit 0; fi + +ARLA_RELEASE=${AFSROOT}/stacken.kth.se/ftp/pub/arla/arla-0.34.tar.gz + +mkdir src || exit 1 +mkdir obj || exit 1 + +cd src || exit 1 +gzip -dc $ARLA_RELEASE | tar xf - +cd ../obj || exit 1 +../src/*/configure || exit 1 +make || exit 1 +cd milko || exit 1 +make || exit 1 +exit 0 diff --git a/src/tests/bos.pm b/src/tests/bos.pm new file mode 100644 index 0000000..9d85792 --- /dev/null +++ b/src/tests/bos.pm @@ -0,0 +1,679 @@ +# CMUCS AFStools +# Copyright (c) 1996, Carnegie Mellon University +# All rights reserved. +# +# See CMU_copyright.ph for use and distribution information +# +#: * bos.pm - Wrappers around BOS commands (basic overseer server) +#: * This module provides wrappers around the various bosserver +#: * commands, giving them a nice perl-based interface. Someday, they might +#: * talk to the servers directly instead of using 'bos', but not anytime +#: * soon. +#: + +package OpenAFS::bos; +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT :afs_internal); +use OpenAFS::wrapper; +use Exporter; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&AFS_bos_create &AFS_bos_addhost + &AFS_bos_addkey &AFS_bos_adduser + &AFS_bos_delete &AFS_bos_exec + &AFS_bos_getdate &AFS_bos_getlog + &AFS_bos_getrestart &AFS_bos_install + &AFS_bos_listhosts &AFS_bos_listkeys + &AFS_bos_listusers &AFS_bos_prune + &AFS_bos_removehost &AFS_bos_removekey + &AFS_bos_removeuser &AFS_bos_restart + &AFS_bos_salvage &AFS_bos_setauth + &AFS_bos_setcellname &AFS_bos_setrestart + &AFS_bos_shutdown &AFS_bos_start + &AFS_bos_startup &AFS_bos_status + &AFS_bos_stop &AFS_bos_uninstall); + +#: AFS_bos_addhost($server, $host, [$clone], [$cell]) +#: Add a new database server host named $host to the database +#: on $server. +#: If $clone is specified, create an entry for a clone server. +#: On success, return 1. +#: +$AFS_Help{bos_addhost} = '$server, $host, [$clone], [$cell] => Success?'; +sub AFS_bos_addhost { + my($server, $host, $clone, $cell) = @_; + my(@args); + + @args = ('addhost', '-server', $server, '-host', $host); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-clone') if ($clone); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_addkey($server, $key, $kvno, [$cell]) +#: Add a key $key with key version number $kvno on server $server +#: On success, return 1. +#: +$AFS_Help{bos_addkey} = '$server, $key, $kvno, [$cell] => Success?'; +sub AFS_bos_addkey { + my($server, $key, $kvno, $cell) = @_; + my(@args); + + @args = ('addkey', '-server', $server, '-key', $key, '-kvno', $kvno); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_adduser($server, \@user, [$cell]) +#: Add users specified in @users to bosserver superuser list on $server. +#: On success, return 1. +#: +$AFS_Help{bos_adduser} = '$server, \@user, [$cell] => Success?'; +sub AFS_bos_adduser { + my($server, $user, $cell) = @_; + my(@args); + + @args = ('adduser', '-server', $server, '-user', @$user); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_create($server, $instance, $type, \@cmd, [$cell]) +#: Create a bnode with name $instance +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_create} = '$server, $instance, $type, \@cmd, [$cell] => Success?'; +sub AFS_bos_create { + my($server, $instance, $type, $cmd, $cell) = @_; + my(@args); + + @args = ('create', '-server', $server, '-instance', $instance, '-type', + $type, '-cmd', @$cmd); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_delete($server, $instance, [$cell]) +#: Delete a bnode with name $instance +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_delete} = '$server, $instance, [$cell] => Success?'; +sub AFS_bos_delete { + my($server, $instance, $cell) = @_; + my(@args); + + @args = ('delete', '-server', $server, '-instance', $instance); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_exec($server, $cmd, [$cell]) +#: Exec a process on server $server +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_exec} = '$server, $cmd, [$cell] => Success?'; +sub AFS_bos_exec { + my($server, $cmd, $cell) = @_; + my(@args); + + @args = ('exec', '-server', $server, '-cmd', $cmd); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_getdate($server, $file, [$cell]) +#: Get the date for file $file from server $server +#: On success, return ($exedate, $bakdate, $olddate). +#: +$AFS_Help{bos_getdate} = '$server, $file, [$cell] => ($exedate, $bakdate, $olddate)'; +sub AFS_bos_getdate { + my($server, $file, $cell) = @_; + my(@args, $exedate, $bakdate, $olddate); + + @args = ('getdate', '-server', $server, '-file', $file); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args, + [[ 'dated (.*), (no )?\.BAK', \$exedate], + [ '\.BAK file dated (.*), (no )?\.OLD', \$bakdate], + [ '\.OLD file dated (.*)\.', \$olddate]]); + ($exedate, $bakdate, $olddate); +} + +#: AFS_bos_getlog($server, $file, [$cell]) +#: Get log named $file from server $server +#: On success, return 1. +#: +$AFS_Help{bos_getlog} = '$server, $file, [$cell] => Success?'; +sub AFS_bos_getlog { + my($server, $file, $cell) = @_; + my(@args); + + @args = ('getlog', '-server', $server, '-file', $file); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args, + [[ '^Fetching log file .*', '.']], { pass_stdout }); + 1; +} + +#: AFS_bos_getrestart($server, [$cell]) +#: Get the restart time for server $server +#: On success, return ($genrestart, $binrestart). +#: +$AFS_Help{bos_getrestart} = '$server, [$cell] => ($genrestart, $binrestart)'; +sub AFS_bos_getrestart { + my($server, $cell) = @_; + my(@args, $genrestart, $binrestart); + + @args = ('getrestart', '-server', $server); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args, + [[ '^Server .* restarts at\s*(.*\S+)', \$genrestart], + [ '^Server .* restarts for new binaries at\s*(.*\S+)', \$binrestart]]); + ($genrestart, $binrestart); +} + +#: AFS_bos_install($server, \@files, [$dir], [$cell]) +#: Install files in \@files on server $server in directory $dir +#: or the default directory. +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_install} = '$server, \@files, [$dir], [$cell] => Success?'; +sub AFS_bos_install { + my($server, $files, $dir, $cell) = @_; + my(@args, $file); + + @args = ('install', '-server', $server, '-file', @$files); + push(@args, '-dir', $dir) if ($dir); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args, [[ 'bos: installed file .*', '.' ]], + { 'errors_last' => 1 }); + 1; +} + +#: AFS_bos_listhosts($server, [$cell]) +#: Get host list on server $server. +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, an array of hosts with the first entry being the cellname. +#: +$AFS_Help{bos_listhosts} = '$server, [$cell] => @ret'; +sub AFS_bos_listhosts { + my($server, $cell) = @_; + my(@args, @ret); + + @args = ('listhosts', '-server', $server); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args, + [[ '^Cell name is (.*)', sub { + push(@ret, $_[0]); + } ], + [ 'Host \S+ is (\S+)', sub { + push(@ret, $_[0]); + } ] + ]); + @ret; +} + +#: AFS_bos_listkeys($server, [$showkey], [$cell]) +#: Get key list on server $server. +#: The server name ($server) may be a hostname or IP address +#: If specified, $showkey indicates keys and not checksums should be shown. +#: If specified, work in $cell instead of the default cell. +#: On success, an array of hosts with the first entry being the cellname. +#: +$AFS_Help{bos_listkeys} = '$server, [$showkey], [$cell] => %ret'; +sub AFS_bos_listkeys { + my($server, $showkey, $cell) = @_; + my(@args, %ret); + + @args = ('listkeys', '-server', $server); + push(@args, '-showkey') if ($showkey); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + %ret = &wrapper('bos', \@args, + [[ '^key (\d+) has cksum (\d+)', sub { + my(%ret) = %OpenAFS::wrapper::result; + $ret{$_[0]} = $_[1]; + %OpenAFS::wrapper::result = %ret; + } ], + [ '^key (\d+) is \'(\S+)\'', sub { + my(%ret) = %OpenAFS::wrapper::result; + $ret{$_[0]} = $_[1]; + %OpenAFS::wrapper::result = %ret; + } ], + [ '^Keys last changed on\s*(.*\S+)', sub { + my(%ret) = %OpenAFS::wrapper::result; + $ret{'date'} = $_[0]; + %OpenAFS::wrapper::result = %ret; + } ], + [ 'All done.', '.']]); + %ret; +} + +#: AFS_bos_listusers($server, [$cell]) +#: Get superuser list on server $server. +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, an array of users. +#: +$AFS_Help{bos_listusers} = '$server, [$cell] => @ret'; +sub AFS_bos_listusers { + my($server, $cell) = @_; + my(@args, @ret); + + @args = ('listusers', '-server', $server); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args, [[ '^SUsers are: (\S+)', sub { + push(@ret, split(' ',$_[0])); + } ]]); + @ret; +} + +#: AFS_bos_prune($server, [$bak], [$old], [$core], [$all], [$cell]) +#: Prune files on server $server +#: If $bak is specified, remove .BAK files +#: If $old is specified, remove .OLD files +#: If $core is specified, remove core files +#: If $all is specified, remove all junk files +#: On success, return 1. +#: +$AFS_Help{bos_prune} = '$server, [$bak], [$old], [$core], [$all], [$cell] => Success?'; +sub AFS_bos_prune { + my($server, $bak, $old, $core, $all, $cell) = @_; + my(@args); + + @args = ('prune', '-server', $server, '-bak', $bak, '-old', $old, '-core', $core, '-all', $all); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-bak') if ($bak); + push(@args, '-old') if ($old); + push(@args, '-core') if ($core); + push(@args, '-all') if ($all); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_removehost($server, $host, [$cell]) +#: Remove a new database server host named $host from the database +#: on $server. +#: On success, return 1. +#: +$AFS_Help{bos_removehost} = '$server, $host, [$cell] => Success?'; +sub AFS_bos_removehost { + my($server, $host, $cell) = @_; + my(@args); + + @args = ('removehost', '-server', $server, '-host', $host); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_removekey($server, $kvno, [$cell]) +#: Remove a key with key version number $kvno on server $server +#: On success, return 1. +#: +$AFS_Help{bos_removekey} = '$server, $kvno, [$cell] => Success?'; +sub AFS_bos_removekey { + my($server, $kvno, $cell) = @_; + my(@args); + + @args = ('removekey', '-server', $server, '-kvno', $kvno); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_removeuser($server, \@user, [$cell]) +#: Remove users specified in @users to bosserver superuser list on $server. +#: On success, return 1. +#: +$AFS_Help{bos_removeuser} = '$server, \@user, [$cell] => Success?'; +sub AFS_bos_removeuser { + my($server, $user, $cell) = @_; + my(@args); + + @args = ('removeuser', '-server', $server, '-user', @$user); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_restart($server, [\@inst], [$bosserver], [$all], [$cell]) +#: Restart bosserver instances specified in \@inst, or if $all is +#: specified, all instances. +#: If $bosserver is specified, restart the bosserver. +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_restart} = '$server, [\@inst], [$bosserver], [$all], [$cell] => Success?'; +sub AFS_bos_restart { + my($server, $inst, $bosserver, $all, $cell) = @_; + my(@args); + + @args = ('restart', '-server', $server); + push(@args, '-instance', @$inst) if ($inst); + push(@args, '-bosserver') if ($bosserver); + push(@args, '-all') if ($all); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_salvage($server, [$partition], [$volume], [$file], [$all], [$showlog], [$parallel], [$tmpdir], [$orphans], [$cell]) +#: Invoke the salvager, providing a partition $partition if specified, and +#: further a volume id $volume if specified. +#: If specified, $file is a file to write the salvager output into. +#: If specified, $all indicates all partitions should be salvaged. +#: If specified, $showlog indicates the log should be displayed on completion. +#: If specified, $parallel indicates the number salvagers that should be run +#: in parallel. +#: If specified, $tmpdir indicates a directory in which to store temporary +#: files. +#: If specified, $orphans indicates how to handle orphans in a volume +#: (valid options are ignore, remove and attach). +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_salvage} = '$server, [$partition], [$volume], [$file], [$all], [$showlog], [$parallel], [$tmpdir], [$orphans], [$cell] => Success?'; +sub AFS_bos_salvage { + my($server, $partition, $volume, $file, $all, $showlog, $parallel, $tmpdir, $orphans, $cell) = @_; + my(@args); + + @args = ('salvage', '-server', $server); + push(@args, '-partition', $partition)if ($partition); + push(@args, '-volume', $volume) if ($volume); + push(@args, '-file', $file) if ($file); + push(@args, '-all') if ($all); + push(@args, '-showlog') if ($showlog); + push(@args, '-parallel', $parallel) if ($parallel); + push(@args, '-tmpdir', $tmpdir) if ($tmpdir); + push(@args, '-orphans', $orphans)if ($orphans); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args, [['bos: shutting down fs.', '.'], + ['Starting salvage.', '.'], + ['bos: waiting for salvage to complete.', '.'], + ['bos: salvage completed', '.'], + ['bos: restarting fs.', '.']], + { 'errors_last' => 1 }); + 1; +} + +#: AFS_bos_setauth($server, $authrequired, [$cell]) +#: Set the authentication required flag for server $server to +#: $authrequired. +#: On success, return 1. +#: +$AFS_Help{bos_setauth} = '$server, $authrequired, [$cell] => Success?'; +sub AFS_bos_setauth { + my($server, $authrequired, $cell) = @_; + my(@args); + + @args = ('setauth', '-server', $server, '-authrequired', $authrequired); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_setcellname($server, $name, [$cell]) +#: Set the cellname for server $server to $name +#: On success, return 1. +#: +$AFS_Help{bos_setcellname} = '$server, $name, [$cell] => Success?'; +sub AFS_bos_setcellname { + my($server, $name, $cell) = @_; + my(@args); + + @args = ('setcellname', '-server', $server, '-name', $name); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_setrestart($server, $time, [$general], [$newbinary], [$cell]) +#: Set the restart time for server $server to $time +#: If specified, $general indicates only the general restart time should be +#: set. +#: If specified, $newbinary indicates only the binary restart time should be +#: set. +#: On success, return 1. +#: +$AFS_Help{bos_setrestart} = '$server, $time, [$general], [$newbinary], [$cell] => Success?'; +sub AFS_bos_setrestart { + my($server, $time, $general, $newbinary, $cell) = @_; + my(@args); + + @args = ('setrestart', '-server', $server, '-time', $time); + push(@args, '-general') if ($general); + push(@args, '-newbinary') if ($newbinary); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_shutdown($server, [\@inst], [$wait], [$cell]) +#: Stop all bosserver instances or if \@inst is specified, +#: only those in \@inst on server $server +#: waiting for them to stop if $wait is specified. +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_shutdown} = '$server, [\@inst], [$wait], [$cell] => Success?'; +sub AFS_bos_shutdown { + my($server, $inst, $wait, $cell) = @_; + my(@args); + + @args = ('shutdown', '-server', $server); + push(@args, '-instance', @$inst) if ($inst); + push(@args, '-wait') if ($wait); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_start($server, \@inst, [$cell]) +#: Start bosserver instances in \@inst on server $server . +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_start} = '$server, \@inst, [$cell] => Success?'; +sub AFS_bos_start { + my($server, $inst, $cell) = @_; + my(@args); + + @args = ('start', '-server', $server, '-instance', @$inst); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_startup($server, [\@inst], [$cell]) +#: Start all bosserver instances or if \@inst is specified, only +#: those in \@inst on server $server . +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_startup} = '$server, [\@inst], [$cell] => Success?'; +sub AFS_bos_startup { + my($server, $inst, $cell) = @_; + my(@args); + + @args = ('startup', '-server', $server); + push(@args, '-instance', @$inst) if ($inst); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_status($server, [\@bnodes], [$cell]) +#: Get status for the specified bnodes on $server, or for all bnodes +#: if none are given. +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return an associative array whose keys are the names +#: of bnodes on the specified server, and each of whose values is +#: an associative array describing the status of the corresponding +#: bnode, containing some or all of the following elements: +#: - name Name of this bnode (same as key) +#: - type Type of bnode (simple, cron, fs) +#: - status Basic status +#: - aux_status Auxillary status string, for bnode types that provide it +#: - num_starts Number of process starts +#: - last_start Time of last process start +#: - last_exit Time of last exit +#: - last_error Time of last error exit +#: - error_code Exit code from last error exit +#: - error_signal Signal from last error exit +#: - commands Ref to list of commands +#: +$AFS_Help{bos_status} = '$server, [\@bnodes], [$cell] => %bnodes'; +sub AFS_bos_status { + my($server, $bnodes, $cell) = @_; + my(@args, %finres, %blist, @cmds); + + @args = ('status', '-server', $server, '-long'); + push(@args, '-instance', @$bnodes) if ($bnodes); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + %finres = &wrapper('bos', \@args, + [['^(Instance)', sub { + my(%binfo) = %OpenAFS::wrapper::result; + + if ($binfo{name}) { + $binfo{commands} = [@cmds] if (@cmds); + $blist{$binfo{name}} = \%binfo; + + @cmds = (); + %OpenAFS::wrapper::result = (); + } + }], + ['^Instance (.*), \(type is (\S+)\)\s*(.*)', 'name', 'type', 'status' ], + ['Auxilliary status is: (.*)\.', 'aux_status' ], + ['Process last started at (.*) \((\d+) proc starts\)', 'last_start', 'num_starts' ], + ['Last exit at (.*\S+)', 'last_exit' ], + ['Last error exit at (.*),', 'last_error' ], + ['by exiting with code (\d+)', 'error_code' ], + ['due to signal (\d+)', 'error_signal' ], + [q/Command \d+ is '(.*)'/, sub { push(@cmds, $_[0]) }], + ]); + if ($finres{name}) { + $finres{commands} = [@cmds] if (@cmds); + $blist{$finres{name}} = \%finres; + } + %blist; +} + +#: AFS_bos_stop($server, \@inst, [$wait], [$cell]) +#: Stop bosserver instances in \@inst on server $server +#: waiting for them to stop if $wait is specified. +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_stop} = '$server, \@inst, [$wait], [$cell] => Success?'; +sub AFS_bos_stop { + my($server, $inst, $wait, $cell) = @_; + my(@args); + + @args = ('stop', '-server', $server, '-instance', @$inst); + push(@args, '-wait') if ($wait); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args); + 1; +} + +#: AFS_bos_uninstall($server, \@files, [$dir], [$cell]) +#: Uninstall files in \@files on server $server in directory $dir +#: or the default directory. +#: The server name ($server) may be a hostname or IP address +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{bos_uninstall} = '$server, \@files, [$dir], [$cell] => Success?'; +sub AFS_bos_uninstall { + my($server, $files, $dir, $cell) = @_; + my(@args); + + @args = ('uninstall', '-server', $server, '-file', @$files); + push(@args, '-dir', $dir) if ($dir); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('bos', \@args, [[ '^bos: uninstalled file .*', '.' ]], + { 'errors_last' => 1 }); + 1; +} + +1; diff --git a/src/tests/bosaddhost.pl b/src/tests/bosaddhost.pl new file mode 100755 index 0000000..549ecb7 --- /dev/null +++ b/src/tests/bosaddhost.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_addhost(localhost,"128.2.1.2",,); + +exit(0); + + + diff --git a/src/tests/bosaddkey.pl b/src/tests/bosaddkey.pl new file mode 100755 index 0000000..6a5e596 --- /dev/null +++ b/src/tests/bosaddkey.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_addkey(localhost,"\000\001\002\003\004\005\006\007",250,); + +exit(0); + + + diff --git a/src/tests/bosadduser.pl b/src/tests/bosadduser.pl new file mode 100755 index 0000000..7495042 --- /dev/null +++ b/src/tests/bosadduser.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_adduser(localhost,[testuser1],); + +exit(0); + + + diff --git a/src/tests/boscreate.pl b/src/tests/boscreate.pl new file mode 100755 index 0000000..9161e9d --- /dev/null +++ b/src/tests/boscreate.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +open(FOO, ">sleeper.sh"); +print FOO "#!/bin/sh\n"; +print FOO "while true; do sleep 60; done\n"; +print FOO "exit 0\n"; +close FOO; +chmod 0755, "sleeper.sh"; + +&AFS_bos_install(localhost,["sleeper.sh"],,); +&AFS_bos_create(localhost,sleeper,simple,["/usr/afs/bin/sleeper.sh"],); + +exit(0); + + + diff --git a/src/tests/bosdelete.pl b/src/tests/bosdelete.pl new file mode 100755 index 0000000..6d0819b --- /dev/null +++ b/src/tests/bosdelete.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_delete(localhost,sleeper,); + +exit(0); + + + diff --git a/src/tests/bosdeleterunning.pl b/src/tests/bosdeleterunning.pl new file mode 100755 index 0000000..db96930 --- /dev/null +++ b/src/tests/bosdeleterunning.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +eval { &AFS_bos_delete(localhost,sleeper,); }; + +if (! $@) { + exit (1); +} +exit(0); + + + diff --git a/src/tests/bosexec.pl b/src/tests/bosexec.pl new file mode 100755 index 0000000..37a3487 --- /dev/null +++ b/src/tests/bosexec.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; +use OpenAFS::ConfigUtils; +use OpenAFS::Dirpath; +use OpenAFS::OS; + +my ($host); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_exec(localhost,"$openafsdirpath->{'afssrvbindir'}/foo.sh",); +if (-f "/usr/tmp/garbage") { +} else { + exit(1); +} +unlink "/usr/tmp/garbage"; +exit(0); + + + diff --git a/src/tests/bosinstall.pl b/src/tests/bosinstall.pl new file mode 100755 index 0000000..ddaa7c2 --- /dev/null +++ b/src/tests/bosinstall.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host); +$host = `hostname`; +&AFS_Init(); + +open(FOO, ">foo.sh"); +print FOO "#!/bin/sh\n"; +print FOO "touch /usr/tmp/garbage\n"; +print FOO "exit 0\n"; +close FOO; +chmod 0755, "foo.sh"; + +&AFS_bos_install(localhost,["foo.sh"],,); + +exit(0); + + + diff --git a/src/tests/boslisthosts.pl b/src/tests/boslisthosts.pl new file mode 100755 index 0000000..dfab1ab --- /dev/null +++ b/src/tests/boslisthosts.pl @@ -0,0 +1,31 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, @hosts, $this, $cell, $cnt); +$host = `hostname`; +chomp $host; +&AFS_Init(); +$cell = &AFS_fs_wscell(); + +@hosts = &AFS_bos_listhosts(localhost,); +$this = shift(@hosts); +if ($this ne $cell) { + exit (1); +} +while ($this = shift(@hosts)) { + if ($this ne $host) { + if (($this ne "128.2.1.2")) { + exit (1); + } + } +} +exit(0); + + + diff --git a/src/tests/boslistkeys.pl b/src/tests/boslistkeys.pl new file mode 100755 index 0000000..77affa4 --- /dev/null +++ b/src/tests/boslistkeys.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, @hosts, $this, $cell, $cnt, %ret); +$host = `hostname`; +chomp $host; +&AFS_Init(); +$cell = &AFS_fs_wscell(); + +%ret = &AFS_bos_listkeys(localhost,,); +foreach $this (keys %ret) { + if ($this == 250) { + if ($ret{250} ne 3288840443) { + exit(1); + } + } +} +exit(0); + + + diff --git a/src/tests/boslistusers.pl b/src/tests/boslistusers.pl new file mode 100755 index 0000000..b9fc7c9 --- /dev/null +++ b/src/tests/boslistusers.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, @hosts, $this, $cell, $cnt); +$host = `hostname`; +chomp $host; +&AFS_Init(); + +@hosts = &AFS_bos_listusers(localhost,); +while ($this = shift(@hosts)) { + if ($this ne "admin") { + if (($this ne "testuser1")) { + exit (1); + } + } +} +exit(0); + + + diff --git a/src/tests/bosremovehost.pl b/src/tests/bosremovehost.pl new file mode 100755 index 0000000..5a8133e --- /dev/null +++ b/src/tests/bosremovehost.pl @@ -0,0 +1,30 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, @hosts, $this, $cell, $cnt); +$host = `hostname`; +chomp $host; +&AFS_Init(); +$cell = &AFS_fs_wscell(); + +&AFS_bos_removehost(localhost,"128.2.1.2",); +@hosts = &AFS_bos_listhosts(localhost,); +$this = shift(@hosts); +if ($this ne $cell) { + exit (1); +} +while ($this = shift(@hosts)) { + if ($this ne $host) { + exit (1); + } +} +exit(0); + + + diff --git a/src/tests/bosremovekey.pl b/src/tests/bosremovekey.pl new file mode 100755 index 0000000..3c1a923 --- /dev/null +++ b/src/tests/bosremovekey.pl @@ -0,0 +1,25 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, @hosts, $this, $cell, $cnt, %ret); +$host = `hostname`; +chomp $host; +&AFS_Init(); +$cell = &AFS_fs_wscell(); + +&AFS_bos_removekey(localhost,250,); +foreach $this (keys %ret) { + if ($this == 250) { + exit(1); + } +} +exit(0); + + + diff --git a/src/tests/bosremoveuser.pl b/src/tests/bosremoveuser.pl new file mode 100755 index 0000000..75cc014 --- /dev/null +++ b/src/tests/bosremoveuser.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, @hosts, $this, $cell, $cnt); +$host = `hostname`; +chomp $host; +&AFS_Init(); +$cell = &AFS_fs_wscell(); + +&AFS_bos_removeuser(localhost,[testuser1],); +@hosts = &AFS_bos_listusers(localhost,); +while ($this = shift(@hosts)) { + if ($this ne "admin") { + exit (1); + } +} +exit(0); + + + diff --git a/src/tests/bosrestartstopped.pl b/src/tests/bosrestartstopped.pl new file mode 100755 index 0000000..7b5f59f --- /dev/null +++ b/src/tests/bosrestartstopped.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, %info, %info2, $linfo); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_restart(localhost,[sleeper],,,); +%info = &AFS_bos_status("localhost",[sleeper],); +$linfo=$info{'sleeper'}; +%info2 = %$linfo; +if ($info2{'num_starts'} != 2) { + exit 1; +} +if ($info2{'status'} ne "temporarily enabled, currently running normally.") { + exit 1; +} +exit(0); + + + diff --git a/src/tests/bossalvagepart.pl b/src/tests/bossalvagepart.pl new file mode 100755 index 0000000..87cdc53 --- /dev/null +++ b/src/tests/bossalvagepart.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_salvage("localhost","a",,,,,,,); + +exit(0); + + + diff --git a/src/tests/bossalvageserver.pl b/src/tests/bossalvageserver.pl new file mode 100755 index 0000000..9b6fcd7 --- /dev/null +++ b/src/tests/bossalvageserver.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_salvage("localhost",,,,1,,,,); + +exit(0); + + + diff --git a/src/tests/bossalvagevolume.pl b/src/tests/bossalvagevolume.pl new file mode 100755 index 0000000..f3bc1ed --- /dev/null +++ b/src/tests/bossalvagevolume.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_salvage("localhost","a","unrep",,,,,,); + +exit(0); + + + diff --git a/src/tests/bosshutdown.pl b/src/tests/bosshutdown.pl new file mode 100755 index 0000000..a5cff46 --- /dev/null +++ b/src/tests/bosshutdown.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, %info, %info2, $linfo); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_shutdown(localhost,[sleeper],1,); +%info = &AFS_bos_status("localhost",[sleeper],); +$linfo=$info{'sleeper'}; +%info2 = %$linfo; +if ($info2{'num_starts'} != 2) { + exit 1; +} +if ($info2{'status'} ne "temporarily disabled, currently shutdown.") { + exit 1; +} +exit(0); + + + diff --git a/src/tests/bosstart.pl b/src/tests/bosstart.pl new file mode 100755 index 0000000..2f8d9a5 --- /dev/null +++ b/src/tests/bosstart.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, %info, %info2, $linfo); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_start(localhost,[sleeper],); +%info = &AFS_bos_status("localhost",[sleeper],); +$linfo=$info{'sleeper'}; +%info2 = %$linfo; +if ($info2{'num_starts'} != 2) { + exit 1; +} +if ($info2{'status'} ne "currently running normally.") { + exit 1; +} +exit(0); + + + diff --git a/src/tests/bosstatus.pl b/src/tests/bosstatus.pl new file mode 100755 index 0000000..37428b5 --- /dev/null +++ b/src/tests/bosstatus.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, %info, %info2, $linfo); +$host = `hostname`; +&AFS_Init(); + +%info = &AFS_bos_status("localhost",[sleeper],); +$linfo=$info{'sleeper'}; +%info2 = %$linfo; +if ($info2{'num_starts'} != 1) { + exit 1; +} +if ($info2{'status'} ne "currently running normally.") { + exit 1; +} +exit(0); + + + diff --git a/src/tests/bosstop.pl b/src/tests/bosstop.pl new file mode 100755 index 0000000..ff34697 --- /dev/null +++ b/src/tests/bosstop.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, %info, %info2, $linfo); +$host = `hostname`; +&AFS_Init(); + +&AFS_bos_stop(localhost,[sleeper],1,); +%info = &AFS_bos_status("localhost",[sleeper],); +$linfo=$info{'sleeper'}; +%info2 = %$linfo; +if ($info2{'num_starts'} != 1) { + exit 1; +} +if ($info2{'status'} ne "disabled, currently shutdown.") { + exit 1; +} +exit(0); + + + diff --git a/src/tests/build-and-run-rcs b/src/tests/build-and-run-rcs new file mode 100755 index 0000000..744281f --- /dev/null +++ b/src/tests/build-and-run-rcs @@ -0,0 +1,29 @@ +#!/bin/sh +set -x +# $Id$ +##if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +echo -n pwd before is ' ' +pwd +# +# copied from generic-build because rcs wants to put (hard)links into tar balls. +# +filename=$AFSROOT/stacken.kth.se/ftp/pub/gnu/rcs/rcs-5.7.tar.gz +b=rcs-5.7 +obj=$b-obj +gzip -dc $filename | tar xvf - >&4 2>&1 +mkdir $obj || exit 1 +cd $obj || exit 1 +../$b/configure >&4 || exit 1 +make $MAKEFLAGS || exit 1 +echo -n pwd after is ' ' +pwd +echo row1 > testfile +echo log1 | ./src/ci -u testfile +./src/co -l testfile +echo row2 >> testfile +echo log2 | ./src/ci -u testfile +./src/co -l testfile +echo row3 >> testfile +echo log3 | ./src/ci -u testfile +wc -l testfile | grep '3 testfile' || exit 1 + diff --git a/src/tests/build-emacs b/src/tests/build-emacs new file mode 100755 index 0000000..d5cfb5b --- /dev/null +++ b/src/tests/build-emacs @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +$SHELL $SHELLVERBOSE $srcdir/generic-build $AFSROOT/stacken.kth.se/ftp/pub/gnu/emacs/emacs-20.7.tar.gz emacs-20.7 diff --git a/src/tests/build-emacs-j b/src/tests/build-emacs-j new file mode 100644 index 0000000..3cac279 --- /dev/null +++ b/src/tests/build-emacs-j @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +env MAKEFLAGS="-j" $SHELL $SHELLVERBOSE $srcdir/generic-build $AFSROOT/stacken.kth.se/ftp/pub/gnu/emacs/emacs-20.7.tar.gz emacs-20.7 diff --git a/src/tests/build-gdb b/src/tests/build-gdb new file mode 100755 index 0000000..f030054 --- /dev/null +++ b/src/tests/build-gdb @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +$SHELL $SHELLVERBOSE $srcdir/generic-build $AFSROOT/stacken.kth.se/ftp/pub/gnu/gdb/gdb-5.0.tar.gz diff --git a/src/tests/build-openafs b/src/tests/build-openafs new file mode 100755 index 0000000..8a14add --- /dev/null +++ b/src/tests/build-openafs @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id$ +FS=${FS:-${objdir}/../appl/fs/fs} + +${FS} sq . 0 +wget http://www.openafs.org/dl/1.2.2/openafs-1.2.2-src.tar.gz >& 4 +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +$SHELL $SHELLVERBOSE $srcdir/generic-build openafs-1.2.2-src.tar.gz openafs-1.2.2 +openafs-1.2.2/src/finale/translate_et 180480 >& /dev/null diff --git a/src/tests/checkpwd b/src/tests/checkpwd new file mode 100755 index 0000000..502a3dd --- /dev/null +++ b/src/tests/checkpwd @@ -0,0 +1,3 @@ +#!/bin/sh +# $Id$ +$objdir/apwd diff --git a/src/tests/compare-inum-mp b/src/tests/compare-inum-mp new file mode 100755 index 0000000..ce92bcf --- /dev/null +++ b/src/tests/compare-inum-mp @@ -0,0 +1,8 @@ +#!/bin/sh +# $Id$ +FS=${FS:-${objdir}/../appl/fs/fs} +${FS} sa . system:anyuser all || exit 1 +${FS} mkm root.cell root.cell || exit 1 +$objdir/readdir-vs-lstat . || exit 1 +$objdir/readdir-vs-lstat root.cell || exit 1 +${FS} rmm root.cell || exit 1 diff --git a/src/tests/compare-inums b/src/tests/compare-inums new file mode 100755 index 0000000..614560d --- /dev/null +++ b/src/tests/compare-inums @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ +$objdir/create-files 100 0 || exit 1 +$objdir/readdir-vs-lstat . || exit 1 diff --git a/src/tests/compare-with-local b/src/tests/compare-with-local new file mode 100755 index 0000000..8c7a495 --- /dev/null +++ b/src/tests/compare-with-local @@ -0,0 +1,77 @@ +#!/bin/sh +# $Id$ +################################################################# +# +# Copy file back and forth between $TMPDIR (defaults to /tmp) +# which is hopefully on local disk or any other well tested +# file system and the filesystem we want to test (in $PWD). +# +################################################################# + +test $SHELLVERBOSE && set $SHELLVERBOSE + +function compare () { + if cmp $1 $2; then + : + else + diff $1 $2 + exit 1 + fi +} + +test $TMPDIR || TMPDIR=/tmp +TMPDIR=$TMPDIR/compare-with-local-$$ +mkdir $TMPDIR || exit 1 + +# Generate test file +cat > $TMPDIR/bar << EOF +This is an arla temporary test file. +You may remove it any time. +Kontrollen blinkar blå. +EOF + +cp $TMPDIR/bar bar +compare $TMPDIR/bar bar +mv bar $TMPDIR/bas +compare $TMPDIR/bar $TMPDIR/bas + # this is for later overwrite test + test -f bar && echo bar should not exist && exit 1 + cp $TMPDIR/bar bar + compare $TMPDIR/bar bar +cat $TMPDIR/bas > bat +compare $TMPDIR/bar bat +cat bat > $TMPDIR/bau +compare $TMPDIR/bar $TMPDIR/bau +mv $TMPDIR/bau bav +compare $TMPDIR/bar bav + # this is for later overwrite test + test -f $TMPDIR/bau && echo $TMPDIR/bau should not exist && exit 1 + cp $TMPDIR/bar $TMPDIR/bau +cp bav $TMPDIR/baw +compare $TMPDIR/bar $TMPDIR/baw + +# If we get so far we can write new files. +# Now test overwrite. + +# Generate test file slightly different +cat > $TMPDIR/bar << EOF +This is an arla temporary test file. +You may remove it any time. +Mera jul. +EOF + +cp $TMPDIR/bar bar +compare $TMPDIR/bar bar +mv bar $TMPDIR/bas +compare $TMPDIR/bar $TMPDIR/bas +cat $TMPDIR/bas > bat +compare $TMPDIR/bar bat +cat bat > $TMPDIR/bau +compare $TMPDIR/bar $TMPDIR/bau +mv $TMPDIR/bau bav +compare $TMPDIR/bar bav +cp bav $TMPDIR/baw +compare $TMPDIR/bar $TMPDIR/baw + +${objdir}/rm-rf $TMPDIR +exit 0 diff --git a/src/tests/config.pm b/src/tests/config.pm new file mode 100644 index 0000000..0de0a54 --- /dev/null +++ b/src/tests/config.pm @@ -0,0 +1,125 @@ +# CMUCS AFStools +# Copyright (c) 1996, Carnegie Mellon University +# All rights reserved. +# +# See CMU_copyright.pm for use and distribution information + +package OpenAFS::config; + +=head1 NAME + +OpenAFS::config - AFStools configuration + +=head1 SYNOPSIS + + use OpenAFS::config; + +=head1 DESCRIPTION + +This module contains various AFStools configuration variables which are used +by the other AFStools modules. These describe how AFStools should act in a +particular installation, and are mostly pretty mundane. All of the defaults +here are pretty reasonable, so you shouldn't have to change anything unless +your site is particularly exotic. + +Note that this file only describes how a particular B of AFStools +should act, not how it should act upon a particular B. Since the cell +AFStools is running in is not necessarily the same as the cell on which it +is acting, most configuration that is really per-cell should be located in a +cell-specific module. + +This module should only be used by other parts of AFStools. As such, the +variables described here are not normally visible to user programs, and this +file is mostly of interest to administrators who are installing AFStools. + +=over 4 + +=cut + +use OpenAFS::CMU_copyright; +use OpenAFS::Dirpath; +use Exporter; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw($def_ConfDir + @CmdList + @CmdPath + $err_table_dir + ); + +# The following configuration variables are defined here. Mention them +# all an extra time, to suppress annoying warnings. Doesn't perl have +# a way of doing this??? +@x = (); +@x = ($def_ConfDir, @CmdList, @CmdPath); + +=item $def_ConfDir - Default configuration directory + +This is the default AFS configuration directory, where files like ThisCell, +CellServDB, and so on are found. If the AFStools parameter I is +set, it will generally be searched before this directory. Normally, this +should be set to F and not changed, as that path is hardwired +into AFS. However, it might be necessary to modify this if your site uses +an exotic locally-compiled version of AFS. + +=cut + +$def_ConfDir = "$openafsdirpath->{'viceetcdir'}"; +#$def_ConfDir = "/usr/vice/etc"; + + +=item @CmdList - List of AFS commands + +This is a list of AFS commands that the AFStools package might want to invoke +using B. Don't remove anything from this list if you +know what's good for you. It's OK to add things, though, if you think you +might use the wrapper features for something. + +=cut + +@CmdList = ('fs', 'pts', 'vos', 'bos', 'kas', 'krbkas', 'sys'); + + +=item @CmdPath - Path to search for AFS commands + +This is the list of directories where B will look for +AFS commands. For AFStools to work properly, every command listed in +I<@OpenAFS::config::CmdList> must appear in one of these directories. The default +should be sufficient for most sites; we deal with Transarc's reccommendations +as well as common practice. Note that on machines for which /usr/afs/bin +exists (typically, AFS fileservers), that directory is first. This is probably +what you want... + +=cut + +@CmdPath = (split(/:/, $ENV{PATH}), + "$openafsdirpath->{'afssrvbindir'}", # For servers + '/usr/local/bin', # Many sites put AFS in /usr/local + '/usr/local/etc', + '/usr/afsws/bin', # For people who use Transarc's + '/usr/afsws/etc'); # silly reccommendations + +=item $err_table_dir - Error table directory + +This is the location of error tables used by the errcode and errstr +routines in OpenAFS::errtrans. Each file in this directory should be a +com_err error table (in source form), and should be named the same +as the com_err error package contained within. + +=cut + +$err_table_dir = '/usr/local/lib/errtbl'; + +1; + +=back + +=head1 COPYRIGHT + +The CMUCS AFStools, including this module are +Copyright (c) 1996, Carnegie Mellon University. All rights reserved. +For use and redistribution information, see CMUCS/CMU_copyright.pm + +=cut diff --git a/src/tests/copy-and-diff-gnu-mirror b/src/tests/copy-and-diff-gnu-mirror new file mode 100755 index 0000000..3f608a8 --- /dev/null +++ b/src/tests/copy-and-diff-gnu-mirror @@ -0,0 +1,7 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +if test "X$LARGE" = "X" ; then echo "Not running large test $0" ; exit 0 ; fi +original=${1-$AFSROOT/stacken.kth.se/ftp/pub} +(cd $original; tar cvf - gnu) 2>&4 | tar xvf - >&4 +find gnu -type f -exec cmp '{}' $original/'{}' \; diff --git a/src/tests/copy-file b/src/tests/copy-file new file mode 100755 index 0000000..ade0946 --- /dev/null +++ b/src/tests/copy-file @@ -0,0 +1,26 @@ +#!/bin/sh +# $Id$ +cat > foo < foobar +test -f foobar || exit 1 +test -s foobar && exit 1 +rm foobar || exit 1 diff --git a/src/tests/create-dirs.c b/src/tests/create-dirs.c new file mode 100644 index 0000000..9864cdd --- /dev/null +++ b/src/tests/create-dirs.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +creat_dirs (int count) +{ + int i; + + for (i = 0; i < count; ++i) { + char num[17]; + int ret; + + snprintf (num, sizeof(num), "%d", i); + + ret = mkdir (num, 0777); + if (ret < 0) + err (1, "mkdir %s", num); + } + return 0; +} + +static void +usage (int ret) +{ + fprintf (stderr, "%s number-of-dirs\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *ptr; + int count; + + + if (argc != 2) + usage (1); + + count = strtol (argv[1], &ptr, 0); + if (count == 0 && ptr == argv[1]) + errx (1, "'%s' not a number", argv[1]); + + return creat_dirs (count); +} diff --git a/src/tests/create-files.c b/src/tests/create-files.c new file mode 100644 index 0000000..50eca70 --- /dev/null +++ b/src/tests/create-files.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#undef min +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +creat_files (int count, long startsize) +{ + int i; + long size = 0; + + for (i = 0; i < count; ++i) { + char num[17]; + int fd; + + snprintf (num, sizeof(num), "%d", i); + + fd = open (num, O_WRONLY | O_CREAT | O_EXCL, 0777); + if (fd < 0) + err (1, "open %s", num); + size = startsize; + while (size > 0) { + char buf[8192]; + size_t len; + ssize_t ret; + + len = min(sizeof(buf), size); + + ret = write (fd, buf, len); + if (ret < 0) + err (1, "write to %s", num); + if (ret != len) + errx (1, "short write to %s", num); + size -= ret; + } + if (close (fd) < 0) + err (1, "close %s", num); + } + return 0; +} + +static void +usage (int ret) +{ + fprintf (stderr, "%s number-of-files size-of-files\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *ptr; + int count; + long size; + + + if (argc != 3) + usage (1); + + count = strtol (argv[1], &ptr, 0); + if (count == 0 && ptr == argv[1]) + errx (1, "'%s' not a number", argv[1]); + + size = strtol (argv[2], &ptr, 0); + if (size == 0 && ptr == argv[2]) + errx (1, "`%s' not a number", argv[2]); + + return creat_files (count, size); +} diff --git a/src/tests/create-remove-dirs b/src/tests/create-remove-dirs new file mode 100644 index 0000000..58175ab --- /dev/null +++ b/src/tests/create-remove-dirs @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +$objdir/create-remove dir 1000 diff --git a/src/tests/create-remove-files b/src/tests/create-remove-files new file mode 100644 index 0000000..19cb161 --- /dev/null +++ b/src/tests/create-remove-files @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +$objdir/create-remove file 1000 diff --git a/src/tests/create-remove.c b/src/tests/create-remove.c new file mode 100644 index 0000000..8debf07 --- /dev/null +++ b/src/tests/create-remove.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +creat_dir (const char *name) +{ + int ret = mkdir (name, 0777); + if (ret < 0) err (1, "mkdir %s", name); + return 0; +} + +static int +remove_dir (const char *name) +{ + int ret = rmdir (name); + if (ret < 0) err (1, "rmdir %s", name); + return 0; +} + +static int +creat_file (const char *name) +{ + int ret = open (name, O_CREAT|O_RDWR, 0777); + if (ret < 0) err (1, "mkdir %s", name); + close (ret); + return 0; +} + +static int +unlink_file (const char *name) +{ + int ret = unlink (name); + if (ret < 0) err (1, "unlink %s", name); + return 0; +} + + +static void +usage (int ret) +{ + fprintf (stderr, "%s [file|dir] number-of-dirs\n", __progname); + exit (ret); +} + +#ifndef MAXPATHLEN +#ifdef PATH_MAX +#define MAXPATHLEN PATH_MAX +#else +#define MAXPATHLEN 4096 +#endif +#endif + +static int +creat_many (int num, + int (*c) (const char *name), + int (*d) (const char *name)) +{ + char name[MAXPATHLEN]; + + if (num < 0) + errx (1, "not be negative"); + + snprintf (name, sizeof(name), "foo-%d-%d", num, getpid()); + + while (num-- > 0) { + (c) (name); + (d) (name); + } + return 0; +} + + +int +main(int argc, char **argv) +{ + char *ptr; + int count; + + + if (argc != 3) + usage (1); + + count = strtol (argv[2], &ptr, 0); + if (count == 0 && ptr == argv[2]) + errx (1, "'%s' not a number", argv[2]); + + if (strcmp ("file", argv[1]) == 0) + return creat_many (count, creat_file, unlink_file); + else if (strcmp("dir", argv[1]) == 0) + return creat_many (count, creat_dir, remove_dir); + else + errx (1, "unknown type: %s", argv[1]); + return 0; +} diff --git a/src/tests/create-stat.c b/src/tests/create-stat.c new file mode 100644 index 0000000..c9ef14c --- /dev/null +++ b/src/tests/create-stat.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct VenusFid { + afs_int32 Cell; + struct AFSFid Fid; +}; + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static void +usage (int ret) +{ + fprintf (stderr, "%s file\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *file; + int ret; + struct stat sb; + struct stat sb_new; + struct stat sb_old; + struct VenusFid fid; + char *filename; + ino_t afsfileid; + + if (argc != 2) + usage (1); + + file = argv[1]; + + asprintf (&filename, "%s.new", file); + + ret = open (file, O_RDWR, 0600); + if (ret < 0) + err (1, "open"); + close (ret); + + ret = open (filename, O_RDWR|O_CREAT|O_EXCL, 0600); + if (ret < 0) { + unlink(file); + err (1, "open"); + } + close (ret); + + ret = stat (file, &sb); + if (ret < 0) { + unlink(filename); + unlink(file); + err (1, "stat"); + } + + ret = lstat (filename, &sb_new); + if (ret < 0) { + unlink(filename); + unlink(file); + err (1, "stat"); + } + + if (sb.st_ino == sb_new.st_ino) + err (1, "sb.st_ino == sb_new.st_ino"); + + ret = lstat (file, &sb_old); + if (ret < 0) { + unlink(filename); + unlink(file); + err (1, "stat"); + } + + if (sb_old.st_ino == sb_new.st_ino) + err (1, "sb_old.st_ino == sb_new.st_ino"); + if (sb.st_ino == sb_new.st_ino) + err (1, "sb.st_ino == sb_new.st_ino"); + if (sb_old.st_ino != sb.st_ino) + err (1, "sb_old.st_ino != sb.st_ino"); + + ret = fs_getfid (file, &fid); + if (ret) { + unlink(file); + unlink(filename); + err (1, "fs_getfid: %d", ret); + } + + afsfileid = ((fid.Fid.Volume & 0x7FFF) << 16 | (fid.Fid.Vnode & 0xFFFFFFFF)); + if (sb.st_ino != afsfileid) { + unlink(file); + unlink(filename); + errx (1, "sb.st_ino(%ld) != afsfileid(%ld) (%d.%d.%d.%d)", + (long)sb.st_ino, (long)afsfileid, + fid.Cell, fid.Fid.Volume, fid.Fid.Vnode, fid.Fid.Unique); + } + + unlink(filename); + unlink(file); + + return 0; +} diff --git a/src/tests/create-symlinks.c b/src/tests/create-symlinks.c new file mode 100644 index 0000000..4dc022c --- /dev/null +++ b/src/tests/create-symlinks.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +#define CONTENT_STRING "kaka" + +static FILE *verbose_fp = NULL; + +static int +creat_symlinks (int count) +{ + int ret; + int i; + + fprintf (verbose_fp, "creating:"); + + for (i = 0; i < count; ++i) { + char num[17]; + + fprintf (verbose_fp, " c%d", i); + fflush (verbose_fp); + + snprintf (num, sizeof(num), "%d", i); + + ret = symlink (CONTENT_STRING, num); + if (ret < 0) + err (1, "symlink %s", num); + } + fprintf (verbose_fp, "\n"); + return 0; +} + +#ifndef MAXPATHLEN +#ifdef PATH_MAX +#define MAXPATHLEN PATH_MAX +#else +#define MAXPATHLEN 4096 +#endif +#endif + +static int +verify_contents (int count) +{ + int ret, i; + char file[MAXPATHLEN]; + char content[MAXPATHLEN]; + + fprintf (verbose_fp, "reading:"); + for (i = 0; i < count; i++) { + fprintf (verbose_fp, " r%d", i); + fflush (verbose_fp); + + snprintf (file, sizeof(file), "%d", i); + ret = readlink (file, content, sizeof(content) - 1); + if (ret < 0) + err (1, "readlink: %d", i); + content[ret] = '\0'; + if (strcmp (CONTENT_STRING, content) != 0) + errx (1, "%s != %s", content, CONTENT_STRING); + } + fprintf (verbose_fp, "\n"); + return 0; +} + +static void +usage (int ret) +{ + fprintf (stderr, "%s number-of-symlinks\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *ptr; + int count; + + + if (argc != 2) + usage (1); + + verbose_fp = fdopen (4, "w"); + if (verbose_fp == NULL) { + verbose_fp = fopen ("/dev/null", "w"); + if (verbose_fp == NULL) + err (1, "fopen"); + } + + count = strtol (argv[1], &ptr, 0); + if (count == 0 && ptr == argv[1]) + errx (1, "'%s' not a number", argv[1]); + + return creat_symlinks (count) || + verify_contents(count); +} diff --git a/src/tests/dd b/src/tests/dd new file mode 100755 index 0000000..9f51153 --- /dev/null +++ b/src/tests/dd @@ -0,0 +1,8 @@ +#!/bin/sh +# $Id$ +if test -r /dev/zero; then + dd if=/dev/zero of=foo bs=1k count=20 >/dev/null 2>/dev/null || exit 1 + rm foo || exit 1 +else + echo "not running dd (you have no /dev/zero)" +fi diff --git a/src/tests/deep-tree b/src/tests/deep-tree new file mode 100644 index 0000000..cafecd6 --- /dev/null +++ b/src/tests/deep-tree @@ -0,0 +1,6 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ;exit 0; fi + +mkdir foo && ( cd foo && $SHELL $SHELLVERBOSE ${srcdir}/dir-tree 5 "0 1 2 3 4" ) +${objdir}/rm-rf foo diff --git a/src/tests/deep-tree2 b/src/tests/deep-tree2 new file mode 100644 index 0000000..3252e42 --- /dev/null +++ b/src/tests/deep-tree2 @@ -0,0 +1,12 @@ +#!/bin/sh +# $Id$ + +mkdir foo + +b=foo +for a in 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z å ä ö; do + b=$b/$a + mkdir $b +done + +rm -rf foo \ No newline at end of file diff --git a/src/tests/dir-size-mismatch b/src/tests/dir-size-mismatch new file mode 100644 index 0000000..537de13 --- /dev/null +++ b/src/tests/dir-size-mismatch @@ -0,0 +1,10 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ;exit 0; fi + +for i in `awk 'BEGIN {for(i=0; i < 1000; ++i) printf "%d\n", i}' /dev/null`; do + ln -s hejsan qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq$i +done +find . -name 'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq*' -print | xargs rm +ln -s foo bar +rm bar diff --git a/src/tests/dir-tree b/src/tests/dir-tree new file mode 100755 index 0000000..bb68098 --- /dev/null +++ b/src/tests/dir-tree @@ -0,0 +1,22 @@ +#!/bin/sh +# $Id$ + +####################################################### +# +# Make a directory tree of directories +# dir-tree + +# +####################################################### + +DEPTH=$1; shift +DIRNUMS="$*" +export DIRNUMS DEPTH + +# catch non numeric args and recurse cond +expr $DEPTH '>' 0 > /dev/null 2>&1 || exit 0 + +for a in $DIRNUMS; do + (mkdir $a && cd $a && \ + $SHELL $SHELLVERBOSE ${srcdir}/dir-tree \ + `expr $DEPTH - 1` "$DIRNUMS") || exit 1 +done diff --git a/src/tests/dup2-and-unlog.c b/src/tests/dup2-and-unlog.c new file mode 100644 index 0000000..c9c16b2 --- /dev/null +++ b/src/tests/dup2-and-unlog.c @@ -0,0 +1,32 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + int fd; + + + fd = open ("foo", O_RDWR|O_CREAT, 0666); + if (fd < 0) + err (1, "open"); + + dup2 (fd + 1, fd); + + if (write (fd, "foo\n", 4) != 4) + errx (1, "write"); + + ktc_ForgetAllTokens(); + + close (fd); + close (fd + 1); + + exit (0); +} diff --git a/src/tests/echo-n.c b/src/tests/echo-n.c new file mode 100644 index 0000000..7617a1f --- /dev/null +++ b/src/tests/echo-n.c @@ -0,0 +1,18 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +int +main (int argc, char **argv) +{ + int i; + for (i = 1; i < argc ; i++) { + printf ("%s", argv[i]); + if (argc > i + 1) + printf (" "); + } + fflush (stdout); + return 0; +} diff --git a/src/tests/err.c b/src/tests/err.c new file mode 100644 index 0000000..cc1b031 --- /dev/null +++ b/src/tests/err.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +RCSID("$Id$"); +#endif + +#include "err.h" + +void +err(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verr(eval, fmt, ap); + va_end(ap); +} diff --git a/src/tests/err.h b/src/tests/err.h new file mode 100644 index 0000000..e4dc06d --- /dev/null +++ b/src/tests/err.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef __ERR_H__ +#define __ERR_H__ + +#include +#include +#include +#include +#include + +extern const char *__progname; + +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(x) +#endif + +void warnerr(int doerrno, const char *fmt, va_list ap) + __attribute__ ((format (printf, 2, 0))); + +void verr(int eval, const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 2, 0))); +void err(int eval, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 2, 3))); +void verrx(int eval, const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 2, 0))); +void errx(int eval, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 2, 3))); +void vwarn(const char *fmt, va_list ap) + __attribute__ ((format (printf, 1, 0))); +void warn(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); +void vwarnx(const char *fmt, va_list ap) + __attribute__ ((format (printf, 1, 0))); +void warnx(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +#endif /* __ERR_H__ */ diff --git a/src/tests/errtrans.pm b/src/tests/errtrans.pm new file mode 100644 index 0000000..48cf96a --- /dev/null +++ b/src/tests/errtrans.pm @@ -0,0 +1,310 @@ +# CMUCS AFStools +# Copyright (c) 1996, Carnegie Mellon University +# All rights reserved. +# +# See CMUCS/CMU_copyright.pm for use and distribution information + +package OpenAFS::errtrans; + +=head1 NAME + +OpenAFS::errtrans - com_err error translation + +=head1 SYNOPSIS + + use OpenAFS::errtrans + $code = errcode($name); + $code = errcode($pkg, $err); + $string = errstr($code, [$volerrs]); + +=head1 DESCRIPTION + +This module translates "common" error codes such as those produced +by MIT's com_err package, and used extensively in AFS. It also knows +how to translate system error codes, negative error codes used by Rx, +and a few "special" error codes used by AFS's volume package. + +In order to work, these routines depend on the existence of error +table files in $err_table_dir, which is usually /usr/local/lib/errtbl. +Each file should be named after a com_err error package, and contain +the definition for that package. + +Note that the AFS version of com_err translates package names to uppercase +before generating error codes, so a table which claims to define the 'pt' +package actually defines the 'PT' package when compiled by AFS's compile_et. +Tables that are normally fed to AFS's compile_et should be installed using +the _uppercase_ version of the package name. + +The error tables used in AFS are part of copyrighted AFS source code, and +are not included with this package. However, I have included a utility +(gen_et) which can generate error tables from the .h files normally +produced by compile_et, and Transarc provides many of these header files +with binary AFS distributions (in .../include/afs). See the gen_et +program for more details. + +=cut + +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT :afs_internal); +use OpenAFS::config qw($err_table_dir); +use Symbol; +use Exporter; +use POSIX; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&errcode &errstr); + + +@NumToChar = ('', 'A'..'Z', 'a'..'z', '0'..'9', '_'); +%CharToNum = map(($NumToChar[$_], $_), (1 .. $#NumToChar)); + +%Vol_Codes = ( VSALVAGE => 101, + VNOVNODE => 102, + VNOVOL => 103, + VVOLEXISTS => 104, + VNOSERVICE => 105, + VOFFLINE => 106, + VONLINE => 107, + VDISKFULL => 108, + VOVERQUOTA => 109, + VBUSY => 110, + VMOVED => 111 + ); +%Vol_Desc = ( 101 => "volume needs to be salvaged", + 102 => "no such entry (vnode)", + 103 => "volume does not exist / did not salvage", + 104 => "volume already exists", + 105 => "volume out of service", + 106 => "volume offline (utility running)", + 107 => "volume already online", + 108 => "unknown volume error 108", + 109 => "unknown volume error 109", + 110 => "volume temporarily busy", + 111 => "volume moved" + ); +%Rx_Codes = ( RX_CALL_DEAD => -1, + RX_INVALID_OPERATION => -2, + RX_CALL_TIMEOUT => -3, + RX_EOF => -4, + RX_PROTOCOL_ERROR => -5, + RX_USER_ABORT => -6, + RX_ADDRINUSE => -7, + RX_MSGSIZE => -8, + RXGEN_CC_MARSHAL => -450, + RXGEN_CC_UNMARSHAL => -451, + RXGEN_SS_MARSHAL => -452, + RXGEN_SS_UNMARSHAL => -453, + RXGEN_DECODE => -454, + RXGEN_OPCODE => -455, + RXGEN_SS_XDRFREE => -456, + RXGEN_CC_XDRFREE => -457 + ); +%Rx_Desc = ( -1 => "server or network not responding", + -2 => "invalid RPC (Rx) operation", + -3 => "server not responding promptly", + -4 => "Rx unexpected EOF", + -5 => "Rx protocol error", + -6 => "Rx user abort", + -7 => "port address already in use", + -8 => "Rx message size incorrect", + -450 => "Rx client: XDR marshall failed", + -451 => "Rx client: XDR unmarshall failed", + -452 => "Rx server: XDR marshall failed", + -453 => "Rx server: XDR unmarshall failed", + -454 => "Rx: Decode failed", + -455 => "Rx: Invalid RPC opcode", + -456 => "Rx server: XDR free failed", + -457 => "Rx client: XDR free failed", + map(($_ => "RPC interface mismatch ($_)"), (-499 .. -458)), + -999 => "Unknown error" + ); + + +sub _tbl_to_num { + my(@tbl) = split(//, $_[0]); + my($n); + + @tbl = @tbl[0..3] if (@tbl > 4); + foreach (@tbl) { $n = ($n << 6) + $CharToNum{$_} } + $n << 8; +} + + +sub _num_to_tbl { + my($n) = $_[0] >> 8; + my($tbl); + + while ($n) { + $tbl = @NumToChar[$n & 0x3f] . $tbl; + $n >>= 6; + } + $tbl; +} + + +sub _load_system_errors { + my($file) = @_; + my($fh) = &gensym(); + + return if ($did_include{$file}); +# print "Loading $file...\n"; + $did_include{$file} = 'yes'; + if (open($fh, "/usr/include/$file")) { + while (<$fh>) { + if (/^\#define\s*(E\w+)\s*(\d+)/) { + $Codes{$1} = $2; + } elsif (/^\#include\s*\"([^"]+)\"/ + || /^\#include\s*\<([^>]+)\>/) { + &_load_system_errors($1); + } + } + close($fh); + } +} + + +# Load an error table into memory +sub _load_error_table { + my($pkg) = @_; + my($fh, @words, $curval, $tval, $nval); + my($tid, $tfn, $code, $val, $desc); + + return if ($Have_Table{$pkg}); + # Read in the input file, and split it into words + $fh = &gensym(); + return unless open($fh, "$err_table_dir/$pkg"); +# print "Loading $pkg...\n"; + line: while (<$fh>) { + s/^\s*//; # Strip leading whitespace + while ($_) { + next line if (/^#/); + if (/^(error_table|et)\s*/) { push(@words, 'et'); $_ = $' } + elsif (/^(error_code|ec)\s*/) { push(@words, 'ec'); $_ = $' } + elsif (/^end\s*/) { push(@words, 'end'); $_ = $' } + elsif (/^(\w+)\s*/) { push(@words, $1); $_ = $' } + elsif (/^\"([^"]*)\"\s*/) { push(@words, $1); $_ = $' } + elsif (/^([,=])\s*/) { push(@words, $1); $_ = $' } + else { close($fh); return } + } + } + close($fh); + + # Parse the table header + $_ = shift(@words); return unless ($_ eq 'et'); + if ($words[1] eq 'ec') { $tid = shift(@words) } + elsif ($words[2] eq 'ec') { ($tfn, $tid) = splice(@words, 0, 2) } + else { return; } + if ($tid ne $pkg) { + $Have_Table{$tid} = 'yes'; + $_ = $tid; + $_ =~ tr/a-z/A-Z/; + $tid = $_ if ($_ eq $pkg); + } + $tval = &_tbl_to_num($tid); + $Have_Table{$pkg} = 'yes'; +# print "Package $pkg: table-id = $tid, table-fun = $tfn, base = $tval\n"; + + while (@words) { + $_ = shift(@words); return unless ($_ eq 'ec'); + $code = shift(@words); + $_ = shift(@words); + if ($_ eq '=') { + $val = shift(@words); + $_ = shift(@words); + } else { + $val = $curval; + } + return unless ($_ eq ','); + $desc = shift(@words); + $nval = $tval + $val; + $curval = $val + 1; + $Desc{$nval} = $desc; + $Codes{$code} = $nval; +# print " code $code: value = $nval ($tval + $val), desc = \"$desc\"\n"; + } +} + +=head2 errcode($name) + +Returns the numeric error code corresponding to the specified error +name. This routine knows about names of system errors, a few special +Rx and volume-package errors, and any errors defined in installed +error tables. If the specified error code is not found, returns -999. + +=head2 errcode($pkg, $code) + +Shifts $code into the specified error package, and returns the +resulting com_err code. This can be used to generate error codes +for _any_ valid com_err package. + +=cut + +sub errcode { + if (@_ > 1) { + my($pkg, $code) = @_; + &_tbl_to_num($pkg) + $code; + } else { + my($name) = @_; + my($dir, @tbls, $code); + + &_load_system_errors("errno.h"); + if ($Vol_Codes{$name}) { $Vol_Codes{$name} } + elsif ($Rx_Codes{$name}) { $Rx_Codes{$name} } + elsif ($Codes{$name}) { $Codes{$name} } + else { + if ($name =~ /^E/) { # Might be a POSIX error constant + $! = 0; + $code = &POSIX::constant($name, 0); + if (!$!) { return $code; } + } + $dir = &gensym(); + if (opendir($dir, $err_table_dir)) { + @tbls = grep(!/^\.?\.$/, readdir($dir)); + close($dir); + foreach (@tbls) { &_load_error_table($_) } + } + $Codes{$name} ? $Codes{$name} : -999; + } + } +} + + +=head2 errstr($code, [$volerrs]) + +Returns the error string corresponding to a specified com_err, Rx, +or system error code. If $volerrs is specified and non-zero, then +volume-package errors are considered before system errors with the +same values. + +=cut + +sub errstr { + my($code, $volerrs) = @_; + my($pkg, $sub); + + if ($Rx_Desc{$code}) { return $Rx_Desc{$code} } + if ($volerrs && $Vol_Desc{$code}) { return $Vol_Desc{$code} } + $sub = $code & 0xff; + $pkg = &_num_to_tbl($code); + if ($pkg eq '') { + $! = $sub + 0; + $_ = $! . ''; + if (/^(Error )?\d+$/) { $Vol_Desc{$sub} ? $Vol_Desc{$sub} : "Error $sub" } + else { $_ } + } else { + &_load_error_table($pkg); + $Desc{$code} ? $Desc{$code} : "Unknown code $pkg $sub ($code)"; + } +} + +1; + +=head1 COPYRIGHT + +The CMUCS AFStools, including this module are +Copyright (c) 1996, Carnegie Mellon University. All rights reserved. +For use and redistribution information, see CMUCS/CMU_copyright.pm + +=cut diff --git a/src/tests/errx.c b/src/tests/errx.c new file mode 100644 index 0000000..da47e4d --- /dev/null +++ b/src/tests/errx.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +RCSID("$Id$"); +#endif + +#include "err.h" + +void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verrx(eval, fmt, ap); + va_end(ap); +} diff --git a/src/tests/exec b/src/tests/exec new file mode 100755 index 0000000..f6535c0 --- /dev/null +++ b/src/tests/exec @@ -0,0 +1,9 @@ +#!/bin/sh +echo '#!/bin/sh' > foo.sh +export objdir +echo '$objdir/echo-n "foo"' >> foo.sh +test -f foo.sh || exit 1 +chmod +x foo.sh +test -x foo.sh || exit 1 +FOO=`./foo.sh` +test "X"$FOO = "Xfoo" || exit 1 diff --git a/src/tests/exit-wo-close.c b/src/tests/exit-wo-close.c new file mode 100644 index 0000000..c2ff56f --- /dev/null +++ b/src/tests/exit-wo-close.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +child (const char *filename) +{ + int fd; + int ret; + + fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + err (1, "open %s", filename); + ret = write (fd, "hej", 3); + if (ret != 3) + err (1, "write %s", filename); + return 0; +} + +static int +parent (const char *filename, pid_t child_pid) +{ + int stat; + int ret; + int fd; + struct stat sb; + char buf[3]; + + ret = waitpid (child_pid, &stat, 0); + if (ret < 0) + err (1, "waitpid %u", (unsigned)child_pid); + if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) + errx (1, "weird child %u", (unsigned)child_pid); + fd = open (filename, O_RDONLY, 0); + if (fd < 0) + err (1, "open %s", filename); + ret = fstat (fd, &sb); + if (ret < 0) + err (1, "fstat %s", filename); + if (sb.st_size != 3) + errx (1, "size of %s = %u != 3", filename, (unsigned)sb.st_size); + ret = read (fd, buf, sizeof(buf)); + if (ret < 0) + err (1, "read %s", filename); + if (ret != 3) + errx (1, "short read from %s", filename); + if (memcmp (buf, "hej", 3) != 0) + errx (1, "bad contents of %s = `%.3s'\n", filename, buf); + close (fd); + return 0; +} + +static int +doit (const char *filename) +{ + pid_t pid; + + pid = fork (); + if (pid < 0) + err (1, "fork"); + + if (pid == 0) + return child (filename); + else + return parent (filename, pid); +} + +int +main(int argc, char **argv) +{ + const char *file = "foo"; + + + if (argc != 2 && argc != 1) + errx (1, "usage: %s [file]", argv[0]); + if (argc == 2) + file = argv[1]; + return doit (file); +} diff --git a/src/tests/extcopyin b/src/tests/extcopyin new file mode 100755 index 0000000..a5f5790 --- /dev/null +++ b/src/tests/extcopyin @@ -0,0 +1,11 @@ +#!/bin/sh +FS=${FS:-${objdir}/../appl/fs/fs} +${FS} sa . system:anyuser all || exit 1 +${objdir}/write-rand /usr/tmp/$$ 262144 || exit 1 +${objdir}/afscp -i -b 56k /usr/tmp/$$ `pwd`/$$ || exit 1 +diff /usr/tmp/$$ `pwd`/$$ || exit 1 +${objdir}/afscp -i -b 32k /usr/tmp/$$ `pwd`/$$ || exit 1 +diff /usr/tmp/$$ `pwd`/$$ || exit 1 +exit 0 + + diff --git a/src/tests/extcopyout b/src/tests/extcopyout new file mode 100755 index 0000000..0347dd8 --- /dev/null +++ b/src/tests/extcopyout @@ -0,0 +1,11 @@ +#!/bin/sh +FS=${FS:-${objdir}/../appl/fs/fs} +${FS} sa . system:anyuser all || exit 1 +${objdir}/write-rand $$ 262144 || exit 1 +${objdir}/afscp -o -b 56k `pwd`/$$ /usr/tmp/$$ || exit 1 +diff /usr/tmp/$$ `pwd`/$$ || exit 1 +${objdir}/afscp -o -b 32k `pwd`/$$ /usr/tmp/$$ || exit 1 +diff /usr/tmp/$$ `pwd`/$$ || exit 1 +exit 0 + + diff --git a/src/tests/fcachesize-dir b/src/tests/fcachesize-dir new file mode 100644 index 0000000..c9a9879 --- /dev/null +++ b/src/tests/fcachesize-dir @@ -0,0 +1,13 @@ +#!/bin/sh +# $Id$ + +FS=${FS:-${objdir}/../appl/fs/fs} +SIZE1=`$FS getcache -b | awk '{ print $4 ; exit }'` +mkdir foo +SIZE2=`$FS getcache -b | awk '{ print $4 ; exit }'` +test $SIZE2 = `expr $SIZE1 + 2048` || exit 1 +rmdir foo +#SIZE3=`$FS getcache -b | awk '{ print $4 ; exit }'` +#test $SIZE3 = $SIZE1 || exit 1 + +exit 0 diff --git a/src/tests/fcachesize-file-small b/src/tests/fcachesize-file-small new file mode 100644 index 0000000..62800c1 --- /dev/null +++ b/src/tests/fcachesize-file-small @@ -0,0 +1,13 @@ +#!/bin/sh +# $Id$ + +FS=${FS:-${objdir}/../appl/fs/fs} +SIZE1=`$FS getcache -b | awk '{ print $4 ; exit }'` +echo foo > foo +SIZE2=`$FS getcache -b | awk '{ print $4 ; exit }'` +test $SIZE2 = `expr $SIZE1 + 4` || exit 1 +rm foo +#SIZE3=`$FS getcache -b | awk '{ print $4 ; exit }'` +#test $SIZE3 = $SIZE1 || exit 1 + +exit 0 diff --git a/src/tests/fcachesize-read-file b/src/tests/fcachesize-read-file new file mode 100644 index 0000000..6dd4b72 --- /dev/null +++ b/src/tests/fcachesize-read-file @@ -0,0 +1,14 @@ +#!/bin/sh +# $Id$ + +FS=${FS:-${objdir}/../appl/fs/fs} +SIZE1=`$FS getcache | awk '{ print $8 ; exit }'` +SIZE2=`expr $SIZE1 + 4` +if test -w /dev/null; then + dd if=../foo of=/dev/null bs=1k count=$SIZE2 >/dev/null 2>/dev/null || exit 1 + rm ../foo || exit 1 +else + echo "not running dd (you have no /dev/null)" +fi + +exit 0 diff --git a/src/tests/fcachesize-write-file b/src/tests/fcachesize-write-file new file mode 100644 index 0000000..8b60ad2 --- /dev/null +++ b/src/tests/fcachesize-write-file @@ -0,0 +1,13 @@ +#!/bin/sh +# $Id$ + +FS=${FS:-${objdir}/../appl/fs/fs} +SIZE1=`$FS getcache | awk '{ print $8 ; exit }'` +SIZE2=`expr $SIZE1 + 4` +if test -r /dev/zero; then + dd if=/dev/zero of=../foo bs=1k count=$SIZE2 >/dev/null 2>/dev/null || exit 1 +else + echo "not running dd (you have no /dev/zero)" +fi + +exit 0 diff --git a/src/tests/fchmod.c b/src/tests/fchmod.c new file mode 100644 index 0000000..3dbee05 --- /dev/null +++ b/src/tests/fchmod.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +int +main(int argc, char **argv) +{ + int fd, ret; + struct stat sb; + + + fd = open ("deps", O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (fd < 0) + err (1, "open"); + ret = fstat (fd, &sb); + if (ret < 0) + err (1, "fstat"); + ret = write (fd, "# DO NOT DELETE\n", 16); + if (ret != 16) + err (1, "write"); + ret = fchmod (fd, 0100644); + if (ret < 0) + errx (1, "fchmod"); + ret = close (fd); + if (ret < 0) + errx (1, "close"); + + unlink("deps"); + return 0; +} diff --git a/src/tests/fhbench.c b/src/tests/fhbench.c new file mode 100644 index 0000000..98b2b4d --- /dev/null +++ b/src/tests/fhbench.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_IOCCOM_H +#include +#endif + +#include + +#include +#include + +#include +#include + +RCSID("$Id$"); + +struct fhb_handle { + char data[512]; +}; + +static int help_flag; +static int num_files; +static int write_file = 0; +static int num_runs = 3; + +static struct agetargs args[] = { + {"num", 'n', aarg_integer, &num_files, "number of files"}, + {"write", 'w', aarg_integer, &write_file, "write num kb"}, + {"runs", 'r', aarg_integer, &num_runs, "number of runs"}, + {"help", 0, aarg_flag, &help_flag, NULL, NULL}, + {NULL, 0, aarg_end, NULL, NULL, NULL} +}; + + +static void +fhb_fhget (char *filename, struct fhb_handle *handle) +{ + int ret = 0; +#if defined(HAVE_GETFH) && defined(HAVE_FHOPEN) + { + fhandle_t fh; + + ret = getfh (filename, &fh); + if (ret) + err (1, "getfh"); + memcpy (handle, &fh, sizeof(fh)); + } +#endif + { + struct ViceIoctl vice_ioctl; + + vice_ioctl.in = NULL; + vice_ioctl.in_size = 0; + + vice_ioctl.out = (caddr_t)handle; + vice_ioctl.out_size = sizeof(*handle); + + ret = pioctl (filename, VIOC_FHGET, &vice_ioctl, 0); + if (ret) + errx (1, "k_pioctl"); + } +} + + +static int +fhb_fhopen (struct fhb_handle *handle, int flags) +{ + int ret; +#if defined(HAVE_GETFH) && defined(HAVE_FHOPEN) + { + fhandle_t fh; + + memcpy (&fh, handle, sizeof(fh)); + ret = fhopen (&fh, flags); + if (ret >= 0) + return ret; + } +#endif + +#ifdef KERBEROS /* really KAFS */ + { + struct ViceIoctl vice_ioctl; + + vice_ioctl.in = (caddr_t)handle; + vice_ioctl.in_size = sizeof(*handle); + + vice_ioctl.out = NULL; + vice_ioctl.out_size = 0; + + ret = k_pioctl (NULL, VIOC_FHOPEN, &vice_ioctl, flags); + if (ret >= 0) + return ret; + } +#endif + errx (1, "fhopen/k_pioctl"); +} + +static void +nop_call (void) +{ +#ifdef KERBEROS /* really KAFS */ + { + struct ViceIoctl vice_ioctl; + char c[8]; + int ret; + + vice_ioctl.in = (caddr_t)&c; + vice_ioctl.in_size = sizeof(c); + + vice_ioctl.out = NULL; + vice_ioctl.out_size = 0; + + ret = k_pioctl (NULL, VIOC_XFSDEBUG, &vice_ioctl, 0); + if (ret < 0) + err (1, "k_pioctl"); + } +#else + { + static first = 1; + if (first) { + warnx ("can't test this"); + first = 0; + } + } +#endif +} + +static void +create_file (int num, struct fhb_handle *handle) +{ + int fd; + char filename[1024]; + + snprintf (filename, sizeof(filename), "file-%d", num); + + fd = open (filename, O_CREAT|O_EXCL|O_RDWR, 0666); + if (fd < 0) + err (1, "open"); + + close (fd); + + fhb_fhget(filename, handle); +} + +char databuf[1024]; + +static void +write_to_file (int fd, int num) +{ + int ret; + while (num > 0) { + ret = write (fd, databuf, sizeof(databuf)); + if (ret != sizeof(databuf)) + err (1, "write"); + num--; + } +} + +static void +fhopen_file (int num, struct fhb_handle *handle) +{ + int fd; + + fd = fhb_fhopen(handle, O_RDWR); + if (fd < 0) + err (1, "open"); + + if (write_file) + write_to_file(fd, write_file); + close(fd); +} + +static void +open_file (int num) +{ + int fd; + char filename[1024]; + + snprintf (filename, sizeof(filename), "file-%d", num); + + fd = open (filename, O_RDWR, 0666); + if (fd < 0) + err (1, "open"); + + if (write_file) + write_to_file(fd, write_file); + + close (fd); +} + +static void +unlink_file (int num) +{ + int ret; + char filename[1024]; + + snprintf (filename, sizeof(filename), "file-%d", num); + + ret = unlink(filename); + if (ret < 0) + err (1, "unlink"); +} + +struct timeval time1, time2; + +static void +starttesting(char *msg) +{ + printf("testing %s...\n", msg); + fflush (stdout); + gettimeofday(&time1, NULL); +} + +static void +endtesting(void) +{ + gettimeofday(&time2, NULL); + timevalsub(&time2, &time1); + printf("timing: %ld.%06ld\n", (long)time2.tv_sec, (long)time2.tv_usec); +} + +static void +usage (int exit_val) +{ + aarg_printusage (args, NULL, "number of files", AARG_GNUSTYLE); + exit (exit_val); +} + +static void +open_bench (int i, struct fhb_handle *handles) +{ + printf ("====== test run %d\n" + "==================\n", + i); + + starttesting ("fhopening files"); + for (i = 0; i < num_files; i++) + fhopen_file (i, &handles[i]); + endtesting (); + + starttesting ("opening files"); + for (i = 0; i < num_files; i++) + open_file (i); + endtesting (); +} + +int +main (int argc, char **argv) +{ + int optind = 0; + int i; + struct fhb_handle *handles; + + + if (agetarg (args, argc, argv, &optind, AARG_GNUSTYLE)) + usage (1); + + if (help_flag) + usage (0); + + if (num_files <= 0) + usage (1); + + if (write_file < 0) + usage (1); + +#ifdef KERBEROS + if (!k_hasafs()) +#endif + errx (1, "no afs kernel module"); + + handles = emalloc (num_files * sizeof(*handles)); + + starttesting ("creating files"); + for (i = 0; i < num_files; i++) + create_file (i, &handles[i]); + endtesting (); + + for (i = 0 ; i < num_runs; i++) + open_bench (i, handles); + + printf ( "==================\n"); + starttesting ("unlink files"); + for (i = 0; i < num_files; i++) + unlink_file (i); + endtesting (); + + printf ( "==================\n"); + starttesting ("nop call"); + for (i = 0; i < num_files; i++) + nop_call (); + endtesting (); + + return 0; +} diff --git a/src/tests/find-and-cat-netbsd b/src/tests/find-and-cat-netbsd new file mode 100644 index 0000000..9048ecc --- /dev/null +++ b/src/tests/find-and-cat-netbsd @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +netbsd_ftp_mirror=${1-$AFSROOT/stacken.kth.se/ftp/pub/NetBSD/NetBSD-1.4/} +find ${netbsd_ftp_mirror} -type f -exec cat '{}' \; > /dev/null diff --git a/src/tests/find-linux b/src/tests/find-linux new file mode 100644 index 0000000..d347707 --- /dev/null +++ b/src/tests/find-linux @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +linux_src=${1-$AFSROOT/pdc.kth.se/src/OS/Linux/} +(cd ${linux_src} ; find . ) >&4 diff --git a/src/tests/fs-flush b/src/tests/fs-flush new file mode 100644 index 0000000..36fe37e --- /dev/null +++ b/src/tests/fs-flush @@ -0,0 +1,6 @@ +#!/bin/sh +# $Id$ +FS=${FS:-${objdir}/../appl/fs/fs} +> foobar +${FS} flush +test -f foobar || exit 1 \ No newline at end of file diff --git a/src/tests/fs-sa-la b/src/tests/fs-sa-la new file mode 100755 index 0000000..20f0ccb --- /dev/null +++ b/src/tests/fs-sa-la @@ -0,0 +1,6 @@ +#!/bin/sh +# $Id$ +FS=${FS:-${objdir}/../appl/fs/fs} +${FS} sa . kalle-anka-nu rl 2>&4 +${FS} la >&4 2>&4 +exit 0 diff --git a/src/tests/fs.pm b/src/tests/fs.pm new file mode 100644 index 0000000..4093237 --- /dev/null +++ b/src/tests/fs.pm @@ -0,0 +1,817 @@ +# CMUCS AFStools +# Copyright (c) 1996, 2001 Carnegie Mellon University +# All rights reserved. +# +# See CMU_copyright.ph for use and distribution information +# +#: * fs.pm - Wrappers around the FS commands (fileserver/cache manager) +#: * This module provides wrappers around the various FS commands, which +#: * perform fileserver and cache manager control operations. Right now, +#: * these are nothing more than wrappers around 'fs'; someday, we might +#: * talk to the cache manager directly, but not anytime soon. +#: + +package OpenAFS::fs; +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT :afs_internal); +use OpenAFS::wrapper; +use Exporter; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&AFS_fs_getacl &AFS_fs_setacl + &AFS_fs_cleanacl &AFS_fs_getquota + &AFS_fs_setquota &AFS_fs_whereis + &AFS_fs_examine &AFS_fs_setvol + &AFS_fs_getmount &AFS_fs_mkmount + &AFS_fs_rmmount &AFS_fs_checkvolumes + &AFS_fs_flush &AFS_fs_flushmount + &AFS_fs_flushvolume &AFS_fs_messages + &AFS_fs_newcell &AFS_fs_rxstatpeer + &AFS_fs_rxstatproc &AFS_fs_setcachesize + &AFS_fs_setcell &AFS_fs_setcrypt + &AFS_fs_setclientaddrs &AFS_fs_copyacl + &AFS_fs_storebehind &AFS_fs_setserverprefs + &AFS_fs_checkservers &AFS_fs_checkservers_interval + &AFS_fs_exportafs &AFS_fs_getcacheparms + &AFS_fs_getcellstatus &AFS_fs_getclientaddrs + &AFS_fs_getcrypt &AFS_fs_getserverprefs + &AFS_fs_listcells &AFS_fs_setmonitor + &AFS_fs_getmonitor &AFS_fs_getsysname + &AFS_fs_setsysname &AFS_fs_whichcell + &AFS_fs_wscell); + +#: ACL-management functions: +#: AFS access control lists are represented as a Perl list (or usually, a +#: reference to such a list). Each element in such a list corresponds to +#: a single access control entry, and is a reference to a 2-element list +#: consisting of a PTS entity (name or ID), and a set of rights. The +#: rights are expressed in the usual publically-visible AFS notation, as +#: a string of characters drawn from the class [rlidwkaABCDEFGH]. No +#: rights are denoted by the empty string; such an ACE will never returned +#: by this library, but may be used as an argument to remove a particular +#: ACE from a directory's ACL. +#: +#: One might be inclined to ask why we chose this representation, instead of +#: using an associative array, as might seem obvious. The answer is that +#: doing so would have implied a nonambiguity that isn't there. Suppose you +#: have an ACL %x, and want to know if there is an entry for user $U on that +#: list. You might think you could do this by looking at $x{$U}. The +#: problem here is that two values for $U (one numeric and one not) refer to +#: the same PTS entity, even though they would reference different elements +#: in such an ACL. So, we instead chose a representation that wasn't a hash, +#: so people wouldn't try to do hash-like things to it. If you really want +#: to be able to do hash-like operations, you should turn the list-form ACL +#: into a hash table, and be sure to do name-to-number translation on all the +#: keys as you go. +#: +#: AFS_fs_getacl($path) +#: Get the ACL on a specified path. +#: On success, return a list of two references to ACLs; the first is the +#: positive ACL for the specified path, and the second is the negative ACL. +#: +$AFS_Help{fs_getacl} = '$path => (\@posacl, \@negacl)'; +sub AFS_fs_getacl { + my($path) = @_; + my(@args, @posacl, @negacl, $neg); + + @args = ('listacl', '-path', $path); + &wrapper('fs', \@args, + [ + [ '^(Normal|Negative) rights\:', sub { + $neg = ($_[0] eq 'Negative'); + }], + [ '^ (.*) (\S+)$', sub { #',{ + if ($neg) { + push(@negacl, [@_]); + } else { + push(@posacl, [@_]); + } + }]]); + (\@posacl, \@negacl); +} + +#: AFS_fs_setacl(\@paths, \@posacl, \@negacl, [$clear]) +#: Set the ACL on a specified path. Like the 'fs setacl' command, this +#: function normally only changes ACEs that are mentioned in one of the two +#: argument lists. If a given ACE already exists, it is changed; if not, it +#: is added. To delete a single ACE, specify the word 'none' or the empty +#: string in the rights field. ACEs that already exist but are not mentioned +#: are left untouched, unless $clear is specified. In that case, all +#: existing ACE's (both positive and negative) are deleted. +$AFS_Help{fs_setacl} = '\@paths, \@posacl, \@negacl, [$clear] => Success?'; +sub AFS_fs_setacl { + my($paths, $posacl, $negacl, $clear) = @_; + my($ace, $U, $access); + + if (@$posacl) { + @args = ('setacl', '-dir', @$paths); + push(@args, '-clear') if ($clear); + push(@args, '-acl'); + foreach $e (@$posacl) { + ($U, $access) = @$e; + $access = 'none' if ($access eq ''); + push(@args, $U, $access); + } + &wrapper('fs', \@args); + } + if (@$negacl) { + @args = ('setacl', '-dir', @$paths, '-negative'); + push(@args, '-clear') if ($clear && !@$posacl); + push(@args, '-acl'); + foreach $e (@$negacl) { + ($U, $access) = @$e; + $access = 'none' if ($access eq ''); + push(@args, $U, $access); + } + &wrapper('fs', \@args); + } + if ($clear && !@$posacl && !@$negacl) { + @args = ('setacl', '-dir', @$paths, + '-acl', 'system:anyuser', 'none', '-clear'); + &wrapper('fs', \@args); + } + 1; +} + +#: AFS_fs_cleanacl(\@paths) +#: Clean the ACL on the specified path, removing any ACEs which refer to PTS +#: entities that no longer exist. All the work is done by 'fs'. +#: +$AFS_Help{'fs_cleanacl'} = '\@paths => Success?'; +sub AFS_fs_cleanacl { + my($paths) = @_; + my(@args); + + @args = ('cleanacl', '-path', @$paths); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_getquota($path) [listquota] +#: Get the quota on the specified path. +#: On success, returns the quota. +#: +$AFS_Help{'fs_getquota'} = '$path => $quota'; +sub AFS_fs_getquota { + my($path) = @_; + my(@args, $quota); + + @args = ('listquota', '-path', $path); + &wrapper('fs', \@args, + [[ '^\S+\s+(\d+)\s+\d+\s+\d+\%', \$quota ]]); + $quota; +} + +#: AFS_fs_setquota($path, $quota) [setquota] +#: Set the quota on the specified path to $quota. If $quota is +#: given as 0, there will be no limit to the volume's size. +#: On success, return 1 +#: +$AFS_Help{'fs_setquota'} = '$path, $quota => Success?'; +sub AFS_fs_setquota { + my($path, $quota) = @_; + my(@args); + + @args = ('setquota', '-path', $path, '-max', $quota); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_whereis($path) [whereis, whichcell] +#: Locate the fileserver housing the specified path, and the cell in which it +#: is located. +#: On success, returns a list of 2 or more elements. The first element is the +#: name of the cell in which the volume is located. The remaining elements +#: the names of servers housing the volume; for a replicated volume, there may +#: (should) be more than one such server. +#: +$AFS_Help{'fs_whereis'} = '$path => ($cell, @servers)'; +sub AFS_fs_whereis { + my($path) = @_; + my(@args, $cell, @servers); + + @args = ('whichcell', '-path', $path); + &wrapper('fs', \@args, + [[ "lives in cell \'(.*)\'", \$cell ]]); + + @args = ('whereis', '-path', $path); + &wrapper('fs', \@args, + [[ 'is on host(s?)\s*(.*)', sub { + @servers = split(' ', $_[1]); + }]]); + ($cell, @servers); +} + +#: AFS_fs_examine($path) +#: Get information about the volume containing the specified path. +#: On success, return an associative array containing some or all +#: of the following elements: +#: - vol_name +#: - vol_id +#: - quota_max +#: - quota_used +#: - quota_pctused +#: - part_size +#: - part_avail +#: - part_used +#: - part_pctused +#: +$AFS_Help{'fs_examine'} = '$path => %info'; +sub AFS_fs_examine { + my($path) = @_; + my(@args, %info); + + @args = ('examine', '-path', $path); + %info = &wrapper('fs', \@args, + [[ 'vid = (\d+) named (\S+)', 'vol_id', 'vol_name' ], + [ 'disk quota is (\d+|unlimited)', 'quota_max' ], + [ 'blocks used are (\d+)', 'quota_used' ], + [ '(\d+) blocks available out of (\d+)', + 'part_avail', 'part_size']]); + if ($info{'quota_max'} eq 'unlimited') { + $info{'quota_max'} = 0; + $info{'quota_pctused'} = 0; + } else { + $info{'quota_pctused'} = ($info{'quota_used'} / $info{'quota_max'}) * 100; + $info{'quota_pctused'} =~ s/\..*//; + } + $info{'part_used'} = $info{'part_size'} - $info{'part_avail'}; + $info{'part_pctused'} = ($info{'part_used'} / $info{'part_size'}) * 100; + $info{'part_pctused'} =~ s/\..*//; + %info; +} + +#: AFS_fs_setvol($path, [$maxquota], [$motd]) +#: Set information about the volume containing the specified path. +#: On success, return 1. +$AFS_Help{'fs_setvol'} = '$path, [$maxquota], [$motd] => Success?'; +sub AFS_fs_setvol { + my($path, $maxquota, $motd) = @_; + my(@args); + + @args = ('setvol', '-path', $path); + push(@args, '-max', $maxquota) if ($maxquota || $maxquota eq '0'); + push(@args, '-motd', $motd) if ($motd); + &wrapper('fs', \@args); + 1; +} + + +#: AFS_fs_getmount($path) +#: Get the contents of the specified AFS mount point. +#: On success, return the contents of the specified mount point. +#: If the specified path is not a mount point, return the empty string. +$AFS_Help{'fs_getmount'} = '$path => $vol'; +sub AFS_fs_getmount { + my($path) = @_; + my(@args, $vol); + + @args = ('lsmount', '-dir', $path); + &wrapper('fs', \@args, + [[ "mount point for volume '(.+)'", \$vol ]]); + $vol; +} + + +#: AFS_fs_mkmount($path, $vol, [$cell], [$rwmount], [$fast]) +#: Create an AFS mount point at $path, leading to the volume $vol. +#: If $cell is specified, create a cellular mount point to that cell. +#: If $rwmount is specified and nonzero, create a read-write mount point. +#: If $fast is specified and nonzero, don't check to see if the volume exists. +#: On success, return 1. +$AFS_Help{'fs_mkmount'} = '$path, $vol, [$cell], [$rwmount], [$fast] => Success?'; +sub AFS_fs_mkmount { + my($path, $vol, $cell, $rwmount, $fast) = @_; + my(@args); + + @args = ('mkmount', '-dir', $path, '-vol', $vol); + push(@args, '-cell', $cell) if ($cell); + push(@args, '-rw') if ($rwmount); + push(@args, '-fast') if ($fast); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_rmmount($path) [rmmount] +#: Remove an AFS mount point at $path +#: On success, return 1 +$AFS_Help{'fs_rmmount'} = '$path => Success?'; +sub AFS_fs_rmmount { + my($path) = @_; + my(@args); + + @args = ('rmmount', '-dir', $path); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_checkvolumes() +#: Check/update volume ID cache +#: On success, return 1 +$AFS_Help{'fs_checkvolumes'} = '=> Success?'; +sub AFS_fs_checkvolumes { + my(@args); + + @args = ('checkvolumes'); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_flush(\@paths) +#: Flush files named by @paths from the cache +#: On success, return 1 +$AFS_Help{'fs_flush'} = '\@paths => Success?'; +sub AFS_fs_flush { + my($paths) = @_; + my(@args); + + @args = ('flush'); + push(@args, '-path', @$paths) if $paths; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_flushmount(\@paths) +#: Flush mount points named by @paths from the cache +#: On success, return 1 +$AFS_Help{'fs_flushmount'} = '\@paths => Success?'; +sub AFS_fs_flushmount { + my($paths) = @_; + my(@args); + + @args = ('flushmount'); + push(@args, '-path', @$paths) if $paths; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_flushvolume(\@paths) +#: Flush volumes containing @paths from the cache +#: On success, return 1 +$AFS_Help{'fs_flushvolume'} = '\@paths => Success?'; +sub AFS_fs_flushvolume { + my($paths) = @_; + my(@args); + + @args = ('flushvolume'); + push(@args, '-path', @$paths) if $paths; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_messages($mode) +#: Set cache manager message mode +#: Valid modes are 'user', 'console', 'all', 'none' +#: On success, return 1 +$AFS_Help{'fs_messages'} = '$mode => Success?'; +sub AFS_fs_messages { + my($mode) = @_; + my(@args); + + @args = ('messages', '-show', $mode); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_newcell($cell, \@dbservers, [$linkedcell]) +#: Add a new cell to the cache manager's list, or updating an existing cell +#: On success, return 1 +$AFS_Help{'fs_newcell'} = '$cell, \@dbservers, [$linkedcell] => Success?'; +sub AFS_fs_newcell { + my($cell, $dbservers, $linkedcell) = @_; + my(@args); + + @args = ('newcell', '-name', $cell, '-servers', @$dbservers); + push(@args, '-linkedcell', $linkedcell) if $linkedcell; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_rxstatpeer($enable, [$clear]) +#: Control per-peer Rx statistics: +#: - if $enable is 1, enable stats +#: - if $enable is 0, disable stats +#: - if $clear is 1, clear stats +#: On success, return 1 +$AFS_Help{'fs_rxstatpeer'} = '$enable, [$clear] => Success?'; +sub AFS_fs_rxstatpeer { + my($enable, $clear) = @_; + my(@args); + + @args = ('rxstatpeer'); + push(@args, '-enable') if $enable; + push(@args, '-disable') if defined($enable) && !$enable; + push(@args, '-clear') if $clear; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_rxstatproc($enable, [$clear]) +#: Control per-process Rx statistics: +#: - if $enable is 1, enable stats +#: - if $enable is 0, disable stats +#: - if $clear is 1, clear stats +#: On success, return 1 +$AFS_Help{'fs_rxstatproc'} = '$enable, [$clear] => Success?'; +sub AFS_fs_rxstatproc { + my($enable, $clear) = @_; + my(@args); + + @args = ('rxstatproc'); + push(@args, '-enable') if $enable; + push(@args, '-disable') if defined($enable) && !$enable; + push(@args, '-clear') if $clear; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_setcachesize($size) +#: Set the cache size to $size K +#: On success, return 1 +$AFS_Help{'fs_setcachesize'} = '$size => Success?'; +sub AFS_fs_setcachesize { + my($size) = @_; + my(@args); + + @args = ('setcachesize', '-blocks', $size); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_setcell(\@cells, $suid) +#: Set cell control bits for @cells +#: - if $suid is 1, enable suid programs +#: - if $suid is 0, disable suid programs +#: On success, return 1 +$AFS_Help{'fs_setcell'} = '\@cells, [$suid] => Success?'; +sub AFS_fs_setcell { + my($cells, $suid) = @_; + my(@args); + + @args = ('setcell', '-cell', @$cells); + push(@args, '-suid') if $suid; + push(@args, '-nosuid') if defined($suid) && !$suid; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_setcrypt($enable) +#: Control cache manager encryption +#: - if $enable is 1, enable encrypted connections +#: - if $enable is 0, disable encrypted connections +#: On success, return 1 +$AFS_Help{'fs_setcrypt'} = '$enable => Success?'; +sub AFS_fs_setcrypt { + my($enable) = @_; + my(@args); + + @args = ('setcrypt', '-crypt', $enable ? 'on' : 'off'); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_setclientaddrs(\@addrs) +#: Set client network interface addresses +#: On success, return 1 +$AFS_Help{'fs_setclientaddrs'} = '\@addrs => Success?'; +sub AFS_fs_setclientaddrs { + my($addrs) = @_; + my(@args); + + @args = ('setclientaddrs'); + push(@args, '-address', @$addrs) if $addrs; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_copyacl($from, \@to, [$clear]) +#: Copy the access control list on $from to each directory named in @to. +#: If $clear is specified and nonzero, the target ACL's are cleared first +#: On success, return 1 +$AFS_Help{'fs_copyacl'} = '$from, \@to, [$clear] => Success?'; +sub AFS_fs_copyacl { + my($from, $to, $clear) = @_; + my(@args); + + @args = ('copyacl', '-fromdir', $from, '-todir', @$to); + push(@args, '-clear') if $clear; + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_storebehind(\@paths, [$size], [$def]) +#: Set amount of date to store after file close +#: If $size is specified, the size for each file in @paths is set to $size. +#: If $default is specified, the default size is set to $default. +#: Returns the new or current default value, and a hash mapping filenames +#: to their storebehind sizes. A hash entry whose value is undef indicates +#: that the corresponding file will use the default size. +$AFS_Help{'fs_storebehind'} = '\@paths, [$size], [$def] => ($def, \%sizes)'; +sub AFS_fs_storebehind { + my($paths, $size, $def) = @_; + my(@args, %sizes, $ndef); + + @args = ('storebehind', '-verbose'); + push(@args, '-kbytes', $size) if defined($size); + push(@args, '-files', @$paths) if $paths && @$paths; + push(@args, '-allfiles', $def) if defined($def); + &wrapper('fs', \@args, [ + ['^Will store up to (\d+) kbytes of (.*) asynchronously', + sub { $sizes{$_[1]} = $_[0] }], + ['^Will store (.*) according to default', + sub { $sizes{$_[0]} = undef }], + ['^Default store asynchrony is (\d+) kbytes', \$ndef], + ]); + ($ndef, \%sizes); +} + +#: AFS_fs_setserverprefs(\%fsprefs, \%vlprefs) +#: Set fileserver and/or VLDB server preference ranks +#: Each of %fsprefs and %vlprefs maps server names to the rank to be +#: assigned to the specified servers. +#: On success, return 1. +$AFS_Help{'fs_setserverprefs'} = '\%fsprefs, \%vlprefs => Success?'; +sub AFS_fs_setserverprefs { + my($fsprefs, $vlprefs) = @_; + my(@args, $srv); + + @args = ('setserverprefs'); + if ($fsprefs && %$fsprefs) { + push(@args, '-servers'); + foreach $srv (keys %$fsprefs) { + push(@args, $srv, $$fsprefs{$srv}); + } + } + if ($vlprefs && %$vlprefs) { + push(@args, '-vlservers'); + foreach $srv (keys %$vlprefs) { + push(@args, $srv, $$vlprefs{$srv}); + } + } + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_checkservers([$fast], [$allcells], [$cell]) +#: Check to see what fileservers are down +#: If $cell is specified, fileservers in the specified cell are checked +#: If $allcells is specified and nonzero, fileservers in all cells are checked +#: If $fast is specified and nonzero, don't probe servers +$AFS_Help{'fs_checkservers'} = '[$fast], [$allcells], [$cell] => @down'; +sub AFS_fs_checkservers { + my($fast, $allcells, $cell) = @_; + my(@args, @down); + + @args = ('checkservers'); + push(@args, '-all') if $allcells; + push(@args, '-fast') if $fast; + push(@args, '-cell', $cell) if $cell; + &wrapper('fs', \@args, [ + ['^These servers unavailable due to network or server problems: (.*)\.', + sub { push(@down, split(' ', $_[0])) }], + ]); + @down; +} + +#: AFS_fs_checkservers_interval([$interval]) +#: Get and/or set the down server check interval +#: If $interval is specified and nonzero, it is set as the new interval +#: On success, returns the old interval in seconds +$AFS_Help{'fs_checkservers_interval'} = '$interval => $oldinterval'; +sub AFS_fs_checkservers_interval { + my($interval) = @_; + my(@args, $oldinterval); + + @args = ('checkservers', '-interval', $interval); + &wrapper('fs', \@args, [ + ['^The new down server probe interval \((\d+) secs\)', \$oldinterval], + ['^The current down server probe interval is (\d+) secs', \$oldinterval], + ]); + $oldinterval; +} + +#: AFS_fs_exportafs($type, \%options); +#: Get and/or modify protocol translator settings +#: $type is the translator type, which must be 'nfs' +#: %options specifies the options to be set. Each key is the name of an +#: option, which is enabled if the value is 1, and disabled if the value +#: is 0. The following options are supported: +#: start Enable exporting of AFS +#: convert Copy AFS owner mode bits to UNIX group/other mode bits +#: uidcheck Strict UID checking +#: submounts Permit mounts of /afs subdirectories +#: On success, returns an associative array %modes, which is of the same +#: form, indicating which options are enabled. +$AFS_Help{'fs_exportafs'} = '$type, \%options => %modes'; +sub AFS_fs_exportafs { + my($type, $options) = @_; + my(@args, %modes); + + @args = ('exportafs', '-type', $type); + foreach (qw(start convert uidcheck submounts)) { + push(@args, "-$_", $$options{$_} ? 'on' : 'off') if exists($$options{$_}); + } + + &wrapper('fs', \@args, [ + ['translator is disabled', sub { $modes{'start'} = 0 }], + ['translator is enabled', sub { $modes{'start'} = 1 }], + ['strict unix', sub { $modes{'convert'} = 0 }], + ['convert owner', sub { $modes{'convert'} = 1 }], + [q/no 'passwd sync'/, sub { $modes{'uidcheck'} = 0 }], + [q/strict 'passwd sync'/, sub { $modes{'uidcheck'} = 1 }], + ['Only mounts', sub { $modes{'submounts'} = 0 }], + ['Allow mounts', sub { $modes{'submounts'} = 1 }], + ]); + %modes; +} + + +#: AFS_fs_getcacheparms() +#: Returns the size of the cache, and the amount of cache space used. +#: Sizes are returned in 1K blocks. +$AFS_Help{'fs_getcacheparms'} = 'void => ($size, $used)'; +sub AFS_fs_getcacheparms { + my(@args, $size, $used); + + @args = ('getcacheparms'); + &wrapper('fs', \@args, [ + [q/AFS using (\d+) of the cache's available (\d+) 1K byte blocks/, + \$used, \$size], + ]); + ($size, $used); +} + +#: AFS_fs_getcellstatus(\@cells) +#: Get cell control bits for cells listed in @cells. +#: On success, returns a hash mapping cells to their status; keys are +#: cell names, and values are 1 if SUID programs are permitted for that +#: cell, and 0 if not. +$AFS_Help{'fs_getcellstatus'} = '\@cells => %status'; +sub AFS_fs_getcellstatus { + my($cells) = @_; + my(@args, %status); + + @args = ('getcellstatus', '-cell', @$cells); + &wrapper('fs', \@args, [ + ['Cell (.*) status: setuid allowed', sub { $status{$_[0]} = 1 }], + ['Cell (.*) status: no setuid allowed', sub { $status{$_[0]} = 0 }], + ]); + %status; +} + +#: AFS_fs_getclientaddrs +#: Returns a list of the client interface addresses +$AFS_Help{'fs_getclientaddrs'} = 'void => @addrs'; +sub AFS_fs_getclientaddrs { + my(@args, @addrs); + + @args = ('getclientaddrs'); + &wrapper('fs', \@args, [ + ['^(\d+\.\d+\.\d+\.\d+)', \@addrs ] + ]); + @addrs; +} + +#: AFS_fs_getcrypt +#: Returns the cache manager encryption flag +$AFS_Help{'fs_getcrypt'} = 'void => $crypt'; +sub AFS_fs_getcrypt { + my(@args, $crypt); + + @args = ('getcrypt'); + &wrapper('fs', \@args, [ + ['^Security level is currently clear', sub { $crypt = 0 }], + ['^Security level is currently crypt', sub { $crypt = 1 }], + ]); + $crypt; +} + +#: AFS_fs_getserverprefs([$vlservers], [$numeric]) +#: Get fileserver or vlserver preference ranks +#: If $vlservers is specified and nonzero, VLDB server ranks +#: are retrieved; otherwise fileserver ranks are retrieved. +#: If $numeric is specified and nonzero, servers are identified +#: by IP address instead of by hostname. +#: Returns a hash whose keys are server names or IP addresses, and +#: whose values are the ranks of those servers. +$AFS_Help{'fs_getserverprefs'} = '[$vlservers], [$numeric] => %prefs'; +sub AFS_fs_getserverprefs { + my($vlservers, $numeric) = @_; + my(@args, %prefs); + + @args = ('getserverprefs'); + push(@args, '-numeric') if $numeric; + push(@args, '-vlservers') if $vlservers; + &wrapper('fs', \@args, [ + ['^(\S+)\s*(\d+)', \%prefs], + ]); + %prefs; +} + +#: AFS_fs_listcells([$numeric') +#: Get a list of cells known to the cache manager, and the VLDB +#: servers for each cell. +#: If $numeric is specified and nonzero, VLDB servers are identified +#: by IP address instead of by hostname. +#: Returns a hash where each key is a cell name, and each value is +#: a list of VLDB servers for the corresponding cell. +$AFS_Help{'fs_listcells'} = '[$numeric] => %cells'; +sub AFS_fs_listcells { + my($numeric) = @_; + my(@args, %cells); + + @args = ('listcells'); + push(@args, '-numeric') if $numeric; + &wrapper('fs', \@args, [ + ['^Cell (\S+) on hosts (.*)\.', + sub { $cells{$_[0]} = [ split(' ', $_[1]) ] }], + ]); + %cells; +} + +#: AFS_fs_setmonitor($server) +#: Set the cache manager monitor host to $server. +#: If $server is 'off' or undefined, monitoring is disabled. +#: On success, return 1. +$AFS_Help{'fs_setmonitor'} = '$server => Success?'; +sub AFS_fs_setmonitor { + my($server) = @_; + my(@args); + + @args = ('monitor', '-server', defined($server) ? $server : 'off'); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_getmonitor +#: Return the cache manager monitor host, or undef if monitoring is disabled. +$AFS_Help{'fs_getmonitor'} = 'void => $server'; +sub AFS_fs_getmonitor { + my(@args, $server); + + @args = ('monitor'); + &wrapper('fs', \@args, [ + ['Using host (.*) for monitor services\.', \$server], + ]); + $server; +} + +#: AFS_fs_getsysname +#: Returns the current list of system type names +$AFS_Help{'fs_getsysname'} = 'void => @sys'; +sub AFS_fs_getsysname { + my(@args, @sys); + + @args = ('sysname'); + &wrapper('fs', \@args, [ + [q/Current sysname is '(.*)'/, \@sys], + [q/Current sysname list is '(.*)'/, + sub { push(@sys, split(q/' '/, $_[0])) }], + ]); + @sys; +} + +#: AFS_fs_setsysname(\@sys) +#: Sets the system type list to @sys +#: On success, return 1. +$AFS_Help{'fs_setsysname'} = '$server => Success?'; +sub AFS_fs_setsysname { + my($sys) = @_; + my(@args); + + @args = ('sysname', '-newsys', @$sys); + &wrapper('fs', \@args); + 1; +} + +#: AFS_fs_whichcell(\@paths) +#: Get the cells containing the specified paths +#: Returns a hash in which each key is a pathname, and each value +#: is the name of the cell which contains the corresponding file. +$AFS_Help{'fs_whichcell'} = '\@paths => %where'; +sub AFS_fs_whichcell { + my($paths) = @_; + my(@args, %where); + + @args = ('whichcell', '-path', @$paths); + &wrapper('fs', \@args, [ + [q/^File (.*) lives in cell '(.*)'/, \%where], + ]); + %where; +} + +#: AFS_fs_wscell +#: Returns the name of the workstation's home cell +$AFS_Help{'fs_wscell'} = 'void => $cell'; +sub AFS_fs_wscell { + my(@args, $cell); + + @args = ('wscell'); + &wrapper('fs', \@args, [ + [q/^This workstation belongs to cell '(.*)'/, \$cell], + ]); + $cell; +} + diff --git a/src/tests/fs_lib.c b/src/tests/fs_lib.c new file mode 100644 index 0000000..04a56b3 --- /dev/null +++ b/src/tests/fs_lib.c @@ -0,0 +1,848 @@ +/* + * Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { PIOCTL_MAXSIZE = 2000 }; + +struct VenusFid { + afs_int32 Cell; + struct AFSFid Fid; +}; + +/* + * fs_getfid, the the `fid' that `path' points on. + */ + +int +fs_getfid(char *path, struct VenusFid *fid) +{ + struct ViceIoctl a_params; + + if (path == NULL || fid == NULL) + return EINVAL; + + a_params.in_size=0; + a_params.out_size=sizeof(struct VenusFid); + a_params.in=NULL; + a_params.out=(void*) fid; + + if(pioctl(path,VIOCGETFID,&a_params,1) == -1) + return errno; + + return 0; +} + +/* + * Do nothing + */ + +int +fs_nop(void) +{ + struct ViceIoctl a_params; + + a_params.in_size=0; + a_params.out_size=0; + a_params.in=NULL; + a_params.out=NULL; + + if (pioctl(NULL,VIOCNOP,&a_params,1) == -1) + return errno; + + return 0; +} + +/* + * Get the `cell' that the `path' ends up in + */ + +int +fs_getfilecellname(char *path, char *cell, size_t len) +{ + struct ViceIoctl a_params; + + a_params.in_size=0; + a_params.out_size=len; + a_params.in=NULL; + a_params.out=cell; + + if (pioctl(path,VIOC_FILE_CELL_NAME,&a_params,1) == -1) + return errno; + + return 0; +} + +/* + * set the level of crypt + */ + +#ifdef VIOC_SETRXKCRYPT +int +fs_setcrypt (u_int32_t n) +{ + struct ViceIoctl a_params; + + a_params.in_size = sizeof(n); + a_params.out_size = 0; + a_params.in = (char *)&n; + a_params.out = NULL; + + if (pioctl (NULL, VIOC_SETRXKCRYPT, &a_params, 0) == -1) + return errno; + + return 0; +} +#endif + +/* + * get currernt level of crypt + */ + +#ifdef VIOC_GETRXKCRYPT +int +fs_getcrypt (u_int32_t *level) +{ + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.out_size = sizeof(*level); + a_params.in = NULL; + a_params.out = (char *) level; + + if (pioctl (NULL, VIOC_GETRXKCRYPT, &a_params, 0) == -1) + return errno; + + return 0; +} +#endif + +/* + * get and set the connect-mode + */ + +#ifdef VIOCCONNECTMODE +int +fs_connect(int32_t type, int32_t *flags) +{ + struct ViceIoctl a_params; + + a_params.in_size = sizeof(type); + a_params.out_size = sizeof (int32_t); + a_params.in = (char *) &type; + a_params.out = (char *) flags; + + if (pioctl (NULL, VIOCCONNECTMODE, &a_params, 0) == -1) + return errno; + + return 0; +} +#endif + +/* + * + */ + +#ifdef VIOC_FPRIOSTATUS +int +fs_setfprio(struct VenusFid fid, int16_t prio) +{ + struct ViceIoctl a_params; + struct vioc_fprio fprio; + + fprio.cmd = FPRIO_SET; + fprio.Cell = fid.Cell; + fprio.Volume = fid.fid.Volume; + fprio.Vnode = fid.fid.Vnode; + fprio.Unique = fid.fid.Unique; + fprio.prio = prio; + + a_params.in_size = sizeof(fprio); + a_params.out_size = 0; + a_params.in = (char *) &fprio; + a_params.out = NULL; + + if (pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1) + return errno; + + return 0; +} +#endif + +#ifdef VIOC_FPRIOSTATUS +int +fs_getfprio(struct VenusFid fid, int16_t *prio) +{ + struct ViceIoctl a_params; + struct vioc_fprio fprio; + + fprio.cmd = FPRIO_GET; + fprio.Cell = fid.Cell; + fprio.Volume = fid.fid.Volume; + fprio.Vnode = fid.fid.Vnode; + fprio.Unique = fid.fid.Unique; + + a_params.in_size = sizeof(fprio); + a_params.out_size = sizeof(*prio); + a_params.in = (char *) &fprio; + a_params.out = (char *) prio; + + if (pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1) + return errno; + + return 0; +} +#endif + +#ifdef VIOC_FPRIOSTATUS +int +fs_setmaxfprio(int16_t maxprio) +{ + struct ViceIoctl a_params; + struct vioc_fprio fprio; + + fprio.cmd = FPRIO_SETMAX; + fprio.prio = maxprio; + + a_params.in_size = sizeof(fprio); + a_params.out_size = 0; + a_params.in = (char *) &fprio; + a_params.out = NULL; + + if (pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1) + return errno; + + return 0; +} +#endif + +#ifdef VIOC_FPRIOSTATUS +int +fs_getmaxfprio(int16_t *maxprio) +{ + struct ViceIoctl a_params; + struct vioc_fprio fprio; + + fprio.cmd = FPRIO_GETMAX; + + a_params.in_size = sizeof(fprio); + a_params.out_size = sizeof(*maxprio); + a_params.in = (char *) &fprio; + a_params.out = (char *) maxprio; + + if (pioctl (NULL, VIOC_FPRIOSTATUS , &a_params, 0) == -1) + return errno; + + return 0; +} +#endif + +/* + * + */ + +#ifdef VIOCGETCACHEPARAMS +int +fs_getfilecachestats(u_int32_t *max_bytes, + u_int32_t *used_bytes, + u_int32_t *max_vnodes, + u_int32_t *used_vnodes) +{ + u_int32_t parms[16]; + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.out_size = sizeof(parms); + a_params.in = NULL; + a_params.out = (char *) parms; + + memset (parms, 0, sizeof(parms)); + + if (pioctl (NULL, VIOCGETCACHEPARAMS , &a_params, 0) == -1) + return errno; + + /* param[0] and param[1] send maxbytes and usedbytes in kbytes */ + + if (max_vnodes) + *max_vnodes = parms[2]; + if (used_vnodes) + *used_vnodes = parms[3]; + if (max_bytes) + *max_bytes = parms[4]; + if (used_bytes) + *used_bytes = parms[5]; + + return 0; +} +#endif + +/* + * + */ + +#ifdef VIOC_AVIATOR +int +fs_getaviatorstats(u_int32_t *max_workers, + u_int32_t *used_workers) +{ + u_int32_t parms[16]; + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.out_size = sizeof(parms); + a_params.in = NULL; + a_params.out = (char *) parms; + + if (pioctl (NULL, VIOC_AVIATOR , &a_params, 0) == -1) + return errno; + + if (max_workers) + *max_workers = parms[0]; + if (used_workers) + *used_workers = parms[1]; + + return 0; +} +#endif + +/* + * + */ + +#ifdef VIOC_GCPAGS +int +fs_gcpags(void) +{ + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.out_size = 0; + a_params.in = NULL; + a_params.out = NULL; + + + if (pioctl(NULL, VIOC_GCPAGS, &a_params, 0) != 0) + return errno; + + return 0; +} +#endif + +/* + * + */ + +#ifdef VIOC_CALCULATE_CACHE +int +fs_calculate_cache(u_int32_t *calculated, + u_int32_t *usedbytes) +{ + u_int32_t parms[16]; + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.out_size = sizeof(parms); + a_params.in = NULL; + a_params.out = (char *) parms; + + if (pioctl (NULL, VIOC_CALCULATE_CACHE , &a_params, 0) == -1) + return errno; + + if (calculated) + *calculated = parms[0]; + if (usedbytes) + *usedbytes = parms[1]; + + return 0; +} +#endif + +/* + * + */ + +#ifdef VIOC_BREAKCALLBACK +int +fs_invalidate (const char *path) +{ + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.out_size = 0; + a_params.in = NULL; + a_params.out = NULL; + + if (pioctl ((char *)path, VIOC_BREAKCALLBACK, &a_params, 0) < 0) + return errno; + else + return 0; +} +#endif + +/* + * Get/set debug levels with pioctl_cmd. + * + * inflags == -1 -> don't change + * outflags == NULL -> don't return + */ + +static int +debug (int pioctl_cmd, int inflags, int *outflags, char *pathname) +{ + struct ViceIoctl a_params; + + int32_t rinflags = inflags; + int32_t routflags; + + if (inflags != -1) { + a_params.in_size = sizeof(rinflags); + a_params.in = (char *) &rinflags; + } else { + a_params.in_size = 0; + a_params.in = NULL; + } + + if (outflags) { + a_params.out_size = sizeof(routflags); + a_params.out = (char *) &routflags; + } else { + a_params.out_size = 0; + a_params.out = NULL; + } + + if (pioctl (pathname, pioctl_cmd, &a_params, 0) == -1) + return errno; + + if (outflags) + *outflags = routflags; + + return 0; +} + +/* + * xfs_debug + */ + +#ifdef VIOC_XFSDEBUG +int +xfs_debug(int inflags, int *outflags) +{ + return debug (VIOC_XFSDEBUG, inflags, outflags, NULL); +} +#endif + +/* + * xfs_debug_print + */ + +#ifdef VIOC_XFSDEBUG_PRINT +int +xfs_debug_print(int inflags, char *pathname) +{ + return debug (VIOC_XFSDEBUG_PRINT, inflags, NULL, pathname); +} +#endif + +/* + * arla_debug + */ + +#ifdef VIOC_ARLADEBUG +int +arla_debug (int inflags, int *outflags) +{ + return debug (VIOC_ARLADEBUG, inflags, outflags, NULL); +} +#endif + +/* + * checkservers + * + * flags is the same flags as in CKSERV flags + * + */ + +int +fs_checkservers(char *cell, int32_t flags, u_int32_t *hosts, int numhosts) +{ + struct ViceIoctl a_params; + char *in = NULL; + int ret; + size_t insize; + + if (cell != NULL) { + insize = strlen(cell) + sizeof(int32_t) + 1; + in = malloc (insize); + if (in == NULL) + errx (1, "malloc"); + + memcpy (in, &flags, sizeof(flags)); + + memcpy (in + sizeof(int32_t), cell, strlen(cell)); + in[sizeof(int32_t) + strlen(cell)] = '\0'; + + a_params.in_size = insize; + a_params.in = in; + } else { + a_params.in_size = sizeof(flags); + a_params.in = (caddr_t )&flags; + } + + a_params.out_size = numhosts * sizeof(u_int32_t); + a_params.out = (caddr_t)hosts; + + ret = 0; + + if (pioctl (NULL, VIOCCKSERV, &a_params, 0) == -1) + ret = errno; + + if (in) + free(in); + + return ret; +} + +/* + * check validity of cached volume information + */ + +int +fs_checkvolumes (void) +{ + struct ViceIoctl a_params; + + a_params.in = NULL; + a_params.in_size = 0; + a_params.out = NULL; + a_params.out_size = 0; + + if (pioctl (NULL, VIOCCKBACK, &a_params, 0) < 0) + return errno; + else + return 0; +} + +/* + * set current sysname to `sys' + */ + +int +fs_set_sysname (const char *sys) +{ + struct ViceIoctl a_params; + int32_t set = 1; + + a_params.in_size = sizeof(set) + strlen(sys) + 1; + a_params.in = malloc(a_params.in_size); + if (a_params.in == NULL) + return ENOMEM; + a_params.out = NULL; + a_params.out_size = 0; + memcpy (a_params.in, &set, sizeof(set)); + strcpy (a_params.in + sizeof(set), sys); + + if(pioctl (NULL, VIOC_AFS_SYSNAME, &a_params, 1) < 0) + return errno; + else + return 0; +} + +/* + * + */ + +int +fs_setcache(int lv, int hv, int lb, int hb) +{ + struct ViceIoctl a_params; + u_int32_t s[4]; + + s[0] = lv; + s[1] = hv; + s[2] = lb; + s[3] = hb; + + a_params.in_size = ((hv == 0) ? 1 : 4) * sizeof(u_int32_t); + a_params.out_size = 0; + a_params.in = (void *)s; + a_params.out = NULL; + + if (pioctl(NULL, VIOCSETCACHESIZE, &a_params, 0) < 0) + return errno; + else + return 0; +} + +/* + * return the local cell in `cell' (of size `cell_sz'). + */ + +int +fs_wscell (char *cell, size_t cell_sz) +{ + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.in = NULL; + a_params.out_size = cell_sz; + a_params.out = cell; + + if (pioctl (NULL, VIOC_GET_WS_CELL, &a_params, 0) < 0) + return errno; + return 0; +} + +/* + * Flush the contents of the volume pointed to by `path'. + */ + +int +fs_flushvolume (const char *path) +{ + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.out_size = 0; + a_params.in = NULL; + a_params.out = NULL; + + if (pioctl ((char *)path, VIOC_FLUSHVOLUME, &a_params, 0) < 0) + return errno; + else + return 0; +} + +/* + * Flush the file `path' from the cache. + */ + +int +fs_flush (const char *path) +{ + struct ViceIoctl a_params; + + a_params.in_size = 0; + a_params.out_size = 0; + a_params.in = NULL; + a_params.out = NULL; + + if (pioctl ((char *)path, VIOCFLUSH, &a_params, 0) < 0) + return errno; + else + return 0; +} + +/* + * + */ + +int +fs_venuslog (void) +{ + struct ViceIoctl a_params; + int32_t status = 0; /* XXX not really right, but anyway */ + + a_params.in_size = sizeof(int32_t); + a_params.out_size = 0; + a_params.in = (caddr_t) &status; + a_params.out = NULL; + + if (pioctl (NULL, VIOC_VENUSLOG, &a_params, 0) < 0) + return errno; + else + return 0; +} + +/* + * Get status for `cell' and put the flags in `flags'. + */ + +int +fs_getcellstatus (char *cellname, u_int32_t *flags) +{ + struct ViceIoctl a_params; + + a_params.in_size = strlen (cellname) + 1; + a_params.out_size = sizeof (u_int32_t); + a_params.in = cellname; + a_params.out = (caddr_t) flags; + + if (pioctl (NULL, VIOC_GETCELLSTATUS, &a_params, 0) < 0) + return errno; + else + return 0; +} + +/* + * Separate `path' into directory and last component and call + * pioctl with `pioctl_cmd'. + */ + +static int +internal_mp (const char *path, int pioctl_cmd, char **res) +{ + struct ViceIoctl a_params; + char *last; + char *path_bkp; + int error; + + path_bkp = strdup (path); + if (path_bkp == NULL) { + printf ("fs: Out of memory\n"); + return ENOMEM; + } + + a_params.out = malloc (PIOCTL_MAXSIZE); + if (a_params.out == NULL) { + printf ("fs: Out of memory\n"); + free (path_bkp); + return ENOMEM; + } + + /* If path contains more than the filename alone - split it */ + + last = strrchr (path_bkp, '/'); + if (last != NULL) { + *last = '\0'; + a_params.in = last + 1; + } else + a_params.in = (char *)path; + + a_params.in_size = strlen (a_params.in) + 1; + a_params.out_size = PIOCTL_MAXSIZE; + + error = pioctl (last ? path_bkp : "." , + pioctl_cmd, &a_params, 1); + if (error < 0) { + error = errno; + free (path_bkp); + free (a_params.out); + return error; + } + + if (res != NULL) + *res = a_params.out; + else + free (a_params.out); + free (path_bkp); + return 0; +} + +int +fs_lsmount (const char *path) +{ + char *res; + int error = internal_mp (path, VIOC_AFS_STAT_MT_PT, &res); + + if (error == 0) { + printf ("'%s' is a mount point for volume '%s'\n", path, res); + free (res); + } + return error; +} + +int +fs_rmmount (const char *path) +{ + return internal_mp (path, VIOC_AFS_DELETE_MT_PT, NULL); +} + +int +fs_incompat_renumber (int *ret) +{ + struct ViceIoctl a_params; + unsigned char buf[1024]; + + a_params.in_size = 0; + a_params.out_size = sizeof(buf); + a_params.in = 0; + a_params.out = (caddr_t) buf; + + /* getcrypt or getinitparams */ + if (pioctl (NULL, _VICEIOCTL(49), &a_params, 0) < 0) { + if (errno == EINVAL) { + + /* not openafs or old openafs */ + + a_params.in_size = 0; + a_params.out_size = 4; + a_params.in = 0; + a_params.out = (caddr_t) buf; + + if (pioctl (NULL, _VICEIOCTL(49), &a_params, 0) < 0) { + if (errno == EINVAL) { + + a_params.in_size = 0; + a_params.out_size = 4; + a_params.in = 0; + a_params.out = (caddr_t) buf; + + /* might be new interface */ + + if (pioctl (NULL, _VICEIOCTL(55), &a_params, 0) < 0) + return errno; /* dunno */ + + *ret = 1; + return 0; + } else { + return errno; + } + } + *ret = 0; + return 0; + } else + return errno; + } + *ret = 1; + return 0; +} diff --git a/src/tests/fsx.c b/src/tests/fsx.c new file mode 100644 index 0000000..0b67ae8 --- /dev/null +++ b/src/tests/fsx.c @@ -0,0 +1,1054 @@ +/* + * Copyright (C) 1991, NeXT Computer, Inc. All Rights Reserverd. + * + * File: fsx.c + * Author: Avadis Tevanian, Jr. + * + * File system exerciser. + * + * Rewritten 8/98 by Conrad Minshall. + */ + +#include +#include +#if defined(_UWIN) || defined(__linux) +# include +# include +# include +# include +# define MAP_FILE 0 +#else +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUMPRINTCOLUMNS 32 /* # columns of data to print on each line */ + +/* + * A log entry is an operation and a bunch of arguments. + */ + +struct log_entry { + int operation; + int args[3]; +}; + +#define LOGSIZE 1000 + +struct log_entry oplog[LOGSIZE]; /* the log */ +int logptr = 0; /* current position in log */ +int logcount = 0; /* total ops */ + +/* + * Define operations + */ + +#define OP_READ 1 +#define OP_WRITE 2 +#define OP_TRUNCATE 3 +#define OP_CLOSEOPEN 4 +#define OP_MAPREAD 5 +#define OP_MAPWRITE 6 +#define OP_SKIPPED 7 + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif +#define PAGE_MASK (PAGE_SIZE - 1) + +char *original_buf; /* a pointer to the original data */ +char *good_buf; /* a pointer to the correct data */ +char *temp_buf; /* a pointer to the current data */ +char *fname; /* name of our test file */ +int fd; /* fd for our test file */ + +off_t file_size = 0; +off_t biggest = 0; +char state[256]; +unsigned long testcalls = 0; /* calls to function "test" */ + +unsigned long simulatedopcount = 0; /* -b flag */ +int closeprob = 0; /* -c flag */ +int debug = 0; /* -d flag */ +unsigned long debugstart = 0; /* -D flag */ +unsigned long maxfilelen = 256 * 1024; /* -l flag */ +int sizechecks = 1; /* -n flag disables them */ +int maxoplen = 64 * 1024; /* -o flag */ +int quiet = 0; /* -q flag */ +unsigned long progressinterval = 0; /* -p flag */ +int readbdy = 1; /* -r flag */ +int style = 0; /* -s flag */ +int truncbdy = 1; /* -t flag */ +int writebdy = 1; /* -w flag */ +long monitorstart = -1; /* -m flag */ +long monitorend = -1; /* -m flag */ +int lite = 0; /* -L flag */ +long numops = -1; /* -N flag */ +int randomoplen = 1; /* -O flag disables it */ +int seed = 1; /* -S flag */ +int mapped_writes = 1; /* -W flag disables */ +int mapped_reads = 1; /* -R flag disables it */ +int fsxgoodfd = 0; +FILE * fsxlogf = NULL; +int badoff = -1; +int closeopen = 0; + + +void +prt(char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vfprintf(stdout, fmt, args); + if (fsxlogf) + vfprintf(fsxlogf, fmt, args); + va_end(args); +} + +void +prterr(char *prefix) +{ + prt("%s%s%s\n", prefix, prefix ? ": " : "", strerror(errno)); +} + + +void +log4(int operation, int arg0, int arg1, int arg2) +{ + struct log_entry *le; + + le = &oplog[logptr]; + le->operation = operation; + if (closeopen) + le->operation = ~ le->operation; + le->args[0] = arg0; + le->args[1] = arg1; + le->args[2] = arg2; + logptr++; + logcount++; + if (logptr >= LOGSIZE) + logptr = 0; +} + + +void +logdump(void) +{ + int i, count, down; + struct log_entry *lp; + + prt("LOG DUMP (%d total operations):\n", logcount); + if (logcount < LOGSIZE) { + i = 0; + count = logcount; + } else { + i = logptr; + count = LOGSIZE; + } + for ( ; count > 0; count--) { + int opnum; + + opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE; + prt("%d(%d mod 256): ", opnum, opnum%256); + lp = &oplog[i]; + if ((closeopen = lp->operation < 0)) + lp->operation = ~ lp->operation; + + switch (lp->operation) { + case OP_MAPREAD: + prt("MAPREAD\t0x%x thru 0x%x\t(0x%x bytes)", + lp->args[0], lp->args[0] + lp->args[1] - 1, + lp->args[1]); + if (badoff >= lp->args[0] && badoff < + lp->args[0] + lp->args[1]) + prt("\t***RRRR***"); + break; + case OP_MAPWRITE: + prt("MAPWRITE 0x%x thru 0x%x\t(0x%x bytes)", + lp->args[0], lp->args[0] + lp->args[1] - 1, + lp->args[1]); + if (badoff >= lp->args[0] && badoff < + lp->args[0] + lp->args[1]) + prt("\t******WWWW"); + break; + case OP_READ: + prt("READ\t0x%x thru 0x%x\t(0x%x bytes)", + lp->args[0], lp->args[0] + lp->args[1] - 1, + lp->args[1]); + if (badoff >= lp->args[0] && + badoff < lp->args[0] + lp->args[1]) + prt("\t***RRRR***"); + break; + case OP_WRITE: + prt("WRITE\t0x%x thru 0x%x\t(0x%x bytes)", + lp->args[0], lp->args[0] + lp->args[1] - 1, + lp->args[1]); + if (lp->args[0] > lp->args[2]) + prt(" HOLE"); + else if (lp->args[0] + lp->args[1] > lp->args[2]) + prt(" EXTEND"); + if ((badoff >= lp->args[0] || badoff >=lp->args[2]) && + badoff < lp->args[0] + lp->args[1]) + prt("\t***WWWW"); + break; + case OP_TRUNCATE: + down = lp->args[0] < lp->args[1]; + prt("TRUNCATE %s\tfrom 0x%x to 0x%x", + down ? "DOWN" : "UP", lp->args[1], lp->args[0]); + if (badoff >= lp->args[!down] && + badoff < lp->args[!!down]) + prt("\t******WWWW"); + break; + case OP_SKIPPED: + prt("SKIPPED (no operation)"); + break; + default: + prt("BOGUS LOG ENTRY (operation code = %d)!", + lp->operation); + } + if (closeopen) + prt("\n\t\tCLOSE/OPEN"); + prt("\n"); + i++; + if (i == LOGSIZE) + i = 0; + } +} + + +void +save_buffer(char *buffer, off_t bufferlength, int fd) +{ + off_t ret; + ssize_t byteswritten; + + if (fd <= 0 || bufferlength == 0) + return; + + if (bufferlength > SSIZE_MAX) { + prt("fsx flaw: overflow in save_buffer\n"); + exit(67); + } + if (lite) { + off_t size_by_seek = lseek(fd, (off_t)0, L_XTND); + if (size_by_seek == (off_t)-1) + prterr("save_buffer: lseek eof"); + else if (bufferlength > size_by_seek) { + warn("save_buffer: .fsxgood file too short... will save 0x%qx bytes instead of 0x%qx\n", (unsigned long long)size_by_seek, + (unsigned long long)bufferlength); + bufferlength = size_by_seek; + } + } + + ret = lseek(fd, (off_t)0, SEEK_SET); + if (ret == (off_t)-1) + prterr("save_buffer: lseek 0"); + + byteswritten = write(fd, buffer, (size_t)bufferlength); + if (byteswritten != bufferlength) { + if (byteswritten == -1) + prterr("save_buffer write"); + else + warn("save_buffer: short write, 0x%x bytes instead of 0x%qx\n", + (unsigned)byteswritten, + (unsigned long long)bufferlength); + } +} + + +void +report_failure(int status) +{ + logdump(); + + if (fsxgoodfd) { + if (good_buf) { + save_buffer(good_buf, file_size, fsxgoodfd); + prt("Correct content saved for comparison\n"); + prt("(maybe hexdump \"%s\" vs \"%s.fsxgood\")\n", + fname, fname); + } + close(fsxgoodfd); + } + exit(status); +} + + +#define short_at(cp) ((unsigned short)((*((unsigned char *)(cp)) << 8) | \ + *(((unsigned char *)(cp)) + 1))) + +void +check_buffers(unsigned offset, unsigned size) +{ + unsigned char c, t; + unsigned i = 0; + unsigned n = 0; + unsigned op = 0; + unsigned bad = 0; + + if (bcmp(good_buf + offset, temp_buf, size) != 0) { + prt("READ BAD DATA: offset = 0x%x, size = 0x%x\n", + offset, size); + prt("OFFSET\tGOOD\tBAD\tRANGE\n"); + while (size > 0) { + c = good_buf[offset]; + t = temp_buf[i]; + if (c != t) { + if (n == 0) { + bad = short_at(&temp_buf[i]); + prt("0x%5x\t0x%04x\t0x%04x", offset, + short_at(&good_buf[offset]), bad); + op = temp_buf[offset & 1 ? i+1 : i]; + } + n++; + badoff = offset; + } + offset++; + i++; + size--; + } + if (n) { + prt("\t0x%5x\n", n); + if (bad) + prt("operation# (mod 256) for the bad data may be %u\n", ((unsigned)op & 0xff)); + else + prt("operation# (mod 256) for the bad data unknown, check HOLE and EXTEND ops\n"); + } else + prt("????????????????\n"); + report_failure(110); + } +} + + +void +check_size(void) +{ + struct stat statbuf; + off_t size_by_seek; + + if (fstat(fd, &statbuf)) { + prterr("check_size: fstat"); + statbuf.st_size = -1; + } + size_by_seek = lseek(fd, (off_t)0, L_XTND); + if (file_size != statbuf.st_size || file_size != size_by_seek) { + prt("Size error: expected 0x%qx stat 0x%qx seek 0x%qx\n", + (unsigned long long)file_size, + (unsigned long long)statbuf.st_size, + (unsigned long long)size_by_seek); + report_failure(120); + } +} + + +void +check_trunc_hack(void) +{ + struct stat statbuf; + + ftruncate(fd, (off_t)0); + ftruncate(fd, (off_t)100000); + fstat(fd, &statbuf); + if (statbuf.st_size != (off_t)100000) { + prt("no extend on truncate! not posix!\n"); + exit(130); + } + ftruncate(fd, 0); +} + + +void +doread(unsigned offset, unsigned size) +{ + off_t ret; + unsigned iret; + + offset -= offset % readbdy; + if (size == 0) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping zero size read\n"); + log4(OP_SKIPPED, OP_READ, offset, size); + return; + } + if (size + offset > file_size) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping seek/read past end of file\n"); + log4(OP_SKIPPED, OP_READ, offset, size); + return; + } + + log4(OP_READ, offset, size, 0); + + if (testcalls <= simulatedopcount) + return; + + if (!quiet && (progressinterval && testcalls % progressinterval == 0 || + debug && + (monitorstart == -1 || + offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend)))) + prt("%lu read\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls, + offset, offset + size - 1, size); + ret = lseek(fd, (off_t)offset, SEEK_SET); + if (ret == (off_t)-1) { + prterr("doread: lseek"); + report_failure(140); + } + iret = read(fd, temp_buf, size); + if (iret != size) { + if (iret == -1) + prterr("doread: read"); + else + prt("short read: 0x%x bytes instead of 0x%x\n", + iret, size); + report_failure(141); + } + check_buffers(offset, size); +} + + +void +domapread(unsigned offset, unsigned size) +{ + unsigned pg_offset; + unsigned map_size; + char *p; + + offset -= offset % readbdy; + if (size == 0) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping zero size read\n"); + log4(OP_SKIPPED, OP_MAPREAD, offset, size); + return; + } + if (size + offset > file_size) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping seek/read past end of file\n"); + log4(OP_SKIPPED, OP_MAPREAD, offset, size); + return; + } + + log4(OP_MAPREAD, offset, size, 0); + + if (testcalls <= simulatedopcount) + return; + + if (!quiet && (progressinterval && testcalls % progressinterval == 0 || + debug && + (monitorstart == -1 || + offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend)))) + prt("%lu mapread\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls, + offset, offset + size - 1, size); + + pg_offset = offset & PAGE_MASK; + map_size = pg_offset + size; + + if ((p = (char *)mmap(0, map_size, PROT_READ, MAP_FILE, fd, + (off_t)(offset - pg_offset))) == (char *)-1) { + prterr("domapread: mmap"); + report_failure(190); + } + memcpy(temp_buf, p + pg_offset, size); + if (munmap(p, map_size) != 0) { + prterr("domapread: munmap"); + report_failure(191); + } + + check_buffers(offset, size); +} + + +void +gendata(char *original_buf, char *good_buf, unsigned offset, unsigned size) +{ + while (size--) { + good_buf[offset] = testcalls % 256; + if (offset % 2) + good_buf[offset] += original_buf[offset]; + offset++; + } +} + + +void +dowrite(unsigned offset, unsigned size) +{ + off_t ret; + unsigned iret; + + offset -= offset % writebdy; + if (size == 0) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping zero size write\n"); + log4(OP_SKIPPED, OP_WRITE, offset, size); + return; + } + + log4(OP_WRITE, offset, size, file_size); + + gendata(original_buf, good_buf, offset, size); + if (file_size < offset + size) { + if (file_size < offset) + bzero(good_buf + file_size, offset - file_size); + file_size = offset + size; + if (lite) { + warn("Lite file size bug in fsx!"); + report_failure(149); + } + } + + if (testcalls <= simulatedopcount) + return; + + if (!quiet && (progressinterval && testcalls % progressinterval == 0 || + debug && + (monitorstart == -1 || + offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend)))) + prt("%lu write\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls, + offset, offset + size - 1, size); + ret = lseek(fd, (off_t)offset, SEEK_SET); + if (ret == (off_t)-1) { + prterr("dowrite: lseek"); + report_failure(150); + } + iret = write(fd, good_buf + offset, size); + if (iret != size) { + if (iret == -1) + prterr("dowrite: write"); + else + prt("short write: 0x%x bytes instead of 0x%x\n", + iret, size); + report_failure(151); + } +} + + +void +domapwrite(unsigned offset, unsigned size) +{ + unsigned pg_offset; + unsigned map_size; + off_t cur_filesize; + char *p; + + offset -= offset % writebdy; + if (size == 0) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping zero size write\n"); + log4(OP_SKIPPED, OP_MAPWRITE, offset, size); + return; + } + cur_filesize = file_size; + + log4(OP_MAPWRITE, offset, size, 0); + + gendata(original_buf, good_buf, offset, size); + if (file_size < offset + size) { + if (file_size < offset) + bzero(good_buf + file_size, offset - file_size); + file_size = offset + size; + if (lite) { + warn("Lite file size bug in fsx!"); + report_failure(200); + } + } + + if (testcalls <= simulatedopcount) + return; + + if (!quiet && (progressinterval && testcalls % progressinterval == 0 || + debug && + (monitorstart == -1 || + offset + size > monitorstart && + (monitorend == -1 || offset <= monitorend)))) + prt("%lu mapwrite\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls, + offset, offset + size - 1, size); + + if (file_size > cur_filesize) { + if (ftruncate(fd, file_size) == -1) { + prterr("domapwrite: ftruncate"); + exit(201); + } + } + pg_offset = offset & PAGE_MASK; + map_size = pg_offset + size; + + if ((p = (char *)mmap(0, map_size, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, fd, + (off_t)(offset - pg_offset))) == (char *)-1) { + prterr("domapwrite: mmap"); + report_failure(202); + } + memcpy(p + pg_offset, good_buf + offset, size); + if (msync(p, map_size, 0) != 0) { + prterr("domapwrite: msync"); + report_failure(203); + } + if (munmap(p, map_size) != 0) { + prterr("domapwrite: munmap"); + report_failure(204); + } +} + + +void +dotruncate(unsigned size) +{ + int oldsize = file_size; + + size -= size % truncbdy; + if (size > biggest) { + biggest = size; + if (!quiet && testcalls > simulatedopcount) + prt("truncating to largest ever: 0x%x\n", size); + } + + log4(OP_TRUNCATE, size, (unsigned)file_size, 0); + + if (size > file_size) + bzero(good_buf + file_size, size - file_size); + file_size = size; + + if (testcalls <= simulatedopcount) + return; + + if (progressinterval && testcalls % progressinterval == 0 || + debug && (monitorstart == -1 || monitorend == -1 || + size <= monitorend)) + prt("%lu trunc\tfrom 0x%x to 0x%x\n", testcalls, oldsize, size); + if (ftruncate(fd, (off_t)size) == -1) { + prt("ftruncate1: %x\n", size); + prterr("dotruncate: ftruncate"); + report_failure(160); + } +} + + +void +writefileimage() +{ + ssize_t iret; + + if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { + prterr("writefileimage: lseek"); + report_failure(171); + } + iret = write(fd, good_buf, file_size); + if ((off_t)iret != file_size) { + if (iret == -1) + prterr("writefileimage: write"); + else + prt("short write: 0x%x bytes instead of 0x%qx\n", + iret, (unsigned long long)file_size); + report_failure(172); + } + if (lite ? 0 : ftruncate(fd, file_size) == -1) { + prt("ftruncate2: %qx\n", (unsigned long long)file_size); + prterr("writefileimage: ftruncate"); + report_failure(173); + } +} + + +void +docloseopen(void) +{ + if (testcalls <= simulatedopcount) + return; + + if (debug) + prt("%lu close/open\n", testcalls); + if (close(fd)) { + prterr("docloseopen: close"); + report_failure(180); + } + fd = open(fname, O_RDWR, 0); + if (fd < 0) { + prterr("docloseopen: open"); + report_failure(181); + } +} + + +void +test(void) +{ + unsigned long offset; + unsigned long size = maxoplen; + unsigned long rv = random(); + unsigned long op = rv % (3 + !lite + mapped_writes); + + /* turn off the map read if necessary */ + + if (op == 2 && !mapped_reads) + op = 0; + + if (simulatedopcount > 0 && testcalls == simulatedopcount) + writefileimage(); + + testcalls++; + + closeopen = (rv >> 3) < (1 << 28) / closeprob; + + if (debugstart > 0 && testcalls >= debugstart) + debug = 1; + + if (!quiet && testcalls < simulatedopcount && testcalls % 100000 == 0) + prt("%lu...\n", testcalls); + + /* + * READ: op = 0 + * WRITE: op = 1 + * MAPREAD: op = 2 + * TRUNCATE: op = 3 + * MAPWRITE: op = 3 or 4 + */ + if (lite ? 0 : op == 3 && (style & 1) == 0) /* vanilla truncate? */ + dotruncate(random() % maxfilelen); + else { + if (randomoplen) + size = random() % (maxoplen+1); + if (lite ? 0 : op == 3) + dotruncate(size); + else { + offset = random(); + if (op == 1 || op == (lite ? 3 : 4)) { + offset %= maxfilelen; + if (offset + size > maxfilelen) + size = maxfilelen - offset; + if (op != 1) + domapwrite(offset, size); + else + dowrite(offset, size); + } else { + if (file_size) + offset %= file_size; + else + offset = 0; + if (offset + size > file_size) + size = file_size - offset; + if (op != 0) + domapread(offset, size); + else + doread(offset, size); + } + } + } + if (sizechecks && testcalls > simulatedopcount) + check_size(); + if (closeopen) + docloseopen(); +} + + +void +cleanup(sig) + int sig; +{ + if (sig) + prt("signal %d\n", sig); + prt("testcalls = %lu\n", testcalls); + exit(sig); +} + + +void +usage(void) +{ + fprintf(stdout, "usage: %s", + "fsx [-dnqLOW] [-b opnum] [-c Prob] [-l flen] [-m start:end] [-o oplen] [-p progressinterval] [-r readbdy] [-s style] [-t truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath] [-S seed] fname\n\ + -b opnum: beginning operation number (default 1)\n\ + -c P: 1 in P chance of file close+open at each op (default infinity)\n\ + -d: debug output for all operations\n\ + -l flen: the upper bound on file size (default 262144)\n\ + -m startop:endop: monitor (print debug output) specified byte range (default 0:infinity)\n\ + -n: no verifications of file size\n\ + -o oplen: the upper bound on operation size (default 65536)\n\ + -p progressinterval: debug output at specified operation interval\n\ + -q: quieter operation\n\ + -r readbdy: 4096 would make reads page aligned (default 1)\n\ + -s style: 1 gives smaller truncates (default 0)\n\ + -t truncbdy: 4096 would make truncates page aligned (default 1)\n\ + -w writebdy: 4096 would make writes page aligned (default 1)\n\ + -D startingop: debug output starting at specified operation\n\ + -L: fsxLite - no file creations & no file size changes\n\ + -N numops: total # operations to do (default infinity)\n\ + -O: use oplen (see -o flag) for every op (default random)\n\ + -P: save .fsxlog and .fsxgood files in dirpath (default ./)\n\ + -S seed: for random # generator (default 1) 0 gets timestamp\n\ + -W: mapped write operations DISabled\n\ + -R: read() system calls only (mapped reads disabled)\n\ + fname: this filename is REQUIRED (no default)\n"); + exit(90); +} + + +int +getnum(char *s, char **e) +{ + int ret = -1; + + *e = (char *) 0; + ret = strtol(s, e, 0); + if (*e) + switch (**e) { + case 'b': + case 'B': + ret *= 512; + *e = *e + 1; + break; + case 'k': + case 'K': + ret *= 1024; + *e = *e + 1; + break; + case 'm': + case 'M': + ret *= 1024*1024; + *e = *e + 1; + break; + case 'w': + case 'W': + ret *= 4; + *e = *e + 1; + break; + } + return (ret); +} + + +int +main(int argc, char **argv) +{ + int i, style, ch; + char *endp; + char goodfile[1024]; + char logfile[1024]; + + goodfile[0] = 0; + logfile[0] = 0; + + setvbuf(stdout, (char *)0, _IOLBF, 0); /* line buffered stdout */ + + while ((ch = getopt(argc, argv, "b:c:dl:m:no:p:qr:s:t:w:D:LN:OP:RS:W")) + != EOF) + switch (ch) { + case 'b': + simulatedopcount = getnum(optarg, &endp); + if (!quiet) + fprintf(stdout, "Will begin at operation %ld\n", + simulatedopcount); + if (simulatedopcount == 0) + usage(); + simulatedopcount -= 1; + break; + case 'c': + closeprob = getnum(optarg, &endp); + if (!quiet) + fprintf(stdout, + "Chance of close/open is 1 in %d\n", + closeprob); + if (closeprob <= 0) + usage(); + break; + case 'd': + debug = 1; + break; + case 'l': + maxfilelen = getnum(optarg, &endp); + if (maxfilelen <= 0) + usage(); + break; + case 'm': + monitorstart = getnum(optarg, &endp); + if (monitorstart < 0) + usage(); + if (!endp || *endp++ != ':') + usage(); + monitorend = getnum(endp, &endp); + if (monitorend < 0) + usage(); + if (monitorend == 0) + monitorend = -1; /* aka infinity */ + debug = 1; + case 'n': + sizechecks = 0; + break; + case 'o': + maxoplen = getnum(optarg, &endp); + if (maxoplen <= 0) + usage(); + break; + case 'p': + progressinterval = getnum(optarg, &endp); + if (progressinterval < 0) + usage(); + break; + case 'q': + quiet = 1; + break; + case 'r': + readbdy = getnum(optarg, &endp); + if (readbdy <= 0) + usage(); + break; + case 's': + style = getnum(optarg, &endp); + if (style < 0 || style > 1) + usage(); + break; + case 't': + truncbdy = getnum(optarg, &endp); + if (truncbdy <= 0) + usage(); + break; + case 'w': + writebdy = getnum(optarg, &endp); + if (writebdy <= 0) + usage(); + break; + case 'D': + debugstart = getnum(optarg, &endp); + if (debugstart < 1) + usage(); + break; + case 'L': + lite = 1; + break; + case 'N': + numops = getnum(optarg, &endp); + if (numops < 0) + usage(); + break; + case 'O': + randomoplen = 0; + break; + case 'P': + strncpy(goodfile, optarg, sizeof(goodfile)); + strcat(goodfile, "/"); + strncpy(logfile, optarg, sizeof(logfile)); + strcat(logfile, "/"); + break; + case 'R': + mapped_reads = 0; + break; + case 'S': + seed = getnum(optarg, &endp); + if (seed == 0) + seed = time(0) % 10000; + if (!quiet) + fprintf(stdout, "Seed set to %d\n", seed); + if (seed < 0) + usage(); + break; + case 'W': + mapped_writes = 0; + if (!quiet) + fprintf(stdout, "mapped writes DISABLED\n"); + break; + + default: + usage(); + /* NOTREACHED */ + } + argc -= optind; + argv += optind; + if (argc != 1) + usage(); + fname = argv[0]; + + signal(SIGHUP, cleanup); + signal(SIGINT, cleanup); + signal(SIGPIPE, cleanup); + signal(SIGALRM, cleanup); + signal(SIGTERM, cleanup); + signal(SIGXCPU, cleanup); + signal(SIGXFSZ, cleanup); + signal(SIGVTALRM, cleanup); + signal(SIGUSR1, cleanup); + signal(SIGUSR2, cleanup); + + initstate(seed, state, 256); + setstate(state); + fd = open(fname, O_RDWR|(lite ? 0 : O_CREAT|O_TRUNC), 0666); + if (fd < 0) { + prterr(fname); + exit(91); + } + strncat(goodfile, fname, 256); + strcat (goodfile, ".fsxgood"); + fsxgoodfd = open(goodfile, O_RDWR|O_CREAT|O_TRUNC, 0666); + if (fsxgoodfd < 0) { + prterr(goodfile); + exit(92); + } + strncat(logfile, fname, 256); + strcat (logfile, ".fsxlog"); + fsxlogf = fopen(logfile, "w"); + if (fsxlogf == NULL) { + prterr(logfile); + exit(93); + } + if (lite) { + off_t ret; + file_size = maxfilelen = lseek(fd, (off_t)0, L_XTND); + if (file_size == (off_t)-1) { + prterr(fname); + warn("main: lseek eof"); + exit(94); + } + ret = lseek(fd, (off_t)0, SEEK_SET); + if (ret == (off_t)-1) { + prterr(fname); + warn("main: lseek 0"); + exit(95); + } + } + original_buf = (char *) malloc(maxfilelen); + for (i = 0; i < maxfilelen; i++) + original_buf[i] = random() % 256; + good_buf = (char *) malloc(maxfilelen); + bzero(good_buf, maxfilelen); + temp_buf = (char *) malloc(maxoplen); + bzero(temp_buf, maxoplen); + if (lite) { /* zero entire existing file */ + ssize_t written; + + written = write(fd, good_buf, (size_t)maxfilelen); + if (written != maxfilelen) { + if (written == -1) { + prterr(fname); + warn("main: error on write"); + } else + warn("main: short write, 0x%x bytes instead of 0x%x\n", + (unsigned)written, maxfilelen); + exit(98); + } + } else + check_trunc_hack(); + + while (numops == -1 || numops--) + test(); + + if (close(fd)) { + prterr("close"); + report_failure(99); + } + prt("All operations completed A-OK!\n"); + + exit(0); + return 0; +} diff --git a/src/tests/ga-test.c b/src/tests/ga-test.c new file mode 100644 index 0000000..ca3782e --- /dev/null +++ b/src/tests/ga-test.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test if agetarg works as expected + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include + +RCSID("$Id$"); + +typedef struct { + int style; + int argc; + char *argv[10]; + enum { GA_SUCCESS = 0, GA_FAILURE } retval ; +} ga_tests; + + +/* XXX TODO: aarg_negative_flag, manualpage generation ? */ + +/* + * + */ + +static void +test_simple_string (void) +{ + char *string; + int i, optind; + ga_tests tests[] = { + { AARG_GNUSTYLE, 2, { "string", "--string=foo", NULL } }, + { AARG_GNUSTYLE, 3, { "string", "-s", "foo", NULL} }, + { AARG_AFSSTYLE, 3, { "string", "-string", "foo", NULL} }, + { AARG_AFSSTYLE, 3, { "string", "-strin", "foo", NULL} }, + { AARG_AFSSTYLE, 3, { "string", "-st", "foo", NULL}, GA_FAILURE }, + { AARG_AFSSTYLE, 2, { "string", "--flag"}, GA_FAILURE }, + { AARG_AFSSTYLE, 2, { "string", "foo", NULL} } + }; + + struct agetargs args[] = { + { "string", 's', aarg_string, NULL, + "string test", "stringfoo", aarg_mandatory}, + { "strip", 0, aarg_string, NULL, + "strip test", "stripfoo", aarg_optional}, + { NULL, 0, aarg_end, NULL, NULL } + }, *a = args; + + a->value = &string; + + for (i = 0 ; i < sizeof(tests)/sizeof(*tests); i++) { + string = NULL; + optind = 0; + + if (agetarg (args, tests[i].argc, tests[i].argv, &optind, + tests[i].style)) { + if (tests[i].retval == GA_FAILURE) + continue; + warnx ("test_string: %s failed for test %d", + tests[i].argv[1], i); + continue; + } else { + if (tests[i].retval != GA_SUCCESS) { + warnx ("test_string: %s failed to fail for test %d", + tests[i].argv[1], i); + continue; + } + } + + if (optind != tests[i].argc) { + warnx ("argc != optind for test %s, %d", tests[i].argv[1], i); + continue; + } + + if (string == NULL || strcmp (string, "foo") != 0) { + warnx ("error parsing for test %d: string", i); + continue; + } + } +} + +/* + * + */ + +static void +test_simple_strings (void) +{ + agetarg_strings strings; + + int i, optind; + ga_tests tests[] = { + { AARG_GNUSTYLE, 3, { "strings", + "--strings=foo", "--strings=bar", NULL } }, + { AARG_GNUSTYLE, 5, { "strings", "-s", "foo", "-s", "bar", NULL} }, + { AARG_AFSSTYLE, 4, { "strings", "-string", "foo", "bar", NULL} } +#if 0 + { AARG_AFSSTYLE, 3, { "strings", "foo", "bar", NULL} } +#endif + }; + + struct agetargs args[] = { + { "strings", 's', aarg_strings, NULL, + "strings test", "stringsfoo", aarg_optional}, + { NULL, 0, aarg_end, NULL, NULL } + }, *a = args; + + a->value = &strings; + + for (i = 0 ; i < sizeof(tests)/sizeof(*tests); i++) { + strings.num_strings = 0; + strings.strings = NULL; + optind = 0; + + if (agetarg (args, tests[i].argc, tests[i].argv, &optind, + tests[i].style)) { + if (tests[i].retval == GA_FAILURE) + continue; + warnx ("test_strings: %s failed for test %d", + tests[i].argv[1], i); + continue; + } else { + if (tests[i].retval != GA_SUCCESS) { + warnx ("test_strings: %s failed to fail for test %d", + tests[i].argv[1], i); + continue; + } + } + + if (optind != tests[i].argc) { + warnx ("argc != optind for test %s, %d", + tests[i].argv[1], i); + continue; + } + + if (strings.num_strings != 2 + || strcmp(strings.strings[0], "foo") != 0 + || strcmp(strings.strings[1], "bar") != 0) + { + warnx ("error parsing for test %d: strings", i); + continue; + } + } +} + +/* + * + */ + +static void +test_simple_integer (void) +{ + int integer; + int i, optind; + ga_tests tests[] = { + { AARG_GNUSTYLE, 2, { "integer", "--integer=4711", NULL } }, + { AARG_GNUSTYLE, 3, { "integer", "-i", "4711", NULL} }, + { AARG_AFSSTYLE, 3, { "integer", "-integer", "4711", NULL} }, + { AARG_AFSSTYLE, 2, { "integer", "4711", NULL} } + }; + + struct agetargs args[] = { + { "integer", 'i', aarg_integer, NULL, + "integer test", "integer", aarg_mandatory}, + { NULL, 0, aarg_end, NULL, NULL } + }, *a = args; + + a->value = &integer; + + for (i = 0 ; i < sizeof(tests)/sizeof(*tests); i++) { + integer = 0; + optind = 0; + + if (agetarg (args, tests[i].argc, tests[i].argv, &optind, + tests[i].style)) { + if (tests[i].retval == GA_FAILURE) + continue; + warnx ("test_integer: %s failed for test %d", + tests[i].argv[1], i); + continue; + } else { + if (tests[i].retval != GA_SUCCESS) { + warnx ("test_integer: %s failed to fail for test %d", + tests[i].argv[1], i); + continue; + } + } + + if (optind != tests[i].argc) { + warnx ("argc != optind for test %s, %d", + tests[i].argv[1], i); + continue; + } + + if (integer != 4711) { + warnx ("error parsing for test %d: integer 4711", i); + continue; + } + } +} + +/* + * + */ + +static void +test_simple_flag (void) +{ + int flag; + int i, optind; + ga_tests tests[] = { + { AARG_GNUSTYLE, 2, { "flag", "--flag=yes", NULL }, GA_SUCCESS }, + { AARG_GNUSTYLE, 2, { "flag", "-g", NULL}, GA_SUCCESS }, + { AARG_AFSSTYLE, 2, { "flag", "--flag"}, GA_FAILURE }, + { AARG_AFSSTYLE, 2, { "flag", "-flag", NULL}, GA_SUCCESS }, +#if 0 + /* XXX */ + { AARG_AFSSTYLE, 2, { "flag", "yes", NULL}, GA_SUCCESS }, +#endif + { AARG_GNUSTYLE, 2, { "flag", "--no-flag", NULL}, GA_SUCCESS } + }; + + struct agetargs args[] = { + { "flag", 'g', aarg_flag, NULL, + "flag", "flag bar", aarg_optional}, + { NULL, 0, aarg_end, NULL, NULL } + }, *a = args; + + a->value = &flag; + + for (i = 0 ; i < sizeof(tests)/sizeof(*tests); i++) { + if (i < 4) + flag = 0; + else + flag = 1; + optind = 0; + + if (agetarg (args, tests[i].argc, tests[i].argv, &optind, + tests[i].style)) { + if (tests[i].retval == GA_FAILURE) + continue; + warnx ("test_flag: %s failed for test %d", + tests[i].argv[1], i); + continue; + } else { + if (tests[i].retval != GA_SUCCESS) { + warnx ("test_flag: %s failed to fail for test %d", + tests[i].argv[1], i); + continue; + } + } + + if (optind != tests[i].argc) { + warnx ("argc != optind for test %s, %d", + tests[i].argv[1], i); + continue; + } + + if (i < 4) { + if (flag == 0) { + warnx ("error parsing for test %d: flag %s", + i, + tests[i].argv[1]); + continue; + } + } else { + if (flag != 0) { + warnx ("error parsing test %d: flag %s", + i, + tests[i].argv[1]); + continue; + } + } + } +} + +/* + * + */ + +int +main (int argc, char **argv) +{ + + test_simple_string(); + test_simple_strings(); + test_simple_integer(); + test_simple_flag(); + + return 0; +} diff --git a/src/tests/generic-build b/src/tests/generic-build new file mode 100755 index 0000000..45e6bab --- /dev/null +++ b/src/tests/generic-build @@ -0,0 +1,18 @@ +#!/bin/sh +# $Id$ +if test $# -ne 1 -a $# -ne 2; then + echo "Usage: $0 file [directory]" + exit 1 +fi +filename=$1 +if test $# -gt 1; then + b=$2 +else + b=`basename $filename .tar.gz` +fi +obj=$b-obj + +gzip -dc $filename | tar xvf - >&4 2>&1 || exit 1 +cd $b || exit 1 +./configure >&4 || exit 1 +make $MAKEFLAGS || exit 1 diff --git a/src/tests/getdents-and-unlink1 b/src/tests/getdents-and-unlink1 new file mode 100755 index 0000000..bb640ff --- /dev/null +++ b/src/tests/getdents-and-unlink1 @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +gzip -dc ${AFSROOT}/stacken.kth.se/ftp/pub/gnu/emacs/emacs-20.7.tar.gz | +tar vxf - >&4 2>&1 || exit 1 +cd emacs-20.7 || exit 1 +$objdir/kill-softer lisp || exit 1 +test -d lisp && exit 1 +exit 0 diff --git a/src/tests/getdents-and-unlink2 b/src/tests/getdents-and-unlink2 new file mode 100755 index 0000000..2c23933 --- /dev/null +++ b/src/tests/getdents-and-unlink2 @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +gzip -dc ${AFSROOT}/stacken.kth.se/ftp/pub/gnu/emacs/emacs-20.7.tar.gz | +tar vxf - >&4 2>&1 || exit 1 +cd emacs-20.7 || exit 1 +$objdir/rm-rf lisp || exit 1 +test -d lisp && exit 1 +exit 0 diff --git a/src/tests/getdents-and-unlink3 b/src/tests/getdents-and-unlink3 new file mode 100755 index 0000000..9d04bc3 --- /dev/null +++ b/src/tests/getdents-and-unlink3 @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +gzip -dc ${AFSROOT}/stacken.kth.se/ftp/pub/gnu/emacs/emacs-20.7.tar.gz | +tar vxf - >&4 2>&1 || exit 1 +cd emacs-20.7 || exit 1 +$objdir/kill-softly lisp || exit 1 +test -d lisp && exit 1 +exit 0 diff --git a/src/tests/grind-arla-with-cvs b/src/tests/grind-arla-with-cvs new file mode 100755 index 0000000..15134bf --- /dev/null +++ b/src/tests/grind-arla-with-cvs @@ -0,0 +1,52 @@ +#!/bin/sh + +if [ x`uname` != xLinux ] ; then + echo This test does not run on this architecture + exit 1 +fi + +echo '***********************************************************' +echo '* *' +echo '* Infinite run until error *' +echo '* *' +echo '***********************************************************' +sleep 5 + +# First argument is our working dir +test $1 || exit 1 +mkdir $1 +cd $1 || exit 1 + +TOPDIR=$PWD +export TOPDIR +CVSROOT=/afs/stacken.kth.se/src/SourceRepository +export CVSROOT + +# test if cvs takes -R +cvs -R help 2>&1 | grep Usage: > /dev/null && exit 1 + +cvs -R checkout arla +while true; do + echo Starting at $TOPDIR + + cd $TOPDIR || exit 1 + cd arla || exit 1 + cvs -R update -A -d + sh HACKING + cd $TOPDIR || exit 1 + mkdir arla-obj + cd arla-obj || exit 1 + + ../arla/configure && mv xfs/linux/Makefile xfs/linux/Makefile.old && sed 's/ -Werror//g' < xfs/linux/Makefile.old > xfs/linux/Makefile && make || exit 1 + + cd $TOPDIR || exit 1 + cd arla || exit 1 + cvs -R update -r arla-0-35-branch -d + sh HACKING + cd $TOPDIR || exit 1 + mkdir arla-obj + cd arla-obj || exit 1 + ../arla/configure && mv xfs/linux/Makefile xfs/linux/Makefile.old && sed 's/ -Werror//g' < xfs/linux/Makefile.old > xfs/linux/Makefile && make || exit 1 +done + + diff --git a/src/tests/hardlink1.c b/src/tests/hardlink1.c new file mode 100644 index 0000000..a6f08ef --- /dev/null +++ b/src/tests/hardlink1.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +int +main(int argc, char *argv[]) +{ + int fd1, fd2; + int ret; + struct stat sb1, sb2; + + + fd1 = open("foo", O_RDWR|O_CREAT, 0666); + if (fd1 < 0) + err (1, "open foo"); + + ret = fstat (fd1, &sb1); + if (ret < 0) + err (1, "stat foo"); + + if (sb1.st_nlink != 1) + errx (1, "foo.st_nlink != 1"); + + ret = link ("foo", "bar"); + if (ret < 0) + err (1, "link foo, bar"); + + ret = fstat (fd1, &sb1); + if (ret < 0) + err (1, "stat foo"); + + ret = lstat ("bar", &sb2); + if (ret < 0) + err (1, "stat bar"); + + if (sb1.st_nlink != 2) + errx (1, "foo.st_nlink != 2"); + + if (sb2.st_nlink != 2) + errx (1, "bar.st_nlink != 2"); + + if (sb1.st_dev != sb2.st_dev + || sb1.st_ino != sb2.st_ino) + errx (1, "dev and ino differ"); + + fd2 = open("bar", O_RDONLY, 0); + if (fd2 < 0) + err (1, "open bar"); + + ret = fstat (fd2, &sb2); + if (ret < 0) + err (1, "fstat bar"); + + if (sb2.st_nlink != 2) + errx (1, "bar.st_nlink != 2"); + + if (write (fd1, "hej", 3) != 3) + errx (1, "write to foo"); + + ret = fstat (fd1, &sb1); + if (ret < 0) + err (1, "stat foo"); + + if (sb1.st_size != 3) + errx (1, "foo.st_size != 3"); + + ret = close (fd1); + if (ret < 0) + err (1, "close foo"); + + ret = fstat (fd2, &sb2); + if (ret < 0) + err (1, "fstat bar"); + + if (sb2.st_size != 3) + errx (1, "bar.st_size != 3"); + + ret = close (fd2); + if (ret < 0) + err (1, "close bar"); + + if (unlink ("foo") < 0) + err (1, "unlink foo"); + + fd2 = open("bar", O_RDONLY, 0); + if (fd2 < 0) + err (1, "open bar"); + + ret = fstat (fd2, &sb2); + if (ret < 0) + err (1, "fstat bar"); + + if (sb2.st_nlink != 1) + errx (1, "bar.st_nlink != 1"); + + ret = close (fd2); + if (ret < 0) + err (1, "close bar"); + + if (unlink ("bar") < 0) + err (1, "unlink bar"); + + return 0; +} diff --git a/src/tests/hardlink2.c b/src/tests/hardlink2.c new file mode 100644 index 0000000..4f5fbd4 --- /dev/null +++ b/src/tests/hardlink2.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +int +main(int argc, char *argv[]) +{ + int fd1; + int ret; + struct stat sb1; + + + ret = mkdir ("1", 0777); + if (ret < 0) + err (1, "mkdir 1"); + + ret = link ("1", "2"); + if (ret == 0) + errx (1, "link 1 2 should have failed"); + + ret = rmdir ("1"); + if (ret < 0) + err (1, "rmdir 1"); + + return 0; +} diff --git a/src/tests/hardlink3 b/src/tests/hardlink3 new file mode 100644 index 0000000..134dcfb --- /dev/null +++ b/src/tests/hardlink3 @@ -0,0 +1,28 @@ +#!/bin/sh +# $Id$ + +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi + +FS=${FS:-${objdir}/../appl/fs/fs} + +touch file +for i in `awk 'BEGIN {for(i=0; i < 1000; ++i) printf "%d\n", i}' /dev/null`; do + ln file file$i +done + +# now trigger bulkstatus +for i in `awk 'BEGIN {for(i=0; i < 1000; ++i) printf "%d\n", i}' /dev/null`; do + ls -l file > /dev/null 2>&1 || exit 1 + ${FS} flush file +done + +# just stat them all +for i in `awk 'BEGIN {for(i=0; i < 1000; ++i) printf "%d\n", i}' /dev/null`; do + ls -l file$i > /dev/null 2>&1 || exit 1 +done + +#clean up +for i in `awk 'BEGIN {for(i=0; i < 1000; ++i) printf "%d\n", i}' /dev/null`; do + rm file$i > /dev/null 2>&1 || exit 1 +done +rm file \ No newline at end of file diff --git a/src/tests/hardlink4.c b/src/tests/hardlink4.c new file mode 100644 index 0000000..2734139 --- /dev/null +++ b/src/tests/hardlink4.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +int +main(int argc, char *argv[]) +{ + int fd1; + int ret; + struct stat sb1; + + + ret = mkdir ("1", 0777); + if (ret < 0) + err (1, "mkdir 1"); + + ret = mkdir ("2", 0777); + if (ret < 0) + err (1, "mkdir 2"); + + fd1 = open("1/foo", O_RDWR|O_CREAT, 0666); + if (fd1 < 0) + err (1, "open 1/foo"); + + ret = fstat (fd1, &sb1); + if (ret < 0) + err (1, "stat foo"); + + if (sb1.st_nlink != 1) + errx (1, "foo.st_nlink != 1"); + + ret = close (fd1); + if (ret < 0) + err (1, "close 1/foo"); + + ret = link ("1/foo", "2/foo"); + if (ret == 0) + unlink ("2/foo"); + if (ret < 0 && errno != EXDEV) + err (1, "link 1/foo, 2/foo"); + + ret = unlink ("1/foo"); + if (ret < 0) + err (1, "unlink 1/foo"); + + ret = rmdir ("1"); + if (ret < 0) + err (1, "rmdir 1"); + + ret = rmdir ("2"); + if (ret < 0) + err (1, "rmdir 2"); + return 0; +} diff --git a/src/tests/hardlink5 b/src/tests/hardlink5 new file mode 100644 index 0000000..3a1ab1b --- /dev/null +++ b/src/tests/hardlink5 @@ -0,0 +1,11 @@ +#!/bin/sh +# $Id$ + +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi + +FS=${FS:-${objdir}/../appl/fs/fs} + +touch file +ln file ../../service/file && exit 1 +rm file + diff --git a/src/tests/hello-world.in b/src/tests/hello-world.in new file mode 100644 index 0000000..09a7a5a --- /dev/null +++ b/src/tests/hello-world.in @@ -0,0 +1,8 @@ +#!/bin/sh +# $Id$ +cat < foo.c +int main() { return 0; } +FOO +%CC% -o foo foo.c || exit 1 +./foo || exit 1 +rm -f foo foo.c diff --git a/src/tests/intr-read.c b/src/tests/intr-read.c new file mode 100644 index 0000000..7c2d9df --- /dev/null +++ b/src/tests/intr-read.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#include + +#define RETSIGTYPE void +#ifndef MAXPATHLEN +#ifdef PATH_MAX +#define MAXPATHLEN PATH_MAX +#else +#define MAXPATHLEN 4096 +#endif +#endif + +static sig_atomic_t set_alarm = 1; + +static RETSIGTYPE +sigalrm(int foo) +{ + signal(SIGALRM, sigalrm); + set_alarm = 1; +} + +static void +try_read(const char *filename) +{ + int fd; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + if (errno == EINTR) + err(1, "open %s was interrupted", filename); + } else { + close(fd); + } +} + +static void +find(const char *dirname) +{ + DIR *dir; + struct dirent *dp; + + dir = opendir(dirname); + if (dir == NULL) + err (1, "opendir %s", dirname); + while ((dp = readdir(dir)) != NULL) { + char fname[MAXPATHLEN]; + struct stat sb; + + if (set_alarm) { + alarm(1); + set_alarm = 0; + } + if (strcmp (dp->d_name, ".") == 0 + || strcmp (dp->d_name, "..") == 0) + continue; + snprintf(fname, sizeof(fname), "%s/%s", dirname, dp->d_name); + if (lstat(fname, &sb) < 0) + err(1, "stat %s", fname); + if (S_ISDIR(sb.st_mode)) + find(fname); + else + try_read(fname); + } + closedir(dir); +} + +int +main(int argc, char **argv) +{ + struct sigaction sa; + + sa.sa_handler = sigalrm; + sigfillset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGALRM, &sa, NULL); + while (--argc) + find(*++argv); + return 0; +} diff --git a/src/tests/intr-read1 b/src/tests/intr-read1 new file mode 100755 index 0000000..97820ec --- /dev/null +++ b/src/tests/intr-read1 @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ +$objdir/intr-read ${AFSROOT}/stacken.kth.se/ftp/pub/gnu/gnu-0.2 || exit 1 +exit 0 diff --git a/src/tests/invalidate-file.c b/src/tests/invalidate-file.c new file mode 100644 index 0000000..75be388 --- /dev/null +++ b/src/tests/invalidate-file.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +#include + +RCSID("$Id$"); + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#ifdef KERBEROS + +static void +create_write_file (char *filename) +{ + int ret; + int fd; + + fs_invalidate (filename); + + fd = open(filename, O_RDWR|O_CREAT, 0666); + if (fd < 0) + err (1, "open(rw): %s", filename); + + ret = write (fd, "foo", 3); + if (ret < 0) + err (1, "write"); + + fs_invalidate (filename); + + ret = write (fd, "foo", 3); + if (ret < 0) + err (1, "write2"); + + ret = close (fd); + if (ret < 0) + err (1, "close"); +} + +static void +read_file (char *filename) +{ + int ret; + int fd; + char buf[3]; + + fs_invalidate (filename); + + fd = open(filename, O_RDONLY, 0666); + if (fd < 0) + err (1, "open(ro)"); + + ret = read (fd, buf, sizeof(buf)); + if (ret < 0) + err (1, "read"); + + fs_invalidate (filename); + + ret = read (fd, buf, sizeof(buf)); + if (ret < 0) + err (1, "read"); + + ret = close (fd); + if (ret < 0) + err (1, "close"); +} + +static void +mmap_read_file (char *filename) +{ + int fd; + void *v; + char buf[6]; + + fs_invalidate (filename); + + fd = open(filename, O_RDONLY, 0666); + if (fd < 0) + err (1, "open(ro-mmap)"); + + v = mmap (NULL, 6, PROT_READ, MAP_SHARED, fd, 0); + if (v == (void *)MAP_FAILED) + err (1, "mmap(ro) %s", filename); + + memcpy (buf, v, 3); + fs_invalidate (filename); + memcpy (buf, v, 3); + + munmap (v, 6); +} + +static void +mmap_write_file (char *filename) +{ + int fd; + void *v; + + fs_invalidate (filename); + + fd = open (filename, O_RDWR, 0666); + if (fd < 0) + err (1, "open(rw-mmap)"); + + v = mmap (NULL, 6, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (v == (void *)MAP_FAILED) + err (1, "mmap(rw) %s", filename); + + memcpy (v, "foo", 3); + fs_invalidate (filename); + memcpy (v, "foo", 3); + + munmap (v, 6); + close (fd); +} + +int +main(int argc, char **argv) +{ + char *filename = "foo"; + + +#ifdef KERBEROS + if (!k_hasafs()) +#endif + exit (1); + + create_write_file (filename); + read_file (filename); + read_file (filename); + read_file (filename); + read_file (filename); + mmap_read_file (filename); + mmap_read_file (filename); + mmap_read_file (filename); + mmap_read_file (filename); + mmap_write_file (filename); + mmap_write_file (filename); + mmap_write_file (filename); + mmap_write_file (filename); + + return 0; +} + +#else + +int +main(int argc, char **argv) +{ + + errx (1, "no kafs support"); +} +#endif diff --git a/src/tests/kas.pm b/src/tests/kas.pm new file mode 100644 index 0000000..376f62a --- /dev/null +++ b/src/tests/kas.pm @@ -0,0 +1,325 @@ +# CMUCS AFStools +# Copyright (c) 1996, Carnegie Mellon University +# All rights reserved. +# +# See CMU_copyright.ph for use and distribution information +# +#: * kas.pm - Wrappers around KAS commands (authentication maintenance) +#: * This module provides wrappers around the various kaserver commands +#: * giving them a nice perl-based interface. At present, this module +#: * requires a special 'krbkas' which uses existing Kerberos tickets +#: * which the caller must have already required (using 'kaslog'). +#: + +package OpenAFS::kas; +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT :afs_internal); +use OpenAFS::wrapper; +use POSIX (); +use Exporter; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&AFS_kas_create &AFS_kas_setf + &AFS_kas_delete &AFS_kas_setkey + &AFS_kas_examine &AFS_kas_setpw + &AFS_kas_randomkey &AFS_kas_stringtokey + &AFS_kas_list); + +# Instructions to parse kas error messages +@kas_err_parse = ( [ ' : \[.*\] (.*), wait one second$', '.' ], + [ ' : \[.*\] (.*) \(retrying\)$', '.' ], + [ ' : \[.*\] (.*)', '-' ]); + +# Instructions to parse attributes of an entry +@kas_entry_parse = ( + [ '^User data for (.*) \((.*)\)$', 'princ', 'flags', '.' ], + [ '^User data for (.*)', 'princ' ], + [ 'key \((\d+)\) cksum is (\d+),', 'kvno', 'cksum' ], + [ 'last cpw: (.*)', \&parsestamp, 'stamp_cpw' ], + [ 'password will (never) expire', 'stamp_pwexp' ], + [ 'password will expire: ([^\.]*)', \&parsestamp, 'stamp_pwexp' ], + [ 'An (unlimited) number of', 'max_badauth' ], + [ '(\d+) consecutive unsuccessful', 'max_badauth' ], + [ 'for this user is ([\d\.]+) minutes', 'locktime' ], + [ 'for this user is (not limited)', 'locktime' ], + [ 'User is locked (forever)', 'locked' ], + [ 'User is locked until (.*)', \&parsestamp, 'locked' ], + [ 'entry (never) expires', 'stamp_expire' ], + [ 'entry expires on ([^\.]*)\.', \&parsestamp, 'stamp_expire' ], + [ 'Max ticket lifetime (.*) hours', 'maxlife' ], + [ 'Last mod on (.*) by', \&parsestamp, 'stamp_update' ], + [ 'Last mod on .* by (.*)', 'last_writer' ]); + + +@Months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); +%Months = map(($Months[$_] => $_), 0..11); + +# Parse a timestamp +sub parsestamp { + my($stamp) = @_; + my($MM, $DD, $YYYY, $hh, $mm, $ss); + + if ($stamp =~ /^\S+ (\S+) (\d+) (\d+):(\d+):(\d+) (\d+)/) { + ($MM, $DD, $hh, $mm, $ss, $YYYY) = ($1, $2, $3, $4, $5, $6); + $YYYY -= 1900; + $MM = $Months{$MM}; + if (defined($MM)) { + $stamp = POSIX::mktime($ss, $mm, $hh, $DD, $MM, $YYYY); + } + } + $stamp; +} + + +# Turn an 8-byte key into a string we can give to kas +sub stringize_key { + my($key) = @_; + my(@chars) = unpack('CCCCCCCC', $key); + + sprintf("\\%03o" x 8, @chars); +} + + +# Turn a string into an 8-byte DES key +sub unstringize_key { + my($string) = @_; + my($char, $key); + + while ($string ne '') { + if ($string =~ /^\\(\d\d\d)/) { + $char = $1; + $string = $'; + $key .= chr(oct($char)); + } else { + $key .= substr($string, 0, 1); + $string =~ s/^.//; + } + } + $key; +} + + +#: AFS_kas_create($princ, $initpass, [$cell]) +#: Create a principal with name $princ, and initial password $initpass +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{kas_create} = '$princ, $initpass, [$cell] => Success?'; +sub AFS_kas_create { + my($print, $initpass, $cell) = @_; + my(@args, $id); + + @args = ('create', '-name', $princ, '-initial_password', $initpass); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('krbkas', \@args, [ @kas_err_parse ]); + 1; +} + + +#: AFS_kas_delete($princ, [$cell]) +#: Delete the principal $princ. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{kas_delete} = '$princ, [$cell] => Success?'; +sub AFS_kas_delete { + my($princ, $cell) = @_; + my(@args); + + @args = ('delete', '-name', $princ); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('krbkas', \@args, [ @kas_err_parse ]); + 1; +} + + +#: AFS_kas_examine($princ, [$cell]) +#: Examine the prinicpal $princ, and return information about it. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return an associative array with some or all of the following: +#: - princ Name of this principal +#: - kvno Key version number +#: - cksum Key checksum +#: - maxlife Maximum ticket lifetime (in hours) +#: - stamp_expire Time this principal expires, or 'never' +#: - stamp_pwexp Time this principal's password expires, or 'never' +#: - stamp_cpw Time this principal's password was last changed +#: - stamp_update Time this princiapl was last modified +#: - last_writer Administrator who last modified this principal +#: - max_badauth Maximum number of bad auth attempts, or 'unlimited' +#: - locktime Penalty time for bad auth (in minutes), or 'not limited' +#: - locked Set and non-empty if account is locked +#: - expired Set and non-empty if account is expired +#: - flags Reference to a list of flags +#: +$AFS_Help{kas_examine} = '$princ, [$cell] => %info'; +sub AFS_kas_examine { + my($vol, $cell) = @_; + my(%result, @args, $flags); + + @args = ('examine', '-name', $princ); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + %result = &wrapper('krbkas', \@args, [ @kas_err_parse, @kas_entry_parse ]); + + if ($result{flags}) { + $result{expired} = 1 if ($result{flags} =~ /expired/); + $result{flags} = [ split(/\+/, $result{flags}) ]; + } + %result; +} + + +#: AFS_kas_list([$cell]) +#: Get a list of principals in the kaserver database +#: If specified, work in $cell instead of the default cell. +#: On success, return an associative array whose keys are names of kaserver +#: principals, and each of whose values is an associative array describing +#: the corresponding principal, containing some or all of the same elements +#: that may be returned by AFS_kas_examine +#: +$AFS_Help{kas_list} = '[$cell] => %princs'; +sub AFS_kas_list { + my($cell) = @_; + my(@args, %finres, %plist); + + @args = ('list', '-long'); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + %finres = &wrapper('krbkas', \@args, + [ @kas_err_parse, + [ '^User data for (.*)', sub { + my(%pinfo) = %OpenAFS::wrapper::result; + + if ($pinfo{name}) { + $plist{$pinfo{name}} = \%pinfo; + %OpenAFS::wrapper::result = (); + } + }], + @kas_entry_parse ]); + + if ($finres{name}) { + $plist{$finres{name}} = \%finres; + } + %plist; +} + + +#: AFS_kas_setf($princ, \%attrs, [$cell]) +#: Change the attributes of the principal $princ. +#: If specified, operate in cell $cell instead of the default cell. +#: The associative array %attrs specifies the attributes to change and +#: their new values. Any of the following attributes may be changed: +#: - flags Entry flags +#: - expire Expiration time (mm/dd/yy) +#: - lifetime Maximum ticket lifetime (seconds) +#: - pwexpires Maximum password lifetime (days) +#: - reuse Permit password reuse (yes/no) +#: - attempts Maximum failed authentication attempts +#: - locktime Authentication failure penalty (minutes or hh:mm) +#: +#: On success, return 1. +#: +$AFS_Help{kas_setf} = '$princ, \%attrs, [$cell] => Success?'; +sub AFS_kas_setf { + my($princ, $attrs, $cell) = @_; + my(%result, @args); + + @args = ('setfields', '-name', $princ); + push(@args, '-flags', $$attrs{flags}) if ($$attrs{flags}); + push(@args, '-expiration', $$attrs{expire}) if ($$attrs{expire}); + push(@args, '-lifetime', $$attrs{lifetime}) if ($$attrs{lifetime}); + push(@args, '-pwexpires', $$attrs{pwexpires}) if ($$attrs{pwexpires}); + push(@args, '-reuse', $$attrs{reuse}) if ($$attrs{reuse}); + push(@args, '-attempts', $$attrs{attempts}) if ($$attrs{attempts}); + push(@args, '-locktime', $$attrs{locktime}) if ($$attrs{locktime}); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('krbkas', \@args, [ @kas_err_parse ]); + 1; +} + + +#: AFS_kas_setkey($princ, $key, [$kvno], [$cell]) +#: Change the key of principal $princ to the specified value. +#: $key is the 8-byte DES key to use for this principal. +#: If specified, set the key version number to $kvno. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{kas_setkey} = '$princ, $key, [$kvno], [$cell] => Success?'; +sub AFS_kas_setkey { + my($princ, $key, $kvno, $cell) = @_; + my(@args); + + @args = ('setkey', '-name', $princ, '-new_key', &stringize_key($key)); + push(@args, '-kvno', $kvno) if (defined($kvno)); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('krbkas', \@args, [ @kas_err_parse ]); + 1; +} + + +#: AFS_kas_setpw($princ, $password, [$kvno], [$cell]) +#: Change the key of principal $princ to the specified value. +#: $password is the new password to use. +#: If specified, set the key version number to $kvno. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{kas_setpw} = '$princ, $password, [$kvno], [$cell] => Success?'; +sub AFS_kas_setpw { + my($princ, $password, $kvno, $cell) = @_; + my(@args); + + @args = ('setpasswd', '-name', $princ, '-new_password', $password); + push(@args, '-kvno', $kvno) if (defined($kvno)); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('krbkas', \@args, [ @kas_err_parse ]); + 1; +} + + +#: AFS_kas_stringtokey($string, [$cell]) +#: Convert the specified string to a DES key +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return the resulting key +$AFS_Help{kas_stringtokey} = '$string, [$cell] => $key'; +sub AFS_kas_stringtokey { + my($string, $cell) = @_; + my(@args, $key); + + @args = ('stringtokey', '-string', $string); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('krbkas', \@args, + [ @kas_err_parse, + [ q/^Converting .* in realm .* yields key='(.*)'.$/, \$key ]]); + &unstringize_key($key); +} + + +#: AFS_kas_randomkey([$cell]) +#: Ask the kaserver to generate a random DES key +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return the resulting key +$AFS_Help{kas_randomkey} = '[$cell] => $key'; +sub AFS_kas_randomkey { + my($cell) = @_; + my(@args, $key); + + @args = ('getrandomkey'); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('krbkas', \@args, + [ @kas_err_parse, + [ '^Key: (\S+)', \$key ]]); + &unstringize_key($key); +} + +1; diff --git a/src/tests/kill-softer.c b/src/tests/kill-softer.c new file mode 100644 index 0000000..d44609d --- /dev/null +++ b/src/tests/kill-softer.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static FILE *verbose; + +struct entry { + char *name; + int status; +}; + +static void +kill_one (struct entry *ents, int ind, int curents); + +static void +do_dir (const char *dirname); + +static void +kill_dir (const char *dirname); + +static void +kill_one (struct entry *ents, int ind, int curents) +{ + int ret; + int i; + + ret = unlink (ents[ind].name); + if (ret < 0) { + if (errno == EISDIR || errno == EPERM) + do_dir (ents[ind].name); + else + err (1, "unlink %s", ents[ind].name); + } + ents[ind].status = 0; + for (i = 0; i <= ind; ++i) { + struct stat sb; + + ret = lstat (ents[i].name, &sb); + if (ret == 0 || errno != ENOENT) + err (1, "%s still exists?", ents[i].name); + } + + for (i = ind + 1; i < curents; ++i) { + struct stat sb; + + ret = lstat (ents[i].name, &sb); + if (ret < 0) + err (1, "stat %s", ents[i].name); + } +} + +static void +do_dir (const char *dirname) +{ + int ret; + + ret = chdir (dirname); + if (ret < 0) + err (1, "chdir %s", dirname); + kill_dir (dirname); + ret = chdir (".."); + if (ret < 0) + err (1, "chdir .."); + ret = rmdir (dirname); + if (ret < 0) + err (1, "rmdir %s", dirname); +} + +static void +kill_dir (const char *dirname) +{ + struct entry *ents; + int maxents; + int curents = 0; + DIR *dir; + struct dirent *dp; + int i; + + fprintf (verbose, "reading %s\n", dirname); + + dir = opendir ("."); + if (dir == NULL) + err (1, "opendir %s", dirname); + maxents = 10; + ents = malloc (sizeof (*ents) * maxents); + if (ents == NULL) + err (1, "malloc"); + while ((dp = readdir (dir)) != NULL) { + if (strcmp (dp->d_name, ".") == 0 + || strcmp (dp->d_name, "..") == 0) + continue; + + if (curents >= maxents) { + maxents *= 2; + ents = realloc (ents, sizeof(*ents) * maxents); + if (ents == NULL) + err (1, "realloc"); + } + ents[curents].name = strdup (dp->d_name); + ents[curents].status = 1; + ++curents; + fprintf (verbose, " adding %s\n", dp->d_name); + } + closedir (dir); + dir = opendir ("."); + if (dir == NULL) + err (1, "opendir %s", dirname); + i = 0; + while((dp = readdir (dir)) != NULL) { + if (strcmp (dp->d_name, ".") == 0 + || strcmp (dp->d_name, "..") == 0) + continue; + + if (strcmp (ents[i].name, dp->d_name) != 0) { + errx (1, "%s != %s", ents[i].name, dp->d_name); + } + fprintf (verbose, " deleting %s\n", ents[i].name); + kill_one (ents, i, curents); + ++i; + } + if (i != curents) + errx (1, "missing %d entries in %s", curents - i, dirname); + closedir (dir); + free (ents); + fprintf (verbose, "end of %s\n", dirname); +} + +int +main(int argc, char **argv) +{ + + verbose = fdopen (4, "w"); + if (verbose == NULL) { + verbose = fopen ("/dev/null", "w"); + if (verbose == NULL) + err (1, "fopen /dev/null"); + } + + if (argc != 2) + errx (1, "usage: %s directory", argv[0]); + do_dir (argv[1]); + return 0; +} diff --git a/src/tests/kill-softly.c b/src/tests/kill-softly.c new file mode 100644 index 0000000..d9a6a4c --- /dev/null +++ b/src/tests/kill-softly.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +struct entry { + char *name; + int status; +}; + +static void +kill_one (struct entry *ents, int ind, int curents); + +static void +do_dir (const char *dirname); + +static void +kill_dir (const char *dirname); + +static void +kill_one (struct entry *ents, int ind, int curents) +{ + int ret; + int i; + + ret = unlink (ents[ind].name); + if (ret < 0) { + if (errno == EISDIR || errno == EPERM) + do_dir (ents[ind].name); + else + err (1, "unlink %s", ents[ind].name); + } + ents[ind].status = 0; + for (i = 0; i <= ind; ++i) { + struct stat sb; + + ret = lstat (ents[i].name, &sb); + if (ret == 0 || errno != ENOENT) + err (1, "%s still exists?", ents[i].name); + } + + for (i = ind + 1; i < curents; ++i) { + struct stat sb; + + ret = lstat (ents[i].name, &sb); + if (ret < 0) + err (1, "stat %s", ents[i].name); + } +} + +static void +do_dir (const char *dirname) +{ + int ret; + + ret = chdir (dirname); + if (ret < 0) + err (1, "chdir %s", dirname); + kill_dir (dirname); + ret = chdir (".."); + if (ret < 0) + err (1, "chdir .."); + ret = rmdir (dirname); + if (ret < 0) + err (1, "rmdir %s", dirname); +} + +static void +kill_dir (const char *dirname) +{ + struct entry *ents; + int maxents; + int curents = 0; + DIR *dir; + struct dirent *dp; + int i; + + dir = opendir ("."); + if (dir == NULL) + err (1, "opendir %s", dirname); + maxents = 10; + ents = malloc (sizeof (*ents) * maxents); + if (ents == NULL) + err (1, "malloc"); + while ((dp = readdir (dir)) != NULL) { + if (strcmp (dp->d_name, ".") == 0 + || strcmp (dp->d_name, "..") == 0) + continue; + + if (curents >= maxents) { + maxents *= 2; + ents = realloc (ents, sizeof(*ents) * maxents); + if (ents == NULL) + err (1, "realloc"); + } + ents[curents].name = strdup (dp->d_name); + ents[curents].status = 1; + ++curents; + } + closedir (dir); + for (i = 0; i < curents; ++i) + kill_one (ents, i, curents); + free (ents); +} + +int +main(int argc, char **argv) +{ + + if (argc != 2) + errx (1, "usage: %s directory", argv[0]); + do_dir (argv[1]); + return 0; +} diff --git a/src/tests/kotest b/src/tests/kotest new file mode 100755 index 0000000..2e163e3 --- /dev/null +++ b/src/tests/kotest @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ + +exec ${objdir}/../lib/ko/kotest diff --git a/src/tests/large-dir-16384 b/src/tests/large-dir-16384 new file mode 100755 index 0000000..a23c566 --- /dev/null +++ b/src/tests/large-dir-16384 @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +$objdir/large-dir large-dir-16384 16384 diff --git a/src/tests/large-dir-extra b/src/tests/large-dir-extra new file mode 100755 index 0000000..589a2d9 --- /dev/null +++ b/src/tests/large-dir-extra @@ -0,0 +1,7 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +for i in 10 20 30 31 40 50 60 70 80 90 100; do + $objdir/large-dir2 large-dir-$i $i || exit 1 + $objdir/large-dir3 large-dir-$i $i || exit 1 +done diff --git a/src/tests/large-dir.c b/src/tests/large-dir.c new file mode 100644 index 0000000..13f6cf5 --- /dev/null +++ b/src/tests/large-dir.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +creat_files (const char *dirname, int count) +{ + struct stat sb; + int i; + DIR *d; + struct dirent *dp; + + if (mkdir (dirname, 0777) < 0) + err (1, "mkdir %s", dirname); + + if (chdir (dirname) < 0) + err (1, "chdir %s", dirname); + if (stat (".", &sb) < 0) + err (1, "stat ."); + if (sb.st_size != 2048) + errx (1, "size != 2048"); + for (i = 0; i < count; ++i) { + char num[17]; + int fd; + + snprintf (num, sizeof(num), "%d", i); + + fd = open (num, O_CREAT | O_EXCL, 0777); + if (fd < 0) + err (1, "open %s", num); + if (close (fd) < 0) + err (1, "close %s", num); + } + if (stat (".", &sb) < 0) + err (1, "stat ."); + + d = opendir ("."); + if (d == NULL) + err (1, "opendir ."); + for (i = -2; i < count; ++i) { + char num[17]; + + dp = readdir (d); + if (dp == NULL) + errx (1, "out of entries at %d?", i); + if (i == -2) + strcpy (num, "."); + else if (i == -1) + strcpy (num, ".."); + else + snprintf (num, sizeof(num), "%d", i); + if (strcmp (num, dp->d_name) != 0) + errx (1, "'%s' != '%s'", num, dp->d_name); + } + if (readdir (d) != NULL) + errx (1, "more entries?"); + closedir (d); + for (i = 0; i < count; ++i) { + char num[17]; + + snprintf (num, sizeof(num), "%d", i); + + if (unlink (num) < 0) + err (1, "unlink %s", num); + } + d = opendir ("."); + if (d == NULL) + err (1, "opendir ."); + dp = readdir (d); + if (dp == NULL || strcmp (dp->d_name, ".") != 0) + errx (1, "where's .?"); + dp = readdir (d); + if (dp == NULL || strcmp (dp->d_name, "..") != 0) + errx (1, "where's ..?"); + if (readdir (d) != NULL) + errx (1, "even more entries?"); + closedir (d); + if (stat (".", &sb) < 0) + err (1, "stat ."); +#if 0 + if (sb.st_size != 2048) + errx (1, "size != 2048"); +#endif + return 0; +} + +static void +usage (int ret) +{ + fprintf (stderr, "%s directory number-of-files\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *ptr; + int count; + + + if (argc != 3) + usage (1); + + count = strtol (argv[2], &ptr, 0); + if (count == 0 && ptr == argv[2]) + errx (1, "'%s' not a number", argv[2]); + + return creat_files (argv[1], count); +} diff --git a/src/tests/large-dir2.c b/src/tests/large-dir2.c new file mode 100644 index 0000000..14b9a82 --- /dev/null +++ b/src/tests/large-dir2.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +creat_files (const char *dirname, int count) +{ + struct stat sb; + int i; + DIR *d; + struct dirent *dp; + + srand (time (NULL)); + + if (mkdir (dirname, 0777) < 0) + err (1, "mkdir %s", dirname); + + if (chdir (dirname) < 0) + err (1, "chdir %s", dirname); + if (stat (".", &sb) < 0) + err (1, "stat ."); +#if 0 + if (sb.st_size != 2048) + errx (1, "size != 2048"); +#endif + for (i = 0; i < count; ++i) { + char fname[256]; + int len; + int j; + int fd; + + len = 1 + rand () % (sizeof(fname) - 2); + + for (j = 0; j < len; ++j) + fname[j] = 'A' + rand() % ('z' - 'A'); + fname[j] = '\0'; + + fd = open (fname, O_CREAT | O_EXCL, 0777); + if (fd < 0) + err (1, "open %s", fname); + if (close (fd) < 0) + err (1, "close %s", fname); + } + if (stat (".", &sb) < 0) + err (1, "stat ."); + + d = opendir ("."); + if (d == NULL) + err (1, "opendir ."); + while ((dp = readdir (d)) != NULL) { + if (strcmp (dp->d_name, ".") == 0 + || strcmp (dp->d_name, "..") == 0) + continue; + + if (unlink (dp->d_name) < 0) + err (1, "unlink %s", dp->d_name); + } + closedir (d); + if (chdir ("..") < 0) + err (1, "chdir .."); + if (rmdir (dirname) < 0) + err (1, "rmdir"); + return 0; +} + +static void +usage (int ret) +{ + fprintf (stderr, "%s directory number-of-files\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *ptr; + int count; + + + if (argc != 3) + usage (1); + + count = strtol (argv[2], &ptr, 0); + if (count == 0 && ptr == argv[2]) + errx (1, "'%s' not a number", argv[2]); + + return creat_files (argv[1], count); +} diff --git a/src/tests/large-dir3.c b/src/tests/large-dir3.c new file mode 100644 index 0000000..a171c81 --- /dev/null +++ b/src/tests/large-dir3.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +creat_files (const char *dirname, int count) +{ + struct stat sb; + int i; + DIR *d; + struct dirent *dp; + + if (mkdir (dirname, 0777) < 0) + err (1, "mkdir %s", dirname); + + if (chdir (dirname) < 0) + err (1, "chdir %s", dirname); + if (stat (".", &sb) < 0) + err (1, "stat ."); + for (i = 0; i < count; ++i) { + char num[17]; + int fd; + + snprintf (num, sizeof(num), "%d", i); + + fd = open (num, O_CREAT | O_EXCL, 0777); + if (fd < 0) + err (1, "open %s", num); + if (close (fd) < 0) + err (1, "close %s", num); + } + if (stat (".", &sb) < 0) + err (1, "stat ."); + + d = opendir ("."); + if (d == NULL) + err (1, "opendir ."); + while ((dp = readdir (d)) != NULL) { + if (strcmp (dp->d_name, ".") == 0 + || strcmp (dp->d_name, "..") == 0) + continue; + + if (unlink (dp->d_name) < 0) + err (1, "unlink %s", dp->d_name); + } + closedir (d); + if (chdir ("..") < 0) + err (1, "chdir .."); + if (rmdir (dirname) < 0) + err (1, "rmdir"); + return 0; +} + +static void +usage (int ret) +{ + fprintf (stderr, "%s directory number-of-files\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *ptr; + int count; + + + if (argc != 3) + usage (1); + + count = strtol (argv[2], &ptr, 0); + if (count == 0 && ptr == argv[2]) + errx (1, "'%s' not a number", argv[2]); + + return creat_files (argv[1], count); +} diff --git a/src/tests/large-filename b/src/tests/large-filename new file mode 100644 index 0000000..fa9f6f0 --- /dev/null +++ b/src/tests/large-filename @@ -0,0 +1,6 @@ +#!/bin/sh +# $Id$ + +touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 2>/dev/null >/dev/null || exit 1 +rm aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 2>/dev/null >/dev/null || exit 1 +exit 0 diff --git a/src/tests/ls-afs b/src/tests/ls-afs new file mode 100644 index 0000000..93ae733 --- /dev/null +++ b/src/tests/ls-afs @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +ls -l $AFSROOT >/dev/null +true diff --git a/src/tests/make-page.c b/src/tests/make-page.c new file mode 100644 index 0000000..7a8ff6b --- /dev/null +++ b/src/tests/make-page.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include + + +#include + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +int +main (int argc, char **argv) +{ + int mb = 10; + int ret; + size_t sz; + void *mmap_buf; + + srand(getpid() * time(NULL)); + + sz = mb * 1024 * 1024; + +#ifdef MAP_ANON + mmap_buf = mmap (NULL, sz, PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0); +#else + { + int fd; + + fd = open ("/dev/zero", O_RDWR); + if (fd < 0) + err (1, "open /dev/zero"); + mmap_buf = mmap (NULL, sz, PROT_READ | PROT_WRITE, + MAP_PRIVATE, fd, 0); + close (fd); + } +#endif + if (mmap_buf == (void *)MAP_FAILED) + err (1, "mmap"); + + while (1) { + int *foo = (int *) ((unsigned char *) mmap_buf + (((rand() % (sz - 9)) + 7) & ~7)); + struct timeval tv = { 0, 1000} ; + *foo = 10; + select (0, NULL, NULL, NULL, &tv); + } + + ret = munmap (mmap_buf, sz); + if (ret) + err (1, "munmap"); +} diff --git a/src/tests/many-dirs b/src/tests/many-dirs new file mode 100644 index 0000000..4e88fb2 --- /dev/null +++ b/src/tests/many-dirs @@ -0,0 +1,6 @@ +#!/bin/sh +# $Id$ + +mkdir foobar || exit 1 +(cd foobar && $objdir/create-dirs 1000) || exit 1 +$objdir/rm-rf foobar || exit 1 diff --git a/src/tests/many-fetchs b/src/tests/many-fetchs new file mode 100644 index 0000000..1ac8168 --- /dev/null +++ b/src/tests/many-fetchs @@ -0,0 +1,15 @@ +#!/bin/sh +# $Id$ + +FS=${FS:-${objdir}/../appl/fs/fs} + +touch foo + +echo "foobar" > foo + +for i in `awk 'BEGIN {for(i=0; i < 1000; ++i) printf "%d\n", i}' /dev/null`; do + ${FS} flush foo + cat foo > /dev/null || exit 1 +done + +rm foo \ No newline at end of file diff --git a/src/tests/many-files b/src/tests/many-files new file mode 100644 index 0000000..6b6ccc8 --- /dev/null +++ b/src/tests/many-files @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ + +$objdir/create-files 1000 0 diff --git a/src/tests/many-files-with-content b/src/tests/many-files-with-content new file mode 100644 index 0000000..0c12b82 --- /dev/null +++ b/src/tests/many-files-with-content @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ + +$objdir/create-files 1000 10 diff --git a/src/tests/many-stores b/src/tests/many-stores new file mode 100644 index 0000000..f64e4ce --- /dev/null +++ b/src/tests/many-stores @@ -0,0 +1,10 @@ +#!/bin/sh +# $Id$ + +touch foo + +for i in `awk 'BEGIN {for(i=0; i < 1000; ++i) printf "%d\n", i}' /dev/null`; do + echo "foo$i" >> foo || exit 1 +done + +rm foo \ No newline at end of file diff --git a/src/tests/many-symlinks b/src/tests/many-symlinks new file mode 100644 index 0000000..2bf1b6f --- /dev/null +++ b/src/tests/many-symlinks @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ + +$objdir/create-symlinks 1000 diff --git a/src/tests/mkdir b/src/tests/mkdir new file mode 100644 index 0000000..bfa7b57 --- /dev/null +++ b/src/tests/mkdir @@ -0,0 +1,10 @@ +#!/bin/sh +# $Id$ +mkdir foo || exit 1 +echo hej > foo/1 || exit 1 +rmdir foo >/dev/null 2>&1 +test -d foo || exit 1 +rm -f foo/1 || exit 1 +rmdir foo || exit 1 +test -d foo && exit 1 +exit 0 diff --git a/src/tests/mkdir-lnk b/src/tests/mkdir-lnk new file mode 100755 index 0000000..f2247a2 --- /dev/null +++ b/src/tests/mkdir-lnk @@ -0,0 +1,12 @@ +#!/bin/sh +mkdir foo || exit 1 +ls -ld foo | awk '{if($2 != 2) { exit(1) }}' || exit 1 +mkdir foo/1 || exit 1 +ls -ld foo | awk '{if($2 != 3) { exit(1) }}' || exit 1 +mkdir foo/2 || exit 1 +ls -ld foo | awk '{if($2 != 4) { exit(1) }}' || exit 1 +rmdir foo/1 || exit 1 +ls -ld foo | awk '{if($2 != 3) { exit(1) }}' || exit 1 +rmdir foo/2 || exit 1 +ls -ld foo | awk '{if($2 != 2) { exit(1) }}' || exit 1 +rmdir foo || exit 1 diff --git a/src/tests/mkdir1 b/src/tests/mkdir1 new file mode 100755 index 0000000..aa6d502 --- /dev/null +++ b/src/tests/mkdir1 @@ -0,0 +1,7 @@ +#!/bin/sh +# $Id$ +mkdir foobar || exit 1 +test -d foobar || exit 1 +test -d foobar/. || exit 1 +test -d foobar/.. || exit 1 +rmdir foobar || exit 1 diff --git a/src/tests/mkdir2.c b/src/tests/mkdir2.c new file mode 100644 index 0000000..4a52722 --- /dev/null +++ b/src/tests/mkdir2.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +int +main(int argc, char *argv[]) +{ + int ret; + struct stat dot_sb, sb; + + + ret = mkdir ("foo", 0777); + if (ret < 0) + err (1, "mkdir foo"); + ret = lstat (".", &dot_sb); + if (ret < 0) + err (1, "lstat ."); + ret = lstat ("foo", &sb); + if (ret < 0) + err (1, "lstat foo"); + if (sb.st_nlink != 2) + errx (1, "sb.st_link != 2"); + ret = lstat ("foo/.", &sb); + if (ret < 0) + err (1, "lstat foo/."); + if (sb.st_nlink != 2) + errx (1, "sb.st_link != 2"); + ret = lstat ("foo/..", &sb); + if (ret < 0) + err (1, "lstat foo"); + if (sb.st_nlink != dot_sb.st_nlink) + errx (1, "sb.st_link != dot_sb.st_nlink"); + ret = rmdir ("foo"); + if (ret < 0) + err (1, "rmdir foo"); + return 0; +} diff --git a/src/tests/mkdir3.c b/src/tests/mkdir3.c new file mode 100644 index 0000000..576d4e8 --- /dev/null +++ b/src/tests/mkdir3.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +int +main(int argc, char *argv[]) +{ + int ret; + struct stat dot_sb, sb; + int fd; + + ret = mkdir ("foo", 0777); + if (ret < 0) + err (1, "mkdir foo"); + ret = lstat (".", &dot_sb); + if (ret < 0) + err (1, "lstat ."); + ret = lstat ("foo", &sb); + if (ret < 0) + err (1, "lstat foo"); + if (sb.st_nlink != 2) + errx (1, "sb.st_link != 2"); + ret = lstat ("foo/.", &sb); + if (ret < 0) + err (1, "lstat foo/."); + if (sb.st_nlink != 2) + errx (1, "sb.st_link != 2"); + ret = lstat ("foo/..", &sb); + if (ret < 0) + err (1, "lstat foo"); + if (sb.st_nlink != dot_sb.st_nlink) + errx (1, "sb.st_link != dot_sb.st_nlink"); + ret = mkdir ("foo/bar", 0777); + if (ret < 0) + err (1, "mkdir bar"); + fd = open ("foo/baz", O_CREAT|O_RDWR, 0600); + if (fd < 0) + err (1, "creat baz"); + close(fd); + ret = lstat ("foo", &sb); + if (ret < 0) + err (1, "lstat foo"); + if (sb.st_nlink != 3) + errx (1, "sb.st_link != 3"); + ret = unlink ("foo/baz"); + if (ret < 0) + err (1, "unlink baz"); + ret = rmdir ("foo/bar"); + if (ret < 0) + err (1, "rmdir bar"); + ret = rmdir ("foo"); + if (ret < 0) + err (1, "rmdir foo"); + return 0; +} diff --git a/src/tests/mkm-rmm b/src/tests/mkm-rmm new file mode 100755 index 0000000..3b67790 --- /dev/null +++ b/src/tests/mkm-rmm @@ -0,0 +1,13 @@ +#!/bin/sh +# $Id$ +FS=${FS:-${objdir}/../appl/fs/fs} +${FS} sa . system:anyuser all || exit 1 +${FS} mkm root.cell root.cell || exit 1 +test -d root.cell || exit 1 +${FS} rmm root.cell || exit 1 +test -d root.cell && exit 1 +${FS} mkm root.cell root.cell || exit 1 +test -d root.cell || exit 1 +${FS} rmm root.cell || exit 1 +test -d root.cell && exit 1 +exit 0 diff --git a/src/tests/mmap-and-read.c b/src/tests/mmap-and-read.c new file mode 100644 index 0000000..0444ec6 --- /dev/null +++ b/src/tests/mmap-and-read.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static char * +generate_random_file (const char *filename, + unsigned npages, + unsigned pagesize, + int writep) +{ + int fd; + char *buf, *fbuf; + int i; + int prot; + int flags; + size_t sz = npages * pagesize; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + + for (i = 0; i < npages; ++i) + memset (buf + pagesize * i, '0' + i, pagesize); + + fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0666); + if (fd < 0) + err (1, "open %s", filename); + + if (ftruncate (fd, sz) < 0) + err (1, "ftruncate"); + + prot = PROT_READ | PROT_WRITE; + flags = MAP_SHARED; + + fbuf = mmap (0, sz, prot, flags, fd, 0); + if (fbuf == (void *)MAP_FAILED) + err (1, "mmap"); + + if (writep) { + if(write(fd, "hej\n", 4) != 4) + err(1, "write"); + } + + memcpy (fbuf, buf, sz); + +#if 0 + if (msync (fbuf, sz, MS_SYNC)) + err(1, "msync"); +#endif + + if (munmap (fbuf, sz) != 0) + err (1, "munmap"); + + if (close (fd)) + err (1, "close"); + return buf; +} + +static char * +read_file (int fd, size_t sz) +{ + char *buf; + ssize_t ret; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + ret = read (fd, buf, sz); + if (ret < 0) + err (1, "read"); + if (ret != sz) + errx(1, "short read %d < %u", (int)ret, (unsigned)sz); + return buf; +} + +static int +test (const char *file, int writep) +{ + const size_t sz = 4 * getpagesize(); + char *buf; + char *malloc_buf; + int fd; + int ret; + + buf = generate_random_file (file, 4, getpagesize(), writep); + + fd = open (file, O_RDONLY, 0); + if (fd < 0) + err (1, "open %s", file); + + malloc_buf = read_file (fd, sz); + close (fd); + ret = memcmp (buf, malloc_buf, sz); + free (buf); + + return ret; +} + + +int +main (int argc, char **argv) +{ + + + srand (time(NULL)); + + if (test ("foo", 1) != 0) + errx (1, "test(1)"); + if (test ("bar", 0) != 0) + errx (1, "test(2)"); + + return 0; +} diff --git a/src/tests/mmap-cat.c b/src/tests/mmap-cat.c new file mode 100644 index 0000000..3893022 --- /dev/null +++ b/src/tests/mmap-cat.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static void +doit_mmap(int fd, struct stat *sb) +{ + void *mmap_buf; + int ret; + + mmap_buf = mmap (NULL, sb->st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mmap_buf == (void *)MAP_FAILED) + err (1, "mmap"); + ret = write (1, mmap_buf, sb->st_size); + if (ret != sb->st_size) + err(1, "write returned %d wanted to write %d", + ret, (int)sb->st_size); + munmap(mmap_buf, sb->st_size); +} + + +static void +doit_read(int fd, struct stat *sb) +{ + int ret; + void *read_buf; + + read_buf = malloc(sb->st_size); + if (read_buf == NULL) + err(1, "malloc(%d)", (int)sb->st_size); + ret = read(fd, read_buf, sb->st_size); + if (ret != sb->st_size) + err(1, "read returned %d wanted to write %d", + ret, (int)sb->st_size); + ret = write (1, read_buf, sb->st_size); + if (ret != sb->st_size) + err(1, "write returned %d wanted to write %d", + ret, (int)sb->st_size); + free(read_buf); +} + +static void +doit (const char *filename, void (*func)(int, struct stat *)) +{ + struct stat sb; + int fd; + int ret; + + fd = open (filename, O_RDONLY); + if (fd < 0) + err(1, "open %s", filename); + ret = fstat (fd, &sb); + (*func)(fd, &sb); + if (ret < 0) + err (1, "stat %s", filename); + close (fd); +} + +static int read_flag; +static int mmap_flag; +static int help_flag; + +static void +usage (int exit_val) +{ + fprintf(stderr, "mmap-cat [-m|-r] filename\n"); + exit (exit_val); +} + +int +main(int argc, char **argv) +{ + int optind = 0; + + if (argc != 2) + usage(1); + + if (!strcmp(argv[1],"-m")) { + mmap_flag++; + } else + if (!strcmp(argv[1],"-r")) { + read_flag++; + } else + usage (1); + + if (read_flag && mmap_flag) + errx(1, "can't do both mmap and read"); + + if (read_flag) + doit(argv[0], doit_read); + if (mmap_flag) + doit(argv[0], doit_mmap); + + return 0; +} diff --git a/src/tests/mmap-shared-write.c b/src/tests/mmap-shared-write.c new file mode 100644 index 0000000..0117d6b --- /dev/null +++ b/src/tests/mmap-shared-write.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +doit (const char *filename) +{ + int fd; + size_t sz = getpagesize (); + void *v; + + fd = open (filename, O_RDWR | O_CREAT, 0600); + if (fd < 0) + err (1, "open %s", filename); + if (ftruncate (fd, sz) < 0) + err (1, "ftruncate %s", filename); + v = mmap (NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (v == (void *)MAP_FAILED) + err (1, "mmap %s", filename); + + memset (v, 'z', sz); + + msync (v, sz, MS_SYNC); + + if (close (fd) < 0) + err (1, "close %s", filename); + return 0; +} + +static void +usage(void) +{ + errx (1, "usage: [filename]"); +} + +int +main (int argc, char **argv) +{ + const char *filename = "foo"; + + + if (argc != 1 && argc != 2) + usage (); + + if (argc == 2) + filename = argv[1]; + + return doit (filename); +} diff --git a/src/tests/mmap-vs-read.c b/src/tests/mmap-vs-read.c new file mode 100644 index 0000000..d491b0f --- /dev/null +++ b/src/tests/mmap-vs-read.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int debug = 0; + +static void +generate_file (const char *filename, int randomp, size_t sz) +{ + int fd; + char *buf; + int i; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + + fd = open (filename, O_WRONLY | O_CREAT, 0666); + if (fd < 0) + err (1, "open %s", filename); + + for (i = 0; i < sz; ++i) + if (randomp) + buf[i] = rand(); + else + buf[0] = 0; + + if (write (fd, buf, sz) != sz) + err (1, "write"); + if (close (fd)) + err (1, "close"); + free (buf); +} + +static char * +read_file (int fd, size_t sz) +{ + char *buf; + ssize_t ret; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + ret = read (fd, buf, sz); + if (ret < 0) + err(1, "read"); + if (ret != sz) + errx(1, "short read %d < %u", (int)ret, (unsigned)sz); + return buf; +} + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static void * +mmap_file (int fd, size_t sz) +{ + void *ret; + + ret = mmap (0, sz, PROT_READ, MAP_SHARED, fd, 0); + if (ret == (void *)MAP_FAILED) + err (1, "mmap"); + return ret; +} + +static void __attribute__ ((__unused__)) +print_area (unsigned char *ptr, size_t len) +{ + while (len--) { + printf ("%x", *ptr); + ptr++; + } +} + +static int +do_test (int randomp) +{ + unsigned char *malloc_buf; + void *mmap_buf; + int fd; + const char *file = "foo"; + const size_t sz = 4 * getpagesize(); + + generate_file (file, randomp, sz); + + fd = open (file, O_RDONLY, 0); + if (fd < 0) + err (1, "open %s", file); + + mmap_buf = mmap_file (fd, sz); + malloc_buf = read_file (fd, sz); + close (fd); + unlink (file); + if (memcmp (malloc_buf, mmap_buf, sz) != 0) { + if (debug) { + printf ("type: %s\n", randomp ? "random" : "allzero"); + printf ("read: "); + print_area (malloc_buf, sz); + printf ("\nmmap: "); + print_area (mmap_buf, sz); + printf ("\n"); + } + return 1; + } + return 0; +} + +int +main (int argc, char **argv) +{ + + if (argc != 1) + debug = 1; + + srand (time(NULL)); + + if (do_test (0)) + return 1; + if (do_test (1)) + return 2; + + return 0; +} diff --git a/src/tests/mmap-vs-read2.c b/src/tests/mmap-vs-read2.c new file mode 100644 index 0000000..55e25e4 --- /dev/null +++ b/src/tests/mmap-vs-read2.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int debug = 0; + +static void +generate_file (const char *filename, int randomp, size_t sz) +{ + int fd; + char *buf; + int i; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + + fd = open (filename, O_WRONLY | O_CREAT, 0666); + if (fd < 0) + err (1, "open %s", filename); + + for (i = 0; i < sz; ++i) + if (randomp) + buf[i] = rand(); + else + buf[0] = 0; + + if (write (fd, buf, sz) != sz) + err (1, "write"); + if (close (fd)) + err (1, "close"); + free (buf); +} + +static unsigned char * +read_file (int fd, size_t sz) +{ + unsigned char *buf; + ssize_t ret; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + ret = read(fd, buf, sz); + if(ret < 0) + err(1, "read"); + if (ret != sz) + errx(1, "short read %d < %u", (int)ret, (unsigned)sz); + return buf; +} + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static void * +mmap_file (int fd, size_t sz) +{ + void *ret; + + ret = mmap (0, sz, PROT_READ, MAP_PRIVATE, fd, 0); + if (ret == (void *)MAP_FAILED) + err (1, "mmap"); + return ret; +} + +static void __attribute__ ((__unused__)) +print_area (unsigned char *ptr, size_t len) +{ + while (len--) { + printf ("%x", *ptr); + ptr++; + } +} + +static int +do_test (int randomp) +{ + unsigned char *malloc_buf; + void *mmap_buf; + int fd; + const char *file = "foo"; + const size_t sz = 3 * getpagesize() / 2; + + generate_file (file, randomp, sz); + + fd = open (file, O_RDONLY, 0); + if (fd < 0) + err (1, "open %s", file); + + mmap_buf = mmap_file (fd, sz); + malloc_buf = read_file (fd, sz); + close (fd); + unlink (file); + if (memcmp (malloc_buf, mmap_buf, sz) != 0) { + if (debug) { + printf ("type: %s\n", randomp ? "random" : "allzero"); + printf ("read: "); + print_area (malloc_buf, sz); + printf ("\nmmap: "); + print_area (mmap_buf, sz); + printf ("\n"); + } + return 1; + } + return 0; +} + +int +main (int argc, char **argv) +{ + + if (argc != 1) + debug = 1; + + srand (time(NULL)); + + if (do_test (0)) + return 1; + if (do_test (1)) + return 2; + + return 0; +} diff --git a/src/tests/mountpoint.in b/src/tests/mountpoint.in new file mode 100644 index 0000000..7213d98 --- /dev/null +++ b/src/tests/mountpoint.in @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id$ +FS=${FS:-${objdir}/../appl/fs/fs} +${FS} sa . system:anyuser all || exit 1 +${FS} mkm no-such-volume no-such-volume 2>/dev/null || exit 1 +if ls no-such-volume 2>/dev/null && touch no-such-volume/foo 2>/dev/null; then + ${FS} rmm no-such-volume; exit 1 +fi +${FS} rmm no-such-volume || exit 1 diff --git a/src/tests/parallel1 b/src/tests/parallel1 new file mode 100644 index 0000000..ec627b7 --- /dev/null +++ b/src/tests/parallel1 @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +$objdir/test-parallel1 1>&4 + diff --git a/src/tests/pine.c b/src/tests/pine.c new file mode 100644 index 0000000..f25e36a --- /dev/null +++ b/src/tests/pine.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#define LOCK "mailbox-name.lock" + +int +main(int argc, char *argv[]) +{ + int ret; + struct stat sb; + char unique[1024]; + int retrycount = 0; + + + snprintf (unique, sizeof(unique), LOCK ".%d.%d", + getpid(), (int)time(NULL)); + + ret = umask(077); + if (ret < 0) + err (1, "umask"); + + ret = open(unique, O_WRONLY|O_CREAT|O_EXCL, 0666); + if (ret < 0) + errx (1, "open"); + + close (ret); + + retry: + retrycount++; + if (retrycount > 10000000) + errx (1, "failed getting the lock"); + ret = link(unique, LOCK); + if (ret < 0) + goto retry; + + ret = stat(unique, &sb); + if (ret < 0) + errx (1, "stat"); + + if (sb.st_nlink != 2) + goto retry; + + ret = chmod (LOCK, 0666); + if (ret < 0) + errx (1, "chmod"); + + ret = unlink (LOCK); + if (ret < 0) + err (1, "unlink " LOCK); + + ret = unlink (unique); + if (ret < 0) + err (1, "unlink: %s", unique); + + return 0; +} diff --git a/src/tests/pts.pm b/src/tests/pts.pm new file mode 100644 index 0000000..715b5e1 --- /dev/null +++ b/src/tests/pts.pm @@ -0,0 +1,306 @@ +# CMUCS AFStools +# Copyright (c) 1996, Carnegie Mellon University +# All rights reserved. +# +# See CMU_copyright.ph for use and distribution information +# +#: * pts.pm - Wrappers around PTS commands (user/group maintenance) +#: * This module provides wrappers around the various PTS commands, giving +#: * them a nice perl-based interface. Someday, they might talk to the +#: * ptserver directly instead of using 'pts', but not anytime soon. +#: + +package OpenAFS::pts; +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT :afs_internal); +use OpenAFS::wrapper; +use Exporter; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&AFS_pts_createuser &AFS_pts_listmax + &AFS_pts_creategroup &AFS_pts_setmax + &AFS_pts_delete &AFS_pts_add + &AFS_pts_rename &AFS_pts_remove + &AFS_pts_examine &AFS_pts_members + &AFS_pts_chown &AFS_pts_listown + &AFS_pts_setf); + + +#: AFS_pts_createuser($user, [$id], [$cell]) +#: Create a PTS user with $user as its name. +#: If specified, use $id as the PTS id; otherwise, AFS picks one. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return the PTS id of the newly-created user. +#: +$AFS_Help{pts_createuser} = '$user, [$id], [$cell] => $uid'; +sub AFS_pts_createuser { + my($user, $id, $cell) = @_; + my(@args, $uid); + + @args = ('createuser', '-name', $user); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + push(@args, '-id', $id) if ($id); + &wrapper('pts', \@args, [[ '^User .* has id (\d+)', \$uid ]]); + $uid; +} + + +#: AFS_pts_creategroup($group, [$id], [$owner], [$cell]) +#: Create a PTS group with $group as its name. +#: If specified, use $id as the PTS id; otherwise, AFS picks one. +#: If specified, use $owner as the owner, instead of the current user. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return the PTS id of the newly-created group. +#: +$AFS_Help{pts_creategroup} = '$group, [$id], [$owner], [$cell] => $gid'; +sub AFS_pts_creategroup { + my($group, $id, $owner, $cell) = @_; + my(@args, $uid); + + @args = ('creategroup', '-name', $group); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + push(@args, '-id', $id) if ($id); + push(@args, '-owner', $owner) if ($owner); + &wrapper('pts', \@args, [[ '^group .* has id (\-\d+)', \$uid ]]); + $uid; +} + + +#: AFS_pts_delete(\@objs, [$cell]) +#: Attempt to destroy PTS objects listed in @objs. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: If multiple objects are specified and only some are destroyed, some +#: operations may be left untried. +#: +$AFS_Help{pts_delete} = '\@objs, [$cell] => Success?'; +sub AFS_pts_delete { + my($objs, $cell) = @_; + my(@args); + + @args = ('delete', '-nameorid', @$objs); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args); + 1; +} + + +#: AFS_pts_rename($old, $new, [$cell]) +#: Rename the PTS object $old to have the name $new. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{pts_rename} = '$old, $new, [$cell] => Success?'; +sub AFS_pts_rename { + my($old, $new, $cell) = @_; + my(@args); + + @args = ('rename', '-oldname', $old, '-newname', $new); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args); + 1; +} + + +#: AFS_pts_examine($obj, [$cell]) +#: Examine the PTS object $obj, and return information about it. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return an associative array with some or all of the following: +#: - name Name of this object +#: - id ID of this object +#: - owner Name or ID of owner +#: - creator Name or ID of creator +#: - mem_count Number of members (group) or memberships (user) +#: - flags Privacy/access flags (as a string) +#: - group_quota Remaining group quota +#: +$AFS_Help{pts_examine} = '$obj, [$cell] => %info'; +sub AFS_pts_examine { + my($obj, $cell) = @_; + my(@args); + + @args = ('examine', '-nameorid', $obj); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args, + [[ '^Name\: (.*)\, id\: ([\-0-9]+)\, owner\: (.*)\, creator\: (.*)\,$', #', + 'name', 'id', 'owner', 'creator' ], + [ '^ membership\: (\d+)\, flags\: (.....)\, group quota\: (\d+)\.$', #', + 'mem_count', 'flags', 'group_quota' ] + ]); +} + + +#: AFS_pts_chown($obj, $owner, [$cell]) +#: Change the owner of the PTS object $obj to be $owner. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{pts_chown} = '$obj, $owner, [$cell] => Success?'; +sub AFS_pts_chown { + my($obj, $owner, $cell) = @_; + my(@args); + + @args = ('chown', '-name', $obj, '-owner', $owner); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args); + 1; +} + + +#: AFS_pts_setf($obj, [$access], [$gquota], [$cell]) +#: Change the access flags and/or group quota for the PTS object $obj. +#: If specified, $access specifies the new access flags in the standard 'SOMAR' +#: format; individual flags may be specified as '.' to keep the current value. +#: If specified, $gquota specifies the new group quota. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{pts_setf} = '$obj, [$access], [$gquota], [$cell] => Success?'; +sub AFS_pts_setf { + my($obj, $access, $gquota, $cell) = @_; + my(%result, @args); + + @args = ('setfields', '-nameorid', $obj); + push(@args, '-groupquota', $gquota) if ($gquota ne ''); + if ($access) { + my(@old, @new, $i); + # Ensure access is 5 characters + if (length($access) < 5) { + $access .= ('.' x (5 - length($access))); + } elsif (length($access) > 5) { + substr($access, 5) = ''; + } + + %result = &AFS_pts_examine($obj, $cell); + + @old = split(//, $result{'flags'}); + @new = split(//, $access); + foreach $i (0 .. 4) { + $new[$i] = $old[$i] if ($new[$i] eq '.'); + } + $access = join('', @new); + if ($access ne $result{'flags'}) { + push(@args, '-access', $access); + } + } + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args); + 1; +} + + +#: AFS_pts_listmax([$cell]) +#: Fetch the maximum assigned group and user ID. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, returns (maxuid, maxgid) +#: +$AFS_Help{pts_listmax} = '[$cell] => ($maxuid, $maxgid)'; +sub AFS_pts_listmax { + my($cell) = @_; + my(@args, $uid, $gid); + + @args = ('listmax'); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args, + [[ '^Max user id is (\d+) and max group id is (\-\d+).', + \$uid, \$gid ]]); + ($uid, $gid); +} + + +#: AFS_pts_setmax([$maxuser], [$maxgroup], [$cell]) +#: Set the maximum assigned group and/or user ID. +#: If specified, $maxuser is the new maximum user ID +#: If specified, $maxgroup is the new maximum group ID +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{pts_setmax} = '[$maxuser], [$maxgroup], [$cell] => Success?'; +sub AFS_pts_setmax { + my($maxuser, $maxgroup, $cell) = @_; + my(@args); + + @args = ('setmax'); + push(@args, '-group', $maxgroup) if ($maxgroup); + push(@args, '-user', $maxuser) if ($maxuser); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args); + 1; +} + +#: AFS_pts_add(\@users, \@groups, [$cell]) +#: Add users specified in @users to groups specified in @groups. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: If multiple users and/or groups are specified and only some memberships +#: are added, some operations may be left untried. +#: +$AFS_Help{pts_add} = '\@users, \@groups, [$cell] => Success?'; +sub AFS_pts_add { + my($users, $groups, $cell) = @_; + my(@args); + + @args = ('adduser', '-user', @$users, '-group', @$groups); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args); + 1; +} + + +#: AFS_pts_remove(\@users, \@groups, [$cell]) +#: Remove users specified in @users from groups specified in @groups. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return 1. +#: If multiple users and/or groups are specified and only some memberships +#: are removed, some operations may be left untried. +#: +$AFS_Help{pts_remove} = '\@users, \@groups, [$cell] => Success?'; +sub AFS_pts_remove { + my($users, $groups, $cell) = @_; + my(@args); + + @args = ('removeuser', '-user', @$users, '-group', @$groups); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args); + 1; +} + + +#: AFS_pts_members($obj, [$cell]) +#: If $obj specifies a group, retrieve a list of its members. +#: If $obj specifies a user, retrieve a list of groups to which it belongs. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return the resulting list. +#: +$AFS_Help{pts_members} = '$obj, [$cell] => @members'; +sub AFS_pts_members { + my($obj, $cell) = @_; + my(@args, @grouplist); + + @args = ('membership', '-nameorid', $obj); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args, [[ '^ (.*)', \@grouplist ]]); + @grouplist; +} + + +#: AFS_pts_listown($owner, [$cell]) +#: Retrieve a list of PTS groups owned by the PTS object $obj. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return the resulting list. +#: +$AFS_Help{pts_listown} = '$owner, [$cell] => @owned'; +sub AFS_pts_listown { + my($owner, $cell) = @_; + my(@args, @grouplist); + + @args = ('listowned', '-nameorid', $owner); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('pts', \@args, [[ '^ (.*)', \@grouplist ]]); + @grouplist; +} + + +1; diff --git a/src/tests/ptsadduser.pl b/src/tests/ptsadduser.pl new file mode 100755 index 0000000..5218bff --- /dev/null +++ b/src/tests/ptsadduser.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +&AFS_Init(); + +&AFS_pts_add([testuser1],[testgroup1],); + +exit(0); + + + diff --git a/src/tests/ptschown.pl b/src/tests/ptschown.pl new file mode 100755 index 0000000..812eac7 --- /dev/null +++ b/src/tests/ptschown.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +&AFS_Init(); + +&AFS_pts_chown(testgroup1,testuser1,); + +exit(0); + + + diff --git a/src/tests/ptscreategroup.pl b/src/tests/ptscreategroup.pl new file mode 100755 index 0000000..8a904c0 --- /dev/null +++ b/src/tests/ptscreategroup.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +&AFS_Init(); + +&AFS_pts_creategroup(testgroup1,,); + +exit(0); + + + diff --git a/src/tests/ptscreateuser.pl b/src/tests/ptscreateuser.pl new file mode 100755 index 0000000..2286fc8 --- /dev/null +++ b/src/tests/ptscreateuser.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +&AFS_Init(); + +&AFS_pts_createuser(testuser1,,); + +exit(0); + + + diff --git a/src/tests/ptsdeletegroup.pl b/src/tests/ptsdeletegroup.pl new file mode 100755 index 0000000..11dbbc0 --- /dev/null +++ b/src/tests/ptsdeletegroup.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +&AFS_Init(); + +&AFS_pts_delete([testgroup1],); + +exit(0); + + + diff --git a/src/tests/ptsdeleteuser.pl b/src/tests/ptsdeleteuser.pl new file mode 100755 index 0000000..f4f2d07 --- /dev/null +++ b/src/tests/ptsdeleteuser.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +&AFS_Init(); + +&AFS_pts_delete([testuser1],); + +exit(0); + + + diff --git a/src/tests/ptsexaminegroup.pl b/src/tests/ptsexaminegroup.pl new file mode 100755 index 0000000..4297a53 --- /dev/null +++ b/src/tests/ptsexaminegroup.pl @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my (%info); +&AFS_Init(); + +%info = &AFS_pts_examine(testgroup1,); +if ($info{'creator'} ne "admin") { + exit(1); +} +if ($info{'mem_count'} != 1) { + exit(1); +} +if ($info{'owner'} ne "testuser1") { + exit(1); +} + +exit(0); + + + diff --git a/src/tests/ptsexamineuser.pl b/src/tests/ptsexamineuser.pl new file mode 100755 index 0000000..c869fed --- /dev/null +++ b/src/tests/ptsexamineuser.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my (%info); +&AFS_Init(); + +%info = &AFS_pts_examine(testuser1,); +if ($info{'creator'} ne "admin") { + exit(1); +} +if ($info{'mem_count'} != 1) { + exit(1); +} + +exit(0); + + + diff --git a/src/tests/ptslistmax.pl b/src/tests/ptslistmax.pl new file mode 100755 index 0000000..dc42ed7 --- /dev/null +++ b/src/tests/ptslistmax.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my (@info); +&AFS_Init(); + +@info = &AFS_pts_listmax(); +if ($info[0] != 100) { + exit(1); +} +if ($info[1] != -300) { + exit(1); +} + +exit(0); + + + diff --git a/src/tests/ptslistown.pl b/src/tests/ptslistown.pl new file mode 100755 index 0000000..0133f9c --- /dev/null +++ b/src/tests/ptslistown.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my (@owned, $group); +&AFS_Init(); + +@owned = &AFS_pts_listown(testuser1,); +while ($group = pop(@owned)) { + if ($group ne "testgroup1") { + exit(1); + } +} + +exit(0); + + + diff --git a/src/tests/ptsmembersgroup.pl b/src/tests/ptsmembersgroup.pl new file mode 100755 index 0000000..ecff23c --- /dev/null +++ b/src/tests/ptsmembersgroup.pl @@ -0,0 +1,35 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my (@membership, $group); +&AFS_Init(); + +@membership = &AFS_pts_members(testgroup1,); +while ($group = pop(@membership)) { + if ($group ne "testuser1") { + exit(1); + } +} +&AFS_pts_add([admin],[testgroup1],); +@membership = &AFS_pts_members(testgroup1,); +while ($group = pop(@membership)) { + if ($group eq "testuser1") { + } else { + if ($group eq "admin") { + } else { + exit(1); + } + } +} +&AFS_pts_remove([admin],["testgroup1"],); + +exit(0); + + + diff --git a/src/tests/ptsmembersuser.pl b/src/tests/ptsmembersuser.pl new file mode 100755 index 0000000..4172b4e --- /dev/null +++ b/src/tests/ptsmembersuser.pl @@ -0,0 +1,35 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my (@membership, $group); +&AFS_Init(); + +@membership = &AFS_pts_members(testuser1,); +while ($group = pop(@membership)) { + if ($group ne "testgroup1") { + exit(1); + } +} +&AFS_pts_add([testuser1],["system:administrators"],); +@membership = &AFS_pts_members(testuser1,); +while ($group = pop(@membership)) { + if ($group eq "testgroup1") { + } else { + if ($group eq "system:administrators") { + } else { + exit(1); + } + } +} +&AFS_pts_remove([testuser1],["system:administrators"],); + +exit(0); + + + diff --git a/src/tests/ptsremove.pl b/src/tests/ptsremove.pl new file mode 100755 index 0000000..67c165a --- /dev/null +++ b/src/tests/ptsremove.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +&AFS_Init(); + +&AFS_pts_remove([testuser1],[testgroup1],); + +exit(0); + + + diff --git a/src/tests/ptssetf.pl b/src/tests/ptssetf.pl new file mode 100755 index 0000000..08c4011 --- /dev/null +++ b/src/tests/ptssetf.pl @@ -0,0 +1,28 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my (%info); +&AFS_Init(); + +&AFS_pts_setf(testuser1,"S-M--",30,); +%info = &AFS_pts_examine(testuser1,); +if ($info{'creator'} ne "admin") { + exit(1); +} +if ($info{'flags'} ne "S-M--") { + exit(1); +} +if ($info{'group_quota'} != 30) { + exit(1); +} + +exit(0); + + + diff --git a/src/tests/ptssetmax.pl b/src/tests/ptssetmax.pl new file mode 100755 index 0000000..ab4c456 --- /dev/null +++ b/src/tests/ptssetmax.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +&AFS_Init(); + +&AFS_pts_setmax(100,-300,); + +exit(0); + + + diff --git a/src/tests/read-vs-mmap.c b/src/tests/read-vs-mmap.c new file mode 100644 index 0000000..4e2cd43 --- /dev/null +++ b/src/tests/read-vs-mmap.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int debug = 0; + +static void +generate_file (const char *filename, int randomp, size_t sz) +{ + int fd; + char *buf; + int i; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + + fd = open (filename, O_WRONLY | O_CREAT, 0666); + if (fd < 0) + err (1, "open %s", filename); + + for (i = 0; i < sz; ++i) + if (randomp) + buf[i] = rand(); + else + buf[0] = 0; + + if (write (fd, buf, sz) != sz) + err (1, "write"); + if (close (fd)) + err (1, "close"); + free (buf); +} + +static unsigned char * +read_file (int fd, size_t sz) +{ + unsigned char *buf; + ssize_t ret; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + ret = read(fd, buf, sz); + if(ret < 0) + err(1, "read"); + if(ret != sz) + errx(1, "short read %d < %u", (int)ret, (unsigned)sz); + return buf; +} + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static void * +mmap_file (int fd, size_t sz) +{ + void *ret; + + ret = mmap (0, sz, PROT_READ, MAP_PRIVATE, fd, 0); + if (ret == (void *)MAP_FAILED) + err (1, "mmap"); + return ret; +} + +static void __attribute__ ((__unused__)) +print_area (unsigned char *ptr, size_t len) +{ + while (len--) { + printf ("%x", *ptr); + ptr++; + } +} + +static int +do_test (int randomp) +{ + unsigned char *malloc_buf; + void *mmap_buf; + int fd; + const char *file = "foo"; + const size_t sz = 16384; + + generate_file (file, randomp, sz); + + fd = open (file, O_RDONLY, 0); + if (fd < 0) + err (1, "open %s", file); + + malloc_buf = read_file (fd, sz); + mmap_buf = mmap_file (fd, sz); + close (fd); + unlink (file); + if (memcmp (malloc_buf, mmap_buf, sz) != 0) { + if (debug) { + printf ("type: %s\n", randomp ? "random" : "allzero"); + printf ("read: "); + print_area (malloc_buf, sz); + printf ("\nmmap: "); + print_area (mmap_buf, sz); + printf ("\n"); + } + return 1; + } + return 0; +} + +int +main (int argc, char **argv) +{ + if (argc != 1) + debug = 1; + + srand (time(NULL)); + + if (do_test (0)) + return 1; + if (do_test (1)) + return 2; + + return 0; +} diff --git a/src/tests/read-vs-mmap2.c b/src/tests/read-vs-mmap2.c new file mode 100644 index 0000000..f2dcd3e --- /dev/null +++ b/src/tests/read-vs-mmap2.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static void +generate_random_file (const char *filename, size_t sz) +{ + int fd; + char *buf; + int i; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + + fd = open (filename, O_WRONLY | O_CREAT, 0666); + if (fd < 0) + err (1, "open %s", filename); + + for (i = 0; i < sz; ++i) + buf[i] = rand(); + + if (write (fd, buf, sz) != sz) + err (1, "write"); + if (close (fd)) + err (1, "close"); + free (buf); +} + +static char * +read_file (int fd, size_t sz) +{ + char *buf; + ssize_t ret; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + ret = read(fd, buf, sz); + if(ret < 0) + err(1, "read"); + if(ret != sz) + errx(1, "short read %d < %u", (int)ret, (unsigned)sz); + return buf; +} + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static void * +mmap_file (int fd, size_t sz) +{ + void *ret; + + ret = mmap (0, sz, PROT_READ, MAP_SHARED, fd, 0); + if (ret == (void *)MAP_FAILED) + err (1, "mmap"); + return ret; +} + +int +main (int argc, char **argv) +{ + const char *file = "foo"; + const size_t sz = 16384; + char *malloc_buf; + void *mmap_buf; + int fd; + + srand (time(NULL)); + + generate_random_file (file, sz); + + fd = open (file, O_RDONLY, 0); + if (fd < 0) + err (1, "open %s", file); + + malloc_buf = read_file (fd, sz); + mmap_buf = mmap_file (fd, sz); + close (fd); + unlink (file); + if (memcmp (malloc_buf, mmap_buf, sz) != 0) + return 1; + return 0; +} diff --git a/src/tests/read-write.c b/src/tests/read-write.c new file mode 100644 index 0000000..22ecf9d --- /dev/null +++ b/src/tests/read-write.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static char * +write_random_file (int fd, size_t sz) +{ + char *buf; + int i; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + + for (i = 0; i < sz; ++i) + buf[i] = rand(); + + if (write (fd, buf, sz) != sz) + err (1, "write"); + + return buf; +} + +static void +write_null_file (int fd, size_t sz) +{ + char *buf; + int i; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + + for (i = 0; i < sz; ++i) + buf[i] = 0; + + if (write (fd, buf, sz) != sz) + err (1, "write"); + + free (buf); +} + +static char * +read_file (int fd, size_t sz) +{ + char *buf; + ssize_t ret; + + buf = malloc (sz); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + ret = read(fd, buf, sz); + if(ret < 0) + err (1, "read"); + else if(ret == 0) + errx(1, "EOF on read"); + return buf; +} + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +int +main (int argc, char **argv) +{ + const char *file = "foo"; + const size_t sz = 16384; + char *random_buf; + char *read_buf1; + char *read_buf2; + int fd; + + + srand (time(NULL)); + + fd = open (file, O_RDWR | O_CREAT, 0); + if (fd < 0) + err (1, "open %s", file); + + if (lseek(fd, 0, SEEK_SET) < 0) + err (1, "lseek"); + write_null_file(fd, sz); + if (lseek(fd, 0, SEEK_SET) < 0) + err (1, "lseek"); + read_buf1 = read_file (fd, sz); + if (lseek(fd, 0, SEEK_SET) < 0) + err (1, "lseek"); + random_buf = write_random_file(fd, sz); + if (lseek(fd, 0, SEEK_SET) < 0) + err (1, "lseek"); + read_buf2 = read_file (fd, sz); + + close (fd); + unlink (file); + if (memcmp (random_buf, read_buf2, sz) != 0) + return 1; + return 0; +} diff --git a/src/tests/readdir-vs-lstat.c b/src/tests/readdir-vs-lstat.c new file mode 100644 index 0000000..fb07d2f --- /dev/null +++ b/src/tests/readdir-vs-lstat.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static int +verify_inodes (const char *dirname) +{ + DIR *d; + struct dirent *dp; + + if (chdir (dirname) < 0) + err (1, "chdir %s", dirname); + + d = opendir ("."); + if (d == NULL) + err (1, "opendir %s", dirname); + while ((dp = readdir (d)) != NULL) { + struct stat sb; + + if (lstat (dp->d_name, &sb) < 0) { + if (errno == EACCES) + continue; + err (1, "lstat %s", dp->d_name); + } + if (dp->d_ino != sb.st_ino) + errx (1, "%s: inode %u != %u", dp->d_name, + (unsigned)dp->d_ino, (unsigned)sb.st_ino); + } + closedir (d); + return 0; +} + +static void +usage (int ret) +{ + fprintf (stderr, "%s [directory]\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *name = "."; + + + if (argc > 2) + usage (1); + + if (argc > 1) + name = argv[1]; + + return verify_inodes (name); +} diff --git a/src/tests/readfile-wo-create b/src/tests/readfile-wo-create new file mode 100755 index 0000000..209fd34 --- /dev/null +++ b/src/tests/readfile-wo-create @@ -0,0 +1,3 @@ +#!/bin/sh +FOO=`cat $AFSROOT/stacken.kth.se/ftp/pub/arla/tests/used-by-arla-check` +test "X"$FOO = "Xfoo" || exit 1 diff --git a/src/tests/reauth.pl b/src/tests/reauth.pl new file mode 100755 index 0000000..1b58555 --- /dev/null +++ b/src/tests/reauth.pl @@ -0,0 +1,12 @@ +#!/usr/bin/env perl -w +use Term::ReadLine; +use strict; +use OpenAFS::ConfigUtils; +use OpenAFS::Dirpath; +use OpenAFS::OS; +use OpenAFS::Auth; +use Getopt::Long; +use vars qw($admin $server $cellname $cachesize $part + $requirements_met $shutdown_needed $csdb); + +&OpenAFS::Auth::authadmin(); diff --git a/src/tests/rename-under-feet.c b/src/tests/rename-under-feet.c new file mode 100644 index 0000000..83cb187 --- /dev/null +++ b/src/tests/rename-under-feet.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define RETSIGTYPE void + +static void +emkdir (const char *path, mode_t mode) +{ + int ret = mkdir (path, mode); + if (ret < 0) + err (1, "mkdir %s", path); +} + +static pid_t child_pid; + +static sig_atomic_t term_sig = 0; + +static RETSIGTYPE +child_sigterm (int signo) +{ + term_sig = 1; +} + +static int +child_chdir (const char *path) +{ + int ret; + int pfd[2]; + + ret = pipe (pfd); + if (ret < 0) + err (1, "pipe"); + + child_pid = fork (); + if (child_pid < 0) + err (1, "fork"); + if (child_pid != 0) { + close (pfd[1]); + return pfd[0]; + } else { + char buf[256]; + struct sigaction sa; + FILE *fp; + + sa.sa_handler = child_sigterm; + sigfillset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGTERM, &sa, NULL); + + close (pfd[0]); + ret = chdir (path); + if (ret < 0) + err (1, "chdir %s", path); + ret = write (pfd[1], "", 1); + if (ret != 1) + err (1, "write"); + while (!term_sig) + pause (); +#if 0 + if(getcwd (buf, sizeof(buf)) == NULL) + err (1, "getcwd"); +#endif + fp = fdopen (4, "w"); + if (fp != NULL) + fprintf (fp, "child: cwd = %s\n", buf); + exit (0); + } +} + +static void +kill_child (void) +{ + kill (child_pid, SIGTERM); +} + +int +main (int argc, char **argv) +{ + struct stat sb; + int ret; + int fd; + char buf[1]; + int status; + + + emkdir ("one", 0777); + emkdir ("two", 0777); + emkdir ("one/a", 0777); + + fd = child_chdir ("one/a"); + atexit (kill_child); + ret = read (fd, buf, 1); + if (ret < 0) + err(1, "read"); + if (ret == 0) + errx(1, "EOF on read"); + + ret = rename ("one/a", "two/a"); + if (ret < 0) + err (1, "rename one/a two"); + ret = lstat ("two/a", &sb); + if (ret < 0) + err (1, "lstat two/a"); + ret = lstat ("one/a", &sb); + if (ret != -1 || errno != ENOENT) + errx (1, "one/a still exists"); + kill_child (); + waitpid (child_pid, &status, 0); + ret = lstat ("one/a", &sb); + if (ret != -1 || errno != ENOENT) + errx (1, "one/a still exists after child"); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + rmdir ("one/a"); + rmdir ("two/a"); + rmdir ("one"); + rmdir ("two"); + return 0; + } else + return 1; +} diff --git a/src/tests/rename1 b/src/tests/rename1 new file mode 100755 index 0000000..d899ae8 --- /dev/null +++ b/src/tests/rename1 @@ -0,0 +1,7 @@ +#!/bin/sh +# $Id$ +touch foo || exit 1 +mv foo bar || exit 1 +test -f foo && exit 1 +test -f bar || exit 1 +rm bar || exit 1 diff --git a/src/tests/rename2 b/src/tests/rename2 new file mode 100644 index 0000000..d3fa0cc --- /dev/null +++ b/src/tests/rename2 @@ -0,0 +1,7 @@ +#!/bin/sh +# $Id$ +touch foo bar || exit 1 +mv foo bar || exit 1 +test -f foo && exit 1 +test -f bar || exit 1 +rm bar || exit 1 diff --git a/src/tests/rename3 b/src/tests/rename3 new file mode 100755 index 0000000..44481f2 --- /dev/null +++ b/src/tests/rename3 @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id$ +echo foo > foo || exit 1 +sed 's/foo/bar/' foo > bar || exit 1 +rm foo || exit 1 +test -f foo && exit 1 +mv bar foo || exit 1 +test -f bar && exit 1 +test -f foo || exit 1 diff --git a/src/tests/rename4 b/src/tests/rename4 new file mode 100755 index 0000000..6948b60 --- /dev/null +++ b/src/tests/rename4 @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id$ +mkdir old_parent new_parent old_parent/victim || exit 1 +mv old_parent/victim new_parent || exit 1 +test -d old_parent || exit 1 +test -d new_parent || exit 1 +test -d old_parent/victim && exit 1 +test -d new_parent/victim || exit 1 +rmdir new_parent/victim new_parent old_parent diff --git a/src/tests/rename5.c b/src/tests/rename5.c new file mode 100644 index 0000000..92441cf --- /dev/null +++ b/src/tests/rename5.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include + +static void +emkdir (const char *path, mode_t mode) +{ + int ret; + + ret = mkdir (path, mode); + if (ret < 0) + err (1, "mkdir %s", path); +} + +static void +elstat (const char *path, struct stat *sb) +{ + int ret; + + ret = lstat (path, sb); + if (ret < 0) + err (1, "lstat %s", path); +} + +static void +check_inum (const struct stat *sb1, const struct stat *sb2) +{ + if (sb1->st_ino != sb2->st_ino) + errx (1, "wrong inode-number %u != %u", + (unsigned)sb1->st_ino, (unsigned)sb2->st_ino); +} + +int +main(int argc, char **argv) +{ + int ret; + struct stat old_sb, new_sb, dot_sb; + + emkdir ("old_parent", 0777); + emkdir ("new_parent", 0777); + emkdir ("old_parent/victim", 0777); + + elstat ("old_parent", &old_sb); + elstat ("new_parent", &new_sb); + elstat ("old_parent/victim/..", &dot_sb); + check_inum (&old_sb, &dot_sb); + + ret = rename("old_parent/victim", "new_parent/victim"); + if (ret < 0) + err (1, "rename old_parent/victim new_parent/victim"); + + elstat ("new_parent/victim/..", &dot_sb); + + check_inum (&new_sb, &dot_sb); + + return 0; +} diff --git a/src/tests/rename6.c b/src/tests/rename6.c new file mode 100644 index 0000000..3b62387 --- /dev/null +++ b/src/tests/rename6.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include + +int +main(int argc, char **argv) +{ + int ret; + int fd; + struct stat old_sb, new_sb, dot_sb; + + fd = open("foo", O_RDWR|O_CREAT|O_TRUNC, 0644); + if (fd < 0) + err (1, "open1"); + ret = close (fd); + if (ret < 0) + err (1, "close1"); + + ret = rename("foo", "../../service/foo"); + if (ret == 0) + err (1, "rename didn't fail"); + + unlink("foo"); + return 0; +} diff --git a/src/tests/rewrite-emacs b/src/tests/rewrite-emacs new file mode 100755 index 0000000..80b021a --- /dev/null +++ b/src/tests/rewrite-emacs @@ -0,0 +1,10 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +emacsver=20.7 +gzip -dc ${AFSROOT}/stacken.kth.se/ftp/pub/gnu/emacs/emacs-${emacsver}.tar.gz | +tar vxf - >&4 2>&1 || exit 1 +find emacs-${emacsver} -size 0 -print | xargs rm || exit 1 +find emacs-${emacsver} -print | xargs chmod u+w || exit 1 +$objdir/truncate-files emacs-${emacsver} || exit 1 +exit 0 diff --git a/src/tests/rm-rf.c b/src/tests/rm-rf.c new file mode 100644 index 0000000..c8ce4e4 --- /dev/null +++ b/src/tests/rm-rf.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static void +kill_one (const char *filename); + +static void +kill_dir (const char *dirname); + +static void +do_dir (const char *dirname); + +static void +kill_one (const char *filename) +{ + int ret; + + ret = unlink (filename); + if (ret < 0) { + if (errno == EISDIR || errno == EPERM) + do_dir (filename); + else + err (1, "unlink %s", filename); + } +} + +static void +do_dir (const char *dirname) +{ + int ret; + + ret = fs_rmmount (dirname); + if (ret == 0) + return; + + ret = chdir (dirname); + if (ret < 0) + err (1, "chdir %s", dirname); + kill_dir (dirname); + ret = chdir (".."); + if (ret < 0) + err (1, "chdir .."); + ret = rmdir (dirname); + if (ret < 0) + err (1, "rmdir %s", dirname); +} + +static void +kill_dir (const char *dirname) +{ + DIR *dir; + struct dirent *dp; + + dir = opendir ("."); + if (dir == NULL) + err (1, "opendir %s", dirname); + while ((dp = readdir (dir)) != NULL) { + if (strcmp (dp->d_name, ".") == 0 + || strcmp (dp->d_name, "..") == 0) + continue; + + kill_one (dp->d_name); + } + closedir(dir); +} + +int +main(int argc, char **argv) +{ + + if (argc < 2) + errx (1, "usage: %s directory [...]", argv[0]); + while (argc >= 2) { + do_dir (argv[1]); + argc--; + argv++; + } + return 0; +} diff --git a/src/tests/run-fsx b/src/tests/run-fsx new file mode 100755 index 0000000..80febe9 --- /dev/null +++ b/src/tests/run-fsx @@ -0,0 +1,7 @@ +#!/bin/sh +# $Id$ +FS=${FS:-${objdir}/../appl/fs/fs} + +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +${objdir}/fsx -N 25000 -RW -c 1 fsxtmp + diff --git a/src/tests/run-rcs b/src/tests/run-rcs new file mode 100755 index 0000000..10000f6 --- /dev/null +++ b/src/tests/run-rcs @@ -0,0 +1,11 @@ +#!/bin/sh +echo row1 > testfile +echo log1 | ci -u testfile +co -l testfile +echo row2 >> testfile +echo log2 | ci -u testfile +co -l testfile +echo row3 >> testfile +echo log3 | ci -u testfile +wc -l testfile | grep '3 testfile' || exit 1 + diff --git a/src/tests/run-tests.in b/src/tests/run-tests.in new file mode 100755 index 0000000..3520979 --- /dev/null +++ b/src/tests/run-tests.in @@ -0,0 +1,415 @@ +#!/bin/sh +# +# $Id$ +# +srcdir=@srcdir@ +objdir=`pwd` +SHELL=/bin/sh +VERSION=@VERSION@ +PACKAGE=@PACKAGE@ +host=@host@ +RUNAS=nobody +FS=/usr/local/bin/fs +export FS + +AFSROOT=${AFSROOT-/afs} +export AFSROOT + +BASIC_TESTS="creat1 \ + mkdir1 \ + mkdir2 \ + symlink \ + hardlink1 \ + hardlink4 \ + hardlink2 \ + hardlink5 \ + touch1 \ + write1 \ + write3 \ + rename1 \ + hardlink3 \ + write2 \ + append1 \ + rename2 \ + rename4 \ + rename6 \ + rename-under-feet \ + large-filename \ + fchmod \ + utime-file \ + utime-dir \ + mkdir3" + +MTPT_TESTS="mkm-rmm \ + mountpoint" + +ACL_TESTS="acladduser.pl \ + acladdgroup.pl \ + acladdrights.pl \ + acladdnegrights.pl \ + aclclearnegrights.pl \ + aclremoveuser.pl \ + aclremovegroup.pl \ + aclcopy.pl" + +EXEC_TESTS="exec \ + hello-world \ + build-openafs" + +MMAP_TESTS="append-over-page \ + mmap-shared-write \ + mmap-vs-read2 \ + mmap-vs-read \ + read-vs-mmap2 \ + read-vs-mmap" + +FS_TESTS="strange-characters \ + pine \ + parallel1 \ + write-large" + +AFS_TESTS="write-ro \ + too-many-files \ + setpag \ + setgroups" + +RMT_TESTS="extcopyin \ + extcopyout" + +ABUSE_TESTS="read-write \ + create-remove-files \ + run-fsx" + +PTS_TESTS="ptscreateuser.pl \ + ptscreategroup.pl \ + ptsadduser.pl \ + ptschown.pl \ + ptsmembersuser.pl \ + ptsmembersgroup.pl \ + ptsexamineuser.pl \ + ptsexaminegroup.pl \ + ptsremove.pl \ + ptslistown.pl \ + ptssetmax.pl \ + ptslistmax.pl \ + ptssetf.pl \ + ptsdeletegroup.pl \ + ptsdeleteuser.pl" + +VOS_TESTS="voscreate.pl \ + vosmove.pl \ + vosaddsite.pl \ + vosrelease.pl \ + vosremsite.pl \ + vosremove.pl \ + vosdelentry.pl \ + vossyncvldb.pl \ + voszap.pl \ + vossyncserv.pl \ + voslock.pl \ + vosunlock.pl \ + vosunlockall.pl \ + vosrename.pl \ + voslistvol.pl \ + voslistvldb.pl \ + vospartinfo.pl \ + voslistpart.pl \ + vosbackup.pl \ + vosexamine.pl \ + vosdump.pl \ + vosrestore.pl" + +BOS_TESTS="bosaddhost.pl \ + boslisthosts.pl \ + bosremovehost.pl \ + bosadduser.pl \ + boslistusers.pl \ + bosremoveuser.pl \ + bosinstall.pl \ + bosexec.pl \ + boscreate.pl \ + bosdeleterunning.pl \ + bosstatus.pl \ + bosstop.pl \ + bosrestartstopped.pl \ + bosstart.pl \ + bosshutdown.pl \ + bosdelete.pl \ + bosaddkey.pl \ + boslistkeys.pl \ + bosremovekey.pl \ + bossalvagevolume.pl \ + bossalvagepart.pl \ + bossalvageserver.pl" + +REG_TESTS="fcachesize-write-file \ + fcachesize-read-file" + +ALL_TESTS="creat1 \ + mkdir1 \ + mkdir2 \ + symlink \ + hardlink1 \ + hardlink4 \ + hardlink2 \ + hardlink5 \ + touch1 \ + write1 \ + write3 \ + rename1 \ + hardlink3 \ + write2 \ + append1 \ + rename2 \ + rename4 \ + rename6 \ + rename-under-feet \ + large-filename \ + fchmod \ + utime-file \ + utime-dir \ + mkdir3 \ + mkm-rmm \ + mountpoint \ + acladduser.pl \ + acladdgroup.pl \ + acladdrights.pl \ + acladdnegrights.pl \ + aclclearnegrights.pl \ + aclremoveuser.pl \ + aclremovegroup.pl \ + aclcopy.pl \ + exec \ + hello-world \ + build-openafs \ + append-over-page \ + mmap-shared-write \ + mmap-vs-read2 \ + mmap-vs-read \ + read-vs-mmap2 \ + read-vs-mmap \ + strange-characters \ + pine \ + parallel1 \ + write-large \ + write-ro \ + too-many-files \ + setpag \ + setgroups \ + extcopyin \ + extcopyout \ + read-write \ + create-remove-files \ + run-fsx \ + ptscreateuser.pl \ + ptscreategroup.pl \ + ptsadduser.pl \ + ptschown.pl \ + ptsmembersuser.pl \ + ptsmembersgroup.pl \ + ptsexamineuser.pl \ + ptsexaminegroup.pl \ + ptsremove.pl \ + ptslistown.pl \ + ptssetmax.pl \ + ptslistmax.pl \ + ptssetf.pl \ + ptsdeletegroup.pl \ + ptsdeleteuser.pl \ + voscreate.pl \ + vosmove.pl \ + vosaddsite.pl \ + vosrelease.pl \ + vosremsite.pl \ + vosremove.pl \ + vosdelentry.pl \ + vossyncvldb.pl \ + voszap.pl \ + vossyncserv.pl \ + voslock.pl \ + vosunlock.pl \ + vosunlockall.pl \ + vosrename.pl \ + voslistvol.pl \ + voslistvldb.pl \ + vospartinfo.pl \ + voslistpart.pl \ + vosbackup.pl \ + vosexamine.pl \ + vosdump.pl \ + vosrestore.pl \ + bosaddhost.pl \ + boslisthosts.pl \ + bosremovehost.pl \ + bosadduser.pl \ + boslistusers.pl \ + bosremoveuser.pl \ + bosinstall.pl \ + bosexec.pl \ + boscreate.pl \ + bosdeleterunning.pl \ + bosstatus.pl \ + bosstop.pl \ + bosrestartstopped.pl \ + bosstart.pl \ + bosshutdown.pl \ + bosdelete.pl \ + bosaddkey.pl \ + boslistkeys.pl \ + bosremovekey.pl \ + bossalvagevolume.pl \ + bossalvagepart.pl \ + bossalvageserver.pl \ + fcachesize-write-file \ + fcachesize-read-file" + +TESTS="$ALL_TESTS" +TEST_MODE="all" + +linebreak=":-------------------------------;" + +PARALLELL= +FAST= +LARGE= +PRINT_CACHESIZE= +usage="Usage: $0 [-user user] [-all] [-fast] [-large] [-j] [-verbose] [-x] tests ..." +while true +do + case $1 in + -all) ALL=yes;; + -fast) FAST=yes;; + -large) LARGE=yes;; + -j) PARALLELL="&";; + -verbose) VERBOSE=yes;; + -user) RUNAS=$1; shift;; + -x) SHELLVERBOSE="-x";; + -p) PRINT_CACHESIZE="yes";; + -basic) TESTS="$BASIC_TESTS";TEST_MODE="basic";; + -mtpt) TESTS="$MTPT_TESTS";TEST_MODE="mtpt";; + -acl) TESTS="$ACL_TESTS";TEST_MODE="acl";; + -exec) TESTS="$EXEC_TESTS";TEST_MODE="exec";; + -mmap) TESTS="$MMAP_TESTS";TEST_MODE="mmap";; + -fs) TESTS="$FS_TESTS";TEST_MODE="fs";; + -afs) TESTS="$AFS_TESTS";TEST_MODE="afs";; + -rmt) TESTS="$RMT_TESTS";TEST_MODE="rmt";; + -abuse) TESTS="$ABUSE_TESTS";TEST_MODE="abuse";; + -pts) TESTS="$PTS_TESTS";TEST_MODE="pts";; + -vos) TESTS="$VOS_TESTS";TEST_MODE="vos";; + -bos) TESTS="$BOS_TESTS";TEST_MODE="bos";; + -reg) TESTS="$REG_TESTS";TEST_MODE="reg";; + -help|--help) echo $usage; + echo "tests available: $linebreak"; for a in "$ALL_TESTS"; do echo $a ; done; + exit 0;; + -version|--version) echo "$0 $Id$"; exit 0;; + -*) echo "$0: Bad option $1"; echo $usage; exit 1;; + *) break;; + esac + shift +done + +if test "X$WORKDIR" = "X";then + echo "WORKDIR=workdir $0 $* or env WORKDIR=workdir $0 $*"; exit 1; +fi + +RUNTESTS= +if test "X$ALL" != "X" ; then + RUNTESTS="$TESTS" +elif test $# -lt 1; then + echo $usage; exit +else + RUNTESTS=$* +fi + +# these are variables exported to the scripts + +export FAST +export LARGE +export VERBOSE +export SHELLVERBOSE + +# and file descriptors + +# 3 - progress +# 4 - details + +if test "$VERBOSE" = "yes"; then + exec 3>/dev/null + exec 4>&1 +else + exec 3>&1 + exec 4>/dev/null +fi + +# Find out where we really are + +srcdir=`cd $srcdir; pwd` +objdir=`cd $objdir; pwd` + +export srcdir +export objdir + +echo "-------------------------------------------------" +echo "$PACKAGE-$VERSION" +echo "hosttype $host" +echo "${SHELL},${SHELLVERBOSE},${VERBOSE},${PARALLELL},${FAST}" +echo "testmode ${TEST_MODE}" +echo "runas ${RUNAS}" +echo "${srcdir}" +echo "${objdir}" +echo "${WORKDIR}" +date +echo "-------------------------------------------------" + +test "X$VERBOSE" != "X" && echo "Running tests" + +FAILEDTESTS= +exitval=0 + +for a in $RUNTESTS; do + # + # XXX Test if binary in $srcdir, shellscript in $srcdir else + # its a binary in objdir + # + if test -x ${srcdir}/$a ; then + b="${srcdir}/$a" + elif test -f ${srcdir}/$a ; then + b="${SHELL} ${SHELLVERBOSE} ${srcdir}/$a" + else + b="${objdir}/$a" + fi + echo "Running $a" + test "X$VERBOSE" != "X" && echo "Running test $a ($b)." + if test "$a" = "setgroups" ; then + b="${objdir}/asu root $b" + else + b="${objdir}/asu $RUNAS $b" + fi + tmpdir="`hostname`-$a-`date +%Y-%m-%d-%H-%M-%S`-$$" + cd $WORKDIR && mkdir $tmpdir && (cd $tmpdir && $b ${PARALLELL}) + saved_res=$? + test "X$VERBOSE" != "X" && echo "Saved res = $saved_res" + if test "X${PARALLELL}" = "X" ;then + if test $saved_res != 0 ; then + echo "Test $a FAILED" + FAILEDTESTS="${FAILEDTESTS} $a"; + exitval=$savedres + else + test "X$VERBOSE" != "X" && echo "Test $a succeeded, tmpdir is removed" + ${objdir}/rm-rf $tmpdir + fi + test "X$VERBOSE" != "X" && echo "Done test $a." + fi + test "X${PRINT_CACHESIZE}" = Xyes && $objdir/../appl/fs/fs calculate +done + +wait +date + +if test "$FAILEDTESTS"; then + echo "-----------------------------------------------------------" + echo "Failed test(s) were: $FAILEDTESTS" +else + echo "All test(s) were succesful!" +fi + +exit $exitval diff --git a/src/tests/setgroups b/src/tests/setgroups new file mode 100755 index 0000000..58ca726 --- /dev/null +++ b/src/tests/setgroups @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ + +$objdir/test-setgroups nobody 1>&4 diff --git a/src/tests/setpag b/src/tests/setpag new file mode 100755 index 0000000..eba07e4 --- /dev/null +++ b/src/tests/setpag @@ -0,0 +1,4 @@ +#!/bin/sh +# $Id$ + +$objdir/test-setpag 1>&4 diff --git a/src/tests/shallow-tree b/src/tests/shallow-tree new file mode 100644 index 0000000..1d42261 --- /dev/null +++ b/src/tests/shallow-tree @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id$ + +mkdir foo && ( cd foo && $SHELL $SHELLVERBOSE ${srcdir}/dir-tree 3 "0 1 2 3 4" ) +${objdir}/rm-rf foo \ No newline at end of file diff --git a/src/tests/still-there-p.c b/src/tests/still-there-p.c new file mode 100644 index 0000000..90b92cd --- /dev/null +++ b/src/tests/still-there-p.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include + +#define TEST_BUFFER_SZ (1024*8) + +int +main(int argc, char **argv) +{ + const char *file = "foo"; + char otherbuf[TEST_BUFFER_SZ]; + char buf[TEST_BUFFER_SZ]; + int fd; + + + fd = open (file, O_RDWR|O_TRUNC|O_CREAT, 0644); + if (fd < 0) + err(1, "open(%s)", file); + + if (write (fd, buf, sizeof(buf)) != sizeof(buf)) + errx(1, "write"); + + while (1) { + if (lseek(fd, 0, SEEK_SET) < 0) + err(1, "lseek"); + + if (read(fd, otherbuf, sizeof(otherbuf)) != sizeof(otherbuf)) { + struct stat sb; + + if (fstat(fd, &sb) < 0) + err(1, "fstat"); + printf("size: %d\n", (int)sb.st_size); + printf ("lseek(SEEK_CUR): %d\n", (int)lseek(fd, 0, SEEK_CUR)); + errx(1, "read"); + } + + if (memcmp(buf, otherbuf, sizeof(buf)) != 0) + errx (1, "buf != otherbuf"); + } + close(fd); + + return 0; +} diff --git a/src/tests/strange-characters b/src/tests/strange-characters new file mode 100755 index 0000000..fb02f71 --- /dev/null +++ b/src/tests/strange-characters @@ -0,0 +1,7 @@ +#!/bin/sh +# $Id$ +for i in å ä ö åäö; do + touch $i || exit 1 + test -f $i || exit 1 + rm $i || exit 1 +done diff --git a/src/tests/strange-characters-c.c b/src/tests/strange-characters-c.c new file mode 100644 index 0000000..ba3419c --- /dev/null +++ b/src/tests/strange-characters-c.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static void +creat_file (char *name) +{ + int fd; + + fd = open (name, O_WRONLY | O_CREAT | O_EXCL, 0777); + if (fd < 0) + err (1, "open %s", name); + if (close (fd) < 0) + err (1, "close %s", name); +} + +static void +look_at_file (char *name) +{ + int fd; + + fd = open (name, O_RDONLY | O_EXCL, 0777); + if (fd < 0) + err (1, "open %s", name); + if (close (fd) < 0) + err (1, "close %s", name); +} + +static void +usage (int ret) +{ + fprintf (stderr, "%s\n", __progname); + exit (ret); +} + +int +main(int argc, char **argv) +{ + char *file = "åäö"; + + + if (argc != 1) + usage (1); + + creat_file (file); + look_at_file (file); + return 0; +} diff --git a/src/tests/strange-other-characters b/src/tests/strange-other-characters new file mode 100644 index 0000000..3986e44 --- /dev/null +++ b/src/tests/strange-other-characters @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id$ +dir=$AFSROOT/stacken.kth.se/ftp/pub/arla/tests + +test -f $dir/åäö || exit 1 diff --git a/src/tests/symlink.c b/src/tests/symlink.c new file mode 100644 index 0000000..f858138 --- /dev/null +++ b/src/tests/symlink.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +int +main(int argc, char **argv) +{ + int ret; + struct stat sb; + + + ret = symlink ("foo", "bar"); + if (ret < 0) + err (1, "symlink foo,bar"); + ret = lstat ("bar", &sb); + if (ret < 0) + err (1, "lstat bar"); + if ((sb.st_mode & S_IFLNK) != S_IFLNK) + errx (1, "bar is not symlink"); + ret = unlink ("bar"); + if (ret < 0) + err (1, "unlink bar"); + return 0; +} diff --git a/src/tests/t.uniq-bad b/src/tests/t.uniq-bad new file mode 100644 index 0000000..1848482 Binary files /dev/null and b/src/tests/t.uniq-bad differ diff --git a/src/tests/test-gunzip-gnu-mirror b/src/tests/test-gunzip-gnu-mirror new file mode 100755 index 0000000..bcb25a5 --- /dev/null +++ b/src/tests/test-gunzip-gnu-mirror @@ -0,0 +1,14 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +original=${1-$AFSROOT/stacken.kth.se/ftp/pub/gnu} +cd $original || exit 1 +find . -name '*.gz' -print | while read i; do + foo=`gunzip --verbose --test $i 2>&1` + echo $foo >& 4 + case "$foo" in +*not*in*gzip*format*) ;; +*OK*) ;; +*) exit 1 ;; + esac +done diff --git a/src/tests/test-parallel1.c b/src/tests/test-parallel1.c new file mode 100644 index 0000000..47d5b1a --- /dev/null +++ b/src/tests/test-parallel1.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +#define WORKER_TIMES 100 +#define NUM_WORKER 10 + +static int +worker (int num) +{ + int i, fd; + + for (i = 0 ; i < WORKER_TIMES ; i++) { + fd = open ("foo", O_CREAT|O_RDWR, 0600); + if (fd >= 0) { + fchmod (fd, 0700); + close (fd); + } + unlink("foo"); + if (i % 1000) { + printf (" %d", num); + fflush (stdout); + } + } + return 0; +} + + +int +main(int argc, char **argv) +{ + int i, ret; + + + for (i = 0; i < NUM_WORKER ; i++) { + int ret; + + ret = fork(); + switch (ret) { + case 0: + return worker(i); + case -1: + err (1, "fork"); + } + } + i = NUM_WORKER; + while (i && wait (&ret)) { + i--; + if (ret) + err (1, "wait: %d", ret); + } + return 0; +} diff --git a/src/tests/test-parallel2.c b/src/tests/test-parallel2.c new file mode 100644 index 0000000..e18fb2a --- /dev/null +++ b/src/tests/test-parallel2.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +#define WORKER_TIMES 1000 +#define NUM_WORKER 100 + +static int +getcwd_worker (int num) +{ + char name[17]; + int i; + + snprintf (name, sizeof(name), "%d", num); + if (mkdir (name, 0777) < 0) + err (1, "mkdir %s", name); + if (chdir (name) < 0) + err (1, "chdir %s", name); + for (i = 0; i < WORKER_TIMES; ++i) { + char buf[256]; + + getcwd (buf, sizeof(buf)); + } + return 0; +} + +static int +mkdir_worker (int num) +{ + int i; + + for (i = 0; i < WORKER_TIMES; ++i){ + char name[256]; + + snprintf (name, sizeof(name), "m%d-%d", num, i); + mkdir (name, 0777); + } + return 0; +} + +static int +mkdir_rmdir_worker (int num) +{ + int i; + + for (i = 0; i < WORKER_TIMES; ++i){ + char name[256]; + + snprintf (name, sizeof(name), "rm%d-%d", num, i); + mkdir (name, 0777); + } + for (i = 0; i < WORKER_TIMES; ++i){ + char name[256]; + + snprintf (name, sizeof(name), "rm%d-%d", num, i); + rmdir (name); + } + return 0; +} + +static int +rename_worker (int num) +{ + int i; + + for (i = 0; i < WORKER_TIMES; ++i){ + char name[256]; + int fd; + + snprintf (name, sizeof(name), "rm%d-%d", num, i); + fd = open (name, O_WRONLY | O_CREAT, 0777); + close (fd); + } + for (i = 0; i < WORKER_TIMES; ++i){ + char name[256], name2[256]; + + snprintf (name, sizeof(name), "rm%d-%d", num, i); + snprintf (name2, sizeof(name2), "rn%d-%d", num, i); + rename (name, name2); + } + return 0; +} + +static int +stat_worker (int num) +{ + char name[17]; + int i; + char buf[256]; + struct stat sb; + + snprintf (name, sizeof(name), "%d", num); + if (mkdir (name, 0777) < 0) + err (1, "mkdir %s", name); + if (chdir (name) < 0) + err (1, "chdir %s", name); + for (i = 0; i < WORKER_TIMES; ++i) { + getcwd (buf, sizeof(buf)); + stat (buf, &sb); + } + return 0; +} + +static int (*workers[])(int) = {getcwd_worker, mkdir_worker, + mkdir_rmdir_worker, rename_worker, + stat_worker}; + +static int nworkers = sizeof(workers)/sizeof(*workers); + +int +main(int argc, char **argv) +{ + int i, ret; + + + for (i = 0; i < NUM_WORKER ; i++) { + int ret; + + ret = fork(); + switch (ret) { + case 0: + return (*workers[i % nworkers])(i); + case -1: + err (1, "fork"); + } + } + i = NUM_WORKER; + while (i && wait (&ret)) { + i--; + if (ret) + err (1, "wait: %d", ret); + } + return 0; +} diff --git a/src/tests/test-setgroups.c b/src/tests/test-setgroups.c new file mode 100644 index 0000000..93724dd --- /dev/null +++ b/src/tests/test-setgroups.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +#if !defined(NGROUPS) && defined(NGROUPS_MAX) +#define NGROUPS NGROUPS_MAX +#endif + +static void +print_groups (int ngroups, gid_t groups[NGROUPS]) +{ + int i; + + printf ("groups: "); + for (i = 0; i < ngroups; ++i) + printf ("%d%s", groups[i], (i < ngroups - 1) ? ", " : ""); + printf ("\n"); +} + +int +main(int argc, char **argv) +{ + char *user; + char *this_user; + struct passwd *this_pwd, *pwd; + int ret; + gid_t groups[NGROUPS]; + int ngroups; + gid_t pag0, pag1, pag2; + + + if (argc != 2) + errx (1, "Usage: %s user", argv[0]); + user = argv[1]; + + this_pwd = getpwuid (getuid ()); + if (this_pwd == NULL) + errx (1, "Who are you?"); + this_user = strdup (this_pwd->pw_name); + + pwd = getpwnam (user); + if (pwd == NULL) + errx (1, "User %s not found", user); + + ngroups = getgroups (NGROUPS, groups); + if (ngroups < 0) + err (1, "getgroups %d", NGROUPS); + printf ("user %s ", this_user); + print_groups (ngroups, groups); + printf ("doing setpag()\n"); + ret = setpag (); + if (ret < 0) + err (1, "setpag"); + + ngroups = getgroups (NGROUPS, groups); + if (ngroups < 0) + err (1, "getgroups %d", NGROUPS); + pag0 = groups[0]; + pag1 = groups[1]; + pag2 = groups[2]; + printf ("user %s ", this_user); + print_groups (ngroups, groups); + + ret = initgroups (user, pwd->pw_gid); + if (ret < 0) + err (1, "initgroups"); + + ngroups = getgroups (NGROUPS, groups); + if (ngroups < 0) + err (1, "getgroups %d", NGROUPS); + printf ("user %s ", user); + print_groups (ngroups, groups); + if ((groups[0] == pag0 && groups[1] == pag1) + || (groups[1] == pag1 && groups[2] == pag2)) + return 0; + else + return 1; +} + diff --git a/src/tests/test-setpag.c b/src/tests/test-setpag.c new file mode 100644 index 0000000..36f7268 --- /dev/null +++ b/src/tests/test-setpag.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +#if !defined(NGROUPS) && defined(NGROUPS_MAX) +#define NGROUPS NGROUPS_MAX +#endif + +static void +print_groups (int ngroups, gid_t groups[NGROUPS]) +{ + int i; + + printf ("groups: "); + for (i = 0; i < ngroups; ++i) + printf ("%d%s", groups[i], (i < ngroups - 1) ? ", " : ""); + printf ("\n"); +} + +int +main(int argc, char **argv) +{ + int ret; + gid_t groups[NGROUPS]; + int ngroups; + gid_t pag1, pag2; + pid_t pid; + + if (argc != 1) + errx (1, "Usage: %s", argv[0]); + + ngroups = getgroups (NGROUPS, groups); + if (ngroups < 0) + err (1, "getgroups %d", NGROUPS); + pag1 = groups[1]; + pag2 = groups[2]; + printf ("in parent "); + print_groups (ngroups, groups); + pid = fork (); + if (pid < 0) + err (1, "fork"); + if (pid == 0) { + ret = setpag (); + if (ret < 0) + err (1, "setpag"); + ngroups = getgroups (NGROUPS, groups); + if (ngroups < 0) + err (1, "getgroups %d", NGROUPS); + printf ("in child "); + print_groups (ngroups, groups); + return 0; + } else { + int status; + + while(waitpid (pid, &status, WNOHANG | WUNTRACED) != pid) + ; + if (status) + return 1; + ngroups = getgroups (NGROUPS, groups); + if (ngroups < 0) + err (1, "getgroups %d", NGROUPS); + printf ("in parent "); + print_groups (ngroups, groups); + if (groups[1] == pag1 && groups[2] == pag2) + return 0; + else + return 1; + } +} diff --git a/src/tests/too-many-files b/src/tests/too-many-files new file mode 100644 index 0000000..717424f --- /dev/null +++ b/src/tests/too-many-files @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi + +$objdir/create-files 31707 0 diff --git a/src/tests/touch1 b/src/tests/touch1 new file mode 100755 index 0000000..61badc5 --- /dev/null +++ b/src/tests/touch1 @@ -0,0 +1,4 @@ +#!/bin/sh +touch foobar || exit 1 +test -f foobar || exit 1 +rm foobar || exit 1 diff --git a/src/tests/truncate-files.c b/src/tests/truncate-files.c new file mode 100644 index 0000000..53c59de --- /dev/null +++ b/src/tests/truncate-files.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static void do_dir(const char *); +static void repeat_dir(const char *); + +static void +do_dir(const char *dirname) +{ + int ret; + + ret = chdir (dirname); + if (ret < 0) + err (1, "chdir %s", dirname); + repeat_dir (dirname); + ret = chdir (".."); + if (ret < 0) + err (1, "chdir .."); +} + +static void +read_and_truncate (const char *filename, const struct stat *sb) +{ + int fd; + char *buf; + int ret; + struct stat sb2; + + buf = malloc (sb->st_size); + if (buf == NULL) + err (1, "malloc %lu", (unsigned long)sb->st_size); + fd = open (filename, O_RDONLY); + if (fd < 0) + err (1, "open readonly %s", filename); + ret = read (fd, buf, sb->st_size); + if (ret < 0) + err (1, "read %s", filename); + if (ret != sb->st_size) + errx (1, "short read from %s", filename); + if (close (fd)) + err (1, "close reading %s", filename); + fd = open (filename, O_WRONLY | O_TRUNC, 0); + if (fd < 0) + err(1, "open wronly-trunc %s", filename); + ret = write (fd, buf, sb->st_size); + if (ret < 0) + err (1, "write %s", filename); + if (ret != sb->st_size) + errx (1, "short write %s", filename); + if (close (fd)) + err (1, "close writing %s", filename); + ret = lstat (filename, &sb2); + if (ret < 0) + err (1, "stat %s", filename); + if (sb2.st_size != sb->st_size) + errx (1, "wrong size after re-writing %s: %lu != %lu", + filename, + (unsigned long)sb->st_size, (unsigned long)sb2.st_size); + free(buf); +} + +static void +repeat_dir (const char *dirname) +{ + DIR *dir; + struct dirent *dp; + + dir = opendir ("."); + if (dir == NULL) + err(1, "opendir %s", dirname); + while ((dp = readdir (dir)) != NULL) { + struct stat sb; + int ret; + + if (strcmp (dp->d_name, ".") == 0 + || strcmp (dp->d_name, "..") == 0) + continue; + + ret = lstat (dp->d_name, &sb); + if (ret < 0) + err (1, "lstat %s", dp->d_name); + if (S_ISDIR(sb.st_mode)) + do_dir (dp->d_name); + else if (S_ISREG(sb.st_mode)) + read_and_truncate (dp->d_name, &sb); + } + closedir (dir); +} + + +int +main(int argc, char **argv) +{ + + if (argc != 2) + errx (1, "usage: %s directory", argv[0]); + do_dir (argv[1]); + return 0; +} diff --git a/src/tests/truncate.c b/src/tests/truncate.c new file mode 100644 index 0000000..0e41bec --- /dev/null +++ b/src/tests/truncate.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include + +static void +create_and_write (char *name, const char *buf) +{ + int fd, ret; + int len = strlen(buf); + + fd = open (name, O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (fd < 0) + err (1, "open"); + ret = write (fd, buf, len); + if (ret != len) + err (1, "write"); + ret = close (fd); + if (ret < 0) + err (1, "close"); +} + +static void +check_size (char *name, int len) +{ + struct stat sb; + int ret; + + ret = stat(name, &sb); + if (ret < 0) + err (1, "stat"); + + if (len != sb.st_size) + errx (1, "len != sb.st_size"); +} + +int +main(int argc, char **argv) +{ + int ret; + + + create_and_write ("foo", "hej\n"); + + ret = truncate ("foo", 0); + if (ret < 0) + err (1, "truncate(0)"); + + check_size ("foo", 0); + + ret = unlink("foo"); + if (ret < 0) + errx (1, "unlink"); + + create_and_write ("bar", "hej\nhej\n"); + + ret = truncate ("bar", 16); + if (ret < 0) + err (1, "truncate(16)"); + + check_size ("bar", 16); + + ret = unlink("bar"); + if (ret < 0) + errx (1, "unlink"); + + return 0; +} diff --git a/src/tests/untar-emacs b/src/tests/untar-emacs new file mode 100755 index 0000000..a74abc1 --- /dev/null +++ b/src/tests/untar-emacs @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +for i in 1 2 3 4 5 6 7 8 9 10; do + $objdir/echo-n '.' >&3 + gzip -dc $AFSROOT/stacken.kth.se/ftp/pub/gnu/emacs/emacs-20.7.tar.gz | tar xvf - >&4 || exit 1 + rm -rf emacs-20.7 +done +echo >&3 diff --git a/src/tests/untar-openafs b/src/tests/untar-openafs new file mode 100755 index 0000000..d2af4e0 --- /dev/null +++ b/src/tests/untar-openafs @@ -0,0 +1,10 @@ +#!/bin/sh +# $Id$ +if test "X$FAST" != "X" ; then echo "Not running $0" ; exit 0 ; fi +wget http://www.openafs.org/dl/1.2.2/openafs-1.2.2-src.tar.gz +for i in 1 2 3 4 5 6 7 8 9 10; do + $objdir/echo-n '.' >&3 + gzip -dc openafs-1.2.2-src.tar.gz | tar xvf - >&4 || exit 1 + rm -rf openafs-1.2.2 +done +echo >&3 diff --git a/src/tests/util.pm b/src/tests/util.pm new file mode 100644 index 0000000..ec1c52a --- /dev/null +++ b/src/tests/util.pm @@ -0,0 +1,356 @@ +# CMUCS AFStools +# Copyright (c) 1996, Carnegie Mellon University +# All rights reserved. +# +# See CMUCS/CMU_copyright.ph for use and distribution information + +package OpenAFS::util; + +=head1 NAME + +OpenAFS::util - General AFS utilities + +=head1 SYNOPSIS + + use OpenAFS::util; + + AFS_Init(); + AFS_Trace($subject, $level); + AFS_SetParm($parm, $value); + + use OpenAFS::util qw(GetOpts_AFS); + %options = GetOpts_AFS(\@argv, \@optlist); + +=head1 DESCRIPTION + +This module defines a variety of AFS-related utility functions. Virtually +every application that uses AFStools will need to use some of the utilities +defined in this module. In addition, a variety of global variables are +defined here for use by all the AFStools modules. Most of these are +private, but a few are semi-public. + +=cut + +use OpenAFS::CMU_copyright; +use OpenAFS::config; +require OpenAFS::afsconf; ## Avoid circular 'use' dependencies +use Exporter; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&AFS_Init + &AFS_Trace + &AFS_SetParm); +@EXPORT_OK = qw(%AFS_Parms + %AFS_Trace + %AFS_Help + %AFScmd + &GetOpts_AFS + &GetOpts_AFS_Help); +%EXPORT_TAGS = (afs_internal => [qw(%AFS_Parms %AFS_Trace %AFScmd %AFS_Help)], + afs_getopts => [qw(&GetOpts_AFS &GetOpts_AFS_Help)] ); + + +=head2 AFS_Init() + +This function does basic initialization of AFStools. It must be called before +any other AFStools function. + +=cut + +sub AFS_Init +{ + my(@dirs, $c, $i, $x); + + $AFS_Parms{'authlvl'} = 1; + $AFS_Parms{'confdir'} = $def_ConfDir; + $AFS_Parms{'cell'} = OpenAFS::afsconf::AFS_conf_localcell(); + + # Search for AFS commands + @dirs = @CmdPath; + foreach $c (@CmdList) + { + $AFScmd{$c} = ''; + foreach $i ($[ .. $#dirs) + { + $x = $dirs[$i]; + if (-x "$x/$c" && ! -d "$x/$c") + { + $AFScmd{$c} = "$x/$c"; + splice(@dirs, $i, 1); # Move this item to the start of the array + unshift(@dirs, $x); + last; + } + } + return "Unable to locate $c!" if (!$AFScmd{$c}); + } + 0; +} + + +=head2 AFS_Trace($subject, $level) + +Sets the tracing level for a particular "subject" to the specified level. +All tracing levels start at 0, and can be set to higher values to get debugging +information from different parts of AFStools. This function is generally +only of use to people debugging or extending AFStools. + +=cut + +$AFS_Help{Trace} = '$subject, $level => void'; +sub AFS_Trace { + my($subject, $level) = @_; + + $AFS_Trace{$subject} = $level; +} + + +=head2 AFS_SetParm($parm, $value) + +Sets the AFStools parameter I<$parm> to I<$value>. AFStools parameters are +used to alter the behaviour of various parts of the system. The following +parameters are currently defined: + +=over 10 + +=item authlvl + +The authentication level to use for commands that talk directly to AFS +servers (bos, vos, pts, etc.). Set to 0 for unauthenticated access (-noauth), +1 to use the user's existing tokens, or 2 to use the AFS service key +(-localauth). + +=item cell + +The default AFS cell in which to work. This is initially the workstation's +local cell. + +=item confdir + +The AFS configuration directory to use. If none is specified, the default +(as defined in OpenAFS::config) will be used. + +=item vostrace + +Set the tracing level used by various B utilities. The default is 0, +which disables any tracing of activity of B commands. A setting of 1 +copies output from all commands except those which are invoked solely to +get information; a setting of 2 additionally uses the "-verbose" command +on any command whose output is copied. If a setting of 3 is used, all +B commands will be invoked with "-verbose", and have their output +copied to stdout. + +=back + +=cut + +$AFS_Help{SetParm} = '$parm, $value => void'; +sub AFS_SetParm { + my($parm, $value) = @_; + + $AFS_Parms{$parm} = $value; +} + + +#: GetOpts_AFS(\@argv, \@optlist) +#: Parse AFS-style options. +#: \@argv is a hard reference to the list of arguments to be parsed. +#: \@optlist is a hard reference to the list of option specifications for valid +#: options; in their default order. Each option specification, in turn, is a +#: hard reference to an associative array containing some of the following +#: elements: +#: name => The name of the argument +#: numargs => Number of arguments (0, 1, or -1 for multiple) +#: required => If nonzero, this argument is required +#: default => Value to give this option if not specified +#: noauto => Don't use this option for unadorned arguments +#: +#: Results are returned in the form of an associative array of options and +#: their values: +#: - Boolean (0-argument) options have a value of 1 if specified. This type +#: of option may not be marked 'required'. +#: - Simple (1-argument) options have a value which is the string given by the +#: user. +#: - Multiple-argument options have a value which is a hard reference to an +#: array of values given by the user. +#: +#: Argument parsing is done in a similar manner to the argument parser used by +#: various AFS utilities. Options have multi-character names, and may not be +#: combined with their arguments or other options. Those options which take +#: arguments use up at least the next argument, regardless of whether it begins +#: with a dash. Options which can take multiple arguments will eat at least +#: one argument, as well as any following argument up to the next option (i.e., +#: the next argument beginning with a dash). An "unadorned" argument will be +#: used by the next argument-taking option. If there are multiple unadorned +#: arguments, they will be used up by successive arguments much in the same +#: way Perl handles list assignment - each one-argument (scalar) option will +#: use one argument; the first multi-argument (list) option will use up any +#: remaining unadorned arguments. +#: +#: On completion, @argv will be left with any unparsed arguments (this can +#: happen if the last option specified is _not_ a multi-argument option, and +#: there are no "defaulted" options). This is considered to be an error +#: condition. +#: +sub GetOpts_AFS_Help { + my($cmd, $optlist) = @_; + my($option, $optname, $desc); + + foreach $option (@$optlist) { + $optname = '-' . $$option{name}; + if ($$option{numargs}) { + $desc = $$option{desc} ? $$option{desc} : $$option{name}; + $desc = " <$desc>"; + $desc .= '+' if ($$option{numargs} < 0); + $optname .= $desc; + } + $optname = "[$optname]" if (!$$option{required}); + $cmd .= " $optname"; + } + $cmd; +} + +sub _which_opt { + my($optname, @options) = @_; + my($o, $which, $n); + + foreach $o (@options) { + next unless ($o =~ /^$optname/); + $n++; + $which = $o; + } + ($n == 1) ? $which : $optname; +} + +sub GetOpts_AFS { + my($argv, $optlist) = @_; + my(@autolist, %opttbl, %result); + my($stop, $key, $value, $diemsg); + + # Initialization: + @autolist = map { + if ($_->{numargs} && !$_->{noauto} && !$stop) { + $stop = 1 if ($_->{numargs} < 0); + ($_->{name}); + } else { + (); + } + } (@$optlist, { name=>'-help', numargs=>0, required=>0 } ); + %opttbl = map { $_->{name} => $_ } @$optlist; + + while (@$argv) { + my($optname, $optkind); + + # Parse the next argument. It can either be an option, or an + # unadorned argument. If the former, shift it off and process it. + # Otherwise, grab the next "automatic" option. If there are no + # more automatic options, we have extra arguments and should return. + if ($argv->[0] =~ /^-(.+)/) { # Got an option! + $optname = $1; + shift(@$argv); + } else { # An unadorned argument + if (@autolist) { + $optname = shift(@autolist); + } else { + $diemsg = join(' ', "Extra arguments:", @$argv) unless ($diemsg); + shift @$argv; + next; + } + } + $optname = &_which_opt($optname, keys %opttbl); + + # Find out how many arguments this thing wants, then remove it from + # the option table and automatic option list. + $optkind = $opttbl{$optname}->{numargs}; + delete $opttbl{$optname}; + @autolist = grep($_ ne $optname, @autolist); + + # Parse arguments (if any), and set the result value + if (!$optkind) { # Boolean! + $result{$optname} = 1; + } elsif ($optkind == 1) { # Single argument + # Shift off a single argument, or signal an error + if (!@$argv) { + $diemsg = "No argument for -$optname" unless ($diemsg); + next; + } + $result{$optname} = shift(@$argv); + } elsif ($optkind < 0) { # Multiple arguments + # Shift off at least one argument, and any additional + # ones that are present. EXCEPT, if there are no more + # explicitly-specified options but there ARE automatic + # options left in our list, then only eat up one. + my($val, @val); + if (!@$argv) { + $diemsg = "No argument for -$optname" unless ($diemsg); + next; + } + $val = shift(@$argv); + push(@val, shift @$argv) while (@$argv && $argv->[0] !~ /^-/); + if (@autolist && !@$argv) { + unshift(@$argv, @val); + @val = ($val); + } else { + unshift(@val, $val); + } + $result{$optname} = [@val]; + } else { + die "Invalid argument spec for -$optname ($optkind)\n"; + } + } + + # Now for a little clean-up + # Set default values for any unspecified option that has them. + # Set an error condition if there are any required options that + # were not specified. + while (($key, $value) = each %opttbl) { + if ($value->{required}) { + $diemsg = "Required option -$key not specified" unless($diemsg); + } + $result{$key} = $value->{default}; + } + if ($diemsg && !$result{help}) { die $diemsg . "\n" } + %result; +} + + +1; + +=head1 VARIABLES + +The following global variables are defined by B. None of these +are exported by default. Those marked "Private" should not be used outside +AFStools; their names, meaning, and even existence may change at any time. + +=over 12 + +=item %AFS_Help - Help info + +This array contains argument lists for all publicly-exported AFStools +functions with names of the form AFS_*. It is intended for programs like +B, which provide a direct interactive interface to AFStools. + +=item %AFS_Parms - Parameter settings [Private] + +This array contains the settings of AFStools parameters set with +B. + +=item %AFS_Trace - Tracing levels [Private] + +This array contains the tracing levels set with B. + +=item %AFScmd - AFS command locations [Private] + +This array contains paths to the various AFS command binaries, for use +by B and possibly other AFStools functions. + +=back + +=head1 COPYRIGHT + +The CMUCS AFStools, including this module are +Copyright (c) 1996, Carnegie Mellon University. All rights reserved. +For use and redistribution information, see CMUCS/CMU_copyright.pm + +=cut diff --git a/src/tests/utime-dir.c b/src/tests/utime-dir.c new file mode 100644 index 0000000..0eece44 --- /dev/null +++ b/src/tests/utime-dir.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static void +doit (const char *filename) +{ + int ret; + struct timeval tv[2]; + + ret = mkdir (filename, 0700); + if (ret < 0) + err (1, "mkdir %s", filename); + gettimeofday (&tv[0], NULL); + tv[1] = tv[0]; + ret = utimes (filename, tv); + if (ret < 0) + err(1, "utimes %s", filename); +} + +int +main(int argc, char **argv) +{ + const char *file = "blaha"; + + if (argc != 1 && argc != 2) + errx (1, "usage: %s [file]", argv[0]); + if (argc == 2) + file = argv[1]; + doit (file); + return 0; +} diff --git a/src/tests/utime-file.c b/src/tests/utime-file.c new file mode 100644 index 0000000..bbbea33 --- /dev/null +++ b/src/tests/utime-file.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef RCSID +RCSID("$Id$"); +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +int +main (int argc, char ** argv) +{ + int len; + int ret; + int fd; + char *filename = "foo"; + char *buf; + struct stat sb; + struct utimbuf t; + + switch (argc) { + case 1: + len = 8 * 1024; break; + case 2: + len = atoi(argv[1]); + if (len == 0) + errx (1, "invalid len"); + default: + errx (1, "argv != [12]"); + } + + buf = malloc (len); + memset (buf, 'a', len); + + fd = open (filename, O_RDWR|O_CREAT|O_EXCL, 0744); + if (fd < 0) + errx (1, "open"); + ret = fstat (fd, &sb); + if (ret < 0) + errx (1, "open"); + + ret = ftruncate (fd, len); + fstat (fd, &sb); + lseek (fd, 0, SEEK_SET); + write (fd, buf, len); + fstat (fd, &sb); + + t.modtime = t.actime = time (NULL); + utime (filename, &t); + + close (fd); + free (buf); + + return 0; +} diff --git a/src/tests/visit-volumes b/src/tests/visit-volumes new file mode 100644 index 0000000..6c3b383 --- /dev/null +++ b/src/tests/visit-volumes @@ -0,0 +1,6 @@ +#!/bin/sh +# $Id$ +ls ${AFSROOT}/nada.kth.se/* >&4 2>&4 || exit 1 +ls -l ${AFSROOT}/nada.kth.se/* >&4 2>&4 || exit 1 +ls ${AFSROOT}/nada.kth.se/*/* >&4 2>&4 || exit 1 +ls -l ${AFSROOT}/nada.kth.se/*/* >&4 2>&4 || exit 1 diff --git a/src/tests/vos.pm b/src/tests/vos.pm new file mode 100644 index 0000000..3f1ae6a --- /dev/null +++ b/src/tests/vos.pm @@ -0,0 +1,803 @@ +# CMUCS AFStools +# Copyright (c) 1996, Carnegie Mellon University +# All rights reserved. +# +# See CMU_copyright.ph for use and distribution information +# +#: * vos.pm - Wrappers around VOS commands (volume maintenance) +#: * This module provides wrappers around the various volserver and VLDB +#: * commands, giving them a nice perl-based interface. Someday, they might +#: * talk to the servers directly instead of using 'vos', but not anytime +#: * soon. +#: + +package OpenAFS::vos; +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT :afs_internal); +use OpenAFS::wrapper; +use Exporter; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&AFS_vos_create &AFS_vos_listvldb + &AFS_vos_remove &AFS_vos_delentry + &AFS_vos_rename &AFS_vos_syncserv + &AFS_vos_move &AFS_vos_syncvldb + &AFS_vos_examine &AFS_vos_lock + &AFS_vos_addsite &AFS_vos_unlock + &AFS_vos_remsite &AFS_vos_unlockvldb + &AFS_vos_release &AFS_vos_changeaddr + &AFS_vos_backup &AFS_vos_listpart + &AFS_vos_backupsys &AFS_vos_partinfo + &AFS_vos_dump &AFS_vos_listvol + &AFS_vos_restore &AFS_vos_zap + &AFS_vos_status); + +$vos_err_parse = [ 'Error in vos (.*) command', '-(.*)' ]; + + +#: AFS_vos_create($vol, $server, $part, [$quota], [$cell]) +#: Create a volume with name $vol +#: The server name ($server) may be a hostname or IP address +#: The partition may be a partition name (/vicepx), letter (x), or number (24) +#: If specified, use $quota for the initial quota instead of 5000 blocks. +#: If specified, work in $cell instead of the default cell. +#: On success, return the volume ID. +#: +$AFS_Help{vos_create} = '$vol, $server, $part, [$quota], [$cell] => $volid'; +sub AFS_vos_create { + my($vol, $server, $part, $quota, $cell) = @_; + my(@args, $id); + + @args = ('create', '-name', $vol, '-server', $server, '-part', $part); + push(@args, '-maxquota', $quota) if ($quota ne ''); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + ['^Volume (\d+) created on partition \/vicep\S+ of \S+', \$id ], + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + $id; +} + + +#: AFS_vos_remove($vol, $server, $part, [$cell]) +#: Remove the volume $vol from the server and partition specified by $server and +#: $part. If appropriate, also remove the corresponding VLDB entry. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_remove} = '$vol, $server, $part, [$cell] => Success?'; +sub AFS_vos_remove { + my($vol, $server, $part, $cell) = @_; + my(@args); + + @args = ('remove', '-id', $vol, '-server', $server, '-part', $part); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_rename($old, $new, [$cell]) +#: Rename the volume $old to have the name $new. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_rename} = '$old, $new, [$cell] => Success?'; +sub AFS_vos_rename { + my($old, $new, $cell) = @_; + my(@args); + + @args = ('rename', '-oldname', $old, '-newname', $new); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_move($vol, $fromsrv, $frompart, $tosrv, $topart, [$cell]) +#: Move the volume specified by $vol. +#: The source location is specified by $fromsrv and $frompart. +#: The destination location is specified by $tosrv and $topart. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. + +#: +$AFS_Help{vos_move} = '$vol, $fromsrv, $frompart, $tosrv, $topart, [$cell] => Success?'; +sub AFS_vos_move { + my($vol, $fromsrv, $frompart, $tosrv, $topart, $cell) = @_; + my(@args); + + @args = ('move', '-id', $vol, + '-fromserver', $fromsrv, '-frompartition', $frompart, + '-toserver', $tosrv, '-topartition', $topart); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_examine($vol, [$cell]) +#: Examine the volume $vol, and return information about it. +#: If specified, operate in cell $cell instead of the default cell. +#: On success, return an associative array with some or all of the following: +#: - name Name of this volume +#: - id ID of this volume +#: - kind Kind of volume (RW, RO, or BK) +#: - inuse Disk space in use +#: - maxquota Maximum disk usage quota +#: - minquota Minimum disk usage quota (optional) +#: - stamp_create Time when volume was originally created +#: - stamp_update Time volume was last modified +#: - stamp_backup Time backup volume was cloned, or 'Never' +#: - stamp_copy Time this copy of volume was made +#: - backup_flag State of automatic backups: empty or 'disabled' +#: - dayuse Number of accesses in the past day +#: - rwid ID of read-write volume (even if this is RO or BK) +#: - roid ID of read-only volume (even if this is RW or BK) +#: - bkid ID of backup volume (even if this is RW or RO) +#: - rwserv Name of server where read/write volume is +#: - rwpart Name of partition where read/write volume is +#: - rosites Reference to a list of read-only sites. Each site, in turn, +#: is a reference to a two-element list (server, part). +#: +$AFS_Help{vos_examine} = '$vol, [$cell] => %info'; +sub AFS_vos_examine { + my($vol, $cell) = @_; + my(%result, @args, @rosites); + + @args = ('examine', '-id', $vol); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + %result = &wrapper('vos', \@args, + [$vos_err_parse, + ['^(\S+)\s*(\d+)\s*(RW|RO|BK)\s*(\d+)\s*K', 'name', 'id', 'kind', 'inuse'], + ['MaxQuota\s*(\d+)\s*K', 'maxquota' ], + ['MinQuota\s*(\d+)\s*K', 'minquota' ], + ['Creation\s*(.*\S+)', 'stamp_create' ], + ['Last Update\s*(.*\S+)', 'stamp_update' ], + ['Backup\s+([^\d\s].*\S+)', 'stamp_backup' ], + ['Copy\s*(.*\S+)', 'stamp_copy' ], + ['Automatic backups are (disabled) for this volume', 'backup_flag' ], + ['(\d+) accesses in the past day', 'dayuse' ], + ['RWrite\:\s*(\d+)', 'rwid' ], + ['ROnly\:\s*(\d+)', 'roid' ], + ['Backup\:\s*(\d+)', 'bkid' ], + ['server (\S+) partition /vicep(\S+) RW Site', 'rwserv', 'rwpart'], + ['server (\S+) partition /vicep(\S+) RO Site', sub { + push(@rosites, [$_[0], $_[1]]); + }], + ($AFS_Parms{'vostrace'} > 2) ? ([ '', '?']) : () ]); + + $result{'rosites'} = \@rosites if (@rosites); + %result; +} + + + +#: AFS_vos_addsite($vol, $server, $part, [$cell]) +#: Add a replication site for volume $vol +#: The server name ($server) may be a hostname or IP address +#: The partition may be a partition name (/vicepx), letter (x), or number (24) +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_addsite} = '$vol, $server, $part, [$cell] => Success?'; +sub AFS_vos_addsite { + my($vol, $server, $part, $cell) = @_; + my(@args); + + @args = ('addsite', '-id', $vol, '-server', $server, '-part', $part); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_remsite($vol, $server, $part, [$cell]) +#: Remove a replication site for volume $vol +#: The server name ($server) may be a hostname or IP address +#: The partition may be a partition name (/vicepx), letter (x), or number (24) +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_remsite} = '$vol, $server, $part, [$cell] => Success?'; +sub AFS_vos_remsite { + my($vol, $server, $part, $cell) = @_; + my(@args); + + @args = ('remsite', '-id', $vol, '-server', $server, '-part', $part); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_release($vol, [$cell], [$force]) +#: Release the volume $vol. +#: If $force is specified and non-zero, use the "-f" switch. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_release} = '$vol, [$cell], [$force] => Success?'; +sub AFS_vos_release { + my($vol, $cell, $force) = @_; + my(@args); + + @args = ('release', '-id', $vol); + push(@args, '-f') if ($force); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_backup($vol, [$cell]) +#: Make a backup of the volume $vol. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_backup} = '$vol, [$cell] => Success?'; +sub AFS_vos_backup { + my($vol, $cell) = @_; + my(@args); + + @args = ('backup', '-id', $vol); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_backupsys([$prefix], [$server, [$part]], [$exclude], [$cell]) +#: Do en masse backups of AFS volumes. +#: If specified, match only volumes whose names begin with $prefix +#: If specified, limit work to the $server and, if given, $part. +#: If $exclude is specified and non-zero, backup only volumes NOT matched. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_backupsys} = '[$prefix], [$server, [$part]], [$exclude], [$cell] => Success?'; +sub AFS_vos_backupsys { + my($prefix, $server, $part, $exclude, $cell) = @_; + my(@args); + + @args = ('backupsys'); + push(@args, '-prefix', $prefix) if ($prefix); + push(@args, '-server', $server) if ($server); + push(@args, '-partition', $part) if ($server && $part); + push(@args, '-exclude') if ($exclude); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_dump($vol, [$time], [$file], [$cell]) +#: Dump the volume $vol +#: If specified, do an incremental dump since $time instead of a full dump. +#: If specified, dump to $file instead of STDOUT +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_dump} = '$vol, [$time], [$file], [$cell] => Success?'; +sub AFS_vos_dump { + my($vol, $time, $file, $cell) = @_; + my(@args); + + @args = ('dump', '-id', $vol); + push(@args, '-time', ($time ? $time : 0)); + push(@args, '-file', $file) if ($file); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ], + { pass_stdout => !$file }); + 1; +} + + +#: AFS_vos_restore($vol, $server, $part, [$file], [$id], [$owmode], [$cell]) +#: Restore the volume $vol to partition $part on server $server. +#: If specified, restore from $file instead of STDIN +#: If specified, use the volume ID $id +#: If specified, $owmode must be 'abort', 'full', or 'incremental', and +#: indicates what to do if the volume exists. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_restore} = '$vol, $server, $part, [$file], [$id], [$owmode], [$cell] => Success?'; +sub AFS_vos_restore { + my($vol, $server, $part, $file, $id, $owmode, $cell) = @_; + my(@args); + + @args = ('restore', '-name', $vol, '-server', $server, '-partition', $part); + push(@args, '-file', $file) if ($file); + push(@args, '-id', $id) if ($id); + push(@args, '-overwrite', $owmode) if ($owmode); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_listvldb([$vol], [$server, [$part]], [$locked], [$cell]) +#: Get a list of volumes in the VLDB. +#: If specified, list only the volume $vol +#: If specified, list only volumes on the server $server. +#: If specified with $server, list only volumes on the partition $part. +#: If $locked is specified and nonzero, list only locked VLDB entries +#: If specified, work in $cell instead of the default cell. +#: On success, return an associative array whose keys are names of volumes +#: on the specified server, and each of whose values is an associative +#: array describing the corresponding volume, containing some or all of +#: these elements: +#: - name Name of this volume (same as key) +#: - rwid ID of read-write volume (even if this is RO or BK) +#: - roid ID of read-only volume (even if this is RW or BK) +#: - bkid ID of backup volume (even if this is RW or RO) +#: - locked Empty or LOCKED to indicate VLDB entry is locked +#: - rwserv Name of server where read/write volume is +#: - rwpart Name of partition where read/write volume is +#: - rosites Reference to a list of read-only sites. Each site, in turn, +#: is a reference to a two-element list (server, part). +#: +$AFS_Help{vos_listvldb} = '[$vol], [$server, [$part]], [$locked], [$cell] => %vols'; +sub AFS_vos_listvldb { + my($vol, $server, $part, $locked, $cell) = @_; + my(%finres, %vlist, @rosites); + + @args = ('listvldb'); + push(@args, '-name', $vol) if ($vol); + push(@args, '-server', $server) if ($server); + push(@args, '-partition', $part) if ($part && $server); + push(@args, '-locked') if ($locked); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + %finres = &wrapper('vos', \@args, + [$vos_err_parse, + ['^(VLDB|Total) entries', '.'], + ['^(\S+)', sub { + my(%vinfo) = %OpenAFS::wrapper::result; + + if ($vinfo{name}) { + $vinfo{rosites} = [@rosites] if (@rosites); + $vlist{$vinfo{name}} = \%vinfo; + + @rosites = (); + %OpenAFS::wrapper::result = (); + } + }], + ['^(\S+)', 'name' ], + ['RWrite\:\s*(\d+)', 'rwid' ], + ['ROnly\:\s*(\d+)', 'roid' ], + ['Backup\:\s*(\d+)', 'bkid' ], + ['Volume is currently (LOCKED)', 'locked' ], + ['server (\S+) partition /vicep(\S+) RW Site', 'rwserv', 'rwpart'], + ['server (\S+) partition /vicep(\S+) RO Site', sub { + push(@rosites, [$_[0], $_[1]]); + }], + ($AFS_Parms{'vostrace'} > 2) ? ([ '', '?']) : () ]); + + if ($finres{name}) { + $finres{rosites} = [@rosites] if (@rosites); + $vlist{$finres{name}} = \%finres; + } + %vlist; +} + + + +#: AFS_vos_delentry($vol, [$cell]) +#: Delete the VLDB entry for the volume $vol +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_delentry} = '$vol, [$cell] => Success?'; +sub AFS_vos_delentry { + my($vol, $cell) = @_; + my(@args); + + @args = ('delentry', '-id', $vol); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_syncserv($server, [$part], [$cell], [$force]) +#: Synchronize the server $server with the VLDB +#: If specified, synchronize only partition $part +#: If specified, work in $cell instead of the default cell +#: If $force is specified, force updates to occur +#: On success, return 1. +#: +$AFS_Help{vos_syncserv} = '$server, [$part], [$cell], [$force] => Success?'; +sub AFS_vos_syncserv { + my($server, $part, $cell, $force) = @_; + my(@args); + + @args = ('syncserv', '-server', $server); + push(@args, '-partition', $part) if ($part); + push(@args, '-force') if ($force); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_syncvldb($server, [$part], [$cell], [$force]) +#: Synchronize the VLDB with server $server +#: If specified, synchronize only partition $part +#: If specified, work in $cell instead of the default cell +#: If $force is specified, force updates to occur +#: On success, return 1. +#: +$AFS_Help{vos_syncvldb} = '$server, [$part], [$cell], [$force] => Success?'; +sub AFS_vos_syncvldb { + my($server, $part, $cell, $force) = @_; + my(@args); + + @args = ('syncvldb', '-server', $server); + push(@args, '-partition', $part) if ($part); + push(@args, '-force') if ($force); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_lock($vol, [$cell]) +#: Lock the VLDB entry for volume $vol. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_lock} = '$vol, [$cell] => Success?'; +sub AFS_vos_lock { + my($vol, $cell) = @_; + my(@args); + + @args = ('lock', '-id', $vol); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_unlock($vol, [$cell]) +#: Unlock the VLDB entry for volume $vol. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_unlock} = '$vol, [$cell] => Success?'; +sub AFS_vos_unlock { + my($vol, $cell) = @_; + my(@args); + + @args = ('unlock', '-id', $vol); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_unlockvldb([$server, [$part]], [$cell]) +#: Unlock some or all VLDB entries +#: If specified, unlock only entries for volumes on server $server +#: If specified with $server, unlock only entries for volumes on +#: partition $part, instead of entries for volumes on all partitions +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_unlockvldb} = '[$server, [$part]], [$cell] => Success?'; +sub AFS_vos_unlockvldb { + my($server, $part, $cell) = @_; + my(@args); + + @args = ('unlockvldb'); + push(@args, '-server', $server) if ($server); + push(@args, '-partition', $part) if ($server && $part); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_changeaddr($old, $new, [$cell]) +#: Change the IP address of server $old to $new. +#: If specified, work in $cell instead of the default cell. +#: On success, return 1. +#: +$AFS_Help{vos_changeaddr} = '$old, $new, [$cell] => Success?'; +sub AFS_vos_changeaddr { + my($old, $new, $cell) = @_; + my(@args); + + @args = ('changeaddr', '-oldaddr', $old, '-newaddr', $new); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_listpart($server, [$cell]) +#: Retrieve a list of partitions on server $server +#: If specified, work in $cell instead of the default cell. +#: On success, return a list of partition letters +#: +$AFS_Help{vos_listpart} = '$server, [$cell] => @parts'; +sub AFS_vos_listpart { + my($server, $cell) = @_; + my(@args, @parts); + + @args = ('listpart', '-server', $server); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + [ '^(.*\/vicep.*)$', #', + sub { + push(@parts, map { + my($x) = $_; + $x =~ s/^\/vicep//; + $x; + } split(' ', $_[0])); + }], + ($AFS_Parms{'vostrace'} > 2) ? ([ '', '?']) : () ]); + @parts; +} + + +#: AFS_vos_partinfo($server, [$part], [$cell]) +#: Get information about partitions on server $server. +#: If specified, only get info about partition $part. +#: If specified, work in $cell instead of the default cell. +#: On success, return an associative array whose keys are partition letters, +#: and each of whose values is a reference to a 2-element list, consisting +#: of the total size of the partition and the amount of space used. +#: +$AFS_Help{vos_partinfo} = '$server, [$part], [$cell] => %info'; +sub AFS_vos_partinfo { + my($server, $part, $cell) = @_; + my(@args, %parts); + + @args = ('partinfo', '-server', $server); + push(@args, '-partition', $part) if ($part); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + [ '^Free space on partition /vicep(.+)\: (\d+) K blocks out of total (\d+)', + sub { + $parts{$_[0]} = [ $_[1], $_[2] ]; + }], + ($AFS_Parms{'vostrace'} > 2) ? ([ '', '?']) : () ]); + %parts; +} + + +#: AFS_vos_listvol($server, [$part], [$cell]) +#: Get a list of volumes on the server $server. +#: If specified, list only volumes on the partition $part. +#: If specified, work in $cell instead of the default cell. +#: On success, return an associative array whose keys are names of volumes +#: on the specified server, and each of whose values is an associative +#: array describing the corresponding volume, containing some or all of +#: these elements: +#: - name Name of this volume (same as key) +#: - id ID of this volume +#: - kind Kind of volume (RW, RO, or BK) +#: - inuse Disk space in use +#: - maxquota Maximum disk usage quota +#: - minquota Minimum disk usage quota (optional) +#: - stamp_create Time when volume was originally created +#: - stamp_update Time volume was last modified +#: - stamp_backup Time backup volume was cloned, or 'Never' +#: - stamp_copy Time this copy of volume was made +#: - backup_flag State of automatic backups: empty or 'disabled' +#: - dayuse Number of accesses in the past day +#: - serv Server where this volume is located +#: - part Partition where this volume is located +#: +$AFS_Help{vos_listvol} = '$server, [$part], [$cell] => %vols'; +sub AFS_vos_listvol { + my($server, $part, $cell) = @_; + my(%finres, %vlist); + + @args = ('listvol', '-server', $server, '-long'); + push(@args, '-partition', $part) if ($part); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + %finres = &wrapper('vos', \@args, + [$vos_err_parse, + ['^\S+\s*\d+\s*(RW|RO|BK)', sub { + my(%vinfo) = %OpenAFS::wrapper::result; + + if ($vinfo{name}) { + $vlist{$vinfo{name}} = \%vinfo; + %OpenAFS::wrapper::result = (); + } + }], + ['^(\S+)\s*(\d+)\s*(RW|RO|BK)\s*(\d+)\s*K', 'name', 'id', 'kind', 'inuse'], + ['(\S+)\s*\/vicep(\S+)\:', 'serv', 'part' ], + ['MaxQuota\s*(\d+)\s*K', 'maxquota' ], + ['MinQuota\s*(\d+)\s*K', 'minquota' ], + ['Creation\s*(.*\S+)', 'stamp_create' ], + ['Last Update\s*(.*\S+)', 'stamp_update' ], + ['Backup\s+([^\d\s].*\S+)', 'stamp_backup' ], + ['Copy\s*(.*\S+)', 'stamp_copy' ], + ['Automatic backups are (disabled) for this volume', 'backup_flag' ], + ['(\d+) accesses in the past day', 'dayuse' ], + ($AFS_Parms{'vostrace'} > 2) ? ([ '', '?']) : () ]); + + if ($finres{name}) { + $vlist{$finres{name}} = \%finres; + } + %vlist; +} + +#: AFS_vos_zap($vol, $server, $part, [$cell], [$force]) +#: Remove the volume $vol from the server and partition specified by $server and +#: $part. Don't bother messing with the VLDB. +#: If specified, work in $cell instead of the default cell. +#: If $force is specified, force the zap to happen +#: On success, return 1. +#: +$AFS_Help{vos_zap} = '$vol, $server, $part, [$cell], [$force] => Success?'; +sub AFS_vos_zap { + my($vol, $server, $part, $cell, $force) = @_; + my(@args); + + @args = ('zap', '-id', $vol, '-server', $server, '-part', $part); + push(@args, '-force') if ($force); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 1); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + $AFS_Parms{'vostrace'} ? ([ '', '?']) : () ]); + 1; +} + + +#: AFS_vos_status($server, [$cell]) +#: Get information about outstanding transactions on $server +#: If specified, work in $cell instead of the default cell +#: On success, return a list of transactions, each of which is a reference +#: to an associative array containing some or all of these elements: +#: - transid Transaction ID +#: - stamp_create Time the transaction was created +#: - volid Volume ID +#: - part Partition letter +#: - action Action or procedure +#: - flags Volume attach flags +#: If there are no transactions, the list will be empty. +#: +$AFS_Help{vos_status} = '$server, [$cell] => @trans'; +sub AFS_vos_status { + my($server, $cell) = @_; + my(@trlist); + + @args = ('status', '-server', $server); + push(@args, '-noauth') if ($AFS_Parms{'authlvl'} == 0); + push(@args, '-localauth') if ($AFS_Parms{'authlvl'} == 2); + push(@args, '-verbose') if ($AFS_Parms{'vostrace'} > 2); + push(@args, '-cell', $cell ? $cell : $AFS_Parms{'cell'}); + &wrapper('vos', \@args, + [$vos_err_parse, + ['^(\-)', sub { + my(%trinfo) = %OpenAFS::wrapper::result; + + if ($trinfo{transid}) { + push(@trlist, \%trinfo); + %OpenAFS::wrapper::result = (); + } + }], + ['^transaction\:\s*(\d+)\s*created: (.*\S+)', 'transid', 'stamp_create'], + ['^attachFlags:\s*(.*\S+)', 'flags'], + ['^volume:\s*(\d+)\s*partition\: \/vicep(\S+)\s*procedure\:\s*(\S+)', + 'volid', 'part', 'action'], + ($AFS_Parms{'vostrace'} > 2) ? ([ '', '?']) : () ]); + + @trlist; +} + +1; diff --git a/src/tests/vosaddsite.pl b/src/tests/vosaddsite.pl new file mode 100755 index 0000000..c23c446 --- /dev/null +++ b/src/tests/vosaddsite.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_addsite("testvol","localhost","b",); + +exit(0); + + + diff --git a/src/tests/vosbackup.pl b/src/tests/vosbackup.pl new file mode 100755 index 0000000..a485829 --- /dev/null +++ b/src/tests/vosbackup.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_backup("rep",); + +exit(0); + + + diff --git a/src/tests/voscreate.pl b/src/tests/voscreate.pl new file mode 100755 index 0000000..fd78e9e --- /dev/null +++ b/src/tests/voscreate.pl @@ -0,0 +1,20 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +$ret = &AFS_vos_create("testvol","localhost","a",,); +$ret = &AFS_vos_create("testvol2","localhost","a",,); + +exit(0); + + + diff --git a/src/tests/vosdelentry.pl b/src/tests/vosdelentry.pl new file mode 100755 index 0000000..9ab7102 --- /dev/null +++ b/src/tests/vosdelentry.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_delentry("testvol",); + +exit(0); + + + diff --git a/src/tests/vosdump.pl b/src/tests/vosdump.pl new file mode 100755 index 0000000..eabc5a2 --- /dev/null +++ b/src/tests/vosdump.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_dump("service",0,"/usr/tmp/service.dump",); + +exit(0); + + + diff --git a/src/tests/vosexamine.pl b/src/tests/vosexamine.pl new file mode 100755 index 0000000..a8be8f0 --- /dev/null +++ b/src/tests/vosexamine.pl @@ -0,0 +1,32 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, %info, %info2, @rosites, $tmp, @rosite); +$host = `hostname`; +chomp $host; +&AFS_Init(); + +%info = &AFS_vos_examine("rep",); +if ($info{'rwpart'} ne "a") { + exit 1; +} + +$ret = $info{'rosites'}; +@rosites = @$ret; +while ($ret = pop(@rosites)) { + @rosite = @$ret; + if ($rosite[1] ne "a") { + exit 1; + } +} + +exit(0); + + + diff --git a/src/tests/voslistpart.pl b/src/tests/voslistpart.pl new file mode 100755 index 0000000..45c5b0a --- /dev/null +++ b/src/tests/voslistpart.pl @@ -0,0 +1,26 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret, @parts, $count); +$host = `hostname`; +&AFS_Init(); + +@parts = &AFS_vos_listpart("localhost",); +$ret = shift(@parts); +if ($ret ne "a") { + exit (1); +} +$ret = shift(@parts); +if ($ret ne "b") { + exit (1); +} +exit(0); + + + diff --git a/src/tests/voslistvldb.pl b/src/tests/voslistvldb.pl new file mode 100755 index 0000000..3a951ca --- /dev/null +++ b/src/tests/voslistvldb.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret, %vols, $lvol, %vol); +$host = `hostname`; +&AFS_Init(); + +%vols = &AFS_vos_listvldb(undef,"localhost","b",,); +$lvol=$vols{'testvol3'}; +%vol=%$lvol; +# if it worked it worked... +if ($vol{'rwpart'} ne "b") { + exit(1); +} +exit(0); + + + diff --git a/src/tests/voslistvol.pl b/src/tests/voslistvol.pl new file mode 100755 index 0000000..f7543fe --- /dev/null +++ b/src/tests/voslistvol.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret, %vols, $lvol, %vol); +$host = `hostname`; +&AFS_Init(); + +%vols = &AFS_vos_listvol("localhost","b",); +$lvol=$vols{'testvol3'}; +%vol=%$lvol; +# if it worked it worked... +if ($vol{'part'} ne "b") { + exit(1); +} +exit(0); + + + diff --git a/src/tests/voslock.pl b/src/tests/voslock.pl new file mode 100755 index 0000000..7f1bec8 --- /dev/null +++ b/src/tests/voslock.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_lock("testvol",); + +exit(0); + + + diff --git a/src/tests/vosmove.pl b/src/tests/vosmove.pl new file mode 100755 index 0000000..5240547 --- /dev/null +++ b/src/tests/vosmove.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_move("testvol","localhost","a","localhost","b",); + +exit(0); + + + diff --git a/src/tests/vospartinfo.pl b/src/tests/vospartinfo.pl new file mode 100755 index 0000000..701cb35 --- /dev/null +++ b/src/tests/vospartinfo.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret, %info); +$host = `hostname`; +&AFS_Init(); + +%info = &AFS_vos_partinfo("localhost",,); + +exit(0); + + + diff --git a/src/tests/vosrelease.pl b/src/tests/vosrelease.pl new file mode 100755 index 0000000..479d297 --- /dev/null +++ b/src/tests/vosrelease.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_release("testvol",,); + +exit(0); + + + diff --git a/src/tests/vosremove.pl b/src/tests/vosremove.pl new file mode 100755 index 0000000..5fd53e7 --- /dev/null +++ b/src/tests/vosremove.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_remove("testvol.readonly","localhost","b",); + +exit(0); + + + diff --git a/src/tests/vosremsite.pl b/src/tests/vosremsite.pl new file mode 100755 index 0000000..c93e271 --- /dev/null +++ b/src/tests/vosremsite.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_remsite("testvol","localhost","b",); + +exit(0); + + + diff --git a/src/tests/vosrename.pl b/src/tests/vosrename.pl new file mode 100755 index 0000000..45bdfdb --- /dev/null +++ b/src/tests/vosrename.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_rename("testvol","testvol3",); + +exit(0); + + + diff --git a/src/tests/vosrestore.pl b/src/tests/vosrestore.pl new file mode 100755 index 0000000..9ab0d93 --- /dev/null +++ b/src/tests/vosrestore.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_restore("service2","localhost","a","/usr/tmp/service.dump",,"full",); + +exit(0); + + + diff --git a/src/tests/vossyncserv.pl b/src/tests/vossyncserv.pl new file mode 100755 index 0000000..a6ed963 --- /dev/null +++ b/src/tests/vossyncserv.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_syncserv("localhost","a",,); + +exit(0); + + + diff --git a/src/tests/vossyncvldb.pl b/src/tests/vossyncvldb.pl new file mode 100755 index 0000000..47c4aa9 --- /dev/null +++ b/src/tests/vossyncvldb.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_syncvldb("localhost","b",,); + +exit(0); + + + diff --git a/src/tests/vosunlock.pl b/src/tests/vosunlock.pl new file mode 100755 index 0000000..5dfd1fc --- /dev/null +++ b/src/tests/vosunlock.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_unlock("testvol",); + +exit(0); + + + diff --git a/src/tests/vosunlockall.pl b/src/tests/vosunlockall.pl new file mode 100755 index 0000000..6d9c55f --- /dev/null +++ b/src/tests/vosunlockall.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_lock("testvol",); +&AFS_vos_lock("service",); +&AFS_vos_unlockvldb("localhost",,); + +exit(0); + + + diff --git a/src/tests/voszap.pl b/src/tests/voszap.pl new file mode 100755 index 0000000..bacce85 --- /dev/null +++ b/src/tests/voszap.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT %AFS_Help); +use OpenAFS::afsconf; +use OpenAFS::fs; +use OpenAFS::pts; +use OpenAFS::vos; +use OpenAFS::bos; + +my ($host, $ret); +$host = `hostname`; +&AFS_Init(); + +&AFS_vos_zap("testvol2","localhost","a",,); + +exit(0); + + + diff --git a/src/tests/warn.c b/src/tests/warn.c new file mode 100644 index 0000000..1ecf4bc --- /dev/null +++ b/src/tests/warn.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +RCSID("$Id$"); +#endif + +#include "err.h" + +void +warn(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarn(fmt, ap); + va_end(ap); +} diff --git a/src/tests/warnx.c b/src/tests/warnx.c new file mode 100644 index 0000000..8fd1388 --- /dev/null +++ b/src/tests/warnx.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +RCSID("$Id$"); +#endif + +#include "err.h" + +void +warnx(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); +} diff --git a/src/tests/wrapper.pm b/src/tests/wrapper.pm new file mode 100644 index 0000000..4e4931f --- /dev/null +++ b/src/tests/wrapper.pm @@ -0,0 +1,729 @@ +# CMUCS AFStools +# Copyright (c) 1996, 2001 Carnegie Mellon University +# All rights reserved. +# +# See CMU_copyright.ph for use and distribution information + +package OpenAFS::wrapper; + +=head1 NAME + +OpenAFS::wrapper - AFS command wrapper + +=head1 SYNOPSIS + + use OpenAFS::wrapper; + %result = &wrapper($cmd, \@args, \@pspec, \%options); + +=head1 DESCRIPTION + +This module provides a generic wrapper for calling an external program and +parsing its output. It is primarily intended for use by AFStools for calling +AFS commands, but is general enough to be used for running just about any +utility program. The wrapper is implemented by a single function, +B, which takes several arguments: + +=over 4 + +=item $cmd + +The command to run. This can be a full path, or it can be a simple command +name, in which case B will find the binary on its internal path. + +=item \@args + +A reference to the list of arguments to be passed to the command. Each +element of the list is passed as a single argument, as in B. + +=item \@pspec + +A reference to the list describing how to parse the command's output. +See below for details. + +=item \%options + +A reference to a table of command execution and parsing options. + +=back + +On success, B returns an associative array of data gathered +from the command's output. The exact contents of this array are +caller-defined, and depend on the parsing instructions given. On failure, +an exception will be thrown (using B), describing the reason for the +failure. + +The I<%options> table may be used to pass any or all of the following +options into B, describing how the command should be executed +and its output parsed: + +=over 4 + +=item pass_stderr + +If specified and nonzero, the command's stderr will be passed directly +to the calling program's, instead of being parsed. This is useful when +we want to process the command's output, but let the user see any +diagnostic output or error messages. + +=item pass_stdout + +If specified and nonzero, the command's stdout will be passed directly +to the calling program's, instead of being parsed. This is useful when +the command being run produces diagnostic or error messages on stderr +that we want to parse, but provides bulk data on stdout that we don't +want to touch (e.g. B when the output file is stdout). + +=item path + +If specified, the path to be used for the program to execute, instead of +deriving it from the command name. This is useful when we want the +command's argv[0] (which is always I<$cmd}) to be different from the +path to the program. + +=item errors_last + +If specified and nonzero, the built-in instructions for catching errors +from the command will be added to the end of the instructions in @pspec +instead of to the beginning. + +=back + +=head1 PARSING COMMAND OUTPUT + +The I<@pspec> list describes how to parse command output. Each element +of the list acts like an "instruction" describing how to parse the command's +output. As each line of output is received from the program, the parsing +instructions are run over that line in order. This process continues for +every line of output until the program terminates, or the process is +aborted early by flow-control operators. + +Each parsing instruction is a reference to a list, which consists of a +regular expression and a list of "actions". As a line of output is +processed, it is compared to each instruction's regexp in turn. Whenever +a match is found, the actions associated with that instruction are taken, +in order. Each instruction's regexp may contain one or more parenthesized +subexpressions; generally, each "action" uses up one subexpression, but there +are some exceptions. Due to the current design of B, each regexp +must have at least one subexpression, even if it is not used. + +The acceptable actions are listed below, each followed by a number in brackets +indicating how many subexpressions are "used" by this action. It is an error +if there are not enough subexpressions left to satisfy an action. In the +following descriptions, I<$action> is the action itself (typically a string or +reference), I<$value> is the value of the subexpression that will be used, and +I<%result> is the result table that will be returned by B when the +command completes. + +=over 4 + +=item string [1] + +Sets $result{$action} to $value. Note that several specific strings have +special meaning, and more may be added in the future. To ensure compatibility +with future versions of B, use only valid Perl identifiers as +"string" actions. + +=item scalar ref [1] + +Sets $$action to $value. + +=item list ref [*] + +Pushes the remaining subexpression values onto @$action. This action uses +all remaining subexpression values. + +=item hash ref [2] + +Sets $$action{$value0} to $value1. + +=item code ref [*] + +Calls the referenced function, with all remaining subexpression values as +its arguments. Any values returned by the function will be used to refill +the (now empty) subexpression value list, and thus may be used as arguments +by subsequent actions. If only a few values are required, use a function +like this: + + sub usetwo { # uses two values and preserves the rest + my($val1, $val2, @rest) = @_; + + print STDOUT "Got $val1, $val2\n"; + @rest; + } + +=item '.' [0] + +End processing for this line of output, ignoring any remaining instructions. +Remaining actions in this instruction will be processed. + +=item '+n' [0] + +Skip the next I instructions. This, along with the '.' action, can be +used to build simple flow-control constructs based on the contents of +lines of output. + +=item '-x' [0..1] + +Signal an error after this instruction. Remaining actions in this instruction +will be processed, but no further instructions will be processed for this +line, and no further lines of output will be processed. If I is given, +it will be used as a regexp to match against the B line of output, +and the first parenthesized subexpression resulting from that match will be +used as the error string. Otherwise, one subexpression from the current +line will be used up as the error string. + +=item '?' [1] + +Prints $value to STDOUT. + +=back + +=cut + +use OpenAFS::CMU_copyright; +use OpenAFS::util qw(:DEFAULT :afs_internal); +use Exporter; +use Symbol; + +$VERSION = ''; +$VERSION = '1.00'; +@ISA = qw(Exporter); +@EXPORT = qw(&wrapper); +@EXPORT_OK = qw(&wrapper &fast_wrapper); + +sub wrapper { + my($cmd, $args, $instrs, $options) = @_; + my($prevline, $pid, $exception); + my(@instrs, $instr, $action, @values, $path); + local(%result); + my(@werrinstrs) = ([ '^(wrapper\:.*)', '-' ]); + my(@cerrinstrs) = ([ '^(' . $cmd . '\:.*)', '-' ], + [ '^(' . $path . '\:.*)', '-' ]); + + if ($options->{errors_last}) { + @instrs = (@werrinstrs, @$instrs, @cerrinstrs); + } else { + @instrs = (@werrinstrs, @cerrinstrs, @$instrs); + } + + if ($options->{path}) { + $path = $options->{path}; + } elsif ($cmd =~ /^\//) { + $path = $cmd; + } else { + $path = $AFScmd{$cmd}; + } + + if ($AFS_Trace{wrapper}) { + print STDERR "Instructions:\n"; + foreach $instr (@$instrs) { + print STDERR " /", $instr->[0], "/\n"; + if ($AFS_Trace{wrapper} > 2) { + my(@actions) = @$instr; + shift(@actions); + print " => ", + join(', ', map { ref($_) ? "<" . ref($_) . " reference>" + : $_ } @actions), + "\n"; + } + } + } + + ## Start the child + if ($options->{pass_stdout}) { + open(REALSTDOUT, ">&STDOUT"); + } + $pid = open(AFSCMD, "-|"); + if (!defined($pid)) { + die "wrapper: Fork failed for $cmd: $!\n"; + } + + ## Run the appropriate program + if (!$pid) { + + if ($AFS_Trace{wrapper} > 1) { + print STDERR "Command: $path ", join(' ', @$args), "\n"; + } + + open(STDERR, ">&STDOUT") if (!$options{pass_stderr}); + if ($options{pass_stdout}) { + open(STDOUT, ">&REALSTDOUT"); + close(REALSTDOUT); + } + + { exec($path $cmd, @$args); } + # Need to be careful here - we might be doing "vos dump" to STDOUT + if ($options{pass_stdout}) { + print STDERR "wrapper: Exec failed for $cmd: $!\n"; + } else { + print STDOUT "wrapper: Exec failed for $cmd: $!\n"; + } + exit(127); + } + if ($options{pass_stdout}) { + close(REALSTDOUT); + } + + ## Now, parse the output + line: + while () { + my($skip) = 0; + + print STDERR $_ if ($AFS_Trace{wrapper} > 3); + chop; + + instr: + foreach $instr (@instrs) { + my($dot, $action, @actions); + + if ($skip) { + $skip--; + next instr; + } + $dot = 0; + if ($instr->[0]) { + @values = ($_ =~ $instr->[0]); + next instr if (!@values); + } else { + @values = (); + } + + act: + @actions = @$instr; + shift(@actions); + foreach $action (@actions) { + if (ref($action) eq 'SCALAR') { + if (@values) { + $$action = shift(@values); + } else { + last act; + } + } elsif (ref($action) eq 'ARRAY') { + push(@$action, @values); + @values = (); + } elsif (ref($action) eq 'HASH') { + if (@values > 1) { + $$action{$values[0]} = $values[1]; + shift(@values); shift(@values); + } elsif (@values) { + $$action{shift @values} = ''; + last act; + } else { + last act; + } + } elsif (ref($action) eq 'CODE') { + @values = &$action(@values); + } elsif (ref($action)) { + $exception = "Unknown reference to " . ref($action) + . "in parse instructions"; + last line; + } else { ## Must be a string! + if ($action eq '.') { + $dot = 1; + } elsif ($action =~ /\+(\d+)/) { + $skip = $1; + } elsif ($action =~ /-(.*)/) { + my($pat) = $1; + + if ($pat && $prevline) { + ($exception) = ($prevline =~ $pat); + } elsif (@values) { + $exception = shift(@values); + } else { + $exception = $_; + } + } elsif ($action eq '?') { + print STDOUT (@values ? shift(@values) : $_), "\n"; + } elsif (@values) { + $result{$action} = shift(@values); + } else { + last act; + } + } + } + + last line if ($exception); + last instr if ($dot); + } + $prevline = $_; + } + close(AFSCMD); + $exception .= "\n" if ($exception && $exception !~ /\n$/); + die $exception if ($exception); + %result; +} + + +## Generate code for a fast wrapper (see example below) +sub _fastwrap_gen { + my($instrs, $refs) = @_; + my($SRC, $N, $N1, $X, $instr, $pattern, @actions, $action); + + $N = $X = 0; + $N1 = 1; + + $SRC = <<'#####'; +sub { + my($FD, $refs) = @_; + my($prevline, @values, $skip, $exception); + + line: while (<$FD>) { +##### + + $SRC .= " print STDERR \$_;\n" if ($AFS_Trace{'wrapper'} > 3); + $SRC .= " chop;\n"; + + foreach $instr (@$instrs) { + ($pattern, @actions) = (@$instr); + $SRC .= ($pattern ? <<"#####" : <<"#####"); + + instr_$N: + die \$exception if \$exception; + if (\$skip) { \$skip-- } else { + \@values = (\$_ =~ /$pattern/); + if (\@values) { +##### + + instr_$N: + die \$exception if \$exception; + if (\$skip) { \$skip-- } else { + \@values = (); + if (1) { +##### + + foreach $action (@actions) { + if (ref($action) eq 'SCALAR') { + $refs[++$X] = $action; + $SRC .= <<"#####"; + + if (\@values) { \${\$refs[$X]} = shift (\@values) } + else { goto instr_$N1 } +##### + + } elsif (ref($action) eq 'ARRAY') { + $refs[++$X] = $action; + $SRC .= <<"#####"; + + push(\@{\$refs[$X]}, \@values); + \@values = (); +##### + + } elsif (ref($action) eq 'HASH') { + $refs[++$X] = $action; + $SRC .= <<"#####"; + + if (\@values > 1) { + \$refs[$X]{\$values[0]} = shift(\$values[1]); + shift(\@values); shift(\@values); + } elsif (\@values) { + \$refs[$X]{shift(\@values)} = ''; + goto instr_$N1; + } else { + goto instr_$N1; + } +##### + + } elsif (ref($action) eq 'CODE') { + $refs[++$X] = $action; + $SRC .= "\n \@values = \$refs[$X]->(\@values);\n"; + + } elsif (ref($action)) { + die "Unknown reference to " . ref($action) . "in parse instructions\n"; + + } elsif ($action eq '.') { + $SRC .= "\n next line;\n"; + + } elsif ($action eq '?') { + $SRC .= <<"#####"; + + if (\@values) { print STDOUT shift(\@values), "\\n" } + else { print STDOUT \$_, "\\n" } +##### + + } elsif ($action =~ /\+(\d+)/) { + $SRC .= "\n \$skip = $1;\n"; + + } elsif ($action =~ /-(.*)/) { + $SRC .= $1 ? <<"#####" : <<"#####"; + + if (\$prevline) { (\$exception) = (\$prevline =~ /$1/) } + elsif (\@values) { \$exception = shift(\@values) } + else { \$exception = \$_ } +##### + + if (\@values) { \$exception = shift(\@values) } + else { \$exception = \$_ } +##### + + } else { + $SRC .= <<"#####"; + + if (\@values) { \$result{"\Q$action\E"} = shift(\@values) } + else { goto instr_$N1 } +##### + } + } + + $N++; $N1++; + $SRC .= <<'#####'; + } + } +##### + } + + $SRC .= <<'#####'; + } continue { + die $exception if $exception; + $prevline = $_; + } +} +##### + + $SRC; +} + +####################### Example code ####################### +# sub { +# my($FD, $refs) = @_; +# my($prevline, @values, $skip, $exception); +# +# line: while (<$FD>) { +# print STDERR $_; ## if ($AFS_Trace{'wrapper'} > 3); +# chop; +# +# ## Following block repeated for each instruction +# instr_N: +# die $exception if $exception; +# if ($skip) { $skip-- } else { +# @values = ($_ =~ /## pattern ##/); ## () if no pattern +# if (@values) { ## 1 if no pattern +# ## For each action, include one of the following blocks: +# +# ## SCALAR ref +# if (@values) { ${$refs[X]} = shift (@values) } +# else { goto instr_N+1 } +# +# ## ARRAY ref +# push(@{$refs[X]}, @values); +# @values = (); +# +# ## HASH ref +# if (@values > 1) { +# $refs[X]{shift(@values)} = shift(@values); +# } elsif (@values) { +# $refs[X]{shift(@values)} = ''; +# goto instr_N+1; +# } else { +# goto instr_N+1; +# } +# +# ## CODE ref +# @values = $refs[X]->(@values); +# +# ## string '.' +# next line; +# +# ## string '?' +# if (@values) { print STDOUT shift(@values), "\n" } +# else { print STDOUT $_, "\n" } +# +# ## string '+DDD' +# $skip = DDD; +# +# ## string '-XXX' +# if ($prevline) { ($exception) = ($prefline =~ /XXX/) } +# elsif (@values) { $exception = shift(@values) } +# else { $exception = $_ } +# +# ## string '-' +# if (@values) { $exception = shift(@values) } +# else { $exception = $_ } +# +# ## anything else +# if (@values) { $result{XXX} = shift(@values) } +# else { goto instr_N+1 } +# } +# } +# +# } continue { +# die $exception if $exception; +# $prevline = $_; +# } +# } +############################################################ + + +## The following does exactly the same thing as wrapper(), +## but should be considerably faster. Instead of interpreting +## parsing instructions, it translates them into perl code, +## which is then compiled into the interpreter. The chief +## benefit to this approach is that we no longer compile +## one RE per instruction per line of input. + +sub fast_wrapper { + my($cmd, $args, $instrs, $options) = @_; + my(@instrs, $SRC, $CODE, $path, $pid, $refs, $FD, $exception); + local(%result); + my(@werrinstrs) = ([ '^(wrapper\:.*)', '-' ]); + my(@cerrinstrs) = ([ '^(' . $cmd . '\:.*)', '-' ], + [ '^(' . $path . '\:.*)', '-' ]); + + $FD = gensym; + $refs = []; + if ($options->{errors_last}) { + @instrs = (@werrinstrs, @$instrs, @cerrinstrs); + } else { + @instrs = (@werrinstrs, @cerrinstrs, @$instrs); + } + $SRC = _fastwrap_gen(\@instrs, $refs); + $CODE = eval $SRC; + + if ($options->{path}) { + $path = $options->{path}; + } elsif ($cmd =~ /^\//) { + $path = $cmd; + } else { + $path = $AFScmd{$cmd}; + } + + if ($AFS_Trace{'wrapper'}) { + print STDERR "Instructions:\n"; + foreach $instr (@$instrs) { + print STDERR " /", $instr->[0], "/\n"; + if ($AFS_Trace{'wrapper'} > 2) { + my(@actions) = @$instr; + shift(@actions); + print " => ", + join(', ', map { ref($_) ? "<" . ref($_) . " reference>" + : $_ } @actions), + "\n"; + } + } + } + + if ($AFS_Trace{'wrapper'} > 2) { print STDERR "Input parse code:\n$SRC\n" } + + ## Start the child + if ($options->{pass_stdout}) { + open(REALSTDOUT, ">&STDOUT"); + } + $pid = open($FD, "-|"); + if (!defined($pid)) { + die "wrapper: Fork failed for $cmd: $!\n"; + } + + ## Run the appropriate program + if (!$pid) { + if ($AFS_Trace{'wrapper'} > 1) { + print STDERR "Command: $path ", join(' ', @$args), "\n"; + } + + open(STDERR, ">&STDOUT") if (!$options{pass_stderr}); + if ($options{pass_stdout}) { + open(STDOUT, ">&REALSTDOUT"); + close(REALSTDOUT); + } + + { exec($path $cmd, @$args) } + # Need to be careful here - we might be doing "vos dump" to STDOUT + if ($options{pass_stdout}) { + print STDERR "wrapper: Exec failed for $cmd: $!\n"; + } else { + print STDOUT "wrapper: Exec failed for $cmd: $!\n"; + } + exit(127); + } + if ($options{pass_stdout}) { + close(REALSTDOUT); + } + + ## Now, parse the output + eval { $CODE->($FD, $refs) }; + $exception = $@; + + close($FD); + + $exception .= "\n" if ($exception && $exception !~ /\n$/); + die $exception if ($exception); + %result; +} + + +1; + +=head1 EXAMPLES + +The following set of instructions is used by B to detect errors +issued by the command, or by the child process spawned to invoke the command. +I<$cmd> is the name of the command to run, and I<$path> is the path to the +binary actually invoked. + + [ '^(wrapper\:.*)', '-' ] + [ '^(' . $cmd . '\:.*)', '-' ] + [ '^(' . $path . '\:.*)', '-' ] + +The following instruction is added by the B module to catch errors +generated by B commands, which often take the form of a generic error +message (Error in vos XXX command), with a description of the specific problem +on the preceeding line: + + [ 'Error in vos (.*) command', '-(.*)' ] + +If the AFStools parameter I is nonzero, the following instruction +is added to force all lines of output to be copied to STDOUT. Note that this +is different from specifying the I option, which would pass the +command's STDOUT directly to ours without parsing it. + + [ '', '?' ] + +B uses the following instructions to parse the +output of "vos listvldb". This is a fairly complex example, which illustrates +many of the features of B. + + 1 ['^(VLDB|Total) entries', '.'] + 2 ['^(\S+)', sub { + my(%vinfo) = %OpenAFS::wrapper::result; + if ($vinfo{name}) { + $vinfo{rosites} = [@rosites] if (@rosites); + $vlist{$vinfo{name}} = \%vinfo; + @rosites = (); + %OpenAFS::wrapper::result = (); + } + }], + 3 ['^(\S+)', 'name' ], + 4 ['RWrite\:\s*(\d+)', 'rwid' ], + 5 ['ROnly\:\s*(\d+)', 'roid' ], + 6 ['Backup\:\s*(\d+)', 'bkid' ], + 7 ['Volume is currently (LOCKED)', 'locked' ], + 8 ['server (\S+) partition /vicep(\S+) RW Site', 'rwserv', 'rwpart'], + 9 ['server (\S+) partition /vicep(\S+) RO Site', sub { + push(@rosites, [$_[0], $_[1]]); + }], + +Instruction 1 matchees the header and trailer lines printed out by B, and +terminates processing of those lines before instructions 2 and 3 have a chance +to match it. This is a simple example of a conditional - the next two +instructions are used only if this one doesn't match. If we wanted to consider +additional instructions even on lines that do match this one, we could place +them above this one, or use '+2' instead of '.', which would skip only the next +two instructions and allow remaining ones to be processed. + +Instruction 2 matches the first line printed for each volume, stores away any +information that has been collected about the previous volume, and prepares for +the new one. Besides being a good example of use of a code reference as an +action, this instruction also takes advantage of the fact that B's +%result array is a dynamically-scoped variable, and so can be modified by code +referenced in parsing instructions. + +The remaining instructions are fairly simple. Instructions 3 through 8 use +simple strings to add information about the volume to %result. Instruction 9 +is a bit more complicated; it uses a function to add a server/partition pair +to the current volume's list of RO sites. + +=head1 COPYRIGHT + +The CMUCS AFStools, including this module are +Copyright (c) 1996, 2001 Carnegie Mellon University. All rights reserved. +For use and redistribution information, see CMUCS/CMU_copyright.pm + +=cut diff --git a/src/tests/write-closed.c b/src/tests/write-closed.c new file mode 100644 index 0000000..7941bf9 --- /dev/null +++ b/src/tests/write-closed.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static void +doit (const char *filename) +{ + int fd; + int ret; + void *buf; + + fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + err (1, "open %s", filename); + ret = ftruncate (fd, 1); + if (ret < 0) + err (1, "ftruncate %s", filename); + buf = mmap (NULL, 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (buf == (void *) MAP_FAILED) + err (1, "mmap"); + if (fchmod (fd, 0) < 0) + err (1, "fchmod %s, 0", filename); + ret = close (fd); + if (ret < 0) + err (1, "close %s", filename); + *((char *)buf) = 0x17; + ret = munmap (buf, 1); + if (ret < 0) + err (1, "munmap"); +} + +int +main(int argc, char **argv) +{ + const char *file = "foo"; + + if (argc != 1 && argc != 2) + errx (1, "usage: %s [file]", argv[0]); + if (argc == 2) + file = argv[1]; + doit (file); + return 0; +} diff --git a/src/tests/write-closed2.c b/src/tests/write-closed2.c new file mode 100644 index 0000000..b68374d --- /dev/null +++ b/src/tests/write-closed2.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#ifdef HAVE_SYS_IOCCOM_H +#include +#endif +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static int +set_acl (char *dir) +{ + struct ViceIoctl a_params; + char *foo = "1\n0\nsystem:anyuser 0\n"; + + a_params.in_size = strlen(foo); + a_params.out_size = 0; + a_params.in = foo; + a_params.out = NULL; + + return pioctl (dir, VIOCSETAL, &a_params, 1); +} + +static void +doit (const char *filename) +{ + int fd; + int ret; + void *buf; + + ret = mkdir ("bad", 0777); + if (ret < 0) + err (1, "mkdir bad"); + + ret = chdir ("bad"); + if (ret < 0) + err (1, "chdir bad"); + + fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + err (1, "open %s", filename); + ret = ftruncate (fd, 1); + if (ret < 0) + err (1, "ftruncate %s", filename); + buf = mmap (NULL, 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (buf == (void *) MAP_FAILED) + err (1, "mmap"); + ret = set_acl ("."); + if (ret < 0) + err (1, "setacl failed"); + + ret = close (fd); + if (ret < 0) + err (1, "close %s", filename); + *((char *)buf) = 0x17; + ret = munmap (buf, 1); + if (ret < 0) + err (1, "munmap"); +} + +int +main(int argc, char **argv) +{ + const char *file = "foo"; + + + if (argc != 1 && argc != 2) + errx (1, "usage: %s [file]", argv[0]); + if (argc == 2) + file = argv[1]; + doit (file); + return 0; +} diff --git a/src/tests/write-large.c b/src/tests/write-large.c new file mode 100644 index 0000000..3d02570 --- /dev/null +++ b/src/tests/write-large.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define _LARGEFILE64_SOURCE + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include +#include +#include + + +#include + +const char *fn = "foobar"; + +static void +check_size(const char *fn, size_t sz, int paranoia) +{ + struct stat sb; + + if (paranoia) + return; + + if (stat(fn, &sb) < 0) + err(1, "stat"); + if (sb.st_size != sz) + errx(1, "st_size mismatch %d != %d", (int)sb.st_size, (int)sz); +} + +int +main(int argc, char **argv) +{ + int fd, cnt, ret; + int buf[1024]; + +#ifdef O_LARGEFILE + fd = open(fn, O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0644); +#else + fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, 0644); +#endif + if (fd < 0) + err(1, "open1"); + cnt=0; + while (cnt < 2097151) { + ret = write(fd,buf,1024); + if (ret != 1024) + errx(1, "write1 %d %d", cnt, ret); + cnt++; + } + ret = write(fd,buf,1024); + if (ret != 1023) + errx(1, "write1 last %d", ret); + if (close(fd) < 0) + err(1, "close1"); + + check_size(fn, 2147483647, 0); + + return 0; +} diff --git a/src/tests/write-rand.c b/src/tests/write-rand.c new file mode 100644 index 0000000..655eb11 --- /dev/null +++ b/src/tests/write-rand.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +static char * +write_random_file (int fd, size_t sz) +{ + char *buf; + int i, j; + + j = sz; + if (j > 2048) { + j = 2048; + } + buf = malloc (j); + if (buf == NULL) + err (1, "malloc %u", (unsigned)sz); + + for (i = 0; i < j; ++i) { + buf[i] = rand(); + } + while (sz > 0) { + if (write (fd, buf, j) != j) + err (1, "write"); + + sz -= j; + j = sz; + if (j > 2048) + j = 2048; + } + + return 0; +} + +int +main (int argc, char **argv) +{ + const char *file; + const size_t sz; + char *random_buf; + char *read_buf1; + char *read_buf2; + int fd; + + if (argc != 3) + errx (1, "usage: %s file size", argv[0]); + + file = argv[1]; + sz = atoi(argv[2]); + + srand (time(NULL)); + + fd = open (file, O_RDWR | O_CREAT, 0755); + if (fd < 0) + err (1, "open %s", file); + + if (lseek(fd, 0, SEEK_SET) < 0) + err (1, "lseek"); + write_random_file(fd, sz); + + close (fd); + return 0; +} diff --git a/src/tests/write-ro b/src/tests/write-ro new file mode 100755 index 0000000..9be34f0 --- /dev/null +++ b/src/tests/write-ro @@ -0,0 +1,3 @@ +#!/bin/sh +touch ../../replicated/foo || exit 0 +exit 1 diff --git a/src/tests/write-ro-file.c b/src/tests/write-ro-file.c new file mode 100644 index 0000000..cdf41bd --- /dev/null +++ b/src/tests/write-ro-file.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#ifdef RCSID +RCSID("$Id$"); +#endif + +int +main(int argc, char *argv[]) +{ + int fd; + int ret; + + fd = open("foo", O_RDWR|O_CREAT, 0); + if (fd < 0) + err (1, "open foo"); + ret = write (fd, "foo", 3); + if (ret < 0) { + unlink("foo"); + err (1, "write foo"); + } + ret = close (fd); + if (ret < 0) { + unlink("foo"); + err (1, "close foo"); + } + unlink("foo"); + return 0; +} diff --git a/src/tests/write-ucc.c b/src/tests/write-ucc.c new file mode 100644 index 0000000..f94afeb --- /dev/null +++ b/src/tests/write-ucc.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static void +doit (const char *filename) +{ + int fd; + int ret; + struct timeval tv[2]; + struct stat sb; + + fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + err (1, "open %s", filename); + ret = write (fd, "hej\n", 4); + if(ret < 0) + err (1, "write %s", filename); + if (ret != 4) + errx (1, "short write to %s", filename); + gettimeofday (&tv[0], NULL); + tv[1] = tv[0]; + ret = utimes (filename, tv); + if(ret < 0) + err (1, "utimes %s", filename); + ret = chmod (filename, 0644); + if (ret < 0) + err (1, "chmod %s", filename); + ret = chown (filename, 0, 0); + ret = fstat (fd, &sb); + if (ret < 0) + err (1, "fstat %s", filename); + if (sb.st_size != 4) + errx (1, "stat 1: size = %lu != 4", (unsigned long)sb.st_size); + ret = close (fd); + if (ret < 0) + err (1, "close %s", filename); + ret = stat (filename, &sb); + if (ret < 0) + err (1, "stat %s", filename); + if (sb.st_size != 4) + errx (1, "stat 1: size = %lu != 4", (unsigned long)sb.st_size); +} + +int +main(int argc, char **argv) +{ + const char *file = "blaha"; + + if (argc != 1 && argc != 2) + errx (1, "usage: %s [file]", argv[0]); + if (argc == 2) + file = argv[1]; + doit (file); + return 0; +} diff --git a/src/tests/write1 b/src/tests/write1 new file mode 100755 index 0000000..00d386d --- /dev/null +++ b/src/tests/write1 @@ -0,0 +1,4 @@ +#!/bin/sh +echo hej > foo || exit 1 +if test X`cat foo` != X"hej"; then exit 1; fi +rm foo || exit 1 diff --git a/src/tests/write2 b/src/tests/write2 new file mode 100755 index 0000000..90808c6 --- /dev/null +++ b/src/tests/write2 @@ -0,0 +1,6 @@ +#!/bin/sh +echo hopp > foo || exit 1 +if test X`cat foo` != "Xhopp"; then exit 1; fi +echo hej > foo || exit 1 +if test X`cat foo` != "Xhej"; then exit 1; fi +rm foo || exit 1 diff --git a/src/tests/write3.c b/src/tests/write3.c new file mode 100644 index 0000000..6de1511 --- /dev/null +++ b/src/tests/write3.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include +#include +#include + + +#include + +const char *fn = "foobar"; + +static void +check_size(const char *fn, size_t sz, int paranoia) +{ + struct stat sb; + + if (paranoia) + return; + + if (stat(fn, &sb) < 0) + err(1, "stat"); + if (sb.st_size != sz) + errx(1, "st_size mismatch %d != %d", (int)sb.st_size, (int)sz); +} + +static void +check_size_read(int fd, size_t sz) +{ + off_t old_off; + size_t sz2; + void *buf; + + if ((old_off = lseek(fd, 0, SEEK_CUR)) < 0) + err(1, "lseek"); + + if (lseek(fd, 0, SEEK_SET) < 0) + err(1, "lseek"); + buf = malloc(sz); + if (buf == NULL) + errx(1, "malloc"); + if ((sz2 = read(fd, buf, sz)) < 0) + errx(1, "read"); + if (sz2 != sz) + errx(1, "end before end: sz2 (%u) != sz (%u)", (unsigned)sz2, + (unsigned)sz); + if ((sz2 = lseek(fd, 0, SEEK_END)) < 0) + errx(1, "lseek"); + if (sz2 != sz) + errx(1, "end past end: sz2 (%u) != sz (%u)", (unsigned)sz2, + (unsigned)sz); + free(buf); +} + + +int +main(int argc, char **argv) +{ + int fd; + + fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, 0644); + if (fd < 0) + err(1, "open1"); + if (write(fd,"kaka", 4) != 4) + errx(1, "write1"); + check_size(fn, 4, 1); + if (close(fd) < 0) + err(1, "close1"); + + check_size(fn, 4, 0); + + fd = open(fn,O_RDWR|O_CREAT|O_TRUNC,644); + if (fd < 0) + err(1, "open2"); + check_size(fn, 0, 1); + if (write(fd,"kaka", 4) != 4) + errx(1, "write2"); + check_size(fn, 4, 1); + check_size_read(fd, 4); + if (close(fd) < 0) + err(1, "close2"); + check_size(fn, 4, 1); + + unlink(fn); + + return 0; +}