[Ocfstest-commits] rev 2 - / CVS Ocfsts Ocfsts/CVS Ocfsts/t Ocfsts/t/CVS client client/CVS monkey monkey/CVS server server/CVS tests tests/CVS

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Aug 19 18:24:41 CDT 2003


Author: gmarsden
Date: 2003-08-19 17:24:38 -0500 (Tue, 19 Aug 2003)
New Revision: 2

Added:
   CVS/
   CVS/Entries
   CVS/Entries.Log
   CVS/Repository
   CVS/Root
   Cmdlist.sample
   Makefile
   Makefile.config
   Nodelist.sample
   Ocfsts/
   Ocfsts/Build.wrapper
   Ocfsts/CVS/
   Ocfsts/CVS/Entries
   Ocfsts/CVS/Entries.Log
   Ocfsts/CVS/Repository
   Ocfsts/CVS/Root
   Ocfsts/Changes
   Ocfsts/MANIFEST
   Ocfsts/Makefile.PL
   Ocfsts/Ocfsts.pm
   Ocfsts/Ocfsts.xs
   Ocfsts/README
   Ocfsts/perlobject.map
   Ocfsts/ppport.h
   Ocfsts/t/
   Ocfsts/t/1.t
   Ocfsts/t/CVS/
   Ocfsts/t/CVS/Entries
   Ocfsts/t/CVS/Repository
   Ocfsts/t/CVS/Root
   Ocfsts/test.pl
   README
   TODO
   client/
   client/CVS/
   client/CVS/Entries
   client/CVS/Repository
   client/CVS/Root
   client/Makefile
   client/cdsl.h
   client/client.c
   client/command.c
   client/command.h
   client/exec.c
   client/exec.h
   client/md5.c
   client/md5.h
   client/ocfstsparse.c
   client/ocfstsparse.h
   client/response.c
   client/response.h
   client/testpacket
   monkey/
   monkey/CVS/
   monkey/CVS/Entries
   monkey/CVS/Repository
   monkey/CVS/Root
   ocfsts.h
   ocfsts.sh
   ocfsts_diff.pl
   server/
   server/CVS/
   server/CVS/Entries
   server/CVS/Repository
   server/CVS/Root
   server/Makefile
   server/apitest.c
   server/comm.c
   server/comm.h
   server/debug.h
   server/logprint.c
   server/logprint.h
   server/md5print.h
   server/nodelist
   server/ocfs_test.c
   server/ocfs_test.h
   server/ocfs_test_server.c
   server/ocfs_test_server.h
   server/ocfstsapi.c
   server/ocfstsapi.h
   server/syntax.h
   testclient.pl
   tests/
   tests/00_simple.pl
   tests/05_tree.pl
   tests/06_tree_delete.pl
   tests/15_mvtests.pl
   tests/30_manyfiles.pl
   tests/45_openclose.pl
   tests/CVS/
   tests/CVS/Entries
   tests/CVS/Repository
   tests/CVS/Root
   tests/Makefile
   tests/ocfsts_config
Log:
OcfsTest first import to SVN



Added: CVS/Entries
===================================================================
--- CVS/Entries	2003-08-16 22:26:26 UTC (rev 1)
+++ CVS/Entries	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,11 @@
+/Cmdlist.sample/1.1/Fri Oct 11 01:03:52 2002//
+/Makefile/1.22/Wed Dec 11 00:39:38 2002//
+/Makefile.config/1.1/Wed Dec 11 00:28:47 2002//
+/Nodelist.sample/1.1/Fri Oct 11 01:03:52 2002//
+/README/1.5/Mon Dec  9 21:26:06 2002//
+/TODO/1.4/Fri Dec 13 00:15:34 2002//
+/ocfsts.h/1.3/Thu Oct 17 00:44:27 2002//
+/ocfsts.sh/1.13/Wed Dec 11 00:28:47 2002//
+/ocfsts_diff.pl/1.3/Thu Oct 17 20:59:41 2002//
+/testclient.pl/1.1/Thu Dec  5 01:00:40 2002//
+D

Added: CVS/Entries.Log
===================================================================
--- CVS/Entries.Log	2003-08-16 22:26:26 UTC (rev 1)
+++ CVS/Entries.Log	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,5 @@
+A D/Ocfsts////
+A D/client////
+A D/monkey////
+A D/server////
+A D/tests////

Added: CVS/Repository
===================================================================
--- CVS/Repository	2003-08-16 22:26:26 UTC (rev 1)
+++ CVS/Repository	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+ocfsts

Added: CVS/Root
===================================================================
--- CVS/Root	2003-08-16 22:26:26 UTC (rev 1)
+++ CVS/Root	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+:pserver:gmarsden at nic1-pc:/cvs/nic

Added: Cmdlist.sample
===================================================================
--- Cmdlist.sample	2003-08-16 22:26:26 UTC (rev 1)
+++ Cmdlist.sample	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,16 @@
+
+R mkdir /tmp/foo 0666
+R chmod /tmp/foo 0766
+
+R create /tmp/foo/bar
+R chmod /tmp/foo/bar 0766
+
+R resize /tmp/foo/bar 2048
+R modify /tmp/foo/bar 1
+
+- R delete /tmp/foo/bar/baz
+
+R delete /tmp/foo/bar
+R rmdir /tmp/foo
+
+R quit

Added: Makefile
===================================================================
--- Makefile	2003-08-16 22:26:26 UTC (rev 1)
+++ Makefile	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,52 @@
+# 
+# ocfsts Makefile
+#
+
+include Makefile.config
+
+SERVERDIR=server
+CLIENTDIR=client
+
+.PHONY: clean tests perl
+
+all: all-redirect library perl
+
+library: $(OCFSTS_LIB_TARGET) $(OCFSTS_LIB_SERVER_TARGET)
+	mv $(OCFSTS_LIB_SERVER_TARGET) $(PERL_DIR)/
+
+perl:
+	make -f Build.wrapper -C $(PERL_DIR)
+
+tests:
+	make -C $(TEST_DIR)
+
+tests-clean:
+	make clean -C $(TEST_DIR)
+
+all-redirect: $(OCFSTS_LIB_TARGET) $(CLIENT_TARGET) $(SERVER_TARGET) 
+
+#include Makefile.depend
+#depend:
+#	$(CC) $(CXXFLAGS) -MM `find . -name '*.c'` > Makefile.depend
+
+$(OCFSTS_LIB_TARGET):
+	make -e -C $(CLIENTDIR) $@
+	mv $(CLIENTDIR)/$@ .
+
+$(SERVER_TARGET): $(OCFSTS_LIB_TARGET)
+	make -e -C $(SERVERDIR) $@
+	mv $(SERVERDIR)/$@ .
+
+$(CLIENT_TARGET): $(OCFSTS_LIB_TARGET)
+	make -e -C $(CLIENTDIR) $@
+	mv $(CLIENTDIR)/$@ .
+
+$(OCFSTS_LIB_SERVER_TARGET):
+	make -e -C $(SERVERDIR) $@
+	mv $(SERVERDIR)/$@ .
+
+clean:
+	make -e -C $(SERVERDIR) clean
+	make -e -C $(CLIENTDIR) clean
+	rm -f $(OCFSTS_LIB_TARGET) $(CLIENT_TARGET) $(SERVER_TARGET) $(OCFSTS_LIB_SERVER_TARGET) *~
+	make -e -C $(PERL_DIR) -f Build.wrapper clean

Added: Makefile.config
===================================================================
--- Makefile.config	2003-08-16 22:26:26 UTC (rev 1)
+++ Makefile.config	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,23 @@
+#
+# Be carefull - this also gets sourced by a bash script.
+# Blame Greg for that one :)
+#
+TARGET=.
+NODEFILE=nodelist
+
+TEST_DIR="tests";
+RESULT_DIR="results";
+ORIGINAL_DIR="diffs";
+PERL_DIR=Ocfsts
+
+SERVER_TARGET=ocfsts_server
+CLIENT_TARGET=ocfsts_client
+OCFSTS_LIB_TARGET=libocfsts.a
+OCFSTS_LIB_SERVER_TARGET=libocfsts_server.so
+
+CLIENT_INSTALL_DIR=/tmp
+CLIENT_USER=root
+
+OCFSTS_PORT=4444
+
+DIFF=ocfsts_diff.pl

Added: Nodelist.sample
===================================================================
--- Nodelist.sample	2003-08-16 22:26:26 UTC (rev 1)
+++ Nodelist.sample	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,11 @@
+# Sample node list for OCFS test suite
+verbose.us.oracle.com 
+verbose.us.oracle.com 
+verbose.us.oracle.com 
+verbose.us.oracle.com 
+#192.168.0.1
+#192.168.0.2
+#192.168.0.3
+#192.168.0.4
+#192.168.0.5
+#nic1-pc.us.oracle.com

Added: Ocfsts/Build.wrapper
===================================================================
--- Ocfsts/Build.wrapper	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/Build.wrapper	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,10 @@
+#needed to build this from the main makefile
+all:
+	perl Makefile.PL
+	make
+
+.PHONY: clean
+
+clean:
+	- make clean
+	rm -f *~ $(OCFSTS_LIB_SERVER_TARGET)

Added: Ocfsts/CVS/Entries
===================================================================
--- Ocfsts/CVS/Entries	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/CVS/Entries	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,11 @@
+/Build.wrapper/1.1/Wed Dec 11 00:20:34 2002//
+/Changes/1.1/Fri Dec  6 03:40:45 2002//
+/MANIFEST/1.1/Fri Dec  6 03:40:45 2002//
+/Makefile.PL/1.2/Thu Dec 12 02:10:18 2002//
+/Ocfsts.pm/1.8/Fri Dec 13 00:35:01 2002//
+/Ocfsts.xs/1.4/Mon Dec  9 19:38:16 2002//
+/README/1.1/Fri Dec  6 03:40:45 2002//
+/perlobject.map/1.1/Fri Dec  6 03:40:45 2002//
+/ppport.h/1.1/Fri Dec  6 03:40:45 2002//
+/test.pl/1.12/Fri Dec 13 00:35:01 2002//
+D

Added: Ocfsts/CVS/Entries.Log
===================================================================
--- Ocfsts/CVS/Entries.Log	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/CVS/Entries.Log	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+A D/t////

Added: Ocfsts/CVS/Repository
===================================================================
--- Ocfsts/CVS/Repository	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/CVS/Repository	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+ocfsts/Ocfsts

Added: Ocfsts/CVS/Root
===================================================================
--- Ocfsts/CVS/Root	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/CVS/Root	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+:pserver:gmarsden at nic1-pc:/cvs/nic

Added: Ocfsts/Changes
===================================================================
--- Ocfsts/Changes	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/Changes	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,6 @@
+Revision history for Perl extension Ocfsts.
+
+0.01  Thu Dec  5 13:54:20 2002
+	- original version; created by h2xs 1.22 with options
+		-A -d ocfsts
+

Added: Ocfsts/MANIFEST
===================================================================
--- Ocfsts/MANIFEST	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/MANIFEST	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,8 @@
+Changes
+Makefile.PL
+MANIFEST
+Ocfsts.pm
+Ocfsts.xs
+ppport.h
+README
+t/1.t

Added: Ocfsts/Makefile.PL
===================================================================
--- Ocfsts/Makefile.PL	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/Makefile.PL	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,30 @@
+use 5.008;
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+
+#my own stuff here to support the fatally broken beast that is C++
+#$CC = 'g++';
+
+WriteMakefile(
+    'NAME'		=> 'Ocfsts',
+    'VERSION_FROM'	=> 'Ocfsts.pm', # finds $VERSION
+    'PREREQ_PM'		=> {}, # e.g., Module::Name => 1.1
+    ($] >= 5.005 ?    ## Add these new keywords supported since 5.005
+      (ABSTRACT_FROM => 'Ocfsts.pm', # retrieve abstract from module
+       AUTHOR     => 'Mark Fasheh <mark.fasheh at oracle.com>') : ()),
+    'LIBS'		=> ['-L. -locfsts_server'], # e.g., '-lm'
+    'DEFINE'		=> '', # e.g., '-DHAVE_SOMETHING'
+#next two lines added for C++
+#    'CC'                => $CC,
+#    'LD'                => '$(CC)',
+
+    'INC'		=> '-I. -I../server/', # e.g., '-I. -I/usr/include/other'
+	# Un-comment this if you add C files to link with later:
+    # 'OBJECT'		=> '$(O_FILES)', # link all the C files too
+    #'OBJECT'		=> '../libocfsts_server.a', # link all the C files too
+
+#next two lines added for C++
+#    'XSOPT'             => '-C++',
+#    'TYPEMAPS'          => ['perlobject.map' ],
+);

Added: Ocfsts/Ocfsts.pm
===================================================================
--- Ocfsts/Ocfsts.pm	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/Ocfsts.pm	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,343 @@
+package Ocfsts;
+
+use 5.008;
+#use strict;
+use warnings;
+use English;
+
+require Exporter;
+
+our @ISA = qw(Exporter);
+
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+
+# This allows declaration	use Ocfsts ':all';
+# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
+# will save memory.
+our %EXPORT_TAGS = ( 'all' => [ qw(
+	
+) ] );
+
+our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+
+our @EXPORT = qw(
+	
+);
+
+our $VERSION = '0.01';
+
+require XSLoader;
+XSLoader::load('Ocfsts', $VERSION);
+
+# Preloaded methods go here.
+
+%NUMARGS = (
+	    "create"    => 1,
+	    "delete"    => 1,
+	    "fstat"     => 1,
+	    "chksum"    => 1,
+	    "rmdir"     => 1,
+	    "link"      => 2,
+	    "symlink"   => 2,
+	    "mv"        => 2,
+	    "mkdir"     => 2,
+	    "chmod"     => 2,
+	    "resize"    => 2,
+	    "modify"    => 2,
+	    "chown"     => 3,
+	    "mknod"     => 4,
+	    "open"      => 1,
+	    "close"     => 1
+	    );
+
+#children pids
+my @children;
+#are we a parent process or not?
+my $isparent = "true";
+
+sub ocfsts_set_child {
+    #print "Child at pid=", $$, "\n";
+    $isparent = "false";
+}
+
+sub ocfsts_set_parent($) {
+    my $pid = shift;
+
+    #print "Parent pushing $pid onto children array.\n";
+    push @children, $pid;
+}
+
+sub ocfsts_read_nodelist($) {
+    $filename = shift;
+    #print "reading nodelist from ", $filename, "\n";
+    open(NODEFILE, $filename) or return;
+
+    while (<NODEFILE>) {
+	/^\s*([\w.-]+)/ and push @NODES, $1;
+    }
+
+    close (NODEFILE);
+
+    return @NODES;
+}
+
+sub ocfsts_connect(@) {
+    @nodes = @_;
+    #$LIST_SEPARATOR="\n";
+    #print "connecting to these nodes:\n";
+    #print "@nodes";
+    #print "\n";
+    if ($#nodes >= 0) {
+	return Ocfsts::ocfsts_open_connection(@nodes);
+    }
+    return -1;
+}
+
+sub ocfsts_connect_n_procs($@) {
+    my $numprocs = shift;
+    my @nodes = shift;
+    my $i;
+    my $cpid;
+    my $retval;
+
+    #print "Will create $numprocs processes on each node\n";
+
+    #print "On nodes:\n";
+    #print "@nodes\n";
+    #print "\n";
+    
+    for ($i=0; $i < ($numprocs-1); $i++) {
+	$cpid = fork();
+	
+	if (!defined $cpid) {
+	    die "Error[$$]: Couldn't fork!\n";
+	}
+	
+	if ($cpid == 0) {
+	    Ocfsts::ocfsts_set_child;
+	      $retval = Ocfsts::ocfsts_connect @nodes;
+	      return $retval;
+	  } else {
+	      Ocfsts::ocfsts_set_parent $cpid;
+	    }
+    }
+
+    $retval = Ocfsts::ocfsts_connect @nodes;
+    return $retval;
+}
+
+sub ocfsts_disconnect {
+    my $child;
+    #If we have a bunch of children, waitpid on them to reap zombies.
+    #This also has the effect of 
+    if ($isparent eq "true") {
+	while (@children) {
+	    $child = pop @children;
+	    waitpid $child, 0;
+	    print "Parent: child $child reaped.\n";
+	}
+    }
+
+    #Actually disconnect from the node now.
+    return Ocfsts::ocfsts_close_connection();
+}
+
+
+#
+# expects as the 1st string argument, the actual command
+# after that, all the arguments to that command, then
+# the last two arguments are node name (leave empty for random)
+# and expected outcome ("f" for fail, empty or anything else for success)
+#
+#  ocfsts_build_command "command", rest-of-command-args, [$node, $expected];
+#
+sub ocfsts_build_command {
+    my $command;
+    my $str;
+    my $node;
+    my $expected;
+    my $i;
+
+    $command = $_[0];
+    if ($command eq "" || !defined $NUMARGS{$command}) {
+	die "ocfsts_build_command called with a null or nonexistent command!\n";
+    }
+
+    $str = $command;
+    for ($i = 1; $i <= $NUMARGS{$command}; $i++) {
+	if (!defined $_[$i]) {
+	    die "ocfsts_build_command: command \"$command\" without enough arguments\n";
+	}
+	$str = $str." ".$_[$i];
+    }
+
+    $node = "";
+    $expected = "";
+    if (defined $_[$i]) {
+	$node = $_[$i];
+	$i++;
+	if (defined $_[$i]) {
+	    $expected = $_[$i];
+	}
+    }
+    #print "node is $node and expected is $expected\n";
+
+    if ($node eq "") {
+	$node = "R";
+    }
+    $str = "$node $str";
+    if ($expected eq "f" || $expected eq "F" || $expected eq "FAIL" || $expected eq "fail") {
+	$str = "- ".$str;
+    }
+    
+    # print "built command: $str\n";
+    return $str;
+}
+
+sub ocfsts_do_command_full {
+    $command = shift;
+    $str = ocfsts_build_command $command, @_;
+    if ($str eq "") {
+	print "ocfsts_do_command_full: Error building command, not sending.";
+	return;
+    }
+
+    #print "Sending execution string: $str\n";
+    $retval = Ocfsts::ocfsts_execute($str);
+    #print "Execute returns: $retval\n";
+    if ($retval != 0) {
+	print "ocfsts_do_command_full: Error returned from command: \"$str\"\n";
+	return;
+    }
+    $retval = Ocfsts::ocfsts_verify($str);
+    #print "Verify returns: $retval\n";
+    if ($retval != 0) {
+	print "ocfsts_do_command_full: Error verifying command, string = \"$str\"\n";
+	return;
+    }
+    return $retval;
+}
+
+sub ocfsts_create {
+    return ocfsts_do_command_full "create", @_;
+}
+
+sub ocfsts_delete {
+    return ocfsts_do_command_full "delete", @_;
+}
+
+sub ocfsts_fstat {
+    return ocfsts_do_command_full "fstat", @_;
+}
+
+sub ocfsts_chksum {
+    return ocfsts_do_command_full "chksum", @_;
+}
+
+sub ocfsts_rmdir {
+    return ocfsts_do_command_full "rmdir", @_;
+}
+
+sub ocfsts_link {
+    return ocfsts_do_command_full "link", @_;
+}
+
+sub ocfsts_symlink {
+    return ocfsts_do_command_full "symlink", @_;
+}
+
+sub ocfsts_mv {
+    return ocfsts_do_command_full "mv", @_;
+}
+
+sub ocfsts_mkdir {
+    return ocfsts_do_command_full "mkdir", @_;
+}
+
+sub ocfsts_chmod {
+    return ocfsts_do_command_full "chmod", @_;
+}
+
+sub ocfsts_resize {
+    return ocfsts_do_command_full "resize", @_;
+}
+
+sub ocfsts_modify {
+    return ocfsts_do_command_full "modify", @_;
+}
+
+sub ocfsts_chown {
+    return ocfsts_do_command_full "chown", @_;
+}
+
+sub ocfsts_mknod {
+    return ocfsts_do_command_full "mknod", @_;
+}
+
+sub ocfsts_open {
+    return ocfsts_do_command_full "open", @_;
+}
+
+sub ocfsts_close {
+    return ocfsts_do_command_full "close", @_;
+}
+
+
+__END__
+# Below is stub documentation for your module. You'd better edit it!
+
+=head1 NAME
+
+Ocfsts - Perl extension for blah blah blah
+
+=head1 SYNOPSIS
+
+  use Ocfsts;
+  blah blah blah
+
+=head1 ABSTRACT
+
+  This should be the abstract for Ocfsts.
+  The abstract is used when making PPD (Perl Package Description) files.
+  If you don't want an ABSTRACT you should also edit Makefile.PL to
+  remove the ABSTRACT_FROM option.
+
+=head1 DESCRIPTION
+
+Stub documentation for Ocfsts, created by h2xs. It looks like the
+author of the extension was negligent enough to leave the stub
+unedited.
+
+Blah blah blah.
+
+=head2 EXPORT
+
+None by default.
+
+
+
+=head1 SEE ALSO
+
+Mention other useful documentation such as the documentation of
+related modules or operating system documentation (such as man pages
+in UNIX), or any relevant external documentation such as RFCs or
+standards.
+
+If you have a mailing list set up for your module, mention it here.
+
+If you have a web site set up for your module, mention it here.
+
+=head1 AUTHOR
+
+Mark Fasheh, E<lt>mfasheh at localdomainE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright 2002 by Mark Fasheh
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself. 
+
+=cut

Added: Ocfsts/Ocfsts.xs
===================================================================
--- Ocfsts/Ocfsts.xs	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/Ocfsts.xs	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,77 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#include "ppport.h"
+
+#include <stdio.h>
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "../server/ocfstsapi.h"
+
+
+MODULE = Ocfsts		PACKAGE = Ocfsts		
+
+int 
+ocfsts_open_connection(...)
+	PREINIT:
+		int i = 0;
+		SV* value = NULL;
+		char *str;
+		char** array = NULL;
+	CODE:
+		/* allocate the memory for our array... */
+		//printf("items=%d\n", items);
+		array = (char **) malloc(items * sizeof(char *));
+		for (i = 0; i < items; i++) {
+			value = ST(i);
+			str = SvPV(value, PL_na);
+			//printf("Passing: %s\n", str);
+			array[i] = strdup(str);
+		}
+		RETVAL = ocfsts_open_connection(items, array);
+		//printf("Freeing these values...\n");
+		fflush(stdout);
+		for (i = 0; i < items; i++) {
+			free(array[i]);
+		}
+		free(array);
+		//printf("Free'd\n");
+	OUTPUT:
+		RETVAL
+        
+int
+ocfsts_close_connection()
+
+int
+ocfsts_execute(command)
+	char *command;
+	SV* value = NULL;
+	CODE:
+		value = ST(0);
+		command = SvPV(value, PL_na);
+		//printf("command string is %s\n", command);
+		RETVAL = ocfsts_execute(command);
+	OUTPUT:
+		RETVAL
+
+
+int
+ocfsts_verify(command)
+	char *command;
+	SV* value = NULL;
+	CODE:
+		value = ST(0);
+		command = SvPV(value, PL_na);
+		//printf("command string (verify) is %s\n", command);
+		RETVAL = ocfsts_verify(command);
+		//printf("\n\ncofsts_verify: returned from verify\n");
+	OUTPUT:
+		RETVAL

Added: Ocfsts/README
===================================================================
--- Ocfsts/README	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/README	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,38 @@
+Ocfsts version 0.01
+===================
+
+The README is used to introduce the module and provide instructions on
+how to install the module, any machine dependencies it may have (for
+example C compilers and installed libraries) and any other information
+that should be provided before the module is installed.
+
+A README file is required for CPAN modules since CPAN extracts the
+README file from a module distribution so that people browsing the
+archive can use it get an idea of the modules uses. It is usually a
+good idea to provide version information here so that people can
+decide whether fixes for the module are worth downloading.
+
+INSTALLATION
+
+To install this module type the following:
+
+   perl Makefile.PL
+   make
+   make test
+   make install
+
+DEPENDENCIES
+
+This module requires these other modules and libraries:
+
+  blah blah blah
+
+COPYRIGHT AND LICENCE
+
+Put the correct copyright and licence information here.
+
+Copyright (C) 2002 Mark Fasheh
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself. 
+

Added: Ocfsts/perlobject.map
===================================================================
--- Ocfsts/perlobject.map	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/perlobject.map	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,106 @@
+# "perlobject.map"  Dean Roehrich, version 19960302
+#
+# TYPEMAPs
+#
+# HV *		-> unblessed Perl HV object.
+# AV *		-> unblessed Perl AV object.
+#
+# INPUT/OUTPUT maps
+#
+# O_*		-> opaque blessed objects
+# T_*		-> opaque blessed or unblessed objects
+#
+# O_OBJECT	-> link an opaque C or C++ object to a blessed Perl object.
+# T_OBJECT	-> link an opaque C or C++ object to an unblessed Perl object.
+# O_HvRV	-> a blessed Perl HV object.
+# T_HvRV	-> an unblessed Perl HV object.
+# O_AvRV	-> a blessed Perl AV object.
+# T_AvRV	-> an unblessed Perl AV object.
+
+TYPEMAP
+
+HV *		T_HvRV
+AV *		T_AvRV
+
+
+######################################################################
+OUTPUT
+
+# The Perl object is blessed into 'CLASS', which should be a
+# char* having the name of the package for the blessing.
+O_OBJECT
+	sv_setref_pv( $arg, CLASS, (void*)$var );
+
+T_OBJECT
+	sv_setref_pv( $arg, Nullch, (void*)$var );
+
+# Cannot use sv_setref_pv() because that will destroy
+# the HV-ness of the object.  Remember that newRV() will increment
+# the refcount.
+O_HvRV
+	$arg = sv_bless( newRV((SV*)$var), gv_stashpv(CLASS,1) );
+
+T_HvRV
+	$arg = newRV((SV*)$var);
+
+# Cannot use sv_setref_pv() because that will destroy
+# the AV-ness of the object.  Remember that newRV() will increment
+# the refcount.
+O_AvRV
+	$arg = sv_bless( newRV((SV*)$var), gv_stashpv(CLASS,1) );
+
+T_AvRV
+	$arg = newRV((SV*)$var);
+
+
+######################################################################
+INPUT
+
+O_OBJECT
+	if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) )
+		$var = ($type)SvIV((SV*)SvRV( $arg ));
+	else{
+		warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" );
+		XSRETURN_UNDEF;
+	}
+
+T_OBJECT
+	if( SvROK($arg) )
+		$var = ($type)SvIV((SV*)SvRV( $arg ));
+	else{
+		warn( \"${Package}::$func_name() -- $var is not an SV reference\" );
+		XSRETURN_UNDEF;
+	}
+
+O_HvRV
+	if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVHV) )
+		$var = (HV*)SvRV( $arg );
+	else {
+		warn( \"${Package}::$func_name() -- $var is not a blessed HV reference\" );
+		XSRETURN_UNDEF;
+	}
+
+T_HvRV
+	if( SvROK($arg) && (SvTYPE(SvRV($arg)) == SVt_PVHV) )
+		$var = (HV*)SvRV( $arg );
+	else {
+		warn( \"${Package}::$func_name() -- $var is not an HV reference\" );
+		XSRETURN_UNDEF;
+	}
+
+O_AvRV
+	if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVAV) )
+		$var = (AV*)SvRV( $arg );
+	else {
+		warn( \"${Package}::$func_name() -- $var is not a blessed AV reference\" );
+		XSRETURN_UNDEF;
+	}
+
+T_AvRV
+	if( SvROK($arg) && (SvTYPE(SvRV($arg)) == SVt_PVAV) )
+		$var = (AV*)SvRV( $arg );
+	else {
+		warn( \"${Package}::$func_name() -- $var is not an AV reference\" );
+		XSRETURN_UNDEF;
+	}
+

Added: Ocfsts/ppport.h
===================================================================
--- Ocfsts/ppport.h	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/ppport.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,540 @@
+
+/* ppport.h -- Perl/Pollution/Portability Version 2.0002 
+ *
+ * Automatically Created by Devel::PPPort on Thu Dec  5 13:54:20 2002 
+ *
+ * Do NOT edit this file directly! -- Edit PPPort.pm instead.
+ *
+ * Version 2.x, Copyright (C) 2001, Paul Marquess.
+ * Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
+ * This code may be used and distributed under the same license as any
+ * version of Perl.
+ * 
+ * This version of ppport.h is designed to support operation with Perl
+ * installations back to 5.004, and has been tested up to 5.8.0.
+ *
+ * If this version of ppport.h is failing during the compilation of this
+ * module, please check if a newer version of Devel::PPPort is available
+ * on CPAN before sending a bug report.
+ *
+ * If you are using the latest version of Devel::PPPort and it is failing
+ * during compilation of this module, please send a report to perlbug at perl.com
+ *
+ * Include all following information:
+ *
+ *  1. The complete output from running "perl -V"
+ *
+ *  2. This file.
+ *
+ *  3. The name & version of the module you were trying to build.
+ *
+ *  4. A full log of the build that failed.
+ *
+ *  5. Any other information that you think could be relevant.
+ *
+ *
+ * For the latest version of this code, please retreive the Devel::PPPort
+ * module from CPAN.
+ * 
+ */
+
+/*
+ * In order for a Perl extension module to be as portable as possible
+ * across differing versions of Perl itself, certain steps need to be taken.
+ * Including this header is the first major one, then using dTHR is all the
+ * appropriate places and using a PL_ prefix to refer to global Perl
+ * variables is the second.
+ *
+ */
+
+
+/* If you use one of a few functions that were not present in earlier
+ * versions of Perl, please add a define before the inclusion of ppport.h
+ * for a static include, or use the GLOBAL request in a single module to
+ * produce a global definition that can be referenced from the other
+ * modules.
+ * 
+ * Function:            Static define:           Extern define:
+ * newCONSTSUB()        NEED_newCONSTSUB         NEED_newCONSTSUB_GLOBAL
+ *
+ */
+ 
+
+/* To verify whether ppport.h is needed for your module, and whether any
+ * special defines should be used, ppport.h can be run through Perl to check
+ * your source code. Simply say:
+ * 
+ * 	perl -x ppport.h *.c *.h *.xs foo/bar*.c [etc]
+ * 
+ * The result will be a list of patches suggesting changes that should at
+ * least be acceptable, if not necessarily the most efficient solution, or a
+ * fix for all possible problems. It won't catch where dTHR is needed, and
+ * doesn't attempt to account for global macro or function definitions,
+ * nested includes, typemaps, etc.
+ * 
+ * In order to test for the need of dTHR, please try your module under a
+ * recent version of Perl that has threading compiled-in.
+ *
+ */ 
+
+
+/*
+#!/usr/bin/perl
+ at ARGV = ("*.xs") if !@ARGV;
+%badmacros = %funcs = %macros = (); $replace = 0;
+foreach (<DATA>) {
+	$funcs{$1} = 1 if /Provide:\s+(\S+)/;
+	$macros{$1} = 1 if /^#\s*define\s+([a-zA-Z0-9_]+)/;
+	$replace = $1 if /Replace:\s+(\d+)/;
+	$badmacros{$2}=$1 if $replace and /^#\s*define\s+([a-zA-Z0-9_]+).*?\s+([a-zA-Z0-9_]+)/;
+	$badmacros{$1}=$2 if /Replace (\S+) with (\S+)/;
+}
+foreach $filename (map(glob($_), at ARGV)) {
+	unless (open(IN, "<$filename")) {
+		warn "Unable to read from $file: $!\n";
+		next;
+	}
+	print "Scanning $filename...\n";
+	$c = ""; while (<IN>) { $c .= $_; } close(IN);
+	$need_include = 0; %add_func = (); $changes = 0;
+	$has_include = ($c =~ /#.*include.*ppport/m);
+
+	foreach $func (keys %funcs) {
+		if ($c =~ /#.*define.*\bNEED_$func(_GLOBAL)?\b/m) {
+			if ($c !~ /\b$func\b/m) {
+				print "If $func isn't needed, you don't need to request it.\n" if
+				$changes += ($c =~ s/^.*#.*define.*\bNEED_$func\b.*\n//m);
+			} else {
+				print "Uses $func\n";
+				$need_include = 1;
+			}
+		} else {
+			if ($c =~ /\b$func\b/m) {
+				$add_func{$func} =1 ;
+				print "Uses $func\n";
+				$need_include = 1;
+			}
+		}
+	}
+
+	if (not $need_include) {
+		foreach $macro (keys %macros) {
+			if ($c =~ /\b$macro\b/m) {
+				print "Uses $macro\n";
+				$need_include = 1;
+			}
+		}
+	}
+
+	foreach $badmacro (keys %badmacros) {
+		if ($c =~ /\b$badmacro\b/m) {
+			$changes += ($c =~ s/\b$badmacro\b/$badmacros{$badmacro}/gm);
+			print "Uses $badmacros{$badmacro} (instead of $badmacro)\n";
+			$need_include = 1;
+		}
+	}
+	
+	if (scalar(keys %add_func) or $need_include != $has_include) {
+		if (!$has_include) {
+			$inc = join('',map("#define NEED_$_\n", sort keys %add_func)).
+			       "#include \"ppport.h\"\n";
+			$c = "$inc$c" unless $c =~ s/#.*include.*XSUB.*\n/$&$inc/m;
+		} elsif (keys %add_func) {
+			$inc = join('',map("#define NEED_$_\n", sort keys %add_func));
+			$c = "$inc$c" unless $c =~ s/^.*#.*include.*ppport.*$/$inc$&/m;
+		}
+		if (!$need_include) {
+			print "Doesn't seem to need ppport.h.\n";
+			$c =~ s/^.*#.*include.*ppport.*\n//m;
+		}
+		$changes++;
+	}
+	
+	if ($changes) {
+		open(OUT,">/tmp/ppport.h.$$");
+		print OUT $c;
+		close(OUT);
+		open(DIFF, "diff -u $filename /tmp/ppport.h.$$|");
+		while (<DIFF>) { s!/tmp/ppport\.h\.$$!$filename.patched!; print STDOUT; }
+		close(DIFF);
+		unlink("/tmp/ppport.h.$$");
+	} else {
+		print "Looks OK\n";
+	}
+}
+__DATA__
+*/
+
+#ifndef _P_P_PORTABILITY_H_
+#define _P_P_PORTABILITY_H_
+
+#ifndef PERL_REVISION
+#   ifndef __PATCHLEVEL_H_INCLUDED__
+#       include "patchlevel.h"
+#   endif
+#   ifndef PERL_REVISION
+#	define PERL_REVISION	(5)
+        /* Replace: 1 */
+#       define PERL_VERSION	PATCHLEVEL
+#       define PERL_SUBVERSION	SUBVERSION
+        /* Replace PERL_PATCHLEVEL with PERL_VERSION */
+        /* Replace: 0 */
+#   endif
+#endif
+
+#define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION)
+
+/* It is very unlikely that anyone will try to use this with Perl 6 
+   (or greater), but who knows.
+ */
+#if PERL_REVISION != 5
+#	error ppport.h only works with Perl version 5
+#endif /* PERL_REVISION != 5 */
+
+#ifndef ERRSV
+#	define ERRSV perl_get_sv("@",FALSE)
+#endif
+
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5))
+/* Replace: 1 */
+#	define PL_Sv		Sv
+#	define PL_compiling	compiling
+#	define PL_copline	copline
+#	define PL_curcop	curcop
+#	define PL_curstash	curstash
+#	define PL_defgv		defgv
+#	define PL_dirty		dirty
+#	define PL_dowarn	dowarn
+#	define PL_hints		hints
+#	define PL_na		na
+#	define PL_perldb	perldb
+#	define PL_rsfp_filters	rsfp_filters
+#	define PL_rsfpv		rsfp
+#	define PL_stdingv	stdingv
+#	define PL_sv_no		sv_no
+#	define PL_sv_undef	sv_undef
+#	define PL_sv_yes	sv_yes
+/* Replace: 0 */
+#endif
+
+#ifdef HASATTRIBUTE
+#  if defined(__GNUC__) && defined(__cplusplus)
+#    define PERL_UNUSED_DECL
+#  else
+#    define PERL_UNUSED_DECL __attribute__((unused))
+#  endif
+#else
+#  define PERL_UNUSED_DECL
+#endif
+
+#ifndef dNOOP
+#  define NOOP (void)0
+#  define dNOOP extern int Perl___notused PERL_UNUSED_DECL
+#endif
+
+#ifndef dTHR
+#  define dTHR          dNOOP
+#endif
+
+#ifndef dTHX
+#  define dTHX          dNOOP
+#  define dTHXa(x)      dNOOP
+#  define dTHXoa(x)     dNOOP
+#endif
+
+#ifndef pTHX
+#    define pTHX	void
+#    define pTHX_
+#    define aTHX
+#    define aTHX_
+#endif         
+
+#ifndef UVSIZE
+#   define UVSIZE IVSIZE
+#endif
+
+#ifndef NVTYPE
+#   if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
+#       define NVTYPE long double
+#   else
+#       define NVTYPE double
+#   endif
+typedef NVTYPE NV;
+#endif
+
+#ifndef INT2PTR
+
+#if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE)
+#  define PTRV                  UV
+#  define INT2PTR(any,d)        (any)(d)
+#else
+#  if PTRSIZE == LONGSIZE
+#    define PTRV                unsigned long
+#  else
+#    define PTRV                unsigned
+#  endif
+#  define INT2PTR(any,d)        (any)(PTRV)(d)
+#endif
+#define NUM2PTR(any,d)  (any)(PTRV)(d)
+#define PTR2IV(p)       INT2PTR(IV,p)
+#define PTR2UV(p)       INT2PTR(UV,p)
+#define PTR2NV(p)       NUM2PTR(NV,p)
+#if PTRSIZE == LONGSIZE
+#  define PTR2ul(p)     (unsigned long)(p)
+#else
+#  define PTR2ul(p)     INT2PTR(unsigned long,p)        
+#endif
+
+#endif /* !INT2PTR */
+
+#ifndef boolSV
+#	define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
+#endif
+
+#ifndef gv_stashpvn
+#	define gv_stashpvn(str,len,flags) gv_stashpv(str,flags)
+#endif
+
+#ifndef newSVpvn
+#	define newSVpvn(data,len) ((len) ? newSVpv ((data), (len)) : newSVpv ("", 0))
+#endif
+
+#ifndef newRV_inc
+/* Replace: 1 */
+#	define newRV_inc(sv) newRV(sv)
+/* Replace: 0 */
+#endif
+
+/* DEFSV appears first in 5.004_56 */
+#ifndef DEFSV
+#  define DEFSV	GvSV(PL_defgv)
+#endif
+
+#ifndef SAVE_DEFSV
+#    define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv))
+#endif
+
+#ifndef newRV_noinc
+#  ifdef __GNUC__
+#    define newRV_noinc(sv)               \
+      ({                                  \
+          SV *nsv = (SV*)newRV(sv);       \
+          SvREFCNT_dec(sv);               \
+          nsv;                            \
+      })
+#  else
+#    if defined(USE_THREADS)
+static SV * newRV_noinc (SV * sv)
+{
+          SV *nsv = (SV*)newRV(sv);       
+          SvREFCNT_dec(sv);               
+          return nsv;                     
+}
+#    else
+#      define newRV_noinc(sv)    \
+        (PL_Sv=(SV*)newRV(sv), SvREFCNT_dec(sv), (SV*)PL_Sv)
+#    endif
+#  endif
+#endif
+
+/* Provide: newCONSTSUB */
+
+/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */
+#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63))
+
+#if defined(NEED_newCONSTSUB)
+static
+#else
+extern void newCONSTSUB(HV * stash, char * name, SV *sv);
+#endif
+
+#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL)
+void
+newCONSTSUB(stash,name,sv)
+HV *stash;
+char *name;
+SV *sv;
+{
+	U32 oldhints = PL_hints;
+	HV *old_cop_stash = PL_curcop->cop_stash;
+	HV *old_curstash = PL_curstash;
+	line_t oldline = PL_curcop->cop_line;
+	PL_curcop->cop_line = PL_copline;
+
+	PL_hints &= ~HINT_BLOCK_SCOPE;
+	if (stash)
+		PL_curstash = PL_curcop->cop_stash = stash;
+
+	newSUB(
+
+#if (PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22))
+     /* before 5.003_22 */
+		start_subparse(),
+#else
+#  if (PERL_VERSION == 3) && (PERL_SUBVERSION == 22)
+     /* 5.003_22 */
+     		start_subparse(0),
+#  else
+     /* 5.003_23  onwards */
+     		start_subparse(FALSE, 0),
+#  endif
+#endif
+
+		newSVOP(OP_CONST, 0, newSVpv(name,0)),
+		newSVOP(OP_CONST, 0, &PL_sv_no),   /* SvPV(&PL_sv_no) == "" -- GMB */
+		newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv))
+	);
+
+	PL_hints = oldhints;
+	PL_curcop->cop_stash = old_cop_stash;
+	PL_curstash = old_curstash;
+	PL_curcop->cop_line = oldline;
+}
+#endif
+
+#endif /* newCONSTSUB */
+
+#ifndef START_MY_CXT
+
+/*
+ * Boilerplate macros for initializing and accessing interpreter-local
+ * data from C.  All statics in extensions should be reworked to use
+ * this, if you want to make the extension thread-safe.  See ext/re/re.xs
+ * for an example of the use of these macros.
+ *
+ * Code that uses these macros is responsible for the following:
+ * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts"
+ * 2. Declare a typedef named my_cxt_t that is a structure that contains
+ *    all the data that needs to be interpreter-local.
+ * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t.
+ * 4. Use the MY_CXT_INIT macro such that it is called exactly once
+ *    (typically put in the BOOT: section).
+ * 5. Use the members of the my_cxt_t structure everywhere as
+ *    MY_CXT.member.
+ * 6. Use the dMY_CXT macro (a declaration) in all the functions that
+ *    access MY_CXT.
+ */
+
+#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \
+    defined(PERL_CAPI)    || defined(PERL_IMPLICIT_CONTEXT)
+
+/* This must appear in all extensions that define a my_cxt_t structure,
+ * right after the definition (i.e. at file scope).  The non-threads
+ * case below uses it to declare the data as static. */
+#define START_MY_CXT
+
+#if (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 ))
+/* Fetches the SV that keeps the per-interpreter data. */
+#define dMY_CXT_SV \
+	SV *my_cxt_sv = perl_get_sv(MY_CXT_KEY, FALSE)
+#else /* >= perl5.004_68 */
+#define dMY_CXT_SV \
+	SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY,		\
+				  sizeof(MY_CXT_KEY)-1, TRUE)
+#endif /* < perl5.004_68 */
+
+/* This declaration should be used within all functions that use the
+ * interpreter-local data. */
+#define dMY_CXT	\
+	dMY_CXT_SV;							\
+	my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv))
+
+/* Creates and zeroes the per-interpreter data.
+ * (We allocate my_cxtp in a Perl SV so that it will be released when
+ * the interpreter goes away.) */
+#define MY_CXT_INIT \
+	dMY_CXT_SV;							\
+	/* newSV() allocates one more than needed */			\
+	my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\
+	Zero(my_cxtp, 1, my_cxt_t);					\
+	sv_setuv(my_cxt_sv, PTR2UV(my_cxtp))
+
+/* This macro must be used to access members of the my_cxt_t structure.
+ * e.g. MYCXT.some_data */
+#define MY_CXT		(*my_cxtp)
+
+/* Judicious use of these macros can reduce the number of times dMY_CXT
+ * is used.  Use is similar to pTHX, aTHX etc. */
+#define pMY_CXT		my_cxt_t *my_cxtp
+#define pMY_CXT_	pMY_CXT,
+#define _pMY_CXT	,pMY_CXT
+#define aMY_CXT		my_cxtp
+#define aMY_CXT_	aMY_CXT,
+#define _aMY_CXT	,aMY_CXT
+
+#else /* single interpreter */
+
+
+#define START_MY_CXT	static my_cxt_t my_cxt;
+#define dMY_CXT_SV	dNOOP
+#define dMY_CXT		dNOOP
+#define MY_CXT_INIT	NOOP
+#define MY_CXT		my_cxt
+
+#define pMY_CXT		void
+#define pMY_CXT_
+#define _pMY_CXT
+#define aMY_CXT
+#define aMY_CXT_
+#define _aMY_CXT
+
+#endif 
+
+#endif /* START_MY_CXT */
+
+#ifndef IVdf
+#  if IVSIZE == LONGSIZE
+#       define	IVdf		"ld"
+#       define	UVuf		"lu"
+#       define	UVof		"lo"
+#       define	UVxf		"lx"
+#       define	UVXf		"lX"
+#   else
+#       if IVSIZE == INTSIZE
+#           define	IVdf	"d"
+#           define	UVuf	"u"
+#           define	UVof	"o"
+#           define	UVxf	"x"
+#           define	UVXf	"X"
+#       endif
+#   endif
+#endif
+
+#ifndef NVef
+#   if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \
+	defined(PERL_PRIfldbl) /* Not very likely, but let's try anyway. */ 
+#       define NVef		PERL_PRIeldbl
+#       define NVff		PERL_PRIfldbl
+#       define NVgf		PERL_PRIgldbl
+#   else
+#       define NVef		"e"
+#       define NVff		"f"
+#       define NVgf		"g"
+#   endif
+#endif
+
+#ifndef AvFILLp			/* Older perls (<=5.003) lack AvFILLp */
+#   define AvFILLp AvFILL
+#endif
+
+#ifdef SvPVbyte
+#   if PERL_REVISION == 5 && PERL_VERSION < 7
+       /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */
+#       undef SvPVbyte
+#       define SvPVbyte(sv, lp) \
+          ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \
+           ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp))
+       static char *
+       my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp)
+       {   
+           sv_utf8_downgrade(sv,0);
+           return SvPV(sv,*lp);
+       }
+#   endif
+#else
+#   define SvPVbyte SvPV
+#endif
+
+#endif /* _P_P_PORTABILITY_H_ */
+
+/* End of File ppport.h */

Added: Ocfsts/t/1.t
===================================================================
--- Ocfsts/t/1.t	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/t/1.t	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,15 @@
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl 1.t'
+
+#########################
+
+# change 'tests => 1' to 'tests => last_test_to_print';
+
+use Test::More tests => 1;
+BEGIN { use_ok('Ocfsts') };
+
+#########################
+
+# Insert your test code below, the Test::More module is use()ed here so read
+# its man page ( perldoc Test::More ) for help writing this test script.
+

Added: Ocfsts/t/CVS/Entries
===================================================================
--- Ocfsts/t/CVS/Entries	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/t/CVS/Entries	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,2 @@
+/1.t/1.1/Fri Dec  6 03:40:45 2002//
+D

Added: Ocfsts/t/CVS/Repository
===================================================================
--- Ocfsts/t/CVS/Repository	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/t/CVS/Repository	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+ocfsts/Ocfsts/t

Added: Ocfsts/t/CVS/Root
===================================================================
--- Ocfsts/t/CVS/Root	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/t/CVS/Root	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+:pserver:gmarsden at nic1-pc:/cvs/nic

Added: Ocfsts/test.pl
===================================================================
--- Ocfsts/test.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ Ocfsts/test.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,33 @@
+#! /usr/bin/perl
+
+use ExtUtils::testlib;
+#use English;
+use Ocfsts;
+
+ at nodes = ("localhost");
+#pop @nodes;
+#Ocfsts::ocfsts_connect_n_procs 5, @nodes;
+print "connecting, ", $#nodes, " nodes\n";
+$retval = Ocfsts::ocfsts_connect @nodes;
+
+#sleep 4;
+#Ocfsts::ocfsts_disconnect;
+
+print "running commands, connect returned $retval\n";
+Ocfsts::ocfsts_create "/tmp/file_$$";
+sleep 9999;
+Ocfsts::ocfsts_close_connection;
+die;
+
+Ocfsts::ocfsts_chmod "/tmp/myfile", "0777";
+
+Ocfsts::ocfsts_resize "/tmp/myfile", "1000";
+
+Ocfsts::ocfsts_modify "/tmp/myfile", "31337";
+
+Ocfsts::ocfsts_delete "/tmp/myfile";
+
+#expect this to fail
+Ocfsts::ocfsts_delete "/tmp/shouldfail", "localhost", "fail";
+
+Ocfsts::ocfsts_close_connection;

Added: README
===================================================================
--- README	2003-08-16 22:26:26 UTC (rev 1)
+++ README	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,147 @@
+
+OCFS Test Suite -- README
+
+Authors:
+	mark.fasheh at oracle.com
+	greg.marsden at oracle.com
+
+Table of Contents
+	0. Quick Start
+	1. Architecture description 
+	2. System requirements
+	3. Configuration file formats
+	  3.1. Node list
+	  3.2. Command list
+	4. Known bugs
+
+0. Quick Start
+
+The ocfsts.sh script provides a wrapper for all important activies 
+in ocfsts, including spawining client processes and cleaning them 
+up after the tests have been run and diff files created against 
+existing "correct" diff files.  
+
+./ocfsts.sh make 
+   compile the test server and clients
+./ocfsts.sh makediffs
+   generate the "original" diff files. These files are NOT 
+   automatically generated correctly, and must be hand tuned.
+   This is a "bug" which could be fixed in the future.
+   Also note that makediffs starts the clients on each node but does not
+   shut them down.
+./ocfsts.sh run
+   run the tests
+./ocfsts.sh kill
+   kill all clients on the cluster
+
+Note that all configuration options, including placement of directories and 
+diff files, is controlled in ocfsts.config
+
+
+1. Architecture description
+
+The OCFS Test Suite is a package for generic cluster-filesystem
+testing from multiple nodes.  The package consists of two independent
+executables, one for each cluster node and one for the server (which 
+can be run on a single node).  
+
+The client waits for input on port 4444, executes the server command,
+and returns the response. The client shuts down only when a "QUIT" 
+command is received.  The server blocks until the client's response 
+is received.
+
+This test suite was designed to exercise the filesystem in routine file
+operations and not under high load conditions. As such, the test server 
+is single-threaded, providing only one file operation at a time and does
+not test behavior under multiple simultaneous queries.
+
+A compile-time flag allows the test suite to bypass verifications on 
+the specified command node.  This function is off by default, except 
+in the cdsl case.
+
+
+2. System requirements
+
+OCFS is not required to run the test suite. Multiple instances of the
+local host (or any other host running the client binary) can be added
+to the nodes file.
+
+
+3. Configuration File formats
+
+Running the client:
+  ./ocfs_test_client
+    or
+  while ! [ ] ; do ./ocfs_test_client ; done
+
+Running the server: 
+  ./ocfs_test_server nodefile < commands
+    or
+  ./ocfs_test_server nodefile commandlist
+
+3.1. Node file format
+
+The node file format is one node per line, any 
+blank lines or extra characters after whitespace 
+discarded. The comment character is '#'.  Nodes 
+can be specified by numeric ip (dotted quad) or 
+by hostname.
+
+3.2. Command file format
+
+The command file format is one command per line, 
+# or leading space is considered to be a comment
+and blank lines are ignored.  The command syntax
+is as follows:
+
+[+-#] <node_name|node_number|R> <command> [filename] [arg1 . . . ] [cdsl[+-]]
+
+Optional success token: (defaults to "expect success")
+  +  expect the command to succeed
+  -  expect a fail
+  #  comment
+
+Node target: (required)
+  R           randomly choose a node
+  node_name   must be exactly as specified in the node file
+  node_number 1-offset list of nodes specified; this can be
+				verified on startup by consulting the node-table
+				in the test suite log
+
+Command: (required)
+Absolute paths are recommended. Commands are specified with 
+their arguments.
+  quit
+  link		  filename  target_filename
+  symlink	  filename  target_filename
+  mv		  filename  target_filename
+  chown	      filename  newuid newgid
+  mkdir       filename  mode
+  chmod       filename  mode
+  mknod       filename  mode major minor
+  rmdir       filename
+  create	  filename
+  delete	  filename
+  fstat		  filename
+  resize	  filename  new_size
+  modify      filename  entropy
+  chksum	  filename
+  cdsl		  filename
+  open		  filename
+  close		  filename
+
+CDSL status: (optional)
+Because CDSL testing involves an alternative method of 
+verification, an optional argument can be appended of the form 
+	cdsl
+at the end of the command string, to "creat" a directory or file
+in the cdsl mode.  See OCFS documentation for more detailed information.
+
+
+4. Known bugs
+
+Timestamps are calculated against Epoch and not against start time of 
+the test program.
+
+Problems with generate_reports do not affect program performance, but does
+not provide correct output.

Added: TODO
===================================================================
--- TODO	2003-08-16 22:26:26 UTC (rev 1)
+++ TODO	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,34 @@
+* Fix bug in server having to do with verification of mv commands (can't
+  verify two times in a row)
+
+* Users should have one command to do everything, including any
+  compilation (if needed) and running all the tests
+
+* One test command (make run-tests) to run all the tests. It should
+  report on what tests passed and more importantly, which
+  failed. Detailed logs should be kept somewhere
+
+* The tests run and create a .errors file per test where all errors are logged
+
+* Config should be minimal. At most one or two lines, preferably none.
+
+* Each file (excluding data files) needs to have an Oranotice at the top.
+  This means:
+		Oracle Copyright
+		Author
+		Filename
+		Description
+
+* More tests need to be created. Go through the bug database and
+  create tests to check that each bug hasn't regressed (what i mean is
+  write a test to make sure the bugs fixed)
+
+* Fix some of the test commands. There's no reason why mkdir should
+  have to specify a mode, modify does not need an entropy, etc.
+
+* Add some way to do process synchronization.
+
+* Update README file. It is waaaay out of sync with the rest of the project.
+
+* Have a cleanup script which we can run to basically cleanup $ROOT on all
+  the nodes...

Added: client/CVS/Entries
===================================================================
--- client/CVS/Entries	2003-08-16 22:26:26 UTC (rev 1)
+++ client/CVS/Entries	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,15 @@
+/Makefile/1.4/Wed Dec 11 00:39:38 2002//
+/cdsl.h/1.1/Wed Oct 16 23:21:16 2002//
+/client.c/1.2/Thu Oct 17 00:44:27 2002//
+/command.c/1.3/Tue Dec  3 23:53:22 2002//
+/command.h/1.3/Tue Dec  3 23:53:22 2002//
+/exec.c/1.7/Tue Dec 10 23:14:09 2002//
+/exec.h/1.1/Wed Oct 16 23:21:16 2002//
+/md5.c/1.1/Wed Oct 16 23:21:16 2002//
+/md5.h/1.1/Wed Oct 16 23:21:16 2002//
+/ocfstsparse.c/1.5/Tue Dec  3 23:53:22 2002//
+/ocfstsparse.h/1.2/Tue Dec  3 01:27:07 2002//
+/response.c/1.1/Wed Oct 16 23:21:16 2002//
+/response.h/1.1/Wed Oct 16 23:21:16 2002//
+/testpacket/1.1/Thu Oct 17 18:53:03 2002//
+D

Added: client/CVS/Repository
===================================================================
--- client/CVS/Repository	2003-08-16 22:26:26 UTC (rev 1)
+++ client/CVS/Repository	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+ocfsts/client

Added: client/CVS/Root
===================================================================
--- client/CVS/Root	2003-08-16 22:26:26 UTC (rev 1)
+++ client/CVS/Root	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+:pserver:gmarsden at nic1-pc:/cvs/nic

Added: client/Makefile
===================================================================
--- client/Makefile	2003-08-16 22:26:26 UTC (rev 1)
+++ client/Makefile	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,29 @@
+#
+# OCFSTS Makefile
+# Client and tslib libraries
+#
+
+GLIB_FLAGS=`glib-config --cflags`
+GLIB_LIBS=`glib-config --libs`
+
+CC	=	gcc 
+CFLAGS= -Wall -ggdb -DOCFSTS_PORT=$(OCFSTS_PORT) ${GLIB_FLAGS}
+
+LIBS= command.o response.o ocfstsparse.o md5.o
+
+include ../Makefile.config
+
+all:  $(OCFSTS_LIB_TARGET) $(CLIENT_TARGET)
+	#	Calling make from the command line interferes with
+	#	running the ocfsts.sh script! If you know what you are
+	#	doing, well, do it.  Otherwise, don't.
+
+$(OCFSTS_LIB_TARGET): $(LIBS)
+	ar rcs $@ $^
+
+$(CLIENT_TARGET): client.c exec.o $(LIBS)
+	${CC} $(CFLAGS) ${GLIB_LIBS} $^ -o $@
+
+clean:
+	rm -f core *.o *~ $(CLIENT_TARGET) $(OCFS_LIB_TARGET)
+

Added: client/cdsl.h
===================================================================
--- client/cdsl.h	2003-08-16 22:26:26 UTC (rev 1)
+++ client/cdsl.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,26 @@
+#ifndef _CDSL_H_
+#define _CDSL_H_
+
+/* ioctl commands */
+#define  OCFS_IOC_MAGIC          'O'
+#define  OCFS_IOC_GETTYPE        _IOR(OCFS_IOC_MAGIC, 1, struct ocfs_ioc)
+
+
+#define  OCFS_IOC_CDSL_MODIFY    _IOR(OCFS_IOC_MAGIC, 2, OCFS_CDSL)
+#define  OCFS_IOC_CDSL_GETINFO   _IOR(OCFS_IOC_MAGIC, 3, OCFS_CDSL)
+
+#define OCFS_CDSL_CREATE        (0x1)
+#define OCFS_CDSL_DELETE        (0x2)
+#define OCFS_FLAG_CDSL_FILE     (0x1)
+#define OCFS_FLAG_CDSL_DIR      (0x2)
+typedef unsigned char ub1;
+typedef unsigned int ub4;
+typedef struct _OCFS_CDSL
+{
+    ub1 Name[1024];
+    ub4 Flags;
+    ub4 Operation;
+} OCFS_CDSL;
+
+
+#endif /* _CDSL_H_ */

Added: client/client.c
===================================================================
--- client/client.c	2003-08-16 22:26:26 UTC (rev 1)
+++ client/client.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,257 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "command.h"
+#include "response.h"
+#include "ocfstsparse.h"
+#include "exec.h"
+
+#define RECVSIZE 2048
+//#define LISTENP 4444
+#define LISTENP OCFSTS_PORT
+#define PROC_CLEANUP_SEC 10
+char *prog = NULL;
+int mypid;
+
+/* returns a newly bound socket in the listen state, -1 if error */
+int setup_listener( void );
+
+/* uses a static buffer which is returned. NULL returned on error or 
+   end of file */
+char *get_next_command(FILE *f);
+
+/* called after accepting a connection. executes the main functionality
+   of the client */
+void child_main(int pid, int sd, struct sockaddr_in* addr, int addrlen);
+
+/* used as a signal handler for sigalarm. We do this to clean up 
+   zombie procs */
+void clean_up_children(int n);
+
+int main(int argc, char **argv) {
+  int ld, sd, cpid;
+  struct sockaddr_in* addr;
+  int addrlen;
+  
+  int logfile = open ("/tmp/client.log", O_CREAT|O_APPEND|O_WRONLY, S_IRWXU);
+  if (open < 0)
+  {
+	  perror("Unable to open logfile /tmp/client.log");
+	  return (1);
+  }
+
+  dup2 (logfile, STDERR_FILENO);
+  dup2 (logfile, STDOUT_FILENO);
+  close (STDIN_FILENO);
+  close(logfile);
+
+  if (daemon(1,1) != 0) {
+	fprintf(stderr, "Could not make daemon process!\n");
+	perror("Error forking daemon");
+	return(1);
+   }
+
+  prog = argv[0];
+  mypid = getpid();
+
+  /* TODO: Set signal handlers here */
+  if (signal(SIGALRM, clean_up_children) == SIG_ERR) {
+	fprintf(stderr, "Could not set signal handler!\n");
+	exit(1);
+  }
+  alarm(PROC_CLEANUP_SEC);
+
+  ld = setup_listener();
+  /*printf("setup listener, ld = %d\n", ld);*/
+  addrlen = sizeof(struct sockaddr_in);
+  addr = malloc(addrlen);
+
+  while (1) {
+	bzero(addr, addrlen);
+	sd = accept(ld, (struct sockaddr *) addr, &addrlen);
+	if (sd == -1) {
+	  fprintf(stderr, "%s: accept(2) error: %s\n", prog, strerror(errno));
+	  return(1);
+	}
+	
+	cpid = fork();
+	if (cpid == 0) {
+	  /* we are the child */
+	  alarm(0);
+	  signal(SIGALRM, SIG_DFL);
+	  child_main(cpid, sd, addr, addrlen);
+	  close(sd);
+	  break;
+	}
+	close(sd);
+  }
+  printf("Client[%d] shutting down\n", mypid);
+  return(0);
+}
+
+void child_main(int pid, int sd, struct sockaddr_in* addr, int addrlen) {
+  char *recvbuff;
+  char *s_response = NULL;
+  command_s * command = NULL;
+  response_s *response = NULL;
+  FILE *sock = fdopen(sd, "r+");
+  
+  mypid = pid;
+  
+  printf("%s[%d]: Connection established from %s\n", prog, mypid, 
+		 inet_ntoa(addr->sin_addr));
+
+  /* Make sure we get the inital 'HELO' */
+  recvbuff = get_next_command(sock);
+  if (recvbuff == NULL) {
+	fprintf(stderr, "Client[%d]: HELO expected, but not transmitted.\n",mypid);
+	return;
+  }
+  
+  command = ParseCommand(recvbuff);
+  if (command->type != CMD_HELO) {
+	fprintf(stderr, "Client[%d]: HELO expected, but not transmitted.\n",mypid);
+	command_s_free(command);
+	return;
+  }
+  command_s_free(command);
+  write(sd, "HELO\n\n", 6);
+  recvbuff = get_next_command(sock);
+
+  while (recvbuff != NULL) {
+	/*	printf("\n--------------------\nraw data received:\n"
+		"%s\n--------------------\n", recvbuff);*/
+	command = ParseCommand(recvbuff);
+	command_s_debug(command);
+	if (command == NULL) {
+	  fprintf(stderr, "Client[%d]: child_main: ParseCommand returned a " \
+			  "NULL value.\n", mypid);
+	  break;
+	}
+	if (command->type == CMD_QUIT) {
+	  printf("Client[%d]: QUIT command received.\n", mypid);
+	  fclose(sock);
+	  return;
+	}
+
+	response = ExecuteCommand(command);
+	if (response == NULL) {
+	  fprintf(stderr, "Client[%d]: child_main: failed call to "  \
+			  "\"ExecuteCommand\".\n", mypid);
+	  break;
+	}
+	response_s_debug(response);
+	fflush(stdout);
+	s_response = BuildResponse(response);
+	if (s_response == NULL) {
+	  fprintf(stderr, "Client[%d]: child_main: call " \
+			  "to \"BuildResponse\" failed\n", mypid);
+	  break;
+	}
+	/*printf("\n--------------------\nResponse Built:\n"
+	  "%s\n--------------------\n", s_response);*/
+	write(sd, s_response, strlen(s_response));
+	
+	free(s_response);
+	response_s_free(response);
+	command_s_free(command);
+
+	recvbuff = get_next_command(sock);
+	if (recvbuff == NULL)
+	  fprintf(stderr, "Client[%d]: Error reading from socket!\n", mypid);
+  } /* while (recvbuff != NULL) */
+
+  fprintf(stderr, "Client[%d]: Quitting on error\n", mypid);
+  fclose(sock);
+  return;
+}
+
+int setup_listener( void ) {
+  int sd, dummy=1, retval;
+  struct sockaddr_in sai;
+
+  sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+  if (sd == -1) {
+	fprintf(stderr, "%s: Socket error: %s\n", prog, strerror(errno));
+	return(-1);
+  }
+  
+  retval = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &dummy, sizeof(int));
+
+  if (retval == -1) {
+	fprintf(stderr, "%s: Error setting socket options: %s\n", prog, 
+			strerror(errno));
+	return(-1);
+  }
+
+  bzero(&sai, sizeof(struct sockaddr_in));
+  sai.sin_family = AF_INET;
+  sai.sin_port = htons(LISTENP);
+  sai.sin_addr.s_addr = htonl(INADDR_ANY);
+
+  retval = bind(sd, (struct sockaddr *) &sai, sizeof(struct sockaddr_in));
+  if (retval == -1) {
+	fprintf(stderr, "%s: Error binding socket: %s\n", prog, strerror(errno));
+	return(-1);
+  }
+
+  retval = listen(sd, 10);
+  if (retval == -1) {
+	fprintf(stderr, "%s: Error listening on socket: %s\n", prog, 
+			strerror(errno));
+	return(-1);
+  }
+
+  return(sd);
+}
+
+char *get_next_command(FILE *f) {
+  /* this could be done slightly easier, but I don't feel like
+	 changing the parsing function to read in a line at a time */
+  static char buff[BUFFSIZE];
+  char currline[BUFFSIZE];
+  char *retval;
+  int len = 0;
+
+  bzero(buff, BUFFSIZE);
+
+  do {
+	currline[0] = '\0';
+	retval = fgets(currline, BUFFSIZE - len, f);
+	if (retval == NULL) {
+	  fprintf(stderr, "get_next_command: fgets error.\n");	  
+	  return(NULL);
+	}
+
+	len = len + strlen(currline);
+	if (len >= BUFFSIZE) {
+	  fprintf(stderr, "get_next_command: input is larger than BUFFSIZE\n");
+	  return(NULL);
+	}
+	strcat(buff, currline);
+  }	while (currline[0] != '\n'); /* commands are ended with a single newline */
+
+  return(buff);
+}
+
+void clean_up_children(int n) {
+  waitpid(0, NULL, WNOHANG|WUNTRACED);
+  if (signal(SIGALRM, clean_up_children) == SIG_ERR) {
+	fprintf(stderr, "clean_up_children: Could not re-set signal handler, continuing anyway.\n");
+	return;
+  }
+  alarm(PROC_CLEANUP_SEC);
+ return;
+}

Added: client/command.c
===================================================================
--- client/command.c	2003-08-16 22:26:26 UTC (rev 1)
+++ client/command.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,124 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "command.h"
+
+char *commandstrs[] = {"QUIT",  "HELO",  "LINK",  "SYMLINK",  "CHOWN",  "MKDIR",  "CHMOD",  "MKNOD",  "RMDIR",  "CREATE",  "DELETE",  "STAT",  "RESIZE",  "MODIFY",  "MD5", "CDSL", "MV", "OPEN", "CLOSE", NULL};
+
+command_s * command_s_new(void) {
+  command_s *c;
+  c = malloc(sizeof(command_s));
+  bzero(c, sizeof(command_s));
+  return(c);
+}
+
+void command_s_debug(command_s *c) {
+  printf("Command Contents:\n");
+  if (c == NULL) {
+	printf("\tEmpty (null) Command!\n");
+	return;
+  }
+  if (c->type < NUMCOMMANDS)
+	printf("\tType:\t%s\n", commandstrs[c->type]);
+  else
+	printf("\tType:\tUNKNOWN\n");
+
+  /*  switch (c->type) {
+  case QUIT:
+	printf("\tQUIT\n");
+	break;
+  case HELO:
+	printf("\tHELO\n");
+	break;
+  case LINK:
+	printf("\tLINK\n");
+	break;
+  case SYMLINK:
+	printf("\tSYMLINK\n");
+	break;
+  case CHOWN:
+	printf("\tCHOWN\n");
+	break;
+  case MKDIR:
+	printf("\tMKDIR\n");
+	break;
+  case CHMOD:
+	printf("\tCHMOD\n");
+	break;
+  case MKNOD:
+	printf("\tMKNOD\n");
+	break;
+  case RMDIR:
+	printf("\tRMDIR\n");
+	break;
+  case CREATE:
+	printf("\tCREATE\n");
+	break;
+  case DELETE:
+	printf("\tDELETE\n");
+	break;
+  case STAT:
+	printf("\tSTAT\n");
+	break;
+  case RESIZE:
+	printf("\tRESIZE\n");
+	break;
+  case MODIFY:
+	printf("\tMODIFY\n");
+	break;
+
+  default:
+	printf("\tUNKNOWN!\n");
+	break;
+	}*/
+
+  printf("\tsrc:\t");
+  if (c->src == NULL)
+	printf("(null)\n");
+  else
+	printf("%s\n", c->src);
+  printf("\tdest:\t");
+  if (c->dest == NULL)
+	printf("(null)\n");
+  else
+	printf("%s\n", c->dest);
+
+  printf("\tuid:\t%d\n", c->uid);
+  printf("\tgid:\t%d\n", c->gid);
+  printf("\tmode:\t%04o\n", c->mode);
+  printf("\tdev:\t%llu\n", c->dev);
+  printf("\tsize:\t%ld\n", c->size);
+  printf("\tentropy:%d\n", c->entropy);
+  //#ifdef HAVE_CDSL
+  printf("\tcdslflag:");
+  if (c->cdslflag == OCFS_FLAG_CDSL_FILE)
+	printf("OCFS_FLAG_CDSL_FILE\n");
+  else if (c->cdslflag == OCFS_FLAG_CDSL_DIR)
+	printf("OCFS_FLAG_CDSL_DIR\n");
+  else
+	printf("unknown flag\n");
+  printf("\tcdslop:\t");
+  if (c->cdslop == OCFS_CDSL_CREATE)
+	printf("OCFS_CDSL_CREATE\n");
+  else if (c->cdslop == OCFS_CDSL_DELETE)
+	printf("OCFS_CDSL_DELETE\n");
+  else
+	printf("unknown operation\n");
+  //#endif
+  printf("\n");
+  return;
+}
+
+void command_s_free(command_s *c) {
+  if (c == NULL)
+	return;
+
+  if (c->src != NULL)
+	free(c->src);
+  if (c->dest != NULL)
+	free(c->dest);
+  
+  free(c);
+  return;
+}

Added: client/command.h
===================================================================
--- client/command.h	2003-08-16 22:26:26 UTC (rev 1)
+++ client/command.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,77 @@
+#ifndef _COMMAND_H_
+#define _COMMAND_H_
+
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+//#ifdef HAVE_CDSL
+#include "cdsl.h"
+//#endif
+
+// C++ magic...
+#ifdef __cplusplus
+extern "C" {
+#endif                          // __cplusplus
+
+
+enum commands {
+  CMD_QUIT = 0,
+  CMD_HELO,
+  CMD_LINK,
+  CMD_SYMLINK,
+  CMD_CHOWN,
+  CMD_MKDIR,
+  CMD_CHMOD,
+  CMD_MKNOD,
+  CMD_RMDIR,
+  CMD_CREATE,
+  CMD_DELETE,
+  CMD_STAT,
+  CMD_RESIZE,
+  CMD_MODIFY,
+  CMD_MD5,
+  CMD_CDSL,
+  CMD_MV,
+  CMD_OPEN,
+  CMD_CLOSE
+};
+
+extern char *commandstrs[];
+#define NUMCOMMANDS 19
+#define MD5_DIGEST_LENGTH 16
+
+typedef struct {
+  enum commands type; /* always used */
+
+  char *src; /* always used except for HELO and QUIT */
+  char *dest; /* LINK, SYMLINK, */
+
+  uid_t uid; /* CHOWN */
+  gid_t gid; /* CHOWN */
+
+  mode_t mode; /* MKDIR, CHMOD, MKNOD */
+
+  dev_t dev; /* MKNOD */
+
+  off_t size; /* RESIZE */
+  int entropy; /* MODIFY */
+
+  /* next two are for CDSL */
+  ub4 cdslflag; /* one of either: OCFS_FLAG_CDSL_FILE or OCFS_FLAG_CDSL_DIR */
+  ub4 cdslop; /* always OCFS_CDSL_CREATE for now */
+} command_s;
+
+command_s * command_s_new(void);
+
+void command_s_debug(command_s *c);
+
+void command_s_free(command_s *c);
+
+// C++ magic...
+#ifdef __cplusplus
+}
+#endif                          // __cplusplus
+
+#endif /* _COMMAND_H_ */

Added: client/exec.c
===================================================================
--- client/exec.c	2003-08-16 22:26:26 UTC (rev 1)
+++ client/exec.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,445 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* #define __USE_GNU */
+#ifndef O_DIRECT
+# warning O_DIRECT is not defined, so making a best guess...
+# warning using for O_DIRECT
+# define O_DIRECT        040000
+#endif
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <libgen.h>
+#include <glib.h>
+
+#include "md5.h"
+#include "exec.h"
+#include "response.h"
+#include "ocfstsparse.h"
+
+/* buffer for reading and writing I/O */
+#define IOBUFFSIZE 1024
+
+static GHashTable *fdtable = NULL; //g_hash_table_new(g_str_hash, g_str_equal);
+
+response_s * do_rmdir(command_s *c);
+response_s * do_create(command_s *c);
+response_s * do_delete(command_s *c);
+response_s * do_stat(command_s *c);
+response_s * do_md5(command_s *c);
+response_s * do_link(command_s *c);
+response_s * do_symlink(command_s *c);
+response_s * do_chown(command_s *c);
+response_s * do_mkdir(command_s *c);
+response_s * do_chmod(command_s *c);
+response_s * do_mknod(command_s *c);
+response_s * do_resize(command_s *c);
+response_s * do_modify(command_s *c);
+response_s * do_cdsl(command_s *c);
+response_s * do_mv(command_s *c);
+response_s * do_open(command_s *c);
+response_s * do_close(command_s *c);
+
+/* computes an md5 digest of the file 'f' and returns it. The digest
+ * is a bunch of chars of length 'MD5_DIGEST_LENGTH' and should be
+ * free'd 
+ */
+char * md5sum(const char *f);
+
+/* output is similar to the command 'md5sum [file]' */
+void md5sum_debug(const char *digest);
+
+/* executes our command. a response struct which has the results in
+ * it... return NULL on error
+ */
+response_s * ExecuteCommand(command_s *command) {
+  response_s *retval = NULL;
+
+  /* Initialize our fdtable if need be... */
+  if (fdtable == NULL) {
+	  fdtable = g_hash_table_new(g_str_hash, g_str_equal);
+	  if (fdtable == NULL) {
+		  fprintf(stderr, 
+			  "ExecuteCommand: glib error, cannot continue.\n");
+		  return(NULL);
+	  }
+  }
+  
+  switch (command->type) {
+  case CMD_RMDIR:
+	retval = do_rmdir(command);
+	break;
+
+  case CMD_CREATE:
+	retval = do_create(command);
+	break;
+
+  case CMD_DELETE:
+	retval = do_delete(command);
+	break;
+
+  case CMD_STAT:
+	retval = do_stat(command);
+	break;
+
+  case CMD_MD5:
+	retval = do_md5(command);
+	break;
+
+  case CMD_LINK:
+	retval = do_link(command);
+	break;
+
+  case CMD_SYMLINK:
+	retval = do_symlink(command);
+	break;
+
+  case CMD_CHOWN:
+	retval = do_chown(command);
+	break;
+
+  case CMD_MKDIR:
+	retval = do_mkdir(command);
+	break;
+
+  case CMD_CHMOD:
+	retval = do_chmod(command);
+	break;
+
+  case CMD_MKNOD:
+	retval = do_mknod(command);
+	break;
+
+  case CMD_RESIZE:
+	retval = do_resize(command);
+	break;
+
+  case CMD_MODIFY:
+	retval = do_modify(command);
+	break;
+
+  case CMD_CDSL:
+	retval = do_cdsl(command);
+	break;
+
+  case CMD_MV:
+	retval = do_mv(command);
+	break;
+
+  case CMD_OPEN:
+	retval = do_open(command);
+	break;
+
+  case CMD_CLOSE:
+	retval = do_close(command);
+	break;
+
+  default:
+	fprintf(stderr, "ExecuteCommand: Uknown command type!\n");
+	return(NULL);
+	break;
+  }
+
+  if (retval == NULL)
+	fprintf(stderr, "ExecuteCommand: internal failure\n");
+
+  return(retval);
+}
+
+response_s * do_rmdir(command_s *c) {
+  int err = rmdir(c->src);
+  if (err == -1)
+	return(response_s_new_fail(CMD_RMDIR, errno, NULL));
+  return(response_s_new_success(CMD_RMDIR));
+}
+
+response_s * do_create(command_s *c) {
+  int err = open(c->src, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+  if (err == -1)
+	return(response_s_new_fail(CMD_CREATE, errno, NULL));
+  close(err);
+  return(response_s_new_success(CMD_CREATE));
+}
+
+response_s * do_delete(command_s *c) {
+  int err = unlink(c->src);
+  if (err == -1)
+	return(response_s_new_fail(CMD_DELETE, errno, NULL));
+  return(response_s_new_success(CMD_DELETE));
+}
+
+response_s * do_link(command_s *c) {
+  int err = link(c->src, c->dest);
+  if (err == -1)
+	return(response_s_new_fail(CMD_LINK, errno, NULL));
+  return(response_s_new_success(CMD_LINK));
+}
+
+response_s * do_mv(command_s *c) {
+  int err = rename(c->src, c->dest);
+  if (err == -1)
+        return(response_s_new_fail(CMD_MV, errno, NULL));
+  return(response_s_new_success(CMD_MV));
+}
+
+response_s * do_symlink(command_s *c) {
+  int err = symlink(c->src, c->dest);
+  if (err == -1)
+	return(response_s_new_fail(CMD_SYMLINK, errno, NULL));
+  return(response_s_new_success(CMD_SYMLINK));
+}
+
+response_s * do_chown(command_s *c) {
+  int err = chown(c->src, c->uid, c->gid);
+  if (err == -1)
+	return(response_s_new_fail(CMD_CHOWN, errno, NULL));
+  return(response_s_new_success(CMD_CHOWN));
+}
+
+response_s * do_mkdir(command_s *c) {
+  int err = mkdir(c->src, c->mode);
+  if (err == -1)
+	return(response_s_new_fail(CMD_MKDIR, errno, NULL));
+  return(response_s_new_success(CMD_MKDIR));
+}
+
+response_s * do_chmod(command_s *c) {
+  int err = chmod(c->src, c->mode);
+  if (err == -1)
+	return(response_s_new_fail(CMD_CHMOD, errno, NULL));
+  return(response_s_new_success(CMD_CHMOD));
+}
+
+response_s * do_mknod(command_s *c) {
+  int err = mknod(c->src, c->mode, c->dev);
+  if (err == -1)
+	return(response_s_new_fail(CMD_MKNOD, errno, NULL));
+  return(response_s_new_success(CMD_MKNOD));
+}
+
+response_s * do_resize(command_s *c) {
+  int err = truncate(c->src, c->size);
+  if (err == -1)
+	return(response_s_new_fail(CMD_RESIZE, errno, NULL));
+  return(response_s_new_success(CMD_RESIZE));
+}
+
+response_s * do_open(command_s *c) {
+	int fd;
+	gpointer oldkey;
+	if (g_hash_table_lookup_extended(fdtable, c->src, &oldkey, (gpointer *) &fd)==TRUE)
+		return(response_s_new_fail(CMD_OPEN, -1, 
+					   "File is already opened."));
+
+/*#ifdef O_DIRECT
+	fd = open(c->src, O_RDWR|O_CREAT|O_DIRECT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+#else
+#warning O_DIRECT not defined, so not using it!
+#warning Your client build will not use direct I/O.
+	fd = open(c->src, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+	#endif*/
+
+	fd = open(c->src, O_RDWR|O_CREAT|O_DIRECT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+	if (fd == -1)
+		return(response_s_new_fail(CMD_OPEN, errno, NULL));
+	g_hash_table_insert(fdtable, g_strdup(c->src), GINT_TO_POINTER(fd));
+	return(response_s_new_success(CMD_OPEN));
+}
+
+response_s * do_close(command_s *c) {
+	gpointer oldkey = NULL;
+	gpointer fd;
+	if (g_hash_table_lookup_extended(fdtable, c->src, &oldkey, &fd)==FALSE)
+		return(response_s_new_fail(CMD_CLOSE, -1, 
+					   "File was not previously opened."));
+	g_free(oldkey);
+	if (close(GPOINTER_TO_INT(fd)) == -1)
+		return(response_s_new_fail(CMD_CLOSE, errno, NULL));
+	return(response_s_new_success(CMD_CLOSE));
+}
+
+response_s * do_cdsl(command_s *c) {
+  int fd, err=0;
+  OCFS_CDSL cdsl;
+  struct stat tmp;
+  char *dir, *src, *base;
+
+  bzero(&tmp, sizeof(struct stat));
+
+  src = strdup(c->src);
+  if (src == NULL)
+	return(response_s_new_fail(CMD_CDSL, -1, "Error returned from strdup."));
+
+  dir = dirname(src);
+  free(src);
+  if (dir == NULL)
+	return(response_s_new_fail(CMD_CDSL, errno, NULL));
+  fd = open(dir, O_RDONLY);
+  if (fd == -1)
+	return(response_s_new_fail(CMD_CDSL, errno, NULL));
+
+  src = strdup(c->src);
+  if (src == NULL)
+	return(response_s_new_fail(CMD_CDSL, -1, "Error returned from strdup."));
+
+  base = basename(src);
+  free(src);
+
+  memset(&cdsl, 0, sizeof(OCFS_CDSL));
+  strncpy(cdsl.Name, base, 1023);
+  cdsl.Flags = c->cdslflag;
+  cdsl.Operation = c->cdslop;
+
+  err = ioctl(fd, OCFS_IOC_CDSL_MODIFY, &cdsl);
+  close(fd);
+  if (err == -1)
+	return(response_s_new_fail(CMD_CDSL, errno, NULL));
+  return(response_s_new_success(CMD_CDSL));
+}
+
+response_s * do_modify(command_s *c) {
+  response_s *r = NULL;
+  int numchanges = 0, i, loc, fd;
+  struct stat filestats;
+  char * filler = "abcdefg";
+
+  /* modify the file here */
+  
+  if (stat(c->src, &filestats) == -1)
+	return(response_s_new_fail(CMD_MODIFY, errno, NULL));
+
+  fd = open(c->src, O_WRONLY);
+  if (fd == -1)
+	return(response_s_new_fail(CMD_MODIFY, errno, NULL));
+
+  srand(time(NULL));
+  numchanges = 1 + (int) ((float) filestats.st_size * rand()/(RAND_MAX+1.0));
+  /* we never really wanna make too many changes... */
+  numchanges = numchanges % 150;
+
+  /* printf("do_modify: %d changes to file of size %ld\n", 
+	 numchanges, filestats.st_size);*/
+  for(i = 0; i < numchanges; i++) {
+	loc =  1 + (int) ((float) filestats.st_size * rand()/(RAND_MAX+1.0));
+	if (lseek(fd, loc, SEEK_SET) == -1) {
+	  close(fd);
+	  return(response_s_new_fail(CMD_MODIFY, errno, NULL));
+	}
+	if (write(fd, &filler[i % 7], 1) == -1) {
+	  close(fd);
+	  return(response_s_new_fail(CMD_MODIFY, errno, NULL));
+	}
+  }
+  close(fd);
+
+  /* ok, we managed to get this far! now get the md5 and return a response */
+  r = response_s_new_success(CMD_MODIFY);
+  r->md5sum = md5sum(c->src);
+  if (r->md5sum == NULL) {
+	response_s_free(r);
+	return(response_s_new_fail(CMD_MODIFY, -1, 
+							   "do_modify: error generating md5 digest.\n"));
+  }
+
+  return(r);
+  /*
+	return(response_s_new_fail(CMD_MODIFY, 0, "do_modify: function not implemented yet"));*/
+}
+
+response_s * do_stat(command_s *c) {
+  struct stat fstats;
+  response_s *r = NULL;
+
+  if (stat(c->src, &fstats) == -1)
+	return(response_s_new_fail(CMD_STAT, errno, NULL));
+
+  r = response_s_new();
+  r->status = RESP_OK;
+  r->command = CMD_STAT;
+  r->dev = fstats.st_dev;
+  r->mode = fstats.st_mode;
+  r->uid = fstats.st_uid;
+  r->gid = fstats.st_gid;
+  r->rdev = fstats.st_rdev;
+  r->size = fstats.st_size;
+  return(r);
+  /*
+	return(response_s_new_fail(CMD_STAT, 0, "do_stat: function not implemented yet"));*/
+}
+
+response_s * do_md5(command_s *c) {
+  char *retval = md5sum(c->src);
+  response_s *r;
+
+  if (retval == NULL)
+	response_s_new_fail(CMD_MD5, 0, "do_md5: failed md5sum routine.");
+
+  r = response_s_new_success(CMD_MD5);
+  r->md5sum = retval;
+
+  if (r->md5sum == NULL) {
+	response_s_free(r);
+	return(response_s_new_fail(CMD_MD5, -1, "do_md5: invalid filename, or read error."));
+  }
+  /* debug stuff */
+  /*md5sum_debug(retval);
+	printf("\n");*/
+  /* end debug stuff */
+  return(r);
+}
+
+char *md5sum(const char *f) {
+  md5_state_t *state;
+  md5_byte_t *digest;
+  int fd, len;
+  char buff[IOBUFFSIZE];
+  
+  fd = open(f, O_RDONLY);
+  if (fd == -1) {
+	fprintf(stderr, "md5sum: open(2) error\n");
+	return(NULL);
+  }
+  
+  state = malloc(sizeof(md5_state_t));
+  bzero(state, sizeof(md5_state_t));
+
+  md5_init(state);
+
+  do {
+	len = read(fd, buff, IOBUFFSIZE);
+	if (len == -1) {
+	  fprintf(stderr, "md5sum: read error\n");
+	  free(state);
+	  close(fd);
+	  return(NULL);
+	}
+	md5_append(state, buff, len);
+  } while (len == IOBUFFSIZE);
+
+  digest = malloc(MD5_DIGEST_LENGTH);
+  bzero(digest, MD5_DIGEST_LENGTH);
+  md5_finish(state, digest);
+
+  close(fd);
+  free(state);
+  return(digest);
+}
+
+void md5sum_debug(const char *digest) {
+  int i;
+  
+  if (digest == NULL) {
+	fprintf(stderr, "md5sum_debug: null parameters are illegal.\n");
+	return;
+  }
+  
+  for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
+	printf("%02hhx", digest[i]);
+  }
+
+}

Added: client/exec.h
===================================================================
--- client/exec.h	2003-08-16 22:26:26 UTC (rev 1)
+++ client/exec.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,28 @@
+#ifndef _EXEC_H_
+#define _EXEC_H_
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+// C++ magic...
+#ifdef __cplusplus
+extern "C" {
+#endif                          // __cplusplus
+
+/* actually, we only really need command_s from here... */
+#include "ocfstsparse.h"
+#include "response.h"
+
+/* 
+   executes our command. a response struct which has the results in it... 
+   NULL on error
+*/
+response_s * ExecuteCommand(command_s *command);
+
+// C++ magic...
+#ifdef __cplusplus
+}
+#endif                          // __cplusplus
+
+#endif /* _EXEC_H_ */

Added: client/md5.c
===================================================================
--- client/md5.c	2003-08-16 22:26:26 UTC (rev 1)
+++ client/md5.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,381 @@
+/*
+  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost at aladdin.com
+
+ */
+/* $Id: md5.c,v 1.1 2002/10/16 23:21:16 gmarsden Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost at aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+	either statically or dynamically; added missing #include <string.h>
+	in library.
+  2002-03-11 lpd Corrected argument list for main(), and added int return
+	type, in test program and T value program.
+  2002-02-21 lpd Added missing #include <stdio.h> in test program.
+  2000-07-03 lpd Patched to eliminate warnings about "constant is
+	unsigned in ANSI C, signed in traditional"; made test program
+	self-checking.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+#  define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3    0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6    0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9    0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13    0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16    0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19    0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22    0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25    0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28    0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31    0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35    0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38    0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41    0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44    0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47    0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50    0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53    0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57    0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60    0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63    0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+	a = pms->abcd[0], b = pms->abcd[1],
+	c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+#if BYTE_ORDER > 0
+    /* Define storage only for big-endian CPUs. */
+    md5_word_t X[16];
+#else
+    /* Define storage for little-endian or both types of CPUs. */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+#endif
+
+    {
+#if BYTE_ORDER == 0
+	/*
+	 * Determine dynamically whether this is a big-endian or
+	 * little-endian machine, since we can use a more efficient
+	 * algorithm on the latter.
+	 */
+	static const int w = 1;
+
+	if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0		/* little-endian */
+	{
+	    /*
+	     * On little-endian machines, we can process properly aligned
+	     * data without copying it.
+	     */
+	    if (!((data - (const md5_byte_t *)0) & 3)) {
+		/* data are properly aligned */
+		X = (const md5_word_t *)data;
+	    } else {
+		/* not aligned */
+		memcpy(xbuf, data, 64);
+		X = xbuf;
+	    }
+	}
+#endif
+#if BYTE_ORDER == 0
+	else			/* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0		/* big-endian */
+	{
+	    /*
+	     * On big-endian machines, we must arrange the bytes in the
+	     * right order.
+	     */
+	    const md5_byte_t *xp = data;
+	    int i;
+
+#  if BYTE_ORDER == 0
+	    X = xbuf;		/* (dynamic only) */
+#  else
+#    define xbuf X		/* (static only) */
+#  endif
+	    for (i = 0; i < 16; ++i, xp += 4)
+		xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+	}
+#endif
+    }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+     /* Round 2. */
+     /* Let [abcd k s i] denote the operation
+          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+     /* Round 3. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+     /* Round 4. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+     /* Then perform the following additions. (That is increment each
+        of the four registers by the value it had before this block
+        was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+    pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+	return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+	pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+	memcpy(pms->buf + offset, p, copy);
+	if (offset + copy < 64)
+	    return;
+	p += copy;
+	left -= copy;
+	md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+	md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+	memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}

Added: client/md5.h
===================================================================
--- client/md5.h	2003-08-16 22:26:26 UTC (rev 1)
+++ client/md5.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost at aladdin.com
+
+ */
+/* $Id: md5.h,v 1.1 2002/10/16 23:21:16 gmarsden Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <ghost at aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Removed support for non-ANSI compilers; removed
+	references to Ghostscript; clarified derivation from RFC 1321;
+	now handles byte order either statically or dynamically.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+	added conditionalization for C++ compilation from Martin
+	Purschke <purschke at bnl.gov>.
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];	/* message length in bits, lsw first */
+    md5_word_t abcd[4];		/* digest buffer */
+    md5_byte_t buf[64];		/* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */

Added: client/ocfstsparse.c
===================================================================
--- client/ocfstsparse.c	2003-08-16 22:26:26 UTC (rev 1)
+++ client/ocfstsparse.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,629 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+/* #include <openssl/md5.h> */
+
+#include "command.h"
+#include "response.h"
+#include "cdsl.h"
+#include "ocfstsparse.h"
+
+mode_t parse_mode(char *str);
+dev_t parse_dev(char *str);
+char ctoi(char c);
+
+mode_t parse_mode(char *str) {
+  mode_t m;
+  if (str == NULL) {
+	fprintf(stderr, "parse_mode: Null parameters are illegal\n");
+	return(0);
+  }
+
+  sscanf(str, "%o", &m);
+  return(m);
+}
+
+dev_t parse_dev(char *str) {
+  dev_t d;
+  int major, minor;
+
+  if (str == NULL) {
+	fprintf(stderr, "parse_mode: Null parameters are illegal\n");
+	return(0);
+  }
+
+  sscanf(str, "%d %d\n", &major, &minor);
+  d = makedev(major, minor);
+
+  return(d);
+}
+
+command_s * ParseCommand(char * str) {
+  char *tok = NULL,
+	*next = NULL,
+	*end = NULL; /* make sure we never go over the end of the string */
+  command_s *c;
+  int i;
+
+  if (str == NULL) {
+	fprintf(stderr, "ParseCommand: String parameter cannot be null.\n");
+	return(NULL);
+  }
+  
+  /* just grab tokens as we need them. */
+  end = index(str, '\0');
+  tok =  str;
+  next = index(tok, '\n');
+  *next = '\0';
+  if (end == NULL) {
+	fprintf(stderr, "ParseCommand: Parse error.\n");
+	return(NULL);
+  }
+  
+  c = command_s_new();
+
+  /* figure out the command type */
+  for (i = 0; i < NUMCOMMANDS+1; i++) {
+	if (commandstrs[i] == NULL) {
+	  fprintf(stderr, "ParseCommand: Invalid command type received.\n");
+	  command_s_free(c);
+	  return(NULL);
+	} 
+	if (strcasecmp(commandstrs[i], tok) == 0) {
+	  c->type = i;
+	  break;
+	}
+  }
+  if ((c->type == CMD_QUIT) || (c->type == CMD_HELO)) /* no more args needed */
+	return(c);
+
+  /* all other commands need at least a string 'src' argument. get that now. */
+  if (next >= end) {
+	fprintf(stderr, "ParseCommand: Premature end of input\n");
+	command_s_free(c);
+	return(NULL);
+  }
+  tok = next+1;
+  next = index(tok, '\n');
+  *next = '\0';
+  if (next == NULL) {
+	fprintf(stderr, "ParseCommand: Parse error.\n");
+	command_s_free(c);
+	return(NULL);
+  }
+  c->src = strdup(tok);
+
+  /* for the command whose only argument is a src string, exit now */
+  switch (c->type) {
+  case CMD_RMDIR:
+  case CMD_CREATE:
+  case CMD_DELETE:
+  case CMD_STAT:
+  case CMD_MD5:
+  case CMD_OPEN:
+  case CMD_CLOSE:
+	return(c);
+	break;
+  default:
+	/* for all other commands, we want to continue parsing */
+	break;
+  }
+
+  /* get the next token */
+  if (next >= end) {
+	fprintf(stderr, "ParseCommand: Premature end of input\n");
+	command_s_free(c);
+	return(NULL);
+  }
+  tok = next+1;
+  next = index(tok, '\n');
+  *next = '\0';
+  if (next == NULL) {
+	fprintf(stderr, "ParseCommand: Parse error.\n");
+	command_s_free(c);
+	return(NULL);
+  }
+
+  switch(c->type) {
+  case CMD_MKNOD:
+	/* need mode, and dev arguments */
+	c->mode = parse_mode(tok);
+
+	if (next >= end) {
+	  fprintf(stderr, "ParseCommand: Premature end of input\n");
+	  command_s_free(c);
+	  return(NULL);
+	}
+	tok = next+1;
+	next = index(tok, '\n');
+	*next = '\0';
+	if (next == NULL) {
+	  fprintf(stderr, "ParseCommand: Parse error.\n");
+	  command_s_free(c);
+	  return(NULL);
+	}
+	c->dev = parse_dev(tok);
+	break;
+
+  case CMD_MV: 
+  case CMD_LINK:
+  case CMD_SYMLINK:
+	/* these two need a 'dest' string */
+	c->dest = strdup(tok);
+	break;
+	
+  case CMD_MKDIR:
+  case CMD_CHMOD:
+	/* these two need a 'mode' argument */
+	c->mode = parse_mode(tok);
+	break;
+	
+  case CMD_RESIZE:
+	/* needs a 'size' argument */
+	sscanf(tok, "%ld", &(c->size));
+	break;
+
+  case CMD_CHOWN:
+	/* needs username and group ids */
+	sscanf(tok, "%d", &(c->uid));
+	if (next >= end) {
+	  fprintf(stderr, "ParseCommand: Premature end of input\n");
+	  command_s_free(c);
+	  return(NULL);
+	}
+	tok = next+1;
+	next = index(tok, '\n');
+	*next = '\0';
+	if (next == NULL) {
+	  fprintf(stderr, "ParseCommand: Parse error.\n");
+	  command_s_free(c);
+	  return(NULL);
+	}
+	sscanf(tok, "%d", &(c->gid));
+	break;
+	
+  case CMD_MODIFY:
+	/* needs an entropy argument */
+	sscanf(tok, "%d", &(c->entropy));
+	break;
+	
+  case CMD_CDSL:
+	/* get the operation from here */
+	if (strcasecmp(tok, "create") == 0) {
+	  c->cdslflag = OCFS_FLAG_CDSL_FILE;
+	  c->cdslop = OCFS_CDSL_CREATE;
+	} else if (strcasecmp(tok, "mkdir") == 0) {
+	  c->cdslflag = OCFS_FLAG_CDSL_DIR;
+	  c->cdslop = OCFS_CDSL_CREATE;
+	} else {
+	  fprintf(stderr,"ParseCommand: Unknown/Missing option to CDSL command\n");
+	  command_s_free(c);
+	  return(NULL);
+	}
+	break;
+	
+  default:
+	fprintf(stderr, "ParseCommand: Unknown command type.\n");
+	command_s_free(c);
+	return(NULL);
+  }
+  
+  return(c);
+}
+
+char * BuildResponse(response_s *r) {
+  char buff[BUFFSIZE];
+  char *curr;
+  int len = 0;
+  int i;
+
+  if (r == NULL) {
+	fprintf(stderr, "BuildResponse: response_s parameter cannot be null.\n");
+	return(NULL);
+  }
+
+  bzero(buff, BUFFSIZE);
+
+  if (r->command >= NUMCOMMANDS) {
+	fprintf(stderr, "BuildResponse: unknown command type.\n");
+	return(NULL);
+  }
+
+  len = sprintf(buff, "%s\n%s\n", commandstrs[r->command], 
+				responsestrs[r->status]);
+  curr = &buff[len];
+  
+  if (r->status == RESP_FAIL) {
+	/* add the error code, string and final newline, then quit */
+	snprintf(curr, BUFFSIZE-len, "%d\n%s\n\n", r->err, r->desc);
+	return(strdup(buff));
+  }
+
+  switch (r->command) {
+  case CMD_OPEN:
+  case CMD_CLOSE:
+  case CMD_MV:
+  case CMD_LINK:
+  case CMD_SYMLINK:
+  case CMD_CHOWN:
+  case CMD_MKDIR:
+  case CMD_CHMOD:
+  case CMD_MKNOD:
+  case CMD_RMDIR:
+  case CMD_CREATE:
+  case CMD_DELETE:
+  case CMD_HELO:
+  case CMD_RESIZE:
+  case CMD_CDSL:
+	/* yes, we're done */
+	break;
+
+  case CMD_MODIFY:
+  case CMD_MD5:
+	/* print out the md5sum */
+	for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
+	  len += sprintf(curr, "%02hhx", r->md5sum[i]);
+	  curr = &buff[len];
+	}
+	len += sprintf(curr, "\n");
+	curr = &buff[len];
+	break;
+
+  case CMD_STAT:
+	/* dev */
+	len += snprintf(curr, BUFFSIZE-len, "%d %d\n", major(r->dev), 
+					minor(r->dev));
+	curr = &buff[len];
+
+	/* dev type, skipped for now */
+
+	/* mode */
+	len += snprintf(curr, BUFFSIZE-len, "%04o\n", r->mode);
+	curr = &buff[len];
+
+	/* uid */
+	len += snprintf(curr, BUFFSIZE-len, "%d\n", r->uid);
+	curr = &buff[len];
+
+	/* gid */
+	len += snprintf(curr, BUFFSIZE-len, "%d\n", r->gid);
+	curr = &buff[len];
+
+	/* size */
+	len += snprintf(curr, BUFFSIZE-len, "%ld\n", r->size);
+	curr = &buff[len];
+	
+	/* cdsl status */
+	/* TODO */
+	break;
+
+  default:
+	fprintf(stderr, "BuildResponse: Unknown command type in response.\n");
+	return(NULL);
+	break;
+  }
+
+  len += snprintf(curr, BUFFSIZE - len, "\n");
+  return(strdup(buff));
+}
+
+
+char * BuildCommand(command_s *c) {
+  char buff[BUFFSIZE];
+  int len=0;
+  char *curr;
+
+  if (c == NULL) {
+	fprintf(stderr, "BuildResponse: response_s parameter cannot be null.\n");
+	return(NULL);
+  }
+  
+  if (c->type >= NUMCOMMANDS) {
+	fprintf(stderr, "BuildCommand: unknown command type. (NUMCOMMANDS=%d)\n", NUMCOMMANDS);
+	return(NULL);
+  }
+
+  /* get rid of the trivial cases */
+  if (c->type == CMD_HELO)
+	return(strdup("HELO\n\n"));
+  if (c->type == CMD_QUIT)
+	return(strdup("QUIT\n\n"));
+
+  bzero(buff, BUFFSIZE);
+  len = sprintf(buff, "%s\n", commandstrs[c->type]);
+  curr = &buff[len];
+  
+  /* all the remaining commands need at least a src filename */
+  if (c->src == NULL) {
+	fprintf(stderr, "BuildCommand: Source filename cannot be null.");
+	return(NULL);
+  }
+  len += snprintf(curr, BUFFSIZE - len, "%s\n", c->src);
+  curr = &buff[len];
+
+  /* do the other fields now */
+
+  switch (c->type) {
+  case CMD_OPEN:
+  case CMD_CLOSE:
+  case CMD_MD5:
+  case CMD_STAT:
+  case CMD_RMDIR:
+  case CMD_CREATE:
+  case CMD_DELETE:
+	/* yes, we're done */
+	break;
+
+  case CMD_MKNOD:
+	/* put in mode and device info */
+	len += snprintf(curr, BUFFSIZE - len, "%04o\n", c->mode);
+	curr = &buff[len]; 
+	len += snprintf(curr, BUFFSIZE - len, "%d %d\n", major(c->dev), 
+					minor(c->dev));
+	curr = &buff[len];
+	break;
+
+  case CMD_MKDIR:
+  case CMD_CHMOD:
+	/* put in mode info */
+	len += snprintf(curr, BUFFSIZE - len, "%04o\n", c->mode);
+	curr = &buff[len];
+	break;
+
+  case CMD_CHOWN:
+	/* put in owner and group ids */
+	len += snprintf(curr, BUFFSIZE - len, "%d\n%d\n", c->uid, c->gid);
+	curr = &buff[len];
+	break;
+
+  case CMD_MV:
+  case CMD_LINK:
+  case CMD_SYMLINK:
+	/* put in destination file */
+	if (c->dest == NULL) {
+	  fprintf(stderr, "BuildCommand: Destination filename cannot be null.");
+	  return(NULL);
+	}
+	len += snprintf(curr, BUFFSIZE - len, "%s\n", c->dest);
+	curr = &buff[len];
+	break;
+
+  case CMD_RESIZE:
+	/* put in new size */
+	len += snprintf(curr, BUFFSIZE - len, "%ld\n", c->size);
+	curr = &buff[len];
+	break;
+
+  case CMD_MODIFY:
+	/* put in entropy */
+	len += snprintf(curr, BUFFSIZE - len, "%d\n", c->entropy);
+	curr = &buff[len];
+	break;
+
+  case CMD_CDSL:
+	/* put in the op */
+	if (c->cdslop == OCFS_CDSL_CREATE && c->cdslflag == OCFS_FLAG_CDSL_FILE) {
+	  len += snprintf(curr, BUFFSIZE - len, "create\n");
+	  curr = &buff[len];
+	} else if (c->cdslop == OCFS_CDSL_CREATE && 
+			   c->cdslflag == OCFS_FLAG_CDSL_DIR) {
+	  len += snprintf(curr, BUFFSIZE - len, "mkdir\n");
+	  curr = &buff[len];
+	} else {
+	  fprintf(stderr, "BuildCommand: Invalid cdsl flag/operation.");
+	  return(NULL);
+	}
+	break;
+	
+  default:
+	break;
+  }
+
+  /* insert the final newline */
+  len += snprintf(curr, BUFFSIZE - len, "\n");
+  curr = &buff[len];
+  return(strdup(buff));
+}
+
+response_s * ParseResponse(char *str) {
+  char *tok = NULL;
+  response_s *r;
+  int i, maj, min;
+
+  if (str == NULL) {
+	fprintf(stderr, "ParseResponse: String parameter cannot be null.\n");
+	return(NULL);
+  }
+
+  /* just grab tokens as we need them. */
+  tok = strtok(str, "\n");
+  if (tok == NULL) {
+	fprintf(stderr, "ParseResponse: Parse error.\n");
+	return(NULL);
+  }
+  
+  r = response_s_new();
+
+  /* figure out the command this is a response to */
+  for (i = 0; i < NUMCOMMANDS+1; i++) {
+	if (commandstrs[i] == NULL) {
+	  fprintf(stderr, "ParseResponse: Invalid command type received.\n");
+	  return(NULL);
+	} 
+	if (strcasecmp(commandstrs[i], tok) == 0) {
+	  r->command = i;
+	  break;
+	}
+  }
+  
+  /* trivial cases */
+  if ((r->command == CMD_QUIT) || (r->command == CMD_HELO)) {
+	r->status = RESP_OK;
+	return(r);
+  }
+
+  tok = strtok(NULL, "\n");
+  if (tok == NULL) {
+	fprintf(stderr, "ParseResponse: Parse error.\n");
+	return(NULL);
+  }
+
+  /* get the status from the response */
+  if (strcasecmp(responsestrs[RESP_FAIL], tok) == 0) {
+	/* it's a failure response. they all look the same so 
+	   get the other fields now */
+	r->status = RESP_FAIL;
+	tok = strtok(NULL, "\n");
+	if (tok == NULL) {
+	  fprintf(stderr, "ParseResponse: Parse error.\n");
+	  return(NULL);
+	}
+	sscanf(tok, "%d", &(r->err));
+
+	tok = strtok(NULL, "\n");
+	if (tok == NULL) {
+	  fprintf(stderr, "ParseResponse: Parse error.\n");
+	  return(NULL);
+	}
+	r->desc = strdup(tok);
+	return(r);
+  } else if (strcasecmp(responsestrs[RESP_OK], tok) != 0) {
+	fprintf(stderr, "ParseResponse: Illegal response type\n");
+	return(NULL);
+  }
+
+  /* It's a success response... */
+  r->status = RESP_OK;
+  
+  switch(r->command) {
+  case CMD_OPEN:
+  case CMD_CLOSE:
+  case CMD_MV:
+  case CMD_QUIT:
+  case CMD_HELO:
+  case CMD_LINK:
+  case CMD_SYMLINK:
+  case CMD_CHOWN:
+  case CMD_MKDIR:
+  case CMD_CHMOD:
+  case CMD_MKNOD:
+  case CMD_RMDIR:
+  case CMD_CREATE:
+  case CMD_DELETE:
+  case CMD_RESIZE:
+  case CMD_CDSL:
+	break;
+	
+	/* only need to deal with MD5/MODIFY and STAT */
+
+  case CMD_MD5:
+  case CMD_MODIFY:
+	/* these two get an md5sum */
+	tok = strtok(NULL, "\n");
+	if (tok == NULL) {
+	  fprintf(stderr, "ParseResponse: Parse error.\n");
+	  return(NULL);
+	}
+	if (strlen(tok) != (2 * MD5_DIGEST_LENGTH)) {
+	  fprintf(stderr, "ParseResponse: Invalid Digest.\n");
+	  return(NULL);
+	}
+	r->md5sum = malloc(MD5_DIGEST_LENGTH);
+	for(i = 0; i < strlen(tok); i+=2)
+	  r->md5sum[i/2] = ctoi(tok[i+1]) | (ctoi(tok[i]) << 4);
+	break;
+
+  case CMD_STAT:
+	/* dev */
+	tok = strtok(NULL, "\n");
+	if (tok == NULL) {
+	  fprintf(stderr, "ParseResponse: Parse error.\n");
+	  return(NULL);
+	}
+	sscanf(tok, "%d %d", &maj, &min);
+	r->dev = makedev(maj, min);
+
+	/* dev type, skipped for now */
+
+	/* mode */
+	tok = strtok(NULL, "\n");
+	if (tok == NULL) {
+	  fprintf(stderr, "ParseResponse: Parse error.\n");
+	  return(NULL);
+	}
+	sscanf(tok, "%o", &(r->mode));
+
+	/* uid */
+	tok = strtok(NULL, "\n");
+	if (tok == NULL) {
+	  fprintf(stderr, "ParseResponse: Parse error.\n");
+	  return(NULL);
+	}
+	sscanf(tok, "%d", &(r->uid));
+
+	/* gid */
+	tok = strtok(NULL, "\n");
+	if (tok == NULL) {
+	  fprintf(stderr, "ParseResponse: Parse error.\n");
+	  return(NULL);
+	}
+	sscanf(tok, "%d", &(r->gid));
+
+	/* size */
+	tok = strtok(NULL, "\n");
+	if (tok == NULL) {
+	  fprintf(stderr, "ParseResponse: Parse error.\n");
+	  return(NULL);
+	}
+	sscanf(tok, "%ld", &(r->size));
+	break;
+	
+  } /* switch(r->command) */
+  
+  return(r);
+}
+
+char ctoi(char c) {
+  switch (c) {
+  case '0':
+    return(0);
+  case '1':
+    return(1);
+  case '2':
+    return(2);
+  case '3':
+    return(3);
+  case '4':
+    return(4);
+  case '5':
+    return(5);
+  case '6':
+    return(6);
+  case '7':
+    return(7);
+  case '8':
+    return(8);
+  case '9':
+    return(9);
+  case 'a':
+  case 'A':
+    return(10);
+  case 'b':
+  case 'B':
+    return(11);
+  case 'c':
+  case 'C':
+    return(12);
+  case 'd':
+  case 'D':
+    return(13);
+  case 'e':
+  case 'E':
+    return(14);
+  case 'f': 
+  case 'F':
+   return(15);
+  }
+  fprintf(stderr, "ctoi: character not in 0-9a-zA-Z encountered.\n");
+  return(-1);
+}

Added: client/ocfstsparse.h
===================================================================
--- client/ocfstsparse.h	2003-08-16 22:26:26 UTC (rev 1)
+++ client/ocfstsparse.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,65 @@
+#ifndef _OCFSTSPARSE_H_
+#define _OCFSTSPARSE_H_
+
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "command.h"
+#include "response.h"
+
+// C++ magic...
+#ifdef __cplusplus
+extern "C" {
+#endif                          // __cplusplus
+
+#define BUFFSIZE (NAME_MAX *2 + 300)
+
+/* 
+   stolen from coreutils. needed to make a dev_t from a major/minor
+   int pair
+*/
+#ifndef makedev
+#define makedev(maj, min)  (((maj) << 8) | (min))
+#endif
+
+/* 
+   Build a command string from the command struct.
+   The returned string needs to be free'd 
+   NULL will be returned on error.
+*/
+char * BuildCommand(command_s *c);
+
+/* 
+   Given a string, parse out the command. Each field on the command
+   should be ended with a '\n'. Only one command can be passed per
+   call
+   Return a new command type or NULL on error
+   The string str will be changed.
+*/
+command_s * ParseCommand(char * str);
+
+/* 
+   Build a response string from the response struct.
+   The returned string needs to be free'd 
+   NULL will be returned on error.
+*/
+char * BuildResponse(response_s *r);
+
+/*    
+   Given a string, parse out the response. Each field on the response
+   should be ended with a '\n'. Only one response can be passed per
+   call return a parsed response.
+   Return a new command type or NULL on error
+   The string str will be changed.
+*/
+response_s * ParseResponse(char *str);
+
+// C++ magic...
+#ifdef __cplusplus
+}
+#endif                          // __cplusplus
+
+#endif /* OCFSTSPARSE */

Added: client/response.c
===================================================================
--- client/response.c	2003-08-16 22:26:26 UTC (rev 1)
+++ client/response.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,93 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "response.h"
+#include "command.h" /* for MD5_DIGEST_LENGTH */
+
+char *responsestrs[] = {"OK", "FAIL"};
+
+response_s * response_s_new( void ) {
+  response_s *r = malloc(sizeof(response_s));
+  bzero(r, sizeof(response_s));
+  return(r);
+}
+
+response_s * response_s_new_fail(enum commands c, int err, char *error) {
+  response_s *r = response_s_new();
+  r->status = RESP_FAIL;
+  r->command = c;
+  r->err = err;
+
+  if (error == NULL)
+	error = strerror(err);
+
+  r->desc = strdup(error);
+  return(r);
+}
+
+response_s * response_s_new_success(enum commands c) {
+  response_s *r = response_s_new();
+  r->status = RESP_OK;
+  r->command = c;
+  return(r);
+}
+
+void response_s_debug(response_s *r) {
+  int i;
+
+  if (r == NULL) {
+	fprintf(stderr, "response_s_debug: handed a null value.\n");
+	return;
+  }
+
+  printf("Command Response:\n");
+  if (r->command < NUMCOMMANDS)
+	printf("\tcommand:%s\n", commandstrs[r->command]);
+  else
+	printf("\tcommand:UNKNOWN\n");
+  printf("\tstatus:\t");
+  if (r->status == RESP_OK)
+	printf("%s\n", responsestrs[RESP_OK]);
+  else {
+	printf("%s\n", responsestrs[RESP_FAIL]);
+	printf("\terr:\t%d\n", r->err);
+	printf("\tdesc:\t%s\n", r->desc);
+  }
+
+  if (r->md5sum != NULL) {
+	printf("\tmd5sum:\t");
+	for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
+	  printf("%02hhx", r->md5sum[i]);
+	}
+	printf("\n");
+  }
+
+  if (r->command == CMD_STAT) {
+	printf("\tmajor:\t%d\n", major(r->dev));
+	printf("\tminor:\t%d\n", minor(r->dev));
+	printf("\tmode:\t%04o\n", r->mode);
+	printf("\tuid:\t%d\n", r->uid);
+	printf("\tgid:\t%d\n", r->gid);
+	printf("\tsize:\t%ld\n", r->size);
+  }
+
+  printf("\n");
+  return;
+}
+
+/* response_t destructor. */
+void response_s_free(response_s *r) {
+  if (r == NULL)
+	return;
+
+  if (r->desc != NULL)
+	free(r->desc);
+
+  if (r->md5sum != NULL)
+	free(r->md5sum);
+
+  free(r);
+  return;
+}

Added: client/response.h
===================================================================
--- client/response.h	2003-08-16 22:26:26 UTC (rev 1)
+++ client/response.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,63 @@
+#ifndef _RESPONSE_H_
+#define _RESPONSE_H_
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "command.h"
+
+// C++ magic...
+#ifdef __cplusplus
+extern "C" {
+#endif                          // __cplusplus
+
+enum responses {RESP_OK=0, RESP_FAIL};
+extern char *responsestrs[];
+#define NUMRESPONSES 2
+
+typedef struct {
+  enum responses status;
+  enum commands command; /* the command type this is a response to */
+  /* used if there's an error */
+  int err; /* what is errno set to? -1 for internal errors */
+  char *desc; /* the results of strerror or a copy of our own internal string*/
+
+  /* from an md5 or modify command */
+  char *md5sum; /* IMPORTANT! This is not an actual string. It is
+				   simply a byte array of length
+				   'MD5_DIGEST_LENGTH'. It is not NULL terminated.*/
+
+  /* return values from a stat command */
+  dev_t    dev;      /* device */
+  dev_t    rdev;     /* device type (if inode device) */
+  mode_t   mode;     /* protection */
+  uid_t    uid;      /* user ID of owner */
+  gid_t    gid;      /* group ID of owner */
+  off_t    size;     /* total size, in bytes */
+} response_s;
+
+
+response_s * response_s_new( void );
+
+/*
+  returns a FAILURE response. The errno field is automatically
+  populated by 'err' and desc is pointed to a copy of 'error'. if
+  'error' is null, then a copy of the string returned by strerror(err)
+  is used instead. 
+ */
+response_s * response_s_new_fail(enum commands c, int err, char *error);
+
+response_s * response_s_new_success(enum commands c);
+
+/* response_t destructor. */
+void response_s_free(response_s *r);
+
+void response_s_debug(response_s *r);
+
+// C++ magic...
+#ifdef __cplusplus
+}
+#endif                          // __cplusplus
+
+#endif /* _RESPONSE_H_ */

Added: client/testpacket
===================================================================
--- client/testpacket	2003-08-16 22:26:26 UTC (rev 1)
+++ client/testpacket	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,44 @@
+helo
+
+delete
+/home/mfasheh/foobarbaz
+
+create
+/home/mfasheh/foobarbaz
+
+resize
+/home/mfasheh/foobarbaz
+409600
+
+modify
+/home/mfasheh/foobarbaz
+1000
+
+md5
+/home/mfasheh/foobarbaz
+
+md5
+/home/mfasheh/foobarbaz
+
+md5
+/home/mfasheh/foobarbaz
+
+quit
+
+chmod
+/tmp/foo
+644
+
+resize
+/tmp/foo
+4096
+
+modify
+/tmp/foo
+9999
+
+md5
+/tmp/foo
+
+quit
+

Added: monkey/CVS/Entries
===================================================================
--- monkey/CVS/Entries	2003-08-16 22:26:26 UTC (rev 1)
+++ monkey/CVS/Entries	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+D

Added: monkey/CVS/Repository
===================================================================
--- monkey/CVS/Repository	2003-08-16 22:26:26 UTC (rev 1)
+++ monkey/CVS/Repository	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+ocfsts/monkey

Added: monkey/CVS/Root
===================================================================
--- monkey/CVS/Root	2003-08-16 22:26:26 UTC (rev 1)
+++ monkey/CVS/Root	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+:pserver:gmarsden at nic1-pc:/cvs/nic

Added: ocfsts.h
===================================================================
--- ocfsts.h	2003-08-16 22:26:26 UTC (rev 1)
+++ ocfsts.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,8 @@
+#ifndef _ocfsts_h_
+#define _ocfsts_h_
+
+#include "client/ocfstsparse.h"
+#include "client/command.h"
+#include "client/response.h"
+
+#endif //_ocfsts_h_

Added: ocfsts.sh
===================================================================
--- ocfsts.sh	2003-08-16 22:26:26 UTC (rev 1)
+++ ocfsts.sh	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,162 @@
+#!/bin/bash 
+#
+# OCFS testing script
+#
+
+source Makefile.config
+
+do_usage() {
+	echo "usage:	$0 make"
+	echo "	$0 makediffs"
+	echo "	$0 run"
+	echo "	$0 kill"
+	echo ""
+	echo "$0 is a simple command line interface to the "
+	echo "ocfs test suite. Run 'make' to begin installation."
+	echo ""
+	echo "$0 commands:"
+	echo "make - compile ocfsts"
+	echo "makediffs - prepare default 'correct' output in $ORIGINAL_DIR"
+	echo "run - perform tests and place diff output in $RESULT_DIR"
+	echo "kill - close client processes on each node"
+	echo ""
+}
+
+
+do_installer() {
+	echo "Building binaries..."
+
+	export SERVER_TARGET CLIENT_TARGET OCFSTS_LIB_TARGET
+
+	make -e clean
+
+	if ! make -e all-redirect
+	then
+		echo "Compile/make error."
+		exit -1;
+	fi
+
+	echo "done."
+
+	echo -e "Installing binaries..."
+	echo "done."
+
+	echo -e "Setting up directories..."
+	mkdir -p $TARGET/$TEST_DIR 
+	mkdir -p $TARGET/$RESULT_DIR
+	mkdir -p $TARGET/$ORIGINAL_DIR
+	echo "done"
+
+	echo "	* * * "
+	echo "	Now set up diffs by running \"$0 makediffs\" and"
+	echo "	hand correcting the output in the $ORIGINAL_DIR directory."
+	echo "	* * * "
+}
+
+do_makediffs() {
+	echo "WARNING!!!";
+	echo " You are about to nuke potentially hand edited files."
+	echo " You WILL have to re-edit these files by hand!"
+	echo " "
+	echo " Press CTRL-C now to abort."
+	read
+
+	spawn_clients
+
+	for i in `ls -1 $TEST_DIR/test*`
+	do
+		VAR=$(echo $i | sed -e "s/$TEST_DIR/$ORIGINAL_DIR/" | sed -e "s/$/.orig/");
+		echo ...creating $VAR
+		touch $VAR
+		$TARGET/$SERVER_TARGET $NODEFILE < $i > $VAR
+	done
+}
+
+do_tests() {
+
+	spawn_clients
+
+	DATE=$(date)
+	
+	for i in `ls -1 $TEST_DIR/test*`
+	do
+		ORIGINAL=$(echo $i | sed -e "s/$TEST_DIR/$ORIGINAL_DIR/" | sed -e "s/$/.orig/");
+		NEW=$(echo $i | sed -e "s/$TEST_DIR/$RESULT_DIR/" | sed -e "s/$/.$DATE/");
+		LOG=$(echo $i | sed -e "s/$TEST_DIR/$RESULT_DIR/" | sed -e "s/$/.$DATE.out/");
+
+		echo testing $i now...;
+		#$TARGET/$SERVER_TARGET $NODEFILE < $i | tee "$NEW" | $DIFF "$ORIGINAL" | tee "$LOG"
+		$TARGET/$SERVER_TARGET $NODEFILE < $i | tee "$NEW" 
+
+		$TARGET/$DIFF "$ORIGINAL" "$NEW" | tee "$LOG"
+
+		echo done;
+	done
+
+	kill_clients
+}
+
+kill_clients() {
+	for node in `cat $NODEFILE | awk '{print $1}'|grep -v ^#|sort|uniq`
+	do
+		ping -c1 $node  >& /dev/null
+		if [ $? -eq 0 ]
+		then
+			echo "Killing client on $node."
+			ssh $CLIENT_USER@$node killall -9 $CLIENT_TARGET
+		else
+			echo "Host $node not alive!"
+		fi
+
+	done
+}
+
+spawn_clients() {
+	for node in `cat $NODEFILE | awk '{print $1}'|grep -v ^#|sort|uniq`
+	do
+		ping -c1 $node  >& /dev/null
+		if [ $? -eq 0 ]
+		then
+			echo "Testing port $OCFSTS_PORT on $node"
+			nc $node $OCFSTS_PORT -q0 < /dev/null >& /dev/null
+			if [ $? -eq 0 ]
+			then
+				echo "Client already started"
+			else
+				echo "Starting client on $node"
+				echo "Use authorized_keys on target machine to avoid entering password."
+				scp $CLIENT_TARGET root@$node:$CLIENT_INSTALL_DIR/
+				ssh $CLIENT_USER@$node $CLIENT_INSTALL_DIR/$CLIENT_TARGET 
+			fi
+		else
+			echo "Host $node not alive!"
+		fi
+
+	done
+}
+
+
+# Handle options
+
+case "$1" in 
+	make)
+		do_installer
+		;;
+	kill)
+		kill_clients	
+		;;
+	spawn)
+		spawn_clients
+		;;
+	makediffs)
+		do_makediffs
+		;;
+	run)
+		do_tests
+		;;
+	*)
+		do_usage
+		exit 1
+		;;
+esac
+


Property changes on: ocfsts.sh
___________________________________________________________________
Name: svn:executable
   + 

Added: ocfsts_diff.pl
===================================================================
--- ocfsts_diff.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ ocfsts_diff.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,20 @@
+#!/usr/bin/perl -w
+
+unless (defined $ARGV[0] and defined $ARGV[1]) {
+	usage();
+	exit;
+}
+
+open (ORIGINAL, $ARGV[0]) or die "no original file";
+open (OUTPUT,   $ARGV[1]) or die "no output data!";
+
+while ($orig_line=<ORIGINAL>) {
+	$out_line = <OUTPUT>;
+	if ($out_line =~ /Time/) {
+		next;
+	}
+	if ($orig_line ne $out_line) {
+		print "> $out_line";
+		print "< $orig_line";
+	}
+}


Property changes on: ocfsts_diff.pl
___________________________________________________________________
Name: svn:executable
   + 

Added: server/CVS/Entries
===================================================================
--- server/CVS/Entries	2003-08-16 22:26:26 UTC (rev 1)
+++ server/CVS/Entries	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,17 @@
+/Makefile/1.17/Thu Dec 12 01:32:16 2002//
+/apitest.c/1.4/Tue Dec 10 23:14:09 2002//
+/comm.c/1.6/Thu Dec 12 01:32:16 2002//
+/comm.h/1.5/Thu Oct 17 00:44:27 2002//
+/debug.h/1.3/Thu Oct 17 00:44:27 2002//
+/logprint.c/1.6/Wed Dec  4 23:17:45 2002//
+/logprint.h/1.3/Thu Oct 17 18:53:03 2002//
+/md5print.h/1.1/Tue Dec 10 18:57:30 2002//
+/nodelist/1.2/Thu Oct 10 22:11:50 2002//
+/ocfs_test.c/1.26/Thu Dec 12 01:32:16 2002//
+/ocfs_test.h/1.7/Thu Dec  5 23:21:34 2002//
+/ocfs_test_server.c/1.13/Thu Dec 12 01:32:16 2002//
+/ocfs_test_server.h/1.2/Thu Dec  5 18:56:02 2002//
+/ocfstsapi.c/1.5/Thu Dec 12 01:32:16 2002//
+/ocfstsapi.h/1.3/Tue Dec 10 21:17:58 2002//
+/syntax.h/1.3/Mon Dec  9 23:03:47 2002//
+D

Added: server/CVS/Repository
===================================================================
--- server/CVS/Repository	2003-08-16 22:26:26 UTC (rev 1)
+++ server/CVS/Repository	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+ocfsts/server

Added: server/CVS/Root
===================================================================
--- server/CVS/Root	2003-08-16 22:26:26 UTC (rev 1)
+++ server/CVS/Root	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+:pserver:gmarsden at nic1-pc:/cvs/nic

Added: server/Makefile
===================================================================
--- server/Makefile	2003-08-16 22:26:26 UTC (rev 1)
+++ server/Makefile	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,43 @@
+#
+# OCFSTS Makefile
+# Server 
+#
+#
+
+CC=gcc
+CFLAGS= -Wall -ggdb -p -DOCFSTS_PORT=$(OCFSTS_PORT)
+LDFLAGS= 
+CFLAGSLIBRARY=-DOCFSTS_LIBRARY
+
+OBJS= comm.o ocfs_test_server.o ocfs_test.o logprint.o ocfstsapi.o
+
+include ../Makefile.config
+
+all: depend $(SERVER_TARGET)
+
+Makefile.depend: depend
+
+include Makefile.depend
+depend:
+	$(CC) $(CXXFLAGS) -MM `find . -name '*.c'` > Makefile.depend
+
+$(SERVER_TARGET): $(OBJS) ../$(OCFSTS_LIB_TARGET)
+	$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
+
+clean:
+	rm -f *.o $(SERVER_TARGET)
+
+$(OCFSTS_LIB_SERVER_TARGET):  $(OBJS) ../$(OCFSTS_LIB_TARGET) 
+	$(CC) $(CFLAGS) $(CFLAGSLIBRARY) -c ocfs_test_server.c
+	#ar rcs $@ $^
+	$(CC) $(CFLAGS) -shared -o $@ $^
+
+#ocfs_test.o: ocfs_test.c ocfs_test.h
+#		$(CC) $(CFLAGS) $< $(CLIENT_OBJS) -c -o $@
+#
+
+
+apitest: 
+	make -C .. clean all library
+	g++ -Wall -ggdb -p -DOCFSTS_PORT=4444 -DOCFSTS_LIBRARY comm.o ocfs_test_server.o ocfs_test.o logprint.o ocfstsapi.o ../libocfsts.a apitest.c -o apitest 
+

Added: server/apitest.c
===================================================================
--- server/apitest.c	2003-08-16 22:26:26 UTC (rev 1)
+++ server/apitest.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include "ocfstsapi.h"
+
+/* to run this
+ * do make -C .. clean library 
+ * then 
+ * g++ -Wall -ggdb -p -DOCFSTS_PORT=4444 -DOCFSTS_LIBRARY comm.o ocfs_test_server.o ocfs_test.o logprint.o ocfstsapi.o ../libocfsts.a apitest.c -o apitest -lefence
+ * hehe
+ */
+
+char *nodes[]={"expo.us.oracle.com"};
+int 
+main (void)
+{
+	ocfsts_open_connection (1, nodes);
+/*	ocfsts_execute ("R create /tmp/myfile1");
+	ocfsts_verify ("R create /tmp/myfile1");
+	ocfsts_execute ("R chmod /tmp/myfile1 0666");
+	ocfsts_execute ("R chksum /tmp/myfile1");
+	ocfsts_verify ("R chksum /tmp/myfile1");
+*/
+	ocfsts_execute ("R create /tmp/myfile");
+	ocfsts_verify ("R create /tmp/myfile");
+
+	ocfsts_execute ("R chmod /tmp/myfile 0777");
+	ocfsts_verify ("R chmod /tmp/myfile 0777");
+
+	ocfsts_execute ("R resize /tmp/myfile 1000");
+	ocfsts_verify ("R resize /tmp/myfile 1000");
+
+	ocfsts_execute ("R modify /tmp/myfile 31337");
+	ocfsts_verify ("R modify /tmp/myfile 31337");
+
+	ocfsts_execute ("R delete /tmp/myfile");
+	ocfsts_verify ("R delete /tmp/myfile");
+
+	ocfsts_close_connection();
+
+}
+

Added: server/comm.c
===================================================================
--- server/comm.c	2003-08-16 22:26:26 UTC (rev 1)
+++ server/comm.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,150 @@
+/*
+ * comm.c
+ * --
+ *  Communication protocol for ocfs test server;
+ *  the "Master" side is a client which connects 
+ *  to servers running on the "Slave" machines.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+
+#include "comm.h"
+#include "debug.h"
+#include "../ocfsts.h"
+
+#define MAXBUF 102400
+
+typedef struct ocfs_socket_real
+{
+	int sd;
+	struct sockaddr_in ServerSocket;
+} ocfs_socket_real;
+
+bool
+comm_send_command (ocfs_socket os, char *buffer)
+{
+	if (send(os->sd, buffer, strlen(buffer), 0) == -1)
+	{
+		perror("send");
+		return false;
+	}
+	return true;
+}
+
+bool 
+comm_get_response (ocfs_socket os, char *buffer, int maxlen)
+{
+	int stat;
+	stat = recv (os->sd, buffer, maxlen, 0);
+	if (stat == -1)
+	{
+		perror("recv");
+		return false;
+	}
+	else
+		buffer[stat] = 0;
+	return true;
+}
+
+bool
+say_helo_ok (ocfs_socket os)
+{
+	char *b;
+	char buffer[2048];
+	command_s *cs = command_s_new();
+	response_s *rs;
+	int stat = 0;
+
+	cs->type = CMD_HELO;
+	b = BuildCommand(cs);
+
+	comm_send_command (os, b);
+	free(b);
+
+	comm_get_response (os, buffer, 2048);
+	rs = ParseResponse(buffer);
+
+	if (rs && rs->status == RESP_OK)
+		stat = 1;
+
+	command_s_free(cs);
+	response_s_free(rs);
+
+	DEBUG((stderr, "[DD] Got helo.\n"));
+
+	return stat;
+}
+
+ocfs_socket
+comm_open_connection (struct hostent *hp)
+{
+	ocfs_socket_real *os;
+	//char send_buffer[MAXBUF];
+	//char recv_buffer[MAXBUF];
+	//command_T command, return_command;
+
+	os = (ocfs_socket_real *) malloc (sizeof(ocfs_socket_real));
+
+	// Open socket
+	os->sd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (os->sd == -1)
+	{
+		perror("socket");
+		return NULL;
+	}
+
+	/*
+	// Establish Connection
+	if ((hp = gethostbyname (node)) == NULL)
+	{
+		perror("gethostbyname");
+		return NULL;
+	}
+	*/
+
+	os->ServerSocket.sin_family = AF_INET;
+	os->ServerSocket.sin_port = htons(OCFS_DEFAULT_PORT);
+
+	memcpy (&os->ServerSocket.sin_addr, 
+			hp->h_addr,
+			hp->h_length);
+
+	if (connect (os->sd, (struct sockaddr*) &os->ServerSocket,
+				sizeof (struct sockaddr_in)) == -1)
+	{
+		perror("connect");
+		return NULL;
+	}
+
+	// Send HELO to server and confirm response
+	if (say_helo_ok(os))
+		return os;
+
+	return NULL;
+}
+
+int
+comm_close_connection (ocfs_socket os)
+{
+	int stat = close(os->sd);
+	//char send_buffer[MAXBUF];
+	//command_T command;
+
+	/* send goodbye command */
+
+	close(os->sd);
+	free(os);
+	return stat;
+}
+

Added: server/comm.h
===================================================================
--- server/comm.h	2003-08-16 22:26:26 UTC (rev 1)
+++ server/comm.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,23 @@
+/* comm.h
+ * --
+ *  Master communications library.
+ */
+
+#ifndef _COMM_H_
+#define _COMM_H_
+
+#define OCFS_DEFAULT_PORT OCFSTS_PORT
+//#define OCFS_DEFAULT_NODE "192.68.0.1"
+
+#define OCFS_CONNECT_ERROR -1
+
+typedef struct ocfs_socket_real* ocfs_socket;
+
+ocfs_socket comm_open_connection (struct hostent *hp);
+int comm_close_connection (ocfs_socket os);
+
+bool comm_send_command (ocfs_socket os, char *buffer);
+bool comm_get_response (ocfs_socket os, char *buffer, int maxlen);
+
+
+#endif // _COMM_H_

Added: server/debug.h
===================================================================
--- server/debug.h	2003-08-16 22:26:26 UTC (rev 1)
+++ server/debug.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,7 @@
+#ifndef DEBUG
+
+//#define DEBUG(a) fprintf a
+#undef DEBUG
+#define DEBUG(a) ;
+
+#endif //DEBUG

Added: server/logprint.c
===================================================================
--- server/logprint.c	2003-08-16 22:26:26 UTC (rev 1)
+++ server/logprint.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,177 @@
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include "logprint.h"
+
+#include "../ocfsts.h"
+
+void
+logprint_header(int mode)
+{
+	struct timeval tv;
+
+	gettimeofday(&tv, NULL);
+	fprintf (stdout, "\n%s\nTime: %ld.%lds\n",	
+			mode == C_COMMAND?"-----------------------------------":"--",
+			tv.tv_sec, tv.tv_usec);
+
+}
+
+void
+logprint_footer()
+{
+	fprintf (stdout,"\n\n");
+}
+
+void
+logprint_vfymethod (const struct cmdline *cmdline)
+{
+	switch (cmdline->vmethod)
+	{
+		case VFY_EXIST:
+			fprintf (stdout, "\tfstat %s\n", cmdline->arg[0]);
+			break;
+		case VFY_NEXIST:
+			fprintf (stdout, "\tfstat %s (file should not exist)\n", cmdline->arg[0]);
+			break;
+		case VFY_OWNER:
+			fprintf (stdout, "\tfstat %s for owner \n", cmdline->arg[0]);
+			break;
+		case VFY_MODE:
+			fprintf (stdout, "\tfstat %s for file mode\n", cmdline->arg[0]);
+			break;
+		case VFY_SIZE:
+			fprintf (stdout, "\fstat %s for file size\n", cmdline->arg[0]);
+			break;
+		case VFY_MD5:
+			fprintf (stdout, "\tmd5 %s\n", cmdline->arg[0]);
+			break;
+
+		case VFY_NONE:
+		default:
+			break;
+	};
+}
+
+void
+logprint_success (const struct cmdline *cmdline, int mode, int target)
+{
+	logprint_header(mode);
+	
+	if (target == -1)
+		target = cmdline->targetnode;
+
+	target += 1; // pretty print format
+
+	if (mode == C_COMMAND)
+	{
+		fprintf (stdout, "(CMD Success) (Node %d) (Line %d) %s"
+				"\tExpected %s, got %s.\n",
+				target, cmdline->lineno, cmdline->raw,
+				cmdline->expecttrue?"success":"failure", 
+				cmdline->expecttrue?"success":"failure");
+	}
+	else
+	{
+		fprintf (stdout, "(VFY Success) (Node %d) (Line %d) %s",
+				target, cmdline->lineno, cmdline->raw);
+		logprint_vfymethod(cmdline);
+	}
+
+	/*
+	fprintf (stdout, "[ %s%s ] <Node %d, Line %d> (%s %s), %s %s\n",
+			cmdline->expecttrue?"+":"-", 
+			mode==C_COMMAND?"c":" ", 
+			target, cmdline->lineno, 
+			get_command_for_action(cmdline->command),
+			cmdline->arg[0], 
+			mode==C_COMMAND?"cmd":"vfy",
+			cmdline->expecttrue?"succeeded":"failed");
+			*/
+	logprint_footer();
+}
+
+void
+logprint_state (const struct cmdline *cmdline, const response_s *rs)
+{
+	if (cmdline->cs != NULL)
+	{
+		//fprintf (stdout, "<contents of command_s...>\n");
+		command_s_debug ((command_s*)cmdline->cs);
+	}
+
+	if (rs != NULL)
+	{
+		//fprintf (stdout, "<contents of response_s...>\n");
+		response_s_debug((response_s*)rs);
+	}
+}
+
+void
+logprint_failure (const struct cmdline *cmdline, const response_s *rs, int mode, int target)
+{
+
+	logprint_header(mode);
+
+	if (target == -1) target = cmdline->targetnode;
+	target += 1;
+
+	if (mode == C_COMMAND)
+	{
+		fprintf (stdout, 
+				"(CMD FAILURE) (Node %d) (Line %d) %s"
+				"\tExpected %s, got %s.\n"
+				"\t(%d) %s\n",
+				target+1, cmdline->lineno, cmdline->raw,
+				cmdline->expecttrue?"success":"failure", 
+				!cmdline->expecttrue?"success":"failure",
+				rs->err, rs->desc);
+	}
+	else
+	{
+		fprintf (stdout, "(VFY FAILURE) (Node %d) (Line %d) %s",
+				target, cmdline->lineno, cmdline->raw);
+		logprint_vfymethod(cmdline);
+		fprintf (stdout, "\t(%d) %s\n",
+				rs->err, rs->desc);
+	}
+
+	logprint_state(cmdline, rs);
+
+	logprint_footer();
+}
+
+void
+logprint_syntax_real (const struct cmdline *cmdline, const char *desc, int opti, char *opts)
+{
+	logprint_header(0);
+	fprintf (stderr, "(SYNTAX) Line %d, %s\n", cmdline->lineno, desc);
+
+	if (opti != -1)
+		fprintf (stdout, "(SYNTAX) %s %d\n"
+				"\t cmd: %s", desc, opti, cmdline->raw);
+	else if (opts != NULL)
+		fprintf (stdout, "(SYNTAX) %s %s\n"
+				"\t cmd: %s", desc, opts, cmdline->raw);
+	logprint_footer();
+}
+void
+logprint_syntax (const struct cmdline *cmdline, const char *desc)
+{
+	logprint_syntax_real (cmdline, desc, -1, NULL);
+}
+
+void
+logprint_syntax_int (const struct cmdline *cmdline, const char *desc, int opti)
+{
+	logprint_syntax_real (cmdline, desc, opti, NULL);
+}
+
+void
+logprint_syntax_str (const struct cmdline *cmdline, const char *desc, char *opts)
+{
+	logprint_syntax_real (cmdline, desc, -1, opts);
+}
+
+

Added: server/logprint.h
===================================================================
--- server/logprint.h	2003-08-16 22:26:26 UTC (rev 1)
+++ server/logprint.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,15 @@
+#ifndef _logprint_h_
+#define _logprint_h_
+
+#include "ocfs_test.h"
+#include "../ocfsts.h"
+
+void logprint_success (const struct cmdline *cmdline, int mode, int target);
+
+void logprint_failure (const struct cmdline *cmdline, const response_s *rs, int mode, int target);
+
+void logprint_syntax (const struct cmdline *cmdline, const char *desc);
+void logprint_syntax_int (const struct cmdline *cmdline, const char *desc, int opti);
+void logprint_syntax_str (const struct cmdline *cmdline, const char *desc, char *opts);
+
+#endif //_logprint_h_

Added: server/md5print.h
===================================================================
--- server/md5print.h	2003-08-16 22:26:26 UTC (rev 1)
+++ server/md5print.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,18 @@
+#ifndef _md5out_h_
+#define _md5out_h_
+
+void md5sum_debug(const char *digest) {
+  int i;
+  
+  if (digest == NULL) {
+	fprintf(stderr, "md5sum_debug: null parameters are illegal.\n");
+	return;
+  }
+  
+  for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
+	printf("%02hhx", digest[i]);
+  }
+
+}
+
+#endif //_md5out_h_

Added: server/nodelist
===================================================================
--- server/nodelist	2003-08-16 22:26:26 UTC (rev 1)
+++ server/nodelist	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,10 @@
+verbose.us.oracle.com 
+verbose.us.oracle.com 
+verbose.us.oracle.com 
+verbose.us.oracle.com 
+#192.168.0.1
+#192.168.0.2
+#192.168.0.3
+#192.168.0.4
+#192.168.0.5
+#nic1-pc.us.oracle.com

Added: server/ocfs_test.c
===================================================================
--- server/ocfs_test.c	2003-08-16 22:26:26 UTC (rev 1)
+++ server/ocfs_test.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,661 @@
+/*
+ * ocfs_test
+ * --
+ *  This file parses the command line from stdin or a command file,
+ *  uses client code to generate a client-request, waits for response,
+ *  then generates a series of tests for every other node in the system 
+ *  to validate that the test was successful
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "debug.h"
+#include "ocfs_test.h"
+#include "ocfs_test_server.h"
+#include "logprint.h"
+#include "syntax.h"
+//#include "md5print.h"
+
+#define STRTOK_NEXT_TOKEN(a)		strtok (a, " "); \
+				if (!ptr || !ptr[0])	{ \
+					logprint_syntax (cmdline, "unexpected end of command");\
+					free (tmp);\
+					return SYNTAX_ERR; \
+				}
+
+
+
+// BEHAVIOR FLAGS 
+#define IGNORE_ORIGINAL_NODE 0
+#define IGNORE_CDSL_VERIFY 1
+
+#define COMMENT 1
+#define SYNTAX_ERR -1
+#define SYNTAX_OK 0
+
+#define MAX_BUF 2048
+
+
+static char lastmd5[MD5_DIGEST_LENGTH];
+
+void
+set_md5_result(const char *chksum)
+{
+	bcopy (chksum, lastmd5, MD5_DIGEST_LENGTH);
+	//fprintf (stderr, ">> Setting md5 = %16s\n", chksum);
+}
+
+int 
+compare_md5_result (const char *chksum)
+{
+	return !bcmp (chksum, lastmd5, MD5_DIGEST_LENGTH);
+}
+
+
+
+const char *
+get_command_for_action(const int c)
+{
+	int i;
+	for (i=0; i<NUM_SERVER_COMMANDS; i++)
+	{
+		if (cmdtab[i].type == c)
+			return cmdtab[i].name;
+	}
+	return NULL;
+}
+
+int 
+aredigits(const char *string)
+{
+	char *p = (char *)string;
+	while (*p)
+	{
+		if(!isdigit(*p))
+			return 0;
+		p++;
+	}
+	return 1;
+
+}
+
+int
+get_command_type (const char *cmd, int *type, int *numargs, int *vtype)
+{
+	int i;
+	for (i=0;i<NUM_SERVER_COMMANDS; i++)
+	{
+		if (!strcmp(cmdtab[i].name, cmd))
+		{
+			*type = cmdtab[i].type;
+			*numargs = cmdtab[i].numargs;
+			*vtype = cmdtab[i].vtype;
+			return cmdtab[i].type;
+		}
+	}
+	return -1;
+}
+
+int
+analyze_command (const char *cmd, struct cmdline *cmdline)
+{
+	if (get_command_type (cmd, &(cmdline->command), &(cmdline->num_attrs), &(cmdline->vmethod)) == -1)
+		return SYNTAX_ERR;
+
+	return SYNTAX_OK;
+}
+
+
+int 
+parse_command (const char *cmd, struct cmdline *cmdline)
+{
+	/* Syntax:
+	 * [+|-|#] <R|#|Node> <Cmd> [arg1] [arg2] [arg3]
+	 * At the moment, disallow escaped arguments (" or ')
+	 */
+	char *tmp = strdup(cmd);
+	char *ptr = tmp;
+	char *ptr2;
+	int num_arguments_remaining;
+	int i;
+
+	if (!ptr || !ptr[0] || ptr[0] == '\n' || ptr[0] == ' ')
+		return COMMENT; 
+
+	//ptr[strlen(ptr)-1] = '\0'; // chop string .... NO ... CHOMP it.
+	if ((ptr2 = strchr(ptr, '\n')) != NULL)
+		*ptr2 = '\0';
+
+	ptr = STRTOK_NEXT_TOKEN(ptr);
+
+	// Catch optional first argument [+-#] 
+	if (ptr && *ptr && (*ptr == '+' || *ptr == '-' || *ptr == '#'))
+	{
+		if (*ptr == '+' || *ptr == '-')
+			cmdline->expecttrue = (*ptr == '+');
+		else 
+			return COMMENT;
+		
+		ptr = STRTOK_NEXT_TOKEN(NULL);
+	}
+	else
+		cmdline->expecttrue = 1;
+
+	/* Get node destination */
+	if (!strcmp(ptr, "R"))
+		cmdline->targetnode = ocfs_get_random_nodenum(); 
+	else if (aredigits(ptr))
+	{
+		cmdline->targetnode = atoi(ptr);
+		cmdline->targetnode -= 1; // nodenum index starts at 1, arrays are 0-offset
+	}
+	else
+	{
+		cmdline->targetnode = ocfs_get_node_by_name(ptr);
+		if (cmdline->targetnode == -1)
+		{
+			logprint_syntax (cmdline, "Invalid node name");
+			free(tmp);
+			return SYNTAX_ERR;
+		}
+	}
+
+	// Get the command action
+	ptr= STRTOK_NEXT_TOKEN(NULL);
+
+	if (analyze_command(ptr, cmdline) == SYNTAX_ERR)
+	{
+		logprint_syntax (cmdline, "Invalid command keyword");
+		free(tmp);
+		return SYNTAX_ERR;
+	}
+
+	// Get arguments
+	num_arguments_remaining = num_args_per_type [cmdline->num_attrs];
+	for(i=0; ptr && ptr[0] && num_arguments_remaining; i++)
+	{
+		ptr = strtok(NULL, " ");
+		if (ptr == NULL)
+		{
+			logprint_syntax_int (cmdline, "Expected number of arguments:", 
+					cmdline->num_attrs);
+			free(tmp);
+			return SYNTAX_ERR;
+		}
+
+		cmdline->arg[i] = strdup (ptr);
+		num_arguments_remaining -= 1;
+	}
+
+	// Check for command length overrun, CDSL mode
+	cmdline->cdsl = 0;
+	while (ptr && ptr[0])
+	{
+		ptr = strtok(NULL," ");
+		if (!ptr || !ptr[0])
+			break;
+
+		if (!strcmp("cdsl", ptr) || !strcmp("CDSL", ptr))
+		{
+			cmdline->cdsl = 1;
+		}
+		else if (!strcmp("cdsl+", ptr) || !strcmp("CDSL+", ptr))
+		{
+			cmdline->cdsl = 1;
+			cmdline->cdsl_pass_other_nodes = 1;
+		}
+		else if (!strcmp("cdsl-", ptr) || !strcmp("CDSL-", ptr))
+		{
+			cmdline->cdsl = 1;
+			cmdline->cdsl_pass_other_nodes = 0;
+		}
+		else
+		{
+			logprint_syntax (cmdline, "Too many arguments to command.");
+			free(tmp);
+			return SYNTAX_ERR;
+		}
+	}
+
+	free(tmp);
+	return SYNTAX_OK;
+}
+
+char *
+make_cdsl_op (struct cmdline *cmdline, int mode)
+{
+	char *p;
+	command_s *cs = command_s_new();
+	if (cmdline->command == CMD_CREATE || 
+			cmdline->command == CMD_MKDIR)
+	{
+		cmdline->cs = cs;
+		cs->type = (enum commands) CMD_CDSL;
+
+		cs->src = cmdline->arg[0];
+		if (cmdline->command == CMD_CREATE)
+			cs->cdslflag = OCFS_FLAG_CDSL_FILE;
+		else
+			cs->cdslflag = OCFS_FLAG_CDSL_DIR;
+
+		cs->cdslop = OCFS_CDSL_CREATE;
+
+		p = BuildCommand(cs);
+		return p;
+	}
+	
+	logprint_syntax (cmdline, "CDSL flag toggled for unsupported operation");
+	return NULL; // error!
+}
+
+char *
+generate_command (struct cmdline *cmdline, int mode)
+{
+	char *p;
+	command_s *cs = command_s_new();
+
+	if (cmdline->cdsl)
+		return make_cdsl_op (cmdline, mode);
+
+	cmdline->cs = cs;
+	cs->type = (enum commands)cmdline->command;
+
+	if (mode == C_VERIFY)
+	{
+		if (cmdline->vmethod == VFY_MD5)
+			cs->type = CMD_MD5;
+		else if (cmdline->expecttrue)
+			cs->type = CMD_STAT;
+	}
+
+	// command arg. 1
+	if (cmdline->num_attrs != NO_ARGS)
+		cs->src = cmdline->arg[0];
+
+	// command arg. 2..n
+	switch (cmdline->num_attrs) {
+
+		case SRC_ARG:
+			break;
+
+		case SRC_DST_ARG:
+			cs->dest = cmdline->arg[1];
+			break;
+
+		case UID_ARG:
+			cs->uid = atoi(cmdline->arg[1]);
+			cs->gid = atoi(cmdline->arg[2]);
+			break;
+			
+		case NODE_ARG:
+			cs->mode= strtol(cmdline->arg[1], NULL, 8);
+			cs->dev = makedev(atoi(cmdline->arg[2]), atoi(cmdline->arg[3]));
+			break;
+
+		case MODE_ARG:
+			cs->mode= strtol(cmdline->arg[1], NULL, 8);
+			break;
+
+		case SIZE_ARG:
+			cs->size = atoi(cmdline->arg[1]);
+			break;
+
+		case ENTPY_ARG:
+			cs->entropy = atoi(cmdline->arg[1]);
+			break;
+
+		default:
+			fprintf (stderr, "ERROR... Too few arguments? (%d)\n", cmdline->num_attrs);
+			break;
+	}
+
+
+	p = BuildCommand(cs);
+	return p;
+}
+
+void
+exec_quit (struct cmdline *cmdline)
+{
+	char *p = generate_command (cmdline, C_COMMAND);
+	ocfs_send_command(p, cmdline->targetnode);
+}
+
+bool
+exec_command (struct cmdline *cmdline)
+{
+	char buffer[MAX_BUF];
+	char *p;
+	response_s *rs;
+	bool success = false;
+
+	p = generate_command (cmdline, C_COMMAND);
+	if (p == NULL)
+	{
+		fprintf (stderr, "\n(ocfs_test server) server error: generate command NULL\n");
+		return false;
+	}
+
+	ocfs_send_command(p, cmdline->targetnode);
+
+	ocfs_get_response(buffer, MAX_BUF, cmdline->targetnode);
+	rs = ParseResponse(buffer);
+
+	if (rs)
+	{
+		if (rs->status == RESP_OK)
+		{
+			if (cmdline->expecttrue)
+			{
+				logprint_success(cmdline, C_COMMAND, -1);
+				success = true;
+			}
+			else
+				logprint_failure(cmdline, rs, C_COMMAND, -1);
+
+		}
+		else
+		{
+			if (cmdline->expecttrue)
+				logprint_failure(cmdline, rs, C_COMMAND, -1);
+			else
+			{
+				logprint_success(cmdline, C_COMMAND, -1);
+				success = true;
+			}
+		}
+	}
+
+	if (rs->md5sum != NULL && 
+			(cmdline->command == CMD_MD5 || cmdline->command == CMD_MODIFY))
+	set_md5_result(rs->md5sum);
+
+	response_s_free(rs);
+	return success;
+}
+
+bool
+check_result (response_s *rs, struct cmdline *cmdline)
+{
+	bool success = (rs->status==RESP_OK);
+
+	if (rs && rs->status == RESP_OK)
+	{
+		switch(cmdline->vmethod)
+		{
+			case VFY_EXIST:
+				return (success);
+				
+			case VFY_NEXIST:
+				return (!success);
+				
+			case VFY_OWNER:
+				return (rs->uid == cmdline->cs->uid && rs->gid == cmdline->cs->gid);
+
+			case VFY_MODE:
+				return ((rs->mode&0777) == cmdline->cs->mode);
+				break;
+
+			case VFY_SIZE:
+				return (rs->size == cmdline->cs->size);
+
+			case VFY_MD5:
+				return compare_md5_result(rs->md5sum);
+					//(!memcmp(rs->md5sum, cmdline->md5sum, MD5_DIGEST_LENGTH));
+
+			case VFY_NONE:
+			default:
+				return true;
+		}
+	}
+	else
+	{
+		switch (cmdline->vmethod)
+		{
+			case VFY_EXIST:
+				return (success);
+				
+			case VFY_NEXIST:
+				return (!success);
+
+			default:
+				return false;
+		}
+	}
+}
+
+
+
+bool
+verify_command (struct cmdline *cmdline)
+{
+	char buffer[MAX_BUF];
+	char *p;
+	response_s *rs;
+	int numnodes = ocfs_get_numnodes();
+	bool success = true;
+	int i;
+
+	if (IGNORE_CDSL_VERIFY && cmdline->cdsl)
+		return true;
+
+	for (i=0; i<numnodes; i++)
+	{
+		if (IGNORE_ORIGINAL_NODE || (cmdline->cdsl && (cmdline->targetnode == i)))
+		{
+			if (i==numnodes)
+				continue;
+		}
+
+		if (0) // Randomly choose nodes to verify?
+			continue;
+
+		p = generate_command (cmdline, C_VERIFY);
+		ocfs_send_command(p, cmdline->targetnode);
+		ocfs_get_response(buffer, MAX_BUF, cmdline->targetnode);
+		rs = ParseResponse(buffer);
+
+		if (!rs)
+		{
+			DEBUG((stderr, "[WARN] Ack, empty response from client!\n"));
+			continue;
+		}
+
+		if (!cmdline->expecttrue)
+		{
+			if (rs->status == RESP_OK)
+			{
+				logprint_failure (cmdline, rs, C_VERIFY, i);
+				success = false;
+			}
+			else
+			{
+				logprint_success (cmdline, C_VERIFY, i);
+			}
+		}
+		else
+		{
+			if (check_result (rs, cmdline))
+			{
+				logprint_success (cmdline, C_VERIFY, i);
+			}
+			else
+			{
+				logprint_failure (cmdline, rs, C_VERIFY, i);
+				success = false;
+			}
+		}
+
+		response_s_free(rs);
+	}
+	return success;
+}
+
+void
+free_cmdline_members (struct cmdline *cmdline)
+{
+	/*
+	if (cmdline->command == CMD_MD5)
+		free (cmdline->md5sum);
+		*/
+
+	// freeing args is handled by command_s_free
+
+	free(cmdline->raw);
+	command_s_free(cmdline->cs);
+}
+
+void 
+report_init (struct report *report)
+{
+  	int i;
+
+	for (i=0; i<OCFSTS_NUMCOMMANDS; i++)
+	{
+		report->cmd_success[i] = 0;
+		report->cmd_failure[i] = 0;
+		report->vfy_success[i] = 0;
+		report->vfy_failure[i] = 0;
+	}
+	report->syntax = 0;
+}
+
+void 
+report_update (struct report *report, struct cmdline *cmdline, 
+		bool cmd_status, bool vfy_status)
+{
+	if (cmd_status)
+		report->cmd_success[cmdline->command] += 1;
+	else 
+		report->cmd_failure[cmdline->command] += 1;
+
+	if (vfy_status)
+		report->vfy_success[cmdline->command] += 1;
+	else
+		report->vfy_failure[cmdline->command] += 1;
+}
+
+int
+report_generate(struct report *report)
+{
+#if 0
+	fprintf (stdout, "--------------------------------------\n");
+	fprintf (stdout, "|%11s%5s%5s%5s%5s     |\n", "CMD", "C_S", "C_F", "V_S", "V_F");
+	fprintf (stdout, "--------------------------------------\n");
+	for (int i=2; i<OCFSTS_NUMCOMMANDS; i++)
+	{
+		fprintf (stdout, "%12s%5d%5d%5d%5d\n", cmd_strings[i], 
+				report->cmd_success[i], report->cmd_failure[i], 
+				report->vfy_success[i], report->vfy_failure[i]);
+	}
+	fprintf (stdout, "-------------------------------------\n");
+#endif //0
+	fprintf (stdout, "%d syntax errors.\n", report->syntax);
+
+	return 0;
+}
+
+void 
+ocfs_test (char *cmd, int lineno, struct report *report)
+{
+	struct cmdline cmdline;
+	bool cmd_status, vfy_status;
+	int stat;
+
+	cmdline.lineno = lineno;
+	cmdline.raw = strdup(cmd);
+	stat = parse_command(cmd, &cmdline);
+	
+	if (stat == SYNTAX_ERR)
+	{
+		report->syntax += 1;
+		//fprintf (stderr, 
+		//"[WARN] Command syntax errorSyntax error in command file, line %d\n"
+		//		 "[WW] Command: %s", lineno, cmd); // not "chomp"ed
+		return;
+	} 
+	else if (stat == COMMENT)
+		return;
+
+	if (cmdline.command == CMD_QUIT)
+	{
+		exec_quit(&cmdline);
+		return;
+	}
+
+	cmd_status = exec_command (&cmdline);
+
+	vfy_status = verify_command (&cmdline);
+
+	report_update (report, &cmdline, cmd_status, vfy_status);
+	free_cmdline_members (&cmdline);
+}
+
+int
+ocfs_exec_only (char *cmd)
+{
+	struct cmdline cmdline;
+	bool cmd_status;
+	int stat;
+
+	cmdline.lineno = 0;
+	cmdline.raw = strdup(cmd);
+	stat = parse_command(cmd, &cmdline);
+	
+	if (stat == SYNTAX_ERR)
+	{
+		fprintf (stderr, "Syntax error in call to library: %s\n", cmd);
+		return SYNTAX_ERR;
+	} 
+	else if (stat == COMMENT)
+		return 0;
+
+	if (cmdline.command == CMD_QUIT)
+	{
+		exec_quit(&cmdline);
+		return 0;
+	}
+
+	cmd_status = exec_command (&cmdline);
+	free_cmdline_members (&cmdline);
+
+	return cmd_status;
+}
+
+
+int 
+ocfs_vfy_only (char *cmd)
+{
+
+	struct cmdline cmdline;
+	bool vfy_status;
+	int stat;
+
+	cmdline.lineno = 0;
+	cmdline.raw = strdup(cmd);
+	stat = parse_command(cmd, &cmdline);
+	
+	if (stat == SYNTAX_ERR)
+	{
+		fprintf (stderr, "Syntax error in verify-call to library: %s\n", cmd);
+		return SYNTAX_ERR;
+	} 
+	else if (stat == COMMENT)
+		return 0;
+
+	if (cmdline.command == CMD_QUIT)
+	{
+		exec_quit(&cmdline);
+		return 0;
+	}
+
+	vfy_status = verify_command (&cmdline);
+	free(cmdline.raw);
+	//free_cmdline_members_vfy (&cmdline);
+
+	return vfy_status;
+}

Added: server/ocfs_test.h
===================================================================
--- server/ocfs_test.h	2003-08-16 22:26:26 UTC (rev 1)
+++ server/ocfs_test.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,49 @@
+#ifndef _ocfs_test_h_
+#define _ocfs_test_h_
+
+#include "../ocfsts.h"
+
+#define MAX_ARGS 12
+
+struct report {
+	int cmd_success[NUMCOMMANDS];
+	int cmd_failure[NUMCOMMANDS];
+	int vfy_success[NUMCOMMANDS];
+	int vfy_failure[NUMCOMMANDS];
+	int syntax;
+};
+
+enum {C_COMMAND, C_VERIFY};
+
+struct cmdline {
+	int command, num_attrs, vmethod;
+
+	// Flags
+	int expecttrue;
+	int cdsl;
+	int cdsl_pass_other_nodes;
+
+	char *arg[MAX_ARGS];
+	char *raw; 
+
+	int lineno;
+	int targetnode;
+	char *md5sum;
+	
+	command_s *cs;
+};
+
+enum verify {VFY_NONE, VFY_EXIST, VFY_NEXIST, VFY_OWNER, VFY_MODE, VFY_SIZE, VFY_MD5};
+
+
+
+void ocfs_test (char *cmd, int lineno, struct report *report);
+void report_init(struct report *report);
+int report_generate (struct report *report);
+const char * get_command_for_action (const int c);
+
+
+int ocfs_exec_only (char *cmd);
+int ocfs_vfy_only (char *cmd);
+
+#endif //_ocfs_test_h_

Added: server/ocfs_test_server.c
===================================================================
--- server/ocfs_test_server.c	2003-08-16 22:26:26 UTC (rev 1)
+++ server/ocfs_test_server.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,285 @@
+/*
+ * OCFS Test Server
+ * --
+ *  greg.marsden at oracle.com
+ *
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+
+#include "comm.h"
+
+#include "ocfs_test.h"
+#include "debug.h"
+
+#define MAX_BUF 1024
+
+/** Globals */
+static int g_numnodes = 0;
+static struct node {
+	char *name;
+	struct hostent *hp;
+	ocfs_socket os;
+} g_nodes[1024];
+
+void
+usage(char **argv)
+{
+	fprintf (stdout, 
+			"%s: OCFS Test Server\n Usage: \n"
+			"\t %s nodelist < command_file -or-\n"
+			"\t %s nodelist command_file \n"
+			" See documentation for nodelist and command_file format.\n",
+			argv[0], argv[0], argv[0]);
+}
+
+struct hostent *
+validate_address(char *addr)
+{
+	struct hostent *hp;
+	if ((hp = gethostbyname(addr)))
+		return hp;
+	else 
+	{
+		fprintf (stderr, "Invalid node: %s\n", addr);
+		return NULL;
+	}
+}
+
+int
+read_node_file (FILE *NODES)
+{
+	char buffer[MAX_BUF];
+	int numnodes = 0;
+	char *ptr;
+	int lineno;
+
+	for (lineno=1; fgets(buffer, MAX_BUF-1, NODES); lineno++)
+	{
+		struct hostent *hp;
+		//DEBUG((stderr, "[IN-Node] %s", buffer));
+
+		while ((ptr = strchr(buffer, ' '))
+				|| (ptr = strchr(buffer, '\n'))
+				|| (ptr = strchr(buffer, '#')))
+			ptr[0] = '\0';
+
+		if (strlen(buffer) && (hp = validate_address(buffer)))
+		{
+			fprintf (stdout, "[II] Adding node %02d [%s]\n", numnodes+1, buffer);
+			g_nodes[numnodes].hp = hp;
+			g_nodes[numnodes].name = strdup(buffer);
+			numnodes++;
+		}
+	}
+	g_numnodes = numnodes;
+	fclose(NODES);
+	return numnodes;
+}
+
+int
+read_node_strings (int n, char **nodes)
+{
+	char *node_p;
+	int numnodes = 0;
+	int i;
+
+	for (i=0; i<n; i++)
+	{
+		struct hostent *hp;
+		node_p = nodes[i];
+		if (*node_p && (hp = validate_address(node_p)))
+		{
+			fprintf (stdout, "[II] Adding node %02d [%s]\n", numnodes, node_p);
+			g_nodes[numnodes].hp = hp;
+			g_nodes[numnodes].name = strdup(node_p);
+			numnodes ++;
+		}
+		else
+		{
+			perror("validate_address:");
+		}
+	}
+
+	g_numnodes = numnodes;
+	return n;
+}
+
+int 
+disconnect_from_nodes()
+{
+	int i;
+
+	for (i=0; i< g_numnodes; i++)
+	{
+		comm_close_connection (g_nodes[i].os);
+	}
+	return 0;
+}
+	
+int 
+connect_to_nodes()
+{
+	int i;
+
+	for (i=0; i< g_numnodes; i++)
+	{
+		DEBUG((stderr, "[DD] Connecting to %s.\n", g_nodes[i].name));
+		g_nodes[i].os = comm_open_connection (g_nodes[i].hp);
+		if (g_nodes[i].os == NULL)
+		{
+			perror("[EE] Failed!");
+			return 0;
+		}
+		DEBUG((stderr, "[DD] Connected to %s.\n", g_nodes[i].name));
+	}
+	return g_numnodes;
+}
+
+int
+generate_report (struct report *report)
+{
+	fprintf (stderr, "Generating report....\n");
+	return 0;
+}
+
+int
+execute_tests (FILE *TSCRIPT)
+{
+	char cmd[MAX_BUF];
+	struct report report;
+	int lineno;
+
+	if (!connect_to_nodes())
+		return -1;
+
+	report_init (&report);
+
+	/* Parse and execute commands */
+	for (lineno=1; fgets(cmd, MAX_BUF -1, TSCRIPT); lineno++)
+	{
+		//DEBUG((stderr, "[IN] %s", cmd));
+
+		if (strlen(cmd) >= MAX_BUF -1)
+		{
+			fprintf (stderr, "Line %02d too long, operation cancelled.\n",
+					lineno);
+			return -1;
+		} 
+
+		ocfs_test (cmd, lineno, &report);
+	}
+
+	disconnect_from_nodes();
+
+	return report_generate (&report);
+}
+
+#ifndef OCFSTS_LIBRARY
+int 
+main(int argc, char **argv)
+{
+	FILE *NODES, *TSCRIPT;
+	int stat;
+
+	if (argc > 3 || argc < 2
+			|| !strcmp(argv[1], "-help") 
+			|| !strcmp(argv[1], "-h")
+			|| !strcmp(argv[1], "--help"))
+	{
+		usage(argv);
+		return 1;
+	}
+	else 
+	{
+		if (! (argv[1] && argv[1][0] && 
+				(NODES = fopen(argv[1], "r"))))
+		{
+			usage(argv);
+			perror("[EE] Invalid node list.");
+			return -1;
+		}
+
+		if (argc == 2)
+		{
+			DEBUG((stderr, "[DD] Reading test script from stdin\n"));
+			TSCRIPT = stdin;
+		} 
+		else
+		{
+			DEBUG((stderr, "[DE] Reading test script from %s\n", argv[2]));
+			if (! (argv[2] && argv[2][0] && 
+					(TSCRIPT = fopen(argv[2], "r"))))
+			{
+				perror ("Unable open input file.");
+				return -1;
+			}
+		}
+
+	}
+			
+	stat = read_node_file (NODES);
+	if (!stat)
+	{
+		perror ("[EE] No valid nodes in file.");
+		return -1;
+	}
+	else
+		fprintf (stdout, "[II] %02d nodes read from file.\n", stat);
+
+	execute_tests(TSCRIPT);
+
+	return 0;
+}
+#endif //OCFSTS_LIBRARY
+
+int
+ocfs_get_random_nodenum()
+{
+	//return (rand()/RAND_MAX * g_numnodes);
+	return (int) ((double)(g_numnodes)*(double)rand()/(RAND_MAX+1.0));
+}
+
+int 
+ocfs_get_node_by_name (const char *name)
+{
+	int i;
+
+	for (i=0; i<g_numnodes; i++)
+	{
+		if (!strcmp(g_nodes[i].name, name))
+			return i;
+	}
+	return -1;
+}
+
+int 
+ocfs_get_numnodes ()
+{
+	return g_numnodes;
+}
+
+bool
+ocfs_send_command (char *buffer, int nodenum)
+{
+	if (g_nodes[nodenum].os != NULL)
+		return comm_send_command (g_nodes[nodenum].os, buffer);
+
+	fprintf (stderr, "[EE] Node %d not valid, connection not open!\n", nodenum);
+	return false;
+}
+
+bool
+ocfs_get_response (char *buffer, int maxlen, int nodenum)
+{
+	if (g_nodes[nodenum].os != NULL)
+		return comm_get_response (g_nodes[nodenum].os, buffer, maxlen);
+
+	fprintf (stderr, "[EE] Node %d not valid, connection not open!\n", nodenum);
+	return false;
+}
+

Added: server/ocfs_test_server.h
===================================================================
--- server/ocfs_test_server.h	2003-08-16 22:26:26 UTC (rev 1)
+++ server/ocfs_test_server.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,15 @@
+#ifndef _ocfs_test_server_h_
+#define _ocfs_test_server_h_
+
+// helper semi-OO functions
+int ocfs_get_random_nodenum();
+int ocfs_get_node_by_name(const char *name);
+int ocfs_get_numnodes ();
+
+bool ocfs_get_response (char *buffer, int maxlen, int nodenum);
+bool ocfs_send_command (char *buffer, int nodenum);
+
+int read_node_strings (int n, char **nodes);
+int connect_to_nodes();
+int disconnect_from_nodes();
+#endif //_ocfs_test_server_h_

Added: server/ocfstsapi.c
===================================================================
--- server/ocfstsapi.c	2003-08-16 22:26:26 UTC (rev 1)
+++ server/ocfstsapi.c	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,30 @@
+#include <stdbool.h>
+
+#include "ocfstsapi.h"
+#include "ocfs_test.h"
+#include "ocfs_test_server.h"
+
+int 
+ocfsts_open_connection(int num_nodes, char **nodes)
+{
+	read_node_strings(num_nodes, nodes);
+	return connect_to_nodes()?0:1;
+}
+
+int 
+ocfsts_close_connection(void)
+{
+	return disconnect_from_nodes()?0:1;
+}
+
+int 
+ocfsts_execute (char * command)
+{
+	return ocfs_exec_only(command)?0:1;
+}
+
+int
+ocfsts_verify (char * command)
+{
+	return ocfs_vfy_only(command)?0:1;
+}

Added: server/ocfstsapi.h
===================================================================
--- server/ocfstsapi.h	2003-08-16 22:26:26 UTC (rev 1)
+++ server/ocfstsapi.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,15 @@
+/* API for connecting to testserver */
+#ifndef _ocfsapi_h_
+#define _ocfsapi_h_
+
+int ocfsts_open_connection (int num_nodes, char **nodes);
+int ocfsts_close_connection (void);
+
+/*
+ * By convention, exec/vfy return 0 if success and 1 if fail
+ * (not true/false as expected!)
+ */
+int ocfsts_execute (char * command);
+int ocfsts_verify (char * command);
+
+#endif //_ocfsapi_h_

Added: server/syntax.h
===================================================================
--- server/syntax.h	2003-08-16 22:26:26 UTC (rev 1)
+++ server/syntax.h	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,57 @@
+#ifndef _syntax_h_
+#define _syntax_h_
+
+#include "../ocfsts.h"
+#define OCFSTS_NUMCOMMANDS NUMCOMMANDS
+
+enum {MAP_TYPE, MAP_ARGTYPE, MAP_VFYTYPE};
+enum {NO_ARGS, SRC_ARG, SRC_DST_ARG, UID_ARG, MODE_ARG, NODE_ARG, SIZE_ARG, ENTPY_ARG};
+int num_args_per_type[] = {
+	0, //NO_ARGS
+	1, //SRC_ARG
+	2, //SRC_DST_ARG
+	3, //UID_ARG
+	2, //MODE_ARG
+	2, //NODE_ARG
+	2, //SIZE_ARG
+	2, //ENTPY_ARG
+}; 
+
+
+
+#define NUM_SERVER_COMMANDS 22
+
+struct cmd {
+	char *name;
+	int type;
+	int numargs;
+	int vtype;
+} cmdtab[] = {
+	{"quit",		CMD_QUIT,		NO_ARGS,		VFY_NONE},
+	{"helo",		CMD_HELO,		NO_ARGS,		VFY_NONE},
+	{"link",		CMD_LINK,		SRC_DST_ARG,	VFY_EXIST}, 
+	{"symlink",		CMD_SYMLINK,	SRC_DST_ARG,	VFY_EXIST},
+	{"chown",		CMD_CHOWN,		UID_ARG,		VFY_OWNER},
+	{"mkdir",		CMD_MKDIR,		MODE_ARG,		VFY_EXIST},
+	{"chmod",		CMD_CHMOD,		MODE_ARG,		VFY_MODE},
+	{"mknod",		CMD_MKNOD,		NODE_ARG,		VFY_EXIST},
+	{"rmdir",		CMD_RMDIR,		SRC_ARG,		VFY_NEXIST},
+	{"create",		CMD_CREATE,		SRC_ARG,		VFY_EXIST},
+	{"delete",		CMD_DELETE,		SRC_ARG,		VFY_NEXIST},
+	{"rm",			CMD_DELETE,		SRC_ARG,		VFY_NEXIST},
+	{"fstat",		CMD_STAT,		SRC_ARG,		VFY_NONE},
+	{"stat",		CMD_STAT,		SRC_ARG,		VFY_NONE},
+	{"resize",		CMD_RESIZE,		SIZE_ARG,		VFY_SIZE},
+	{"modify",		CMD_MODIFY,		ENTPY_ARG,		VFY_MD5},
+	{"chksum",		CMD_MD5,		SRC_ARG,		VFY_MD5},
+	{"md5",			CMD_MD5,		SRC_ARG,		VFY_MD5},
+	{"mv",			CMD_MV,			SRC_DST_ARG,	VFY_EXIST},
+	{"move",		CMD_MV,			SRC_DST_ARG,	VFY_EXIST},
+	{"open",		CMD_OPEN,		SRC_ARG,		VFY_NONE},
+	{"close",		CMD_CLOSE,		SRC_ARG,		VFY_NONE}
+};
+
+/* known bug: name of listed command in output does not correspond to cmdline
+ * name, but to first name which appears in this list */
+
+#endif //_syntax_h_

Added: testclient.pl
===================================================================
--- testclient.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ testclient.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,29 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Socket;
+
+my ($remote, $port, $iaddr, $paddr, $proto, $line);
+
+$remote = shift || 'verbose';
+$port = shift || 4444;
+if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
+die "No or Bad port" unless $port;
+
+$iaddr = inet_aton($remote)
+    || die "no host: $remote";
+$paddr=sockaddr_in($port, $iaddr);
+$proto = getprotobyname('tcp');
+
+socket (SOCK, PF_INET, SOCK_STREAM, $proto)
+    || die "socket: $!";
+connect (SOCK, $paddr)
+    || die "connect: $!";
+
+print SOCK "HELO\n\n";
+print SOCK "STAT\n/tmp/foo\n\n";
+print SOCK "QUIT\n\n";
+
+close (SOCK)
+    || die "close: $!";
+exit 0;


Property changes on: testclient.pl
___________________________________________________________________
Name: svn:executable
   + 

Added: tests/00_simple.pl
===================================================================
--- tests/00_simple.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/00_simple.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,134 @@
+#!/bin/perl
+
+#
+# Description goes here
+#
+
+use ExtUtils::testlib;
+use Ocfsts;
+use English;
+
+do "ocfsts_config";
+
+if (!defined @NODES) {
+    die "No nodes defined!\n";
+}
+
+$retval = Ocfsts::ocfsts_connect @NODES;
+
+if ($retval != 0) {
+    die "Unable to connect!\n";
+}
+
+
+###
+# File creation and stat tests
+Ocfsts::ocfsts_create "$ROOT/file1";
+Ocfsts::ocfsts_fstat "$ROOT/file1";
+
+###
+# File deletion test
+Ocfsts::ocfsts_delete "$ROOT/file1";
+
+###
+# Can we stat a nonexistant file?
+Ocfsts::ocfsts_fstat "$ROOT/file1", "R", "f";
+
+###
+# Directory creation and stat tests
+Ocfsts::ocfsts_mkdir "$ROOT/dir1", "777";
+Ocfsts::ocfsts_fstat "$ROOT/dir1";
+
+###
+# Directory deletion test
+Ocfsts::ocfsts_rmdir "$ROOT/dir1";
+
+###
+# Can we stat a nonexistant directory?
+Ocfsts::ocfsts_fstat "$ROOT/dir1", "R", "f";
+
+###
+# Hard and symbolic link tests
+Ocfsts::ocfsts_create "$ROOT/source";
+Ocfsts::ocfsts_mkdir "$ROOT/dir1", "777";
+
+Ocfsts::ocfsts_link "$ROOT/source", "$ROOT/link1";
+Ocfsts::ocfsts_symlink "$ROOT/source", "$ROOT/symlink1";
+Ocfsts::ocfsts_symlink "$ROOT/dir1", "$ROOT/dirsymlink1";
+
+Ocfsts::ocfsts_fstat "$ROOT/link1";
+Ocfsts::ocfsts_fstat "$ROOT/symlink1";
+#R fstat $ROOT/dirlink1
+Ocfsts::ocfsts_fstat "$ROOT/dirsymlink1";
+
+Ocfsts::ocfsts_delete "$ROOT/link1";
+Ocfsts::ocfsts_delete "$ROOT/symlink1";
+#R delete $ROOT/dirlink1
+Ocfsts::ocfsts_delete "$ROOT/dirsymlink1";
+Ocfsts::ocfsts_delete "$ROOT/source";
+Ocfsts::ocfsts_rmdir "$ROOT/dir1";
+ 
+Ocfsts::ocfsts_fstat "$ROOT/link1", "R", "f";
+Ocfsts::ocfsts_fstat "$ROOT/symlink1", "R", "f";
+Ocfsts::ocfsts_fstat "$ROOT/dirlink1", "R", "f";
+Ocfsts::ocfsts_fstat "$ROOT/dirsymlink1", "R", "f";
+
+
+###
+# Permission tests
+Ocfsts::ocfsts_mkdir "$ROOT/dir1","755";
+Ocfsts::ocfsts_fstat "$ROOT/dir1";
+Ocfsts::ocfsts_create "$ROOT/dir1/unreachable";
+Ocfsts::ocfsts_chmod "$ROOT/dir1", "000";
+Ocfsts::ocfsts_fstat "$ROOT/dir1/unreachable", "R", "f";
+Ocfsts::ocfsts_delete "$ROOT/dir1/unreachable", "R", "f";
+Ocfsts::ocfsts_create "$ROOT/dir1/uncreatable", "R", "f";
+
+#cleanup
+Ocfsts::ocfsts_chmod "$ROOT/dir1", "755";
+Ocfsts::ocfsts_delete "$ROOT/dir1/unreachable";
+Ocfsts::ocfsts_rmdir "$ROOT/dir1";
+
+###
+# Grow and shrink files
+Ocfsts::ocfsts_create "$ROOT/grow";
+Ocfsts::ocfsts_create "$ROOT/shrink";
+
+#just setup the sizes and content here
+Ocfsts::ocfsts_resize "$ROOT/grow", "10240";
+Ocfsts::ocfsts_resize "$ROOT/shrink", "10240";
+Ocfsts::ocfsts_modify "$ROOT/grow", "999";
+Ocfsts::ocfsts_modify "$ROOT/shrink", "999";
+
+Ocfsts::ocfsts_chksum "$ROOT/grow";
+Ocfsts::ocfsts_chksum "$ROOT/shrink";
+
+Ocfsts::ocfsts_resize "$ROOT/shrink", "256";
+Ocfsts::ocfsts_resize "$ROOT/grow", "40960";
+Ocfsts::ocfsts_modify "$ROOT/grow", "999";
+Ocfsts::ocfsts_modify "$ROOT/shrink", "999";
+
+Ocfsts::ocfsts_chksum "$ROOT/grow";
+Ocfsts::ocfsts_chksum "$ROOT/shrink";
+
+Ocfsts::ocfsts_resize "$ROOT/shrink", "128";
+Ocfsts::ocfsts_resize "$ROOT/grow", "81920";
+Ocfsts::ocfsts_modify "$ROOT/grow", "999";
+Ocfsts::ocfsts_modify "$ROOT/shrink", "999";
+
+Ocfsts::ocfsts_chksum "$ROOT/grow";
+Ocfsts::ocfsts_chksum "$ROOT/shrink";
+
+Ocfsts::ocfsts_delete "$ROOT/grow";
+Ocfsts::ocfsts_delete "$ROOT/shrink";
+
+###
+# Try to delete a dir with a file in it
+Ocfsts::ocfsts_mkdir "$ROOT/dir1", "777";
+Ocfsts::ocfsts_create "$ROOT/dir1/file1";
+Ocfsts::ocfsts_rmdir "$ROOT/dir1", "R", "f";
+Ocfsts::ocfsts_delete "$ROOT/dir1/file1";
+Ocfsts::ocfsts_rmdir "$ROOT/dir1";
+
+Ocfsts::ocfsts_disconnect;
+

Added: tests/05_tree.pl
===================================================================
--- tests/05_tree.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/05_tree.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,66 @@
+#!/bin/perl
+
+#
+# Make a tree of dirs
+#
+#
+#$ROOT
+#
+#	foo	bar	baz	bat
+#	 |		 |	 |
+#	 |		 |	 -->	foo
+#	 |		 |	 -->	bar
+#	 |		 |	 -->	gar
+#	 |		 -->	foo	 |
+#	 |		 -->	bar	 -->foo
+#	 |			 |
+#	 | 			 -->	foo
+#	 |		  |
+#	 |		  -->	baz
+#	 -->	foo
+#		 |
+#		 -->	bar
+#			 |
+#			 -->	baz
+#			 |
+#			 -->	bat
+#
+
+
+use ExtUtils::testlib;
+use Ocfsts;
+use English;
+
+do "ocfsts_config";
+
+if (!defined @NODES) {
+    die "No nodes defined!\n";
+}
+
+$retval = Ocfsts::ocfsts_connect @NODES;
+
+if ($retval != 0) {
+    die "Unable to connect!\n";
+}
+
+Ocfsts::ocfsts_mkdir "$ROOT/foo", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/bar", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/baz", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/bat", "777";
+
+Ocfsts::ocfsts_mkdir "$ROOT/bat/foo", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/bat/bar", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/bat/gar", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/bat/gar/foo", "777";
+
+Ocfsts::ocfsts_mkdir "$ROOT/baz/foo", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/baz/bar", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/baz/baz", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/baz/bar/foo", "777";
+
+Ocfsts::ocfsts_mkdir "$ROOT/foo/foo", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/foo/bar", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/foo/bar/baz", "777";
+Ocfsts::ocfsts_mkdir "$ROOT/foo/bar/bat", "777";
+
+Ocfsts::ocfsts_disconnect;

Added: tests/06_tree_delete.pl
===================================================================
--- tests/06_tree_delete.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/06_tree_delete.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,43 @@
+#!/bin/perl
+
+#
+# Delete our wonderful tree of directories
+#
+
+use ExtUtils::testlib;
+use Ocfsts;
+use English;
+
+do "ocfsts_config";
+
+if (!defined @NODES) {
+    die "No nodes defined!\n";
+}
+
+$retval = Ocfsts::ocfsts_connect @NODES;
+
+if ($retval != 0) {
+    die "Unable to connect!\n";
+}
+
+Ocfsts::ocfsts_rmdir "$ROOT/foo/bar/bat";
+Ocfsts::ocfsts_rmdir "$ROOT/foo/bar/baz";
+Ocfsts::ocfsts_rmdir "$ROOT/foo/bar";
+Ocfsts::ocfsts_rmdir "$ROOT/foo/foo";
+
+Ocfsts::ocfsts_rmdir "$ROOT/baz/bar/foo";
+Ocfsts::ocfsts_rmdir "$ROOT/baz/baz";
+Ocfsts::ocfsts_rmdir "$ROOT/baz/bar";
+Ocfsts::ocfsts_rmdir "$ROOT/baz/foo";
+
+Ocfsts::ocfsts_rmdir "$ROOT/bat/gar/foo";
+Ocfsts::ocfsts_rmdir "$ROOT/bat/gar";
+Ocfsts::ocfsts_rmdir "$ROOT/bat/bar";
+Ocfsts::ocfsts_rmdir "$ROOT/bat/foo";
+
+Ocfsts::ocfsts_rmdir "$ROOT/bat";
+Ocfsts::ocfsts_rmdir "$ROOT/baz";
+Ocfsts::ocfsts_rmdir "$ROOT/bar";
+Ocfsts::ocfsts_rmdir "$ROOT/foo";
+
+Ocfsts::ocfsts_disconnect;

Added: tests/15_mvtests.pl
===================================================================
--- tests/15_mvtests.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/15_mvtests.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,41 @@
+#!/bin/perl
+
+#
+# mv gave us some particularly bad problems and that's 
+# why there's a separate file for these tests.
+#
+
+
+use ExtUtils::testlib;
+use Ocfsts;
+use English;
+
+do "ocfsts_config";
+
+if (!defined @NODES) {
+    die "No nodes defined!\n";
+}
+
+$retval = Ocfsts::ocfsts_connect @NODES;
+
+if ($retval != 0) {
+    die "Unable to connect!\n";
+}
+
+#
+# Simple mv tests
+#
+Ocfsts::ocfsts_create "$ROOT/file1";
+Ocfsts::ocfsts_mkdir "$ROOT/dir1", "777";
+
+Ocfsts::ocfsts_mv "$ROOT/file1", "$ROOT/file2";
+
+Ocfsts::ocfsts_create "$ROOT/dir1/file3";
+Ocfsts::ocfsts_mv "$ROOT/dir1/file3", "$ROOT/file3";
+
+#cleanup
+Ocfsts::ocfsts_delete "$ROOT/file2";
+Ocfsts::ocfsts_delete "$ROOT/file3";
+Ocfsts::ocfsts_rmdir "$ROOT/dir1";
+
+Ocfsts::ocfsts_disconnect;

Added: tests/30_manyfiles.pl
===================================================================
--- tests/30_manyfiles.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/30_manyfiles.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,37 @@
+#!/bin/perl
+
+#
+# Create/delete a ton of files to test dirnode boundaries
+#
+
+use ExtUtils::testlib;
+use Ocfsts;
+
+do "ocfsts_config";
+
+my $NUMFILES=1024;
+my $i;
+
+if (!defined @NODES) {
+    die "No nodes defined!\n";
+}
+
+$retval = Ocfsts::ocfsts_connect @NODES;
+
+if ($retval != 0) {
+    die "Unable to connect!\n";
+}
+
+Ocfsts::ocfsts_mkdir "$ROOT/manyfiles", "755";
+
+for ($i = 0; $i < $NUMFILES; $i++) {
+    Ocfsts::ocfsts_create "$ROOT/manyfiles/myfile$i";
+}
+
+for ($i = 0; $i < $NUMFILES; $i++) {
+    Ocfsts::ocfsts_delete "$ROOT/manyfiles/myfile$i";
+}
+
+Ocfsts::ocfsts_rmdir "$ROOT/manyfiles";
+
+Ocfsts::ocfsts_close_connection;

Added: tests/45_openclose.pl
===================================================================
--- tests/45_openclose.pl	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/45_openclose.pl	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,44 @@
+#!/bin/perl
+
+#
+# Tests the open/close stuff
+#
+
+use ExtUtils::testlib;
+use Ocfsts;
+use English;
+
+do "ocfsts_config";
+
+#if you're gonna make this larger than 1000, you should 
+#change the file descriptor limits on the OS!
+my $NUMFILES=768;
+my $i;
+
+if (!defined @NODES) {
+    die "No nodes defined!\n";
+}
+
+$retval = Ocfsts::ocfsts_connect @NODES;
+
+if ($retval != 0) {
+    die "Unable to connect!\n";
+}
+
+#Ocfsts::ocfsts_delete("$ROOT/myfile");
+#Ocfsts::ocfsts_create("$ROOT/myfile");
+for ($i = 0; $i < $NUMFILES; $i++) {
+    Ocfsts::ocfsts_open "$ROOT/myfile$i";
+}
+
+#don't want to do this for O_DIRECT
+#for ($i = 0; $i < $NUMFILES; $i++) {
+#    Ocfsts::ocfsts_resize "$ROOT/myfile$i", "1024";
+#}
+
+for ($i = 0; $i < $NUMFILES; $i++) {
+    Ocfsts::ocfsts_close "$ROOT/myfile$i";
+}
+
+Ocfsts::ocfsts_close_connection;
+

Added: tests/CVS/Entries
===================================================================
--- tests/CVS/Entries	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/CVS/Entries	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,9 @@
+/00_simple.pl/1.2/Fri Dec 13 00:04:56 2002//
+/05_tree.pl/1.2/Fri Dec 13 00:04:56 2002//
+/06_tree_delete.pl/1.2/Fri Dec 13 00:04:56 2002//
+/15_mvtests.pl/1.3/Fri Dec 13 00:14:50 2002//
+/30_manyfiles.pl/1.2/Fri Dec 13 00:04:56 2002//
+/45_openclose.pl/1.2/Fri Dec 13 00:04:56 2002//
+/Makefile/1.4/Thu Dec 12 23:22:20 2002//
+/ocfsts_config/1.3/Fri Dec 13 00:04:56 2002//
+D

Added: tests/CVS/Repository
===================================================================
--- tests/CVS/Repository	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/CVS/Repository	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+ocfsts/tests

Added: tests/CVS/Root
===================================================================
--- tests/CVS/Root	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/CVS/Root	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1 @@
+:pserver:gmarsden at nic1-pc:/cvs/nic

Added: tests/Makefile
===================================================================
--- tests/Makefile	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/Makefile	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,18 @@
+
+include ../Makefile.config
+
+#objects=00_simple.test 05_tree.test 06_tree_delete.test 15_mvtests.test
+
+#ROOT=\/ocfs
+
+#all: $(objects) perl
+
+#%.test: %.in
+#	cat $< | sed 's/\$$ROOT/${ROOT}/' > $@
+
+perl: 
+	ln -fs ../Ocfsts/blib blib
+
+.PHONY: clean
+clean:
+	rm -f *~ *.test blib

Added: tests/ocfsts_config
===================================================================
--- tests/ocfsts_config	2003-08-16 22:26:26 UTC (rev 1)
+++ tests/ocfsts_config	2003-08-19 22:24:38 UTC (rev 2)
@@ -0,0 +1,17 @@
+#
+# This config file is read in by perl before the tests are executed
+# Any perl code is valid.
+#
+
+# This is where all the action will take place. Choose something on
+# an OCFS mounted volume :)
+$ROOT="/tmp";
+
+# put your client nodes in here. a sample is below for a three node cluster
+# with nodes called node1, node2, node3.
+#@NODES = ("node1", "node2", "node3");
+
+ at NODES = ("localhost");
+
+#this is deprecated
+#$NODELIST_FILE="nodelist";



More information about the Ocfstest-commits mailing list