src/locktest: Add lease testing for basic signal reception
[xfstests-dev.git] / src / locktest.c
index d6198b6c1f1b4c37f080d766426a10fa5a203225..be71866860e2480a15260e39c7ec68efdd6392d5 100644 (file)
@@ -1,23 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2003 Silicon Graphics, Inc.
+ * Copyright (c) 2019 Intel Corp.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 /*
- * Synchronized byte range lock exerciser
+ * Synchronized byte range lock and lease exerciser
  */
 
 #include <stdio.h>
@@ -38,6 +27,8 @@
 #include <byteswap.h>
 #include <errno.h>
 #include <string.h>
+#include <signal.h>
+
 #define     HEX_2_ASC(x)    ((x) > 9) ? (x)-10+'a' : (x)+'0'
 #define        FILE_SIZE       1024
 #define PLATFORM_INIT()     /*no-op*/
@@ -73,8 +64,6 @@ extern int h_errno;
        
 #define HANDLE              int
 #define INVALID_HANDLE      -1
-#define OPEN(N,F)           (open(N, F|O_CREAT|O_RDWR|O_BINARY| \
-                            (D_flag ? O_DIRECT : 0), 0644))
 #define SEEK(H, O)          (lseek(H, O, SEEK_SET))
 #define READ(H, B, L)       (read(H, B, L))
 #define WRITE(H, B, L)      (write(H, B, L))
@@ -82,7 +71,6 @@ extern int h_errno;
 
 #define RAND()              (rand())
 #define SRAND(s)            (srand(s))
-#define SLEEP(s)            (sleep(s))
 
 #define MIN(A,B)            (((A)<(B))?(A):(B))
 #define MAX(A,B)            (((A)>(B))?(A):(B))
@@ -94,24 +82,26 @@ static char *prog;
 static char    *filename = 0;
 static int     debug = 0;
 static int     server = 1;
-static int     maxio = 8192;
-static int     port = 7890;
-static int     reopen=0;
-static int     closed=0;
+static int     port = 0;
 static int     testnumber = -1;
 static int     saved_errno = 0;
+static int      got_sigio = 0;
 
 static SOCKET  s_fd = -1;              /* listen socket    */
 static SOCKET  c_fd = -1;              /* IPC socket       */
 static HANDLE  f_fd = INVALID_HANDLE;  /* shared file      */
-static char    *buf;                   /* I/O buffer       */
-static int     D_flag = 0;
 
-#define        WRLOCK  0
-#define        RDLOCK  1
-#define                UNLOCK  2
-#define                F_CLOSE 3
-#define                F_OPEN  4
+#define        CMD_WRLOCK      0
+#define        CMD_RDLOCK      1
+#define                CMD_UNLOCK      2
+#define                CMD_CLOSE       3
+#define                CMD_OPEN        4
+#define                CMD_WRTEST      5
+#define                CMD_RDTEST      6
+#define        CMD_SETLEASE    7
+#define        CMD_GETLEASE    8
+#define                CMD_SIGIO       9
+#define                CMD_WAIT_SIGIO  10
 
 #define                PASS    1
 #define                FAIL    0
@@ -126,7 +116,26 @@ static int D_flag = 0;
 #define                RESULT          4
 #define                WHO             5
 #define                FLAGS           2 /* index 2 is also used for do_open() flag, see below */
+#define                ARG             FLAGS /* Arguments for Lease operations */
+#define                TIME            FLAGS /* Time for waiting on sigio */
 
+static char *get_cmd_str(int cmd)
+{
+       switch (cmd) {
+               case CMD_WRLOCK: return "write lock"; break;
+               case CMD_RDLOCK: return "read lock"; break;
+               case CMD_UNLOCK: return "unlock"; break;
+               case CMD_CLOSE:  return "close"; break;
+               case CMD_OPEN:   return "open"; break;
+               case CMD_WRTEST: return "Wait for SIGIO"; break;
+               case CMD_RDTEST: return "Truncate"; break;
+               case CMD_SETLEASE: return "Set Lease"; break;
+               case CMD_GETLEASE: return "Get Lease"; break;
+               case CMD_SIGIO:    return "Setup SIGIO"; break;
+               case CMD_WAIT_SIGIO: return "Wait for SIGIO"; break;
+       }
+       return "unknown";
+}
 /* 
  * flags for Mac OS X do_open() 
  * O_RDONLY    0x0000
@@ -151,7 +160,7 @@ static int  D_flag = 0;
  * (or vice versa)
  */
 
-char *descriptions[] = {
+char *lock_descriptions[] = {
     /* 1 */"Add a lock to an empty lock list",
     /* 2 */"Add a lock to the start and end of a list - no overlaps",
     /* 3 */"Add a lock to the middle of a list - no overlap",
@@ -180,368 +189,471 @@ char *descriptions[] = {
     /* 26 */"Acquire read and write locks with overlapping ranges",
     /* 27 */"Acquire whole file write lock and then close without unlocking (and attempt a lock)",
     /* 28 */"Acquire two read locks, close and reopen the file, and test if the inital lock is still there",
+    /* 29 */"Verify that F_GETLK for F_WRLCK doesn't require that file be opened for write",
     #if defined(macosx)
-    /* 29 */"Close the opened file and open the file with SHLOCK, other client will try to open with SHLOCK too",
-    /* 30 */"Close the opened file and open the file with SHLOCK, other client will try to open with EXLOCK",
-    /* 31 */"Close the opened file and open the file with EXLOCK, other client will try to open with EXLOCK too"
+    /* 30 */"Close the opened file and open the file with SHLOCK, other client will try to open with SHLOCK too",
+    /* 31 */"Close the opened file and open the file with SHLOCK, other client will try to open with EXLOCK",
+    /* 32 */"Close the opened file and open the file with EXLOCK, other client will try to open with EXLOCK too"
     #endif
 };
 
-static int64_t tests[][6] =
-       /*      test #  Action  offset          length          expected        server/client */
+static int64_t lock_tests[][6] =
+       /*      test #  Action  [offset|flags]  length          expected        server/client */
        {       
        /* Various simple tests exercising the list */
 
-/* SECTION 1: WRITE and UNLOCK with the same process (SERVER) */
+/* SECTION 1: WRITE and CMD_UNLOCK with the same process (SERVER) */
        /* Add a lock to an empty list */
-               {1,     WRLOCK, 1,              10,             PASS,           SERVER  }, 
-               {1,     UNLOCK, 1,              10,             PASS,           SERVER  }, 
+               {1,     CMD_WRLOCK,     1,              10,             PASS,           SERVER  },
+               {1,     CMD_UNLOCK,     1,              10,             PASS,           SERVER  },
                
        /* Add a lock to the start and end of a list - 1, 13 - no overlap */
-               {2,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {2,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {2,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
-               {2,     WRLOCK, 1,              5,              PASS,           SERVER  }, 
-               {2,     WRLOCK, 70,             5,              PASS,           SERVER  }, 
+               {2,     CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {2,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {2,     CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
+               {2,     CMD_WRLOCK,     1,              5,              PASS,           SERVER  },
+               {2,     CMD_WRLOCK,     70,             5,              PASS,           SERVER  },
                
-               {2,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {2,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
-               {2,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
-               {2,     UNLOCK, 1,              5,              PASS,           SERVER  }, 
-               {2,     UNLOCK, 70,             5,              PASS,           SERVER  }, 
+               {2,     CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {2,     CMD_UNLOCK,     30,             10,             PASS,           SERVER  },
+               {2,     CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
+               {2,     CMD_UNLOCK,     1,              5,              PASS,           SERVER  },
+               {2,     CMD_UNLOCK,     70,             5,              PASS,           SERVER  },
                
        /* Add a lock to the middle of a list - no overlap */
-               {3,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {3,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {3,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
-               {3,     WRLOCK, 42,             5,              PASS,           SERVER  }, 
+               {3,     CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {3,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {3,     CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
+               {3,     CMD_WRLOCK,     42,             5,              PASS,           SERVER  },
                
-               {3,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {3,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
-               {3,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
-               {3,     UNLOCK, 42,             5,              PASS,           SERVER  }, 
+               {3,     CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {3,     CMD_UNLOCK,     30,             10,             PASS,           SERVER  },
+               {3,     CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
+               {3,     CMD_UNLOCK,     42,             5,              PASS,           SERVER  },
                
        /* Add different lock types to middle of the list - overlap exact match - 3 */
-               {4,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {4,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {4,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {4,     CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {4,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {4,     CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* Exact match - same lock type */
-               {4,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
+               {4,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
                /* Exact match - different lock type */
-               {4,     RDLOCK, 30,             10,             PASS,           SERVER  }, 
+               {4,     CMD_RDLOCK,     30,             10,             PASS,           SERVER  },
                /* Exact match - unlock */
-               {4,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
+               {4,     CMD_UNLOCK,     30,             10,             PASS,           SERVER  },
                /* New lock - as above, inserting in the list again */
-               {4,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
+               {4,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
                
-               {4,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {4,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
-               {4,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {4,     CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {4,     CMD_UNLOCK,     30,             10,             PASS,           SERVER  },
+               {4,     CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
                
        /* Add new lock which completely overlaps any old lock in the list - 4,5,6 */
-               {5,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {5,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {5,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {5,     CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {5,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {5,     CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* The start is the same, end overlaps */
-               {5,     WRLOCK, 30,             15,             PASS,           SERVER  }, 
+               {5,     CMD_WRLOCK,     30,             15,             PASS,           SERVER  },
                /* The start is before, end is the same */
-               {5,     WRLOCK, 25,             20,             PASS,           SERVER  }, 
+               {5,     CMD_WRLOCK,     25,             20,             PASS,           SERVER  },
                /* Both start and end overlap */
-               {5,     WRLOCK, 22,             26,             PASS,           SERVER  }, 
+               {5,     CMD_WRLOCK,     22,             26,             PASS,           SERVER  },
                
-               {5,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {5,     UNLOCK, 22,             26,             PASS,           SERVER  }, 
-               {5,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {5,     CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {5,     CMD_UNLOCK,     22,             26,             PASS,           SERVER  },
+               {5,     CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
                
        /* Add new lock which itself is completely overlaped by any old lock in the list - 7,8,10 */
-               {6,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {6,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {6,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {6,     CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {6,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {6,     CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* The start is the same, end is in the middle of old lock - NOP */
-               {6,     WRLOCK, 30,             5,              PASS,           SERVER  }, 
+               {6,     CMD_WRLOCK,     30,             5,              PASS,           SERVER  },
                /* The start and end are in the middle of old lock - NOP */
-               {6,     WRLOCK, 32,             6,              PASS,           SERVER  }, 
+               {6,     CMD_WRLOCK,     32,             6,              PASS,           SERVER  },
                /* Start in the middle and end is the same - NOP */
-               {6,     WRLOCK, 32,             8,              PASS,           SERVER  }, 
+               {6,     CMD_WRLOCK,     32,             8,              PASS,           SERVER  },
                
-               {6,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {6,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
-               {6,     UNLOCK, 32,             8,              PASS,           SERVER  }, 
-               {6,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {6,     CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {6,     CMD_UNLOCK,     30,             10,             PASS,           SERVER  },
+               {6,     CMD_UNLOCK,     32,             8,              PASS,           SERVER  },
+               {6,     CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
                
        /* Add new lock which starts before any old lock in the list - 2,9 */
-               {7,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {7,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {7,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {7,     CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {7,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {7,     CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* Here is the new lock */
-               {7,     WRLOCK, 27,             10,             PASS,           SERVER  }, 
+               {7,     CMD_WRLOCK,     27,             10,             PASS,           SERVER  },
                /* Go again with the end of the new lock matching the start of old lock */
-               {7,     WRLOCK, 25,             2,              PASS,           SERVER  }, 
+               {7,     CMD_WRLOCK,     25,             2,              PASS,           SERVER  },
                
-               {7,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {7,     UNLOCK, 25,             15,             PASS,           SERVER  }, 
-               {7,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {7,     CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {7,     CMD_UNLOCK,     25,             15,             PASS,           SERVER  },
+               {7,     CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
        
        /* Add new lock which starts in the middle of any old lock in the list and ends after - 11,12 */
-               {8,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {8,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {8,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {8,     CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {8,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {8,     CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* Here is the new lock */
-               {8,     WRLOCK, 35,             10,             PASS,           SERVER  }, 
+               {8,     CMD_WRLOCK,     35,             10,             PASS,           SERVER  },
                /* Go again with the end of the new lock matching the start of old lock */
-               {8,     WRLOCK, 45,             2,              PASS,           SERVER  }, 
+               {8,     CMD_WRLOCK,     45,             2,              PASS,           SERVER  },
                
-               {8,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {8,     UNLOCK, 30,             17,             PASS,           SERVER  }, 
-               {8,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
-/* SECTION 2: Overlapping READ and WRITE and UNLOCK with the same process (SERVER) */
+               {8,     CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {8,     CMD_UNLOCK,     30,             17,             PASS,           SERVER  },
+               {8,     CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
+/* SECTION 2: Overlapping READ and WRITE and CMD_UNLOCK with the same process (SERVER) */
        /* Add different new lock types which completely overlaps any old lock in the list - 4,5,6 */
-               {9,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {9,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {9,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {9,     CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {9,     CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {9,     CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* The start is the same, end overlaps */
-               {9,     RDLOCK, 30,             15,             PASS,           SERVER  }, 
+               {9,     CMD_RDLOCK,     30,             15,             PASS,           SERVER  },
                /* The start is before, end is the same */
-               {9,     WRLOCK, 25,             20,             PASS,           SERVER  }, 
+               {9,     CMD_WRLOCK,     25,             20,             PASS,           SERVER  },
                /* Both start and end overlap */
-               {9,     RDLOCK, 22,             26,             PASS,           SERVER  }, 
+               {9,     CMD_RDLOCK,     22,             26,             PASS,           SERVER  },
                
-               {9,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {9,     UNLOCK, 22,             26,             PASS,           SERVER  }, 
-               {9,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {9,     CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {9,     CMD_UNLOCK,     22,             26,             PASS,           SERVER  },
+               {9,     CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
                
        /* Add different new locks which are completely overlaped by an old lock in the list - 7,8,10 */
-               {10,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {10,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {10,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {10,    CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {10,    CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {10,    CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* The start is the same, end is in the middle of old lock */
-               {10,    RDLOCK, 30,             5,              PASS,           SERVER  }, 
+               {10,    CMD_RDLOCK,     30,             5,              PASS,           SERVER  },
                /* The start and end are in the middle of a lock */
-               {10,    WRLOCK, 32,             2,              PASS,           SERVER  }, 
+               {10,    CMD_WRLOCK,     32,             2,              PASS,           SERVER  },
                /* Start in the middle and end is the same */
-               {10,    RDLOCK, 36,             5,              PASS,           SERVER  }, 
+               {10,    CMD_RDLOCK,     36,             5,              PASS,           SERVER  },
                
-               {10,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {10,    UNLOCK, 30,             11,             PASS,           SERVER  }, 
-               {10,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {10,    CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {10,    CMD_UNLOCK,     30,             11,             PASS,           SERVER  },
+               {10,    CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
                
        /* Add different new lock types which start before the old lock in the list - 2,9 */
-               {11,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {11,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {11,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {11,    CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {11,    CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {11,    CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* Here is the new lock */
-               {11,    RDLOCK, 27,             10,             PASS,           SERVER  }, 
+               {11,    CMD_RDLOCK,     27,             10,             PASS,           SERVER  },
                /* Go again with the end of the new lock matching the start of lock */
-               {11,    WRLOCK, 25,             3,              PASS,           SERVER  }, 
+               {11,    CMD_WRLOCK,     25,             3,              PASS,           SERVER  },
                
-               {11,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {11,    UNLOCK, 25,             15,             PASS,           SERVER  }, 
-               {11,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {11,    CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {11,    CMD_UNLOCK,     25,             15,             PASS,           SERVER  },
+               {11,    CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
        
        /* Add different new lock types which start in the middle of an old lock in the list and end after - 11,12 */
-               {12,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {12,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {12,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {12,    CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {12,    CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {12,    CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* Here is the new lock */
-               {12,    RDLOCK, 35,             10,             PASS,           SERVER  }, 
+               {12,    CMD_RDLOCK,     35,             10,             PASS,           SERVER  },
                /* Go again with the end of the new lock matching the start of old lock */
-               {12,    WRLOCK, 44,             3,              PASS,           SERVER  }, 
+               {12,    CMD_WRLOCK,     44,             3,              PASS,           SERVER  },
                
-               {12,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {12,    UNLOCK, 30,             18,             PASS,           SERVER  }, 
-               {12,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {12,    CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {12,    CMD_UNLOCK,     30,             18,             PASS,           SERVER  },
+               {12,    CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
 
-/* SECTION 3: Overlapping READ and WRITE and UNLOCK with the different processes (CLIENT/SERVER) */
+/* SECTION 3: Overlapping READ and WRITE and CMD_UNLOCK with the different processes (CLIENT/SERVER) */
        /* Add new lock, differing types and processes, to middle of the list - exact overlap match - 3 */
-               {13,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {13,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {13,    RDLOCK, 50,             10,             PASS,           SERVER  }, 
+               {13,    CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {13,    CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {13,    CMD_RDLOCK,     50,             10,             PASS,           SERVER  },
                /* Same lock type, different process */
-               {13,    WRLOCK, 30,             10,             FAIL,           CLIENT  }, 
-               {13,    RDLOCK, 50,             10,             PASS,           CLIENT  }, 
+               {13,    CMD_WRLOCK,     30,             10,             FAIL,           CLIENT  },
+               {13,    CMD_RDLOCK,     50,             10,             PASS,           CLIENT  },
                /* Exact match - different lock type, different process */
-               {13,    RDLOCK, 30,             10,             FAIL,           CLIENT  }, 
+               {13,    CMD_RDLOCK,     30,             10,             FAIL,           CLIENT  },
                /* Exact match - unlock */
-               {13,    UNLOCK, 30,             10,             PASS,           CLIENT  }, 
+               {13,    CMD_UNLOCK,     30,             10,             PASS,           CLIENT  },
                /* New lock - as above, inserting in the list again */
-               {13,    UNLOCK, 30,             10,             PASS,           SERVER  }, 
+               {13,    CMD_UNLOCK,     30,             10,             PASS,           SERVER  },
                /* Exact match - same lock type, different process */
-               {13,    WRLOCK, 30,             10,             PASS,           CLIENT  }, 
+               {13,    CMD_WRLOCK,     30,             10,             PASS,           CLIENT  },
                
-               {13,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {13,    UNLOCK, 30,             10,             PASS,           CLIENT  }, 
-               {13,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {13,    CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {13,    CMD_UNLOCK,     30,             10,             PASS,           CLIENT  },
+               {13,    CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
                
        /* Add new lock, differing types and processes, which completely overlap any of the locks in the list - 4,5,6 */
-               {14,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {14,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
-               {14,    RDLOCK, 50,             10,             PASS,           SERVER  }, 
+               {14,    CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {14,    CMD_WRLOCK,     30,             10,             PASS,           SERVER  },
+               {14,    CMD_RDLOCK,     50,             10,             PASS,           SERVER  },
                /* The start is the same, end overlaps */
-               {14,    RDLOCK, 30,             15,             FAIL,           CLIENT  },
-               {14,    WRLOCK, 30,             15,             FAIL,           CLIENT  }, 
+               {14,    CMD_RDLOCK,     30,             15,             FAIL,           CLIENT  },
+               {14,    CMD_WRLOCK,     30,             15,             FAIL,           CLIENT  },
                /* The start is before, end is the same */
-               {14,    RDLOCK, 25,             20,             FAIL,           CLIENT  }, 
-               {14,    WRLOCK, 25,             20,             FAIL,           CLIENT  }, 
+               {14,    CMD_RDLOCK,     25,             20,             FAIL,           CLIENT  },
+               {14,    CMD_WRLOCK,     25,             20,             FAIL,           CLIENT  },
                /* Both start and end overlap */
-               {14,    RDLOCK, 22,             26,             FAIL,           CLIENT  }, 
-               {14,    WRLOCK, 22,             26,             FAIL,           CLIENT  }, 
+               {14,    CMD_RDLOCK,     22,             26,             FAIL,           CLIENT  },
+               {14,    CMD_WRLOCK,     22,             26,             FAIL,           CLIENT  },
                
                /* The start is the same, end overlaps */
-               {14,    RDLOCK, 50,             15,             PASS,           CLIENT  },
-               {14,    WRLOCK, 50,             17,             FAIL,           CLIENT  }, 
+               {14,    CMD_RDLOCK,     50,             15,             PASS,           CLIENT  },
+               {14,    CMD_WRLOCK,     50,             17,             FAIL,           CLIENT  },
                /* The start is before, end is the same */
-               {14,    RDLOCK, 45,             20,             PASS,           CLIENT  }, 
-               {14,    WRLOCK, 43,             22,             FAIL,           CLIENT  }, 
+               {14,    CMD_RDLOCK,     45,             20,             PASS,           CLIENT  },
+               {14,    CMD_WRLOCK,     43,             22,             FAIL,           CLIENT  },
                /* Both start and end overlap */
-               {14,    RDLOCK, 42,             26,             PASS,           CLIENT  }, 
-               {14,    WRLOCK, 41,             28,             FAIL,           CLIENT  }, 
+               {14,    CMD_RDLOCK,     42,             26,             PASS,           CLIENT  },
+               {14,    CMD_WRLOCK,     41,             28,             FAIL,           CLIENT  },
                
-               {14,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {14,    UNLOCK, 22,             26,             PASS,           SERVER  }, 
-               {14,    UNLOCK, 42,             26,             PASS,           CLIENT  }, 
+               {14,    CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {14,    CMD_UNLOCK,     22,             26,             PASS,           SERVER  },
+               {14,    CMD_UNLOCK,     42,             26,             PASS,           CLIENT  },
 
        /* Add new lock, differing types and processes, which are completely overlaped by an old lock in the list - 7,8,10 */
-               {15,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {15,    RDLOCK, 30,             10,             PASS,           SERVER  }, 
-               {15,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {15,    CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {15,    CMD_RDLOCK,     30,             10,             PASS,           SERVER  },
+               {15,    CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* The start is the same, end is in the middle of old lock */
-               {15,    RDLOCK, 50,             5,              FAIL,           CLIENT  }, 
-               {15,    WRLOCK, 50,             5,              FAIL,           CLIENT  }, 
+               {15,    CMD_RDLOCK,     50,             5,              FAIL,           CLIENT  },
+               {15,    CMD_WRLOCK,     50,             5,              FAIL,           CLIENT  },
                /* The start and end are in the middle of old lock */
-               {15,    RDLOCK, 52,             6,              FAIL,           CLIENT  }, 
-               {15,    WRLOCK, 52,             6,              FAIL,           CLIENT  }, 
+               {15,    CMD_RDLOCK,     52,             6,              FAIL,           CLIENT  },
+               {15,    CMD_WRLOCK,     52,             6,              FAIL,           CLIENT  },
                /* Start in the middle and end is the same */
-               {15,    RDLOCK, 52,             8,              FAIL,           CLIENT  }, 
-               {15,    WRLOCK, 52,             8,              FAIL,           CLIENT  }, 
+               {15,    CMD_RDLOCK,     52,             8,              FAIL,           CLIENT  },
+               {15,    CMD_WRLOCK,     52,             8,              FAIL,           CLIENT  },
                /* The start is the same, end is in the middle of old lock */
-               {15,    RDLOCK, 30,             5,              PASS,           CLIENT  }, 
-               {15,    WRLOCK, 30,             5,              FAIL,           CLIENT  }, 
+               {15,    CMD_RDLOCK,     30,             5,              PASS,           CLIENT  },
+               {15,    CMD_WRLOCK,     30,             5,              FAIL,           CLIENT  },
                /* The start and end are in the middle of old lock */
-               {15,    RDLOCK, 32,             6,              PASS,           CLIENT  }, 
-               {15,    WRLOCK, 32,             6,              FAIL,           CLIENT  }, 
+               {15,    CMD_RDLOCK,     32,             6,              PASS,           CLIENT  },
+               {15,    CMD_WRLOCK,     32,             6,              FAIL,           CLIENT  },
                /* Start in the middle and end is the same */
-               {15,    RDLOCK, 32,             8,              PASS,           CLIENT  }, 
-               {15,    WRLOCK, 32,             8,              FAIL,           CLIENT  }, 
+               {15,    CMD_RDLOCK,     32,             8,              PASS,           CLIENT  },
+               {15,    CMD_WRLOCK,     32,             8,              FAIL,           CLIENT  },
                
-               {15,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {15,    UNLOCK, 30,             10,             PASS,           SERVER  }, 
-               {15,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {15,    CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {15,    CMD_UNLOCK,     30,             10,             PASS,           SERVER  },
+               {15,    CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
        /* Add new lock, differing types and processes, which start before a lock in the list - 2,9 */
-               {16,    RDLOCK, 10,             10,             PASS,           SERVER  }, 
-               {16,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {16,    CMD_RDLOCK,     10,             10,             PASS,           SERVER  },
+               {16,    CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* Start is before, end is the start of the old lock in list */
-               {16,    RDLOCK, 5,              6,              PASS,           CLIENT  }, 
-               {16,    WRLOCK, 5,              6,              FAIL,           CLIENT  }, 
+               {16,    CMD_RDLOCK,     5,              6,              PASS,           CLIENT  },
+               {16,    CMD_WRLOCK,     5,              6,              FAIL,           CLIENT  },
                /* Start is before, end is in the middle of the old lock */
-               {16,    RDLOCK, 5,              10,             PASS,           CLIENT  }, 
-               {16,    WRLOCK, 5,              10,             FAIL,           CLIENT  }, 
+               {16,    CMD_RDLOCK,     5,              10,             PASS,           CLIENT  },
+               {16,    CMD_WRLOCK,     5,              10,             FAIL,           CLIENT  },
                /* Start is before, end is the start of the old lock in list */
-               {16,    RDLOCK, 45,             6,              FAIL,           CLIENT  }, 
-               {16,    WRLOCK, 45,             6,              FAIL,           CLIENT  }, 
+               {16,    CMD_RDLOCK,     45,             6,              FAIL,           CLIENT  },
+               {16,    CMD_WRLOCK,     45,             6,              FAIL,           CLIENT  },
                /* Start is before, end is in the middle of the old lock */
-               {16,    RDLOCK, 45,             10,             FAIL,           CLIENT  }, 
-               {16,    WRLOCK, 45,             10,             FAIL,           CLIENT  }, 
+               {16,    CMD_RDLOCK,     45,             10,             FAIL,           CLIENT  },
+               {16,    CMD_WRLOCK,     45,             10,             FAIL,           CLIENT  },
                
-               {16,    UNLOCK, 5,              15,             PASS,           CLIENT  }, 
-               {16,    UNLOCK, 30,             10,             PASS,           SERVER  }, 
-               {16,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {16,    CMD_UNLOCK,     5,              15,             PASS,           CLIENT  },
+               {16,    CMD_UNLOCK,     30,             10,             PASS,           SERVER  },
+               {16,    CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
 
        /* Add new lock, differing types and processes, which starts in the middle of a lock, and ends after - 11,12 */
-               {17,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
-               {17,    RDLOCK, 30,             10,             PASS,           SERVER  }, 
-               {17,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
+               {17,    CMD_WRLOCK,     10,             10,             PASS,           SERVER  },
+               {17,    CMD_RDLOCK,     30,             10,             PASS,           SERVER  },
+               {17,    CMD_WRLOCK,     50,             10,             PASS,           SERVER  },
                /* Start in the middle, end after lock in list */
-               {17,    WRLOCK, 35,             10,             FAIL,           CLIENT  }, 
+               {17,    CMD_WRLOCK,     35,             10,             FAIL,           CLIENT  },
                /* Start matches end of lock in list  */
-               {17,    RDLOCK, 35,             10,             PASS,           CLIENT  }, 
-               {17,    RDLOCK, 44,             2,              PASS,           CLIENT  }, 
+               {17,    CMD_RDLOCK,     35,             10,             PASS,           CLIENT  },
+               {17,    CMD_RDLOCK,     44,             2,              PASS,           CLIENT  },
                /* Start in the middle, end after lock in list */
-               {17,    RDLOCK, 55,             10,             FAIL,           CLIENT  }, 
-               {17,    WRLOCK, 55,             10,             FAIL,           CLIENT  }, 
+               {17,    CMD_RDLOCK,     55,             10,             FAIL,           CLIENT  },
+               {17,    CMD_WRLOCK,     55,             10,             FAIL,           CLIENT  },
                /* Start matches end of lock in list  */
-               {17,    RDLOCK, 59,             5,              FAIL,           CLIENT  }, 
-               {17,    WRLOCK, 59,             5,              FAIL,           CLIENT  }, 
+               {17,    CMD_RDLOCK,     59,             5,              FAIL,           CLIENT  },
+               {17,    CMD_WRLOCK,     59,             5,              FAIL,           CLIENT  },
                
-               {17,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
-               {17,    UNLOCK, 30,             16,             PASS,           CLIENT  }, 
-               {17,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
+               {17,    CMD_UNLOCK,     10,             10,             PASS,           SERVER  },
+               {17,    CMD_UNLOCK,     30,             16,             PASS,           CLIENT  },
+               {17,    CMD_UNLOCK,     50,             10,             PASS,           SERVER  },
 
 /* SECTION 4: overlapping and EOF tests */
        /* Acquire overlapping ranges */
-               {18,    WRLOCK, 11,             7,              PASS,           SERVER  },
-               {18,    WRLOCK, 13,             8,              FAIL,           CLIENT  },
-               {18,    UNLOCK, 11,             7,              PASS,           SERVER  },
+               {18,    CMD_WRLOCK,     11,             7,              PASS,           SERVER  },
+               {18,    CMD_WRLOCK,     13,             8,              FAIL,           CLIENT  },
+               {18,    CMD_UNLOCK,     11,             7,              PASS,           SERVER  },
        /* Acquire different ranges beyond EOF */
-               {19,    WRLOCK, 10,             FILE_SIZE,      PASS,           SERVER  },
-               {19,    WRLOCK, FILE_SIZE + 10, 10,             PASS,           CLIENT  },
-               {19,    UNLOCK, 10,             FILE_SIZE,      PASS,           SERVER  },
-               {19,    UNLOCK, FILE_SIZE + 10, 10,             PASS,           CLIENT  },
+               {19,    CMD_WRLOCK,     10,             FILE_SIZE,      PASS,           SERVER  },
+               {19,    CMD_WRLOCK,     FILE_SIZE + 10, 10,             PASS,           CLIENT  },
+               {19,    CMD_UNLOCK,     10,             FILE_SIZE,      PASS,           SERVER  },
+               {19,    CMD_UNLOCK,     FILE_SIZE + 10, 10,             PASS,           CLIENT  },
        /* Acquire same range beyong EOF */
-               {20,    WRLOCK, 10,             FILE_SIZE,      PASS,           SERVER, },
-               {20,    WRLOCK, 10,             FILE_SIZE,      FAIL,           CLIENT, },
-               {20,    UNLOCK, 10,             FILE_SIZE,      PASS,           SERVER, },
+               {20,    CMD_WRLOCK,     10,             FILE_SIZE,      PASS,           SERVER, },
+               {20,    CMD_WRLOCK,     10,             FILE_SIZE,      FAIL,           CLIENT, },
+               {20,    CMD_UNLOCK,     10,             FILE_SIZE,      PASS,           SERVER, },
        /* Acquire whole file lock */
-               {21,    WRLOCK, 0,              0,              PASS,           SERVER, },
-               {21,    WRLOCK, 0,              0,              FAIL,           CLIENT, },
-               {21,    UNLOCK, 0,              0,              PASS,           SERVER, },
+               {21,    CMD_WRLOCK,     0,              0,              PASS,           SERVER, },
+               {21,    CMD_WRLOCK,     0,              0,              FAIL,           CLIENT, },
+               {21,    CMD_UNLOCK,     0,              0,              PASS,           SERVER, },
        /* Acquire whole file lock, then range */
-               {22,    WRLOCK, 0,              0,              PASS,           SERVER, },
-               {22,    WRLOCK, 1,              5,              FAIL,           CLIENT, },
-               {22,    UNLOCK, 0,              0,              PASS,           SERVER, },
+               {22,    CMD_WRLOCK,     0,              0,              PASS,           SERVER, },
+               {22,    CMD_WRLOCK,     1,              5,              FAIL,           CLIENT, },
+               {22,    CMD_UNLOCK,     0,              0,              PASS,           SERVER, },
        /* Acquire non-overlapping read locks */
-               {23,    RDLOCK, 1,              5,              PASS,           SERVER, },
-               {23,    RDLOCK, 7,              6,              PASS,           CLIENT, },
-               {23,    UNLOCK, 1,              5,              PASS,           SERVER, },
-               {23,    UNLOCK, 7,              6,              PASS,           CLIENT, },
+               {23,    CMD_RDLOCK, 1,          5,              PASS,           SERVER, },
+               {23,    CMD_RDLOCK, 7,          6,              PASS,           CLIENT, },
+               {23,    CMD_UNLOCK, 1,          5,              PASS,           SERVER, },
+               {23,    CMD_UNLOCK, 7,          6,              PASS,           CLIENT, },
        /* Acquire overlapping read locks */
-               {24,    RDLOCK, 1,              5,              PASS,           SERVER, },
-               {24,    RDLOCK, 2,              6,              PASS,           CLIENT, },
-               {24,    UNLOCK, 1,              5,              PASS,           SERVER, },
-               {24,    UNLOCK, 1,              7,              PASS,           CLIENT, },
+               {24,    CMD_RDLOCK, 1,          5,              PASS,           SERVER, },
+               {24,    CMD_RDLOCK, 2,          6,              PASS,           CLIENT, },
+               {24,    CMD_UNLOCK, 1,          5,              PASS,           SERVER, },
+               {24,    CMD_UNLOCK, 1,          7,              PASS,           CLIENT, },
        /* Acquire non-overlapping read and write locks */
-               {25,    RDLOCK, 1,              5,              PASS,           SERVER, },
-               {25,    WRLOCK, 7,              6,              PASS,           CLIENT, },
-               {25,    UNLOCK, 1,              5,              PASS,           SERVER, },
-               {25,    UNLOCK, 7,              6,              PASS,           CLIENT, },
+               {25,    CMD_RDLOCK, 1,          5,              PASS,           SERVER, },
+               {25,    CMD_WRLOCK, 7,          6,              PASS,           CLIENT, },
+               {25,    CMD_UNLOCK, 1,          5,              PASS,           SERVER, },
+               {25,    CMD_UNLOCK, 7,          6,              PASS,           CLIENT, },
        /* Acquire overlapping read and write locks */
-               {26,    RDLOCK, 1,              5,              PASS,           SERVER, },
-               {26,    WRLOCK, 2,              6,              FAIL,           CLIENT, },
-               {26,    UNLOCK, 1,              5,              PASS,           SERVER, },
+               {26,    CMD_RDLOCK, 1,          5,              PASS,           SERVER, },
+               {26,    CMD_WRLOCK, 2,          6,              FAIL,           CLIENT, },
+               {26,    CMD_UNLOCK, 1,          5,              PASS,           SERVER, },
        /* Acquire whole file lock, then close (without unlocking) */
-               {27,    WRLOCK, 0,              0,              PASS,           SERVER, },
-               {27,    WRLOCK, 1,              5,              FAIL,           CLIENT, },
-               {27,    F_CLOSE,0,              0,              PASS,           SERVER, },
-               {27,    WRLOCK, 1,              5,              PASS,           CLIENT, },
-               {27,    F_OPEN, 0,              0,              PASS,           SERVER, },
-               {27,    UNLOCK, 1,              5,              PASS,           CLIENT, },
+               {27,    CMD_WRLOCK,     0,              0,              PASS,           SERVER, },
+               {27,    CMD_WRLOCK,     1,              5,              FAIL,           CLIENT, },
+               {27,    CMD_CLOSE,0,            0,              PASS,           SERVER, },
+               {27,    CMD_WRLOCK,     1,              5,              PASS,           CLIENT, },
+               {27,    CMD_OPEN,       O_RDWR,         0,              PASS,           SERVER, },
+               {27,    CMD_UNLOCK,     1,              5,              PASS,           CLIENT, },
        /* Acquire two read locks, close one file and then reopen to check that first lock still exists */
-               {28,    RDLOCK, 1,              5,              PASS,           SERVER, },
-               {28,    RDLOCK, 1,              5,              PASS,           CLIENT, },
-               {28,    F_CLOSE,0,              0,              PASS,           SERVER, },
-               {28,    F_OPEN, 0,              0,              PASS,           SERVER, },
-               {28,    WRLOCK, 0,              0,              FAIL,           SERVER, },
-               {28,    UNLOCK, 1,              5,              PASS,           SERVER, },
+               {28,    CMD_RDLOCK,     1,              5,              PASS,           SERVER, },
+               {28,    CMD_RDLOCK,     1,              5,              PASS,           CLIENT, },
+               {28,    CMD_CLOSE,0,            0,              PASS,           SERVER, },
+               {28,    CMD_OPEN,       O_RDWR,         0,              PASS,           SERVER, },
+               {28,    CMD_WRLOCK,     0,              0,              FAIL,           SERVER, },
+               {28,    CMD_UNLOCK,     1,              5,              PASS,           SERVER, },
+       /* Verify that F_GETLK for F_WRLCK doesn't require that file be opened for write */
+               {29,    CMD_CLOSE, 0,           0,              PASS,           SERVER, },
+               {29,    CMD_OPEN, O_RDONLY,     0,              PASS,           SERVER, },
+               {29,    CMD_WRTEST, 0,          0,              PASS,           SERVER, },
+               {29,    CMD_CLOSE,0,            0,              PASS,           SERVER, },
+               {29,    CMD_OPEN,       O_RDWR,         0,              PASS,           SERVER, },
 #ifdef macosx
        /* Close the opened file and open the file with SHLOCK, other client will try to open with SHLOCK too */
-               {29,    F_CLOSE,0,              0,              PASS,           SERVER, },
-               {29,    F_OPEN, O_SHLOCK|O_NONBLOCK,    0,      PASS,           SERVER, },
-               {29,    F_CLOSE,0,              0,              PASS,           CLIENT, },
-               {29,    F_OPEN, O_SHLOCK|O_NONBLOCK,    0,      PASS,           CLIENT, },
+               {30,    CMD_CLOSE,0,            0,              PASS,           SERVER, },
+               {30,    CMD_OPEN,       O_RDWR|O_SHLOCK|O_NONBLOCK,     0,      PASS,           SERVER, },
+               {30,    CMD_CLOSE,0,            0,              PASS,           CLIENT, },
+               {30,    CMD_OPEN,       O_RDWR|O_SHLOCK|O_NONBLOCK,     0,      PASS,           CLIENT, },
        /* Close the opened file and open the file with SHLOCK, other client will try to open with EXLOCK */
-               {30,    F_CLOSE,0,              0,              PASS,           SERVER, },
-               {30,    F_CLOSE,0,              0,              PASS,           CLIENT, },
-               {30,    F_OPEN, O_SHLOCK|O_NONBLOCK,    0,      PASS,           SERVER, },
-               {30,    F_OPEN, O_EXLOCK|O_NONBLOCK,    0,      FAIL,           CLIENT, },
+               {31,    CMD_CLOSE,0,            0,              PASS,           SERVER, },
+               {31,    CMD_CLOSE,0,            0,              PASS,           CLIENT, },
+               {31,    CMD_OPEN,       O_RDWR|O_SHLOCK|O_NONBLOCK,     0,      PASS,           SERVER, },
+               {31,    CMD_OPEN,       O_RDWR|O_EXLOCK|O_NONBLOCK,     0,      FAIL,           CLIENT, },
        /* Close the opened file and open the file with EXLOCK, other client will try to open with EXLOCK too */
-               {31,    F_CLOSE,0,              0,              PASS,           SERVER, },
-               {31,    F_CLOSE,0,              0,              FAIL,           CLIENT, },
-               {31,    F_OPEN, O_EXLOCK|O_NONBLOCK,    0,      PASS,           SERVER, },
-               {31,    F_OPEN, O_EXLOCK|O_NONBLOCK,    0,      FAIL,           CLIENT, },
-               {31,    F_CLOSE,0,              0,              PASS,           SERVER, },
-               {31,    F_CLOSE,0,              0,              FAIL,           CLIENT, },
-               {31,    F_OPEN, 0,              0,              PASS,           SERVER, },
-               {31,    F_OPEN, 0,              0,              PASS,           CLIENT, },
+               {32,    CMD_CLOSE,0,            0,              PASS,           SERVER, },
+               {32,    CMD_CLOSE,0,            0,              FAIL,           CLIENT, },
+               {32,    CMD_OPEN,       O_RDWR|O_EXLOCK|O_NONBLOCK,     0,      PASS,           SERVER, },
+               {32,    CMD_OPEN,       O_RDWR|O_EXLOCK|O_NONBLOCK,     0,      FAIL,           CLIENT, },
+               {32,    CMD_CLOSE,0,            0,              PASS,           SERVER, },
+               {32,    CMD_CLOSE,0,            0,              FAIL,           CLIENT, },
+               {32,    CMD_OPEN,       O_RDWR,         0,              PASS,           SERVER, },
+               {32,    CMD_OPEN,       O_RDWR,         0,              PASS,           CLIENT, },
 #endif /* macosx */
+
+       /* indicate end of array */
+               {0,0,0,0,0,SERVER},
+               {0,0,0,0,0,CLIENT}
+       };
+
+
+char *lease_descriptions[] = {
+    /*  1 */"Take Read Lease",
+    /*  2 */"Take Write Lease",
+    /*  3 */"Fail Write Lease if file is open somewhere else",
+    /*  4 */"Fail Read Lease if opened with write permissions",
+    /*  5 */"Read lease gets SIGIO on write open",
+    /*  6 */"Write lease gets SIGIO on read open",
+    /*  7 */"Read lease does _not_ get SIGIO on read open",
+    /*  8 */"Read lease gets SIGIO on write open",
+};
+
+static int64_t lease_tests[][6] =
+       /*      test #  Action  [offset|flags|arg]      length          expected        server/client */
+       /*                      [sigio_wait_time]                                               */
+       {
+       /* Various tests to exercise leases */
+
+/* SECTION 1: Simple verification of being able to take leases */
+       /* Take Read Lease */
+               {1,     CMD_CLOSE,      0,              0,      PASS,           CLIENT  },
+               {1,     CMD_OPEN,       O_RDONLY,       0,      PASS,           CLIENT  },
+               {1,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+               {1,     CMD_OPEN,       O_RDONLY,       0,      PASS,           SERVER  },
+               {1,     CMD_SETLEASE,   F_RDLCK,        0,      PASS,           SERVER  },
+               {1,     CMD_GETLEASE,   F_RDLCK,        0,      PASS,           SERVER  },
+               {1,     CMD_SETLEASE,   F_UNLCK,        0,      PASS,           SERVER  },
+               {1,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+               {1,     CMD_CLOSE,      0,              0,      PASS,           CLIENT  },
+
+       /* Take Write Lease */
+               {2,     CMD_OPEN,       O_RDWR,         0,      PASS,           SERVER  },
+               {2,     CMD_SETLEASE,   F_WRLCK,        0,      PASS,           SERVER  },
+               {2,     CMD_GETLEASE,   F_WRLCK,        0,      PASS,           SERVER  },
+               {2,     CMD_SETLEASE,   F_UNLCK,        0,      PASS,           SERVER  },
+               {2,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+       /* Fail Write Lease with other users */
+               {3,     CMD_OPEN,       O_RDONLY,       0,      PASS,           CLIENT  },
+               {3,     CMD_OPEN,       O_RDWR,         0,      PASS,           SERVER  },
+               {3,     CMD_SETLEASE,   F_WRLCK,        0,      FAIL,           SERVER  },
+               {3,     CMD_GETLEASE,   F_WRLCK,        0,      FAIL,           SERVER  },
+               {3,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+               {3,     CMD_CLOSE,      0,              0,      PASS,           CLIENT  },
+       /* Fail Read Lease if opened for write */
+               {4,     CMD_OPEN,       O_RDWR,         0,      PASS,           SERVER  },
+               {4,     CMD_SETLEASE,   F_RDLCK,        0,      FAIL,           SERVER  },
+               {4,     CMD_GETLEASE,   F_RDLCK,        0,      FAIL,           SERVER  },
+               {4,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+
+/* SECTION 2: Proper SIGIO notifications */
+       /* Get SIGIO when read lease is broken by write */
+               {5,     CMD_OPEN,       O_RDONLY,       0,      PASS,           CLIENT  },
+               {5,     CMD_SETLEASE,   F_RDLCK,        0,      PASS,           CLIENT  },
+               {5,     CMD_GETLEASE,   F_RDLCK,        0,      PASS,           CLIENT  },
+               {5,     CMD_SIGIO,      0,              0,      PASS,           CLIENT  },
+               {5,     CMD_OPEN,       O_RDWR,         0,      PASS,           SERVER  },
+               {5,     CMD_WAIT_SIGIO, 5,              0,      PASS,           CLIENT  },
+               {5,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+               {5,     CMD_CLOSE,      0,              0,      PASS,           CLIENT  },
+
+       /* Get SIGIO when write lease is broken by read */
+               {6,     CMD_OPEN,       O_RDWR,         0,      PASS,           CLIENT  },
+               {6,     CMD_SETLEASE,   F_WRLCK,        0,      PASS,           CLIENT  },
+               {6,     CMD_GETLEASE,   F_WRLCK,        0,      PASS,           CLIENT  },
+               {6,     CMD_SIGIO,      0,              0,      PASS,           CLIENT  },
+               {6,     CMD_OPEN,       O_RDONLY,       0,      PASS,           SERVER  },
+               {6,     CMD_WAIT_SIGIO, 5,              0,      PASS,           CLIENT  },
+               {6,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+               {6,     CMD_CLOSE,      0,              0,      PASS,           CLIENT  },
+
+       /* Don't get SIGIO when read lease is taken by read */
+               {7,     CMD_OPEN,       O_RDONLY,       0,      PASS,           CLIENT  },
+               {7,     CMD_SETLEASE,   F_RDLCK,        0,      PASS,           CLIENT  },
+               {7,     CMD_GETLEASE,   F_RDLCK,        0,      PASS,           CLIENT  },
+               {7,     CMD_SIGIO,      0,              0,      PASS,           CLIENT  },
+               {7,     CMD_OPEN,       O_RDONLY,       0,      PASS,           SERVER  },
+               {7,     CMD_WAIT_SIGIO, 5,              0,      FAIL,           CLIENT  },
+               {7,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+               {7,     CMD_CLOSE,      0,              0,      PASS,           CLIENT  },
+
+       /* Get SIGIO when Read lease is broken by Write */
+               {8,     CMD_OPEN,       O_RDONLY,       0,      PASS,           CLIENT  },
+               {8,     CMD_SETLEASE,   F_RDLCK,        0,      PASS,           CLIENT  },
+               {8,     CMD_GETLEASE,   F_RDLCK,        0,      PASS,           CLIENT  },
+               {8,     CMD_SIGIO,      0,              0,      PASS,           CLIENT  },
+               {8,     CMD_OPEN,       O_RDWR,         0,      PASS,           SERVER  },
+               {8,     CMD_WAIT_SIGIO, 5,              0,      PASS,           CLIENT  },
+               {8,     CMD_CLOSE,      0,              0,      PASS,           SERVER  },
+               {8,     CMD_CLOSE,      0,              0,      PASS,           CLIENT  },
+
        /* indicate end of array */
                {0,0,0,0,0,SERVER},
                {0,0,0,0,0,CLIENT}
@@ -584,12 +696,7 @@ initialize(HANDLE fd)
     int        offset = 0;
     int        togo = FILE_SIZE;
 
-    if (D_flag) {
-        ibuf = (char *)ALLOC_ALIGNED(INIT_BUFSZ);
-    }
-    else {
-        ibuf = (char*)malloc(INIT_BUFSZ);
-    }
+    ibuf = (char*)malloc(INIT_BUFSZ);
     memset(ibuf, ':', INIT_BUFSZ);
 
     SEEK(fd, 0L);
@@ -610,40 +717,94 @@ initialize(HANDLE fd)
     }
 }
 
+void release_lease(int fd)
+{
+       int rc;
 
-int do_open(int flag)
+       rc = fcntl(fd, F_SETLEASE, F_UNLCK);
+       if (rc != 0)
+               fprintf(stderr, "%s Failed to remove lease %d : %d %s\n",
+                       __FILE__, rc, errno, strerror(errno));
+}
+
+void lease_break(int sig, siginfo_t *info, void *p)
 {
-    if ((f_fd = OPEN(filename, flag)) == INVALID_HANDLE) {
-       perror("shared file create");
-       if (!flag)      /* Only exit if the first open fails */
-           exit(1);
-       closed = 0;
+    if (debug)
+       fprintf(stderr, "lease break %d %p fd %d\n",
+               sig, info, info->si_fd);
+    got_sigio = 1;
+    release_lease(f_fd);
+}
+
+struct sigaction lease_break_action = {
+       .sa_sigaction = lease_break,
+       .sa_flags = SA_SIGINFO,
+};
+
+int do_setup_sigio(int fd)
+{
+       int rc;
+
+       got_sigio = 0;
+
+       rc = sigaction(SIGIO, &lease_break_action, NULL);
+       if (rc != 0) {
+               fprintf(stderr, "%s Set '%s' sigaction failed %d\n",
+                       __FILE__, strsignal(SIGIO), rc);
+               return FAIL;
+       }
+
+       if (debug)
+               fprintf(stderr, "Set '%s' sigaction on %d\n",
+                       strsignal(SIGIO), fd);
+
+       rc = fcntl(fd, F_SETSIG, SIGIO);
+       if (rc)
+               fprintf(stderr, "%s Set '%s' sigaction failed %d\n",
+                       __FILE__, strsignal(SIGIO), rc);
+
+       return (rc == 0 ? PASS : FAIL);
+}
+
+int do_wait_sigio(int32_t time)
+{
+    if (time <= 0)
        return FAIL;
-       /*NOTREACHED*/
+
+    while (!got_sigio && time--) {
+       sleep(1);
     }
 
-    closed = 0;
+    if (debug > 1 && !got_sigio)
+       fprintf(stderr, "%s failed to get sigio\n",
+               __FILE__);
 
-#ifdef __sun
-    if (D_flag) {
-        directio(f_fd, DIRECTIO_ON);
-    }
-#elif defined(__APPLE__)
-    if (D_flag) {
-       fcntl(f_fd, F_NOCACHE, 1);
+    return (got_sigio ? PASS: FAIL);
+}
+
+int do_open(int flag)
+{
+    int flags = flag|O_CREAT|O_BINARY;
+
+    if(debug > 1)
+       fprintf(stderr, "do_open %s 0x%x\n", filename, flags);
+
+    if ((f_fd = open(filename, flags, 0666)) == INVALID_HANDLE) {
+       perror("shared file create");
+       return FAIL;
+       /*NOTREACHED*/
     }
-#endif
     return PASS;
 }
 
-int do_lock(int type, int start, int length)
+static int do_lock(int cmd, int type, int start, int length)
 {
     int ret;
     int filedes = f_fd;
     struct flock fl;
 
     if(debug > 1) {
-       fprintf(stderr, "do_lock: start=%d, length=%d\n", start, length);
+       fprintf(stderr, "do_lock: cmd=%d type=%d start=%d, length=%d\n", cmd, type, start, length);
     }
 
     if (f_fd < 0)
@@ -657,40 +818,37 @@ int do_lock(int type, int start, int length)
 
     errno = 0;
 
-    ret = fcntl(filedes, F_SETLK, &fl);
+    ret = fcntl(filedes, cmd, &fl);
     saved_errno = errno;           
 
-    if(debug > 1 && ret)
+    if(ret)
        fprintf(stderr, "do_lock: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
 
     return(ret==0?PASS:FAIL);
 }
 
-int do_unlock(int start, int length)
+static int do_lease(int cmd, int arg, int expected)
 {
     int ret;
-    int filedes = f_fd;
-    struct flock fl;
 
-    if(debug > 1) {
-       fprintf(stderr, "do_unlock: start=%d, length=%d\n", start, length);
-    }
+    if(debug > 1)
+       fprintf(stderr, "do_lease: cmd=%d arg=%d exp=%X\n",
+               cmd, arg, expected);
 
     if (f_fd < 0)
        return f_fd;
-    
-    fl.l_start = start;
-    fl.l_len = length;
-    fl.l_whence = SEEK_SET;
-    fl.l_pid = getpid();
-    fl.l_type = F_UNLCK;
 
     errno = 0;
 
-    ret = fcntl(filedes, F_SETLK, &fl);
-    saved_errno = errno;           
-    if(debug > 1 && ret)
-       fprintf(stderr, "do_lock: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
+    ret = fcntl(f_fd, cmd, arg);
+    saved_errno = errno;
+
+    if (expected && (expected == ret))
+       ret = 0;
+
+    if(ret)
+       fprintf(stderr, "%s do_lease: ret = %d, errno = %d (%s)\n",
+               __FILE__, ret, errno, strerror(errno));
 
     return(ret==0?PASS:FAIL);
 }
@@ -703,12 +861,27 @@ int do_close(void)
 
     errno =0;
     CLOSE(f_fd);
+    f_fd = INVALID_HANDLE;
 
     saved_errno = errno;           
        
-    if (errno)
+    if (errno) {
+       fprintf(stderr, "%s errno = %d (%s)\n",
+               __FILE__, errno, strerror(errno));
        return FAIL;
-    return(PASS);
+    }
+    return PASS;
+}
+
+static void init_ctl(int64_t tests[][6], int32_t index)
+{
+    ctl.test= (int32_t)tests[index][TEST_NUM];
+    ctl.command = (int32_t)tests[index][COMMAND];
+    ctl.offset = tests[index][OFFSET];
+    ctl.length = tests[index][LENGTH];
+    ctl.index = index;
+    ctl.result = (int32_t)tests[index][RESULT];
+    ctl.error = 0;
 }
 
 void
@@ -716,7 +889,7 @@ send_ctl(void)
 {
     int         nwrite;
 
-    if (debug > 1) {
+    if (debug) {
        fprintf(stderr, "send_ctl: test=%d, command=%d offset=%"LL"d, length=%"LL"d, result=%d, error=%d\n", 
                 ctl.test, ctl.command, (long long)ctl.offset, (long long)ctl.length,ctl.result, ctl.error);
     }
@@ -752,10 +925,13 @@ void recv_ctl(void)
 {
     int         nread;
 
+again:
     if ((nread = SOCKET_READ(c_fd, (char*)&ctl, sizeof(ctl))) != sizeof(ctl)) {
-        if (nread < 0)
+        if (nread < 0) {
+           if (errno == EINTR)
+               goto again;
             perror("recv_ctl: read");
-        else {
+        else {
             fprintf(stderr, "recv_ctl[%d]: read() returns %d, not %zu as expected\n", 
                     ctl.test, nread, sizeof(ctl));
            fprintf(stderr, "socket might has been closed by other locktest\n");
@@ -771,7 +947,7 @@ void recv_ctl(void)
     ctl.index= bswap_uint32(ctl.index);
     ctl.error= bswap_uint32(ctl.error);
 
-    if (debug > 1) {
+    if (debug) {
        fprintf(stderr, "recv_ctl: test=%d, command=%d offset=%"LL"d, length=%"LL"d, result=%d, error=%d\n", 
                 ctl.test, ctl.command, (long long)ctl.offset, (long long)ctl.length, ctl.result, ctl.error);
     }
@@ -780,7 +956,7 @@ void recv_ctl(void)
 void
 cleanup(void)
 {
-    if (f_fd>=0 && !reopen && !closed)
+    if (f_fd>=0)
         CLOSE(f_fd);
     
     if (c_fd>=0)
@@ -792,6 +968,9 @@ cleanup(void)
     PLATFORM_CLEANUP();
 }
 
+int
+run(int64_t tests[][6], char *descriptions[]);
+
 int
 main(int argc, char *argv[])
 {
@@ -805,8 +984,8 @@ main(int argc, char *argv[])
     char       *p;
     extern char        *optarg;
     extern int optind;
-    extern int errno;
-    int fail_count = 0;; 
+    int fail_count = 0;
+    int run_leases = 0;
     
     atexit(cleanup);
     
@@ -819,13 +998,17 @@ main(int argc, char *argv[])
            prog = p+1;
     }
 
-    while ((c = getopt(argc, argv, "dn:h:p:?")) != EOF) {
+    while ((c = getopt(argc, argv, "dLn:h:p:?")) != EOF) {
        switch (c) {
 
        case 'd':       /* debug flag */
            debug++;
            break;
 
+       case 'L':       /* Lease testing */
+           run_leases = 1;
+           break;
+
        case 'h':       /* (server) hostname */
            server = 0;
            host = optarg;
@@ -858,25 +1041,10 @@ main(int argc, char *argv[])
     }
 
     filename=argv[optind];
-    do_open(0);
-
-    /*
-     * +10 is slop for the iteration number if do_write() ... never
-     * needed unless maxio is very small
-     */
-    if (D_flag) {
-        if ((buf = (char *)ALLOC_ALIGNED(maxio + 10)) == NULL) {
-           perror("aligned alloc buf");
-           exit(1);
-           /*NOTREACHED*/
-        }
-    } else {
-        if ((buf = (char *)malloc(maxio + 10)) == NULL) {
-           perror("malloc buf");
-           exit(1);
-           /*NOTREACHED*/
-        }
-    }
+    if (debug)
+       fprintf(stderr, "Working on file : %s\n", filename);
+    if (do_open(O_RDWR) == FAIL)
+       exit(1);
 
     setbuf(stderr, NULL);
 
@@ -925,6 +1093,20 @@ main(int argc, char *argv[])
            /*NOTREACHED*/
        }
 
+       if (port == 0) {
+               socklen_t addr_len = sizeof(myAddr);
+
+               if (getsockname(s_fd, &myAddr, &addr_len)) {
+                   perror("getsockname");
+                   exit(1);
+               }
+
+               port = ntohs(myAddr.sin_port);
+       }
+
+       printf("server port: %d\n", port);
+       fflush(stdout);
+
        c_fd = accept(s_fd, NULL, NULL);
        if (c_fd == INVALID_SOCKET) {
            perror("accept");
@@ -939,10 +1121,10 @@ main(int argc, char *argv[])
         struct hostent  *servInfo;
 
         if ((servInfo = gethostbyname(host)) == NULL) {
-           printf("Couldn't get hostbyname for %s", host);
+           fprintf(stderr, "Couldn't get hostbyname for %s", host);
            if (h_errno == HOST_NOT_FOUND)
-               printf(": host not found");
-           printf("\n");
+               fprintf(stderr, ": host not found");
+           fprintf(stderr, "\n");
             exit(1);
             /*NOTREACHED*/
         }
@@ -991,14 +1173,24 @@ main(int argc, char *argv[])
      *
      * real work is in here ...
      */
-    i = 0;
+    if (run_leases)
+       fail_count = run(lease_tests, lease_descriptions);
+    else
+       fail_count = run(lock_tests, lock_descriptions);
+
+    exit(fail_count);
+    /*NOTREACHED*/
+}
+
+int run(int64_t tests[][6], char *descriptions[])
 {
     int index = 0;
     int end = 0;
     int result = 0;
     int last_test = 0;
-    int test_count = 0;
+    int test_count = -1;
     int fail_flag = 0;
+    int fail_count = 0;
     while(!end) {
        if (server) {
            if(testnumber > 0) {
@@ -1009,7 +1201,7 @@ main(int argc, char *argv[])
            }
            /* If we have a server command, deal with it */
            if(tests[index][WHO] == SERVER) {
-               if(debug>1)
+               if(debug)
                    fprintf(stderr, "Got a server command (%d)\n", index);
                if(tests[index][TEST_NUM] == 0) {
                    index++;
@@ -1020,37 +1212,51 @@ main(int argc, char *argv[])
 
                if(tests[index][TEST_NUM] != 0) {
                    switch(tests[index][COMMAND]) {
-                       case WRLOCK:
-                           result = do_lock(F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
+                       case CMD_WRLOCK:
+                           result = do_lock(F_SETLK, F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
                            break;
-                       case RDLOCK:
-                           result = do_lock(F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
+                       case CMD_RDLOCK:
+                           result = do_lock(F_SETLK, F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
                            break;
-                       case UNLOCK:
-                           result = do_unlock(tests[index][OFFSET], tests[index][LENGTH]);
+                       case CMD_UNLOCK:
+                           result = do_lock(F_SETLK, F_UNLCK, tests[index][OFFSET], tests[index][LENGTH]);
                            break;
-                       case F_CLOSE:
+                       case CMD_CLOSE:
                            result = do_close();
                            break;
-                       case F_OPEN:
+                       case CMD_OPEN:
                            result = do_open(tests[index][FLAGS]);
                            break;
+                       case CMD_WRTEST:
+                           result = do_lock(F_GETLK, F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
+                           break;
+                       case CMD_RDTEST:
+                           result = do_lock(F_GETLK, F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
+                           break;
+                       case CMD_SETLEASE:
+                           result = do_lease(F_SETLEASE, tests[index][ARG], 0);
+                           break;
+                       case CMD_GETLEASE:
+                           result = do_lease(F_GETLEASE, tests[index][ARG], tests[index][ARG]);
+                           break;
+                       case CMD_SIGIO:
+                           result = do_setup_sigio(f_fd);
+                           break;
+                       case CMD_WAIT_SIGIO:
+                           result = do_wait_sigio(tests[index][TIME]);
+                           break;
                    }
                    if( result != tests[index][RESULT]) {
                        fail_flag++;
                        /* We have a failure */
-                       if(debug)
-                           fprintf(stderr, "Server failure in test %d, while %sing using offset %lld, length %lld - err = %d:%s\n", 
-                                       ctl.test, tests[index][COMMAND]==WRLOCK?"write lock":
-                                               tests[index][COMMAND]==RDLOCK?"read lock":
-                                               tests[index][COMMAND]==UNLOCK?"unlock":
-                                               tests[index][COMMAND]==F_OPEN?"open":"clos", 
-                                               (long long)tests[index][OFFSET],
-                                               (long long)tests[index][LENGTH],
-                                               saved_errno, strerror(saved_errno));
-                       fprintf(stderr, "Server failure in %lld:%s\n",
-                                       (long long)tests[index][TEST_NUM],
-                                       descriptions[tests[index][TEST_NUM] - 1]);
+                       fprintf(stderr, "     ***** Server failure *****\n");
+                       fprintf(stderr, "     in test %d, while %sing using offset %lld, length %lld - err = %d:%s\n",
+                               ctl.test, get_cmd_str(tests[index][COMMAND]),
+                               (long long)tests[index][OFFSET],
+                               (long long)tests[index][LENGTH],
+                               saved_errno, strerror(saved_errno));
+                       fprintf(stderr, "     %d:%s\n",
+                                       ctl.test, descriptions[ctl.test - 1]);
                    }
                }
            /* else send it off to the client */
@@ -1059,12 +1265,12 @@ main(int argc, char *argv[])
                    ctl.test = 0;
                    end=1;
                } 
-               if(debug > 1)
+               /* get the client to do something */
+               init_ctl(tests, index);
+               if(debug)
                    fprintf(stderr, "Sending command to client (%d) - %s - %lld:%lld\n", 
-                                       index, tests[index][COMMAND]==WRLOCK?"write lock":
-                                       tests[index][COMMAND]==RDLOCK?"read lock":
-                                       tests[index][COMMAND]==UNLOCK?"unlock": 
-                                       tests[index][COMMAND]==F_OPEN?"open":"clos", 
+                                       index,
+                                       get_cmd_str(ctl.command),
                                        (long long)tests[index][OFFSET],
                                        (long long)tests[index][LENGTH]);
                /* get the client to do something */
@@ -1077,38 +1283,28 @@ main(int argc, char *argv[])
                     * not what the command returned */
                    if( ctl.result == FAIL ) {
                        fail_flag++;
-                       if(debug)
-                           fprintf(stderr, "Client failure in test %d, while %sing using offset %lld, length %lld - err = %d:%s\n",
-                                       ctl.test, ctl.command==WRLOCK?"write lock":
-                                       ctl.command==RDLOCK?"read lock":
-                                       ctl.command==UNLOCK?"unlock":
-                                       ctl.command==F_OPEN?"open":"clos",
+                       fprintf(stderr, "     ***** Client failure *****\n");
+                       fprintf(stderr, "     in test %d, while %sing using offset %lld, length %lld - err = %d:%s\n",
+                                       ctl.test, get_cmd_str(ctl.command),
                                        (long long)ctl.offset, (long long)ctl.length,
                                        ctl.error, strerror(ctl.error));
-                       fprintf(stderr, "Client failure in %lld:%s\n",
-                                       (long long)tests[index][TEST_NUM],
-                                       descriptions[tests[index][TEST_NUM] - 1]);
+                       fprintf(stderr, "     %d:%s\n",
+                                       ctl.test, descriptions[ctl.test - 1]);
                    }
                }
            }
-           if (debug > 1) {
-               fprintf(stderr, "server sleeping ...\n");
-               SLEEP(1);
-           }
-           if(tests[index][TEST_NUM] != 0) {
-               if(last_test != tests[index][TEST_NUM]) {
-                   test_count++;
-                   if(fail_flag)
-                       fail_count++;
-                   fail_flag = 0;
 
-               }
-               last_test = tests[index][TEST_NUM];
+           if(last_test != tests[index][TEST_NUM]) {
+               test_count++;
+               if(fail_flag)
+                   fail_count++;
+               fail_flag = 0;
+               last_test = tests[index][TEST_NUM];
            }
                
            index++;
        } else { /* CLIENT */
-           if(debug > 2)
+           if(debug)
                fprintf(stderr,"client: waiting...\n");
            /* wait for the server to do something */
            recv_ctl();
@@ -1124,62 +1320,66 @@ main(int argc, char *argv[])
                end = 1;
                break;
            }
-               
 
-           ctl.command = tests[index][COMMAND];
-           ctl.offset = tests[index][OFFSET];
-           ctl.length = tests[index][LENGTH];
-           switch(tests[index][COMMAND]) {
-               case WRLOCK:
-                   result = do_lock(F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
+           switch(ctl.command) {
+               case CMD_WRLOCK:
+                   result = do_lock(F_SETLK, F_WRLCK, ctl.offset, ctl.length);
                    break;
-               case RDLOCK:
-                   result = do_lock(F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
+               case CMD_RDLOCK:
+                   result = do_lock(F_SETLK, F_RDLCK, ctl.offset, ctl.length);
                    break;
-               case UNLOCK:
-                   result = do_unlock(tests[index][OFFSET], tests[index][LENGTH]);
+               case CMD_UNLOCK:
+                   result = do_lock(F_SETLK, F_UNLCK, ctl.offset, ctl.length);
                    break;
-               case F_CLOSE:
+               case CMD_CLOSE:
                    result = do_close();
                    break;
-               case F_OPEN:
+               case CMD_OPEN:
                    result = do_open(tests[index][FLAGS]);
                    break;
+               case CMD_WRTEST:
+                   result = do_lock(F_GETLK, F_WRLCK, ctl.offset, ctl.length);
+                   break;
+               case CMD_RDTEST:
+                   result = do_lock(F_GETLK, F_RDLCK, ctl.offset, ctl.length);
+                   break;
+               /* NOTE offset carries the argument values */
+               case CMD_SETLEASE:
+                   result = do_lease(F_SETLEASE, ctl.offset, 0);
+                   break;
+               case CMD_GETLEASE:
+                   result = do_lease(F_GETLEASE, ctl.offset, ctl.offset);
+                   break;
+               case CMD_SIGIO:
+                   result = do_setup_sigio(f_fd);
+                   break;
+               case CMD_WAIT_SIGIO:
+                   result = do_wait_sigio(ctl.offset);
+                   break;
            }
-           if( result != tests[index][RESULT] ) {
-               if(debug)
-                   fprintf(stderr,"Got %d, wanted %lld\n", result,
-                                       (long long)tests[index][RESULT]);
+           if( result != ctl.result ) {
+               fprintf(stderr,"Failure in %d:%s\n",
+                       ctl.test, descriptions[ctl.test - 1]);
+               fprintf(stderr,"     Got %d, wanted %d\n",
+                       result, ctl.result);
                ctl.result = FAIL;
                ctl.error = saved_errno;
                fail_count++;
            } else {
                ctl.result = PASS;
+               ctl.error = 0;
            }
-           if(debug > 2)
+           if(debug)
                fprintf(stderr,"client: sending result to server (%d)\n", ctl.index);
            /* Send result to the server */
            send_ctl();
-           if(tests[index][TEST_NUM] != 0) {
-               if(last_test != tests[index][TEST_NUM])
-                   test_count++;
+           if(last_test != tests[index][TEST_NUM]) {
+               test_count++;
                last_test = tests[index][TEST_NUM];
            }
        }
     }
-    if(server)
-       printf("%d tests run, %d failed\n", test_count, fail_count);
-}   
-    if (buf) {
-        if (D_flag)
-            FREE_ALIGNED(buf);
-        else
-            free(buf);
-    }
+    fprintf(stderr, "%d tests run, %d failed\n", test_count, fail_count);
 
-    
-    exit(fail_count);
-    /*NOTREACHED*/
+    return fail_count;
 }
-
-