src/locktest: Remove unnecessary sleep
[xfstests-dev.git] / src / locktest.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000-2003 Silicon Graphics, Inc.
4  * All Rights Reserved.
5  */
6
7 /*
8  * Synchronized byte range lock exerciser
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <malloc.h>
14 #include <fcntl.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <netinet/tcp.h>
21
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <netdb.h>
25 #include <endian.h>
26 #include <byteswap.h>
27 #include <errno.h>
28 #include <string.h>
29 #define     HEX_2_ASC(x)    ((x) > 9) ? (x)-10+'a' : (x)+'0'
30 #define         FILE_SIZE       1024
31 #define PLATFORM_INIT()     /*no-op*/
32 #define PLATFORM_CLEANUP()  /*no-op*/
33 #define LL                  "ll"
34
35 extern int h_errno;
36
37 #define inet_aton(STRING, INADDRP) \
38     (((INADDRP)->s_addr = inet_addr(STRING)) == -1 ? 0 : 1)
39
40 /* this assumes 32 bit pointers */
41 #define PTR_TO_U64(P) ((unsigned __int64)(unsigned int)(P))
42 #define U64_TO_PTR(T,U) ((T)(void *)(unsigned int)(U))
43
44 #if __BYTE_ORDER == __LITTLE_ENDIAN
45 #define bswap_uint16(x)         (uint16_t)bswap_16(x)
46 #define bswap_uint32(x)         (uint32_t)bswap_32(x)
47 #define bswap_uint64(x)         (uint64_t)bswap_64(x)
48 #else
49 #define bswap_uint16(x)         x
50 #define bswap_uint32(x)         x
51 #define bswap_uint64(x)         x
52 #endif
53
54 #define SOCKET              int
55 #define SOCKET_READ         read
56 #define SOCKET_WRITE        write
57 #define SOCKET_CLOSE(S)     (close(S))
58 #define INVALID_SOCKET      -1
59
60 #define O_BINARY            0
61        
62 #define HANDLE              int
63 #define INVALID_HANDLE      -1
64 #define OPEN(N,F)           (open(N, F|O_CREAT|O_BINARY, 0644))
65 #define SEEK(H, O)          (lseek(H, O, SEEK_SET))
66 #define READ(H, B, L)       (read(H, B, L))
67 #define WRITE(H, B, L)      (write(H, B, L))
68 #define CLOSE(H)            (close(H))
69
70 #define RAND()              (rand())
71 #define SRAND(s)            (srand(s))
72
73 #define MIN(A,B)            (((A)<(B))?(A):(B))
74 #define MAX(A,B)            (((A)>(B))?(A):(B))
75
76 #define ALLOC_ALIGNED(S)    (memalign(65536, S)) 
77 #define FREE_ALIGNED(P)     (free(P)) 
78
79 static char     *prog;
80 static char     *filename = 0;
81 static int      debug = 0;
82 static int      server = 1;
83 static int      port = 0;
84 static int      testnumber = -1;
85 static int      saved_errno = 0;
86
87 static SOCKET   s_fd = -1;              /* listen socket    */
88 static SOCKET   c_fd = -1;              /* IPC socket       */
89 static HANDLE   f_fd = INVALID_HANDLE;  /* shared file      */
90
91 #define         WRLOCK  0
92 #define         RDLOCK  1
93 #define         UNLOCK  2
94 #define         F_CLOSE 3
95 #define         F_OPEN  4
96 #define         WRTEST  5
97 #define         RDTEST  6
98
99 #define         PASS    1
100 #define         FAIL    0
101
102 #define         SERVER  0
103 #define         CLIENT  1
104
105 #define         TEST_NUM        0
106 #define         COMMAND         1
107 #define         OFFSET          2
108 #define         LENGTH          3
109 #define         RESULT          4
110 #define         WHO             5
111 #define         FLAGS           2 /* index 2 is also used for do_open() flag, see below */
112
113 /* 
114  * flags for Mac OS X do_open() 
115  * O_RDONLY     0x0000
116  * O_WRONLY     0x0001  
117  * O_RDWR       0x0002
118  * O_NONBLOCK   0x0004  
119  * O_APPEND     0x0008
120  * O_SHLOCK     0x0010  
121  * O_EXLOCK     0x0020
122  * O_ASYNC      0x0040  
123  * O_FSYNC      0x0080
124  * O_NOFOLLOW   0x0100  
125  * O_CREAT      0x0200
126  * O_TRUNC      0x0400
127  * O_EXCL       0x0800
128  */
129
130 /*
131  * When adding tests be sure to add to both the descriptions AND tests array. 
132  * Also, be sure to undo whatever is set for each test (eg unlock any locks)
133  * There is no need to have a matching client command for each server command
134  * (or vice versa)
135  */
136
137 char *descriptions[] = {
138     /* 1 */"Add a lock to an empty lock list",
139     /* 2 */"Add a lock to the start and end of a list - no overlaps",
140     /* 3 */"Add a lock to the middle of a list - no overlap",
141     /* 4 */"Add different lock types to middle of the list - overlap exact match", 
142     /* 5 */"Add new lock which completely overlaps any old lock in the list", 
143     /* 6 */"Add new lock which itself is completely overlaped by any old lock in the list",
144     /* 7 */"Add new lock which starts before any old lock in the list",
145     /* 8 */"Add new lock which starts in the middle of any old lock in the list and ends after",
146     /* 9 */"Add different new lock types which completely overlaps any old lock in the list",
147     /* 10 */"Add different new locks which are completely overlaped by an old lock in the list",
148     /* 11 */"Add different new lock types which start before the old lock in the list",
149     /* 12 */"Add different new lock types which start in the middle of an old lock in the list and end after",
150     /* 13 */"Add new lock, differing types and processes, to middle of the list - exact overlap match",
151     /* 14 */"Add new lock, differing types and processes, which completely overlap any of the locks in the list",
152     /* 15 */"Add new lock, differing types and processes, which are completely overlaped by locks in the list",
153     /* 16 */"Add new lock, differing types and processes, which start before a lock in the list",
154     /* 17 */"Add new lock, differing types and processes, which starts in the middle of a lock, and ends after",
155     /* 18 */"Acquire write locks with overlapping ranges",
156     /* 19 */"Acquire write locks with non-overlapping ranges extending beyond EOF",
157     /* 20 */"Acquire write locks with overlapping ranges extending beyond EOF",
158     /* 21 */"Acquire write locks on whole files",
159     /* 22 */"Acquire write lock on whole file and range write lock",
160     /* 23 */"Acquire read locks with non-overlapping ranges",
161     /* 24 */"Acquire read locks with overlapping ranges",
162     /* 25 */"Acquire read and write locks with no overlapping ranges",
163     /* 26 */"Acquire read and write locks with overlapping ranges",
164     /* 27 */"Acquire whole file write lock and then close without unlocking (and attempt a lock)",
165     /* 28 */"Acquire two read locks, close and reopen the file, and test if the inital lock is still there",
166     /* 29 */"Verify that F_GETLK for F_WRLCK doesn't require that file be opened for write",
167     #if defined(macosx)
168     /* 30 */"Close the opened file and open the file with SHLOCK, other client will try to open with SHLOCK too",
169     /* 31 */"Close the opened file and open the file with SHLOCK, other client will try to open with EXLOCK",
170     /* 32 */"Close the opened file and open the file with EXLOCK, other client will try to open with EXLOCK too"
171     #endif
172 };
173
174 static int64_t tests[][6] =
175         /*      test #  Action  [offset|flags]  length          expected        server/client */
176         {       
177         /* Various simple tests exercising the list */
178
179 /* SECTION 1: WRITE and UNLOCK with the same process (SERVER) */
180         /* Add a lock to an empty list */
181                 {1,     WRLOCK, 1,              10,             PASS,           SERVER  }, 
182                 {1,     UNLOCK, 1,              10,             PASS,           SERVER  }, 
183                 
184         /* Add a lock to the start and end of a list - 1, 13 - no overlap */
185                 {2,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
186                 {2,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
187                 {2,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
188                 {2,     WRLOCK, 1,              5,              PASS,           SERVER  }, 
189                 {2,     WRLOCK, 70,             5,              PASS,           SERVER  }, 
190                 
191                 {2,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
192                 {2,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
193                 {2,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
194                 {2,     UNLOCK, 1,              5,              PASS,           SERVER  }, 
195                 {2,     UNLOCK, 70,             5,              PASS,           SERVER  }, 
196                 
197         /* Add a lock to the middle of a list - no overlap */
198                 {3,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
199                 {3,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
200                 {3,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
201                 {3,     WRLOCK, 42,             5,              PASS,           SERVER  }, 
202                 
203                 {3,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
204                 {3,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
205                 {3,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
206                 {3,     UNLOCK, 42,             5,              PASS,           SERVER  }, 
207                 
208         /* Add different lock types to middle of the list - overlap exact match - 3 */
209                 {4,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
210                 {4,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
211                 {4,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
212                 /* Exact match - same lock type */
213                 {4,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
214                 /* Exact match - different lock type */
215                 {4,     RDLOCK, 30,             10,             PASS,           SERVER  }, 
216                 /* Exact match - unlock */
217                 {4,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
218                 /* New lock - as above, inserting in the list again */
219                 {4,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
220                 
221                 {4,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
222                 {4,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
223                 {4,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
224                 
225         /* Add new lock which completely overlaps any old lock in the list - 4,5,6 */
226                 {5,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
227                 {5,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
228                 {5,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
229                 /* The start is the same, end overlaps */
230                 {5,     WRLOCK, 30,             15,             PASS,           SERVER  }, 
231                 /* The start is before, end is the same */
232                 {5,     WRLOCK, 25,             20,             PASS,           SERVER  }, 
233                 /* Both start and end overlap */
234                 {5,     WRLOCK, 22,             26,             PASS,           SERVER  }, 
235                 
236                 {5,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
237                 {5,     UNLOCK, 22,             26,             PASS,           SERVER  }, 
238                 {5,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
239                 
240         /* Add new lock which itself is completely overlaped by any old lock in the list - 7,8,10 */
241                 {6,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
242                 {6,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
243                 {6,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
244                 /* The start is the same, end is in the middle of old lock - NOP */
245                 {6,     WRLOCK, 30,             5,              PASS,           SERVER  }, 
246                 /* The start and end are in the middle of old lock - NOP */
247                 {6,     WRLOCK, 32,             6,              PASS,           SERVER  }, 
248                 /* Start in the middle and end is the same - NOP */
249                 {6,     WRLOCK, 32,             8,              PASS,           SERVER  }, 
250                 
251                 {6,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
252                 {6,     UNLOCK, 30,             10,             PASS,           SERVER  }, 
253                 {6,     UNLOCK, 32,             8,              PASS,           SERVER  }, 
254                 {6,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
255                 
256         /* Add new lock which starts before any old lock in the list - 2,9 */
257                 {7,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
258                 {7,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
259                 {7,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
260                 /* Here is the new lock */
261                 {7,     WRLOCK, 27,             10,             PASS,           SERVER  }, 
262                 /* Go again with the end of the new lock matching the start of old lock */
263                 {7,     WRLOCK, 25,             2,              PASS,           SERVER  }, 
264                 
265                 {7,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
266                 {7,     UNLOCK, 25,             15,             PASS,           SERVER  }, 
267                 {7,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
268         
269         /* Add new lock which starts in the middle of any old lock in the list and ends after - 11,12 */
270                 {8,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
271                 {8,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
272                 {8,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
273                 /* Here is the new lock */
274                 {8,     WRLOCK, 35,             10,             PASS,           SERVER  }, 
275                 /* Go again with the end of the new lock matching the start of old lock */
276                 {8,     WRLOCK, 45,             2,              PASS,           SERVER  }, 
277                 
278                 {8,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
279                 {8,     UNLOCK, 30,             17,             PASS,           SERVER  }, 
280                 {8,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
281 /* SECTION 2: Overlapping READ and WRITE and UNLOCK with the same process (SERVER) */
282         /* Add different new lock types which completely overlaps any old lock in the list - 4,5,6 */
283                 {9,     WRLOCK, 10,             10,             PASS,           SERVER  }, 
284                 {9,     WRLOCK, 30,             10,             PASS,           SERVER  }, 
285                 {9,     WRLOCK, 50,             10,             PASS,           SERVER  }, 
286                 /* The start is the same, end overlaps */
287                 {9,     RDLOCK, 30,             15,             PASS,           SERVER  }, 
288                 /* The start is before, end is the same */
289                 {9,     WRLOCK, 25,             20,             PASS,           SERVER  }, 
290                 /* Both start and end overlap */
291                 {9,     RDLOCK, 22,             26,             PASS,           SERVER  }, 
292                 
293                 {9,     UNLOCK, 10,             10,             PASS,           SERVER  }, 
294                 {9,     UNLOCK, 22,             26,             PASS,           SERVER  }, 
295                 {9,     UNLOCK, 50,             10,             PASS,           SERVER  }, 
296                 
297         /* Add different new locks which are completely overlaped by an old lock in the list - 7,8,10 */
298                 {10,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
299                 {10,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
300                 {10,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
301                 /* The start is the same, end is in the middle of old lock */
302                 {10,    RDLOCK, 30,             5,              PASS,           SERVER  }, 
303                 /* The start and end are in the middle of a lock */
304                 {10,    WRLOCK, 32,             2,              PASS,           SERVER  }, 
305                 /* Start in the middle and end is the same */
306                 {10,    RDLOCK, 36,             5,              PASS,           SERVER  }, 
307                 
308                 {10,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
309                 {10,    UNLOCK, 30,             11,             PASS,           SERVER  }, 
310                 {10,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
311                 
312         /* Add different new lock types which start before the old lock in the list - 2,9 */
313                 {11,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
314                 {11,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
315                 {11,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
316                 /* Here is the new lock */
317                 {11,    RDLOCK, 27,             10,             PASS,           SERVER  }, 
318                 /* Go again with the end of the new lock matching the start of lock */
319                 {11,    WRLOCK, 25,             3,              PASS,           SERVER  }, 
320                 
321                 {11,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
322                 {11,    UNLOCK, 25,             15,             PASS,           SERVER  }, 
323                 {11,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
324         
325         /* Add different new lock types which start in the middle of an old lock in the list and end after - 11,12 */
326                 {12,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
327                 {12,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
328                 {12,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
329                 /* Here is the new lock */
330                 {12,    RDLOCK, 35,             10,             PASS,           SERVER  }, 
331                 /* Go again with the end of the new lock matching the start of old lock */
332                 {12,    WRLOCK, 44,             3,              PASS,           SERVER  }, 
333                 
334                 {12,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
335                 {12,    UNLOCK, 30,             18,             PASS,           SERVER  }, 
336                 {12,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
337
338 /* SECTION 3: Overlapping READ and WRITE and UNLOCK with the different processes (CLIENT/SERVER) */
339         /* Add new lock, differing types and processes, to middle of the list - exact overlap match - 3 */
340                 {13,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
341                 {13,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
342                 {13,    RDLOCK, 50,             10,             PASS,           SERVER  }, 
343                 /* Same lock type, different process */
344                 {13,    WRLOCK, 30,             10,             FAIL,           CLIENT  }, 
345                 {13,    RDLOCK, 50,             10,             PASS,           CLIENT  }, 
346                 /* Exact match - different lock type, different process */
347                 {13,    RDLOCK, 30,             10,             FAIL,           CLIENT  }, 
348                 /* Exact match - unlock */
349                 {13,    UNLOCK, 30,             10,             PASS,           CLIENT  }, 
350                 /* New lock - as above, inserting in the list again */
351                 {13,    UNLOCK, 30,             10,             PASS,           SERVER  }, 
352                 /* Exact match - same lock type, different process */
353                 {13,    WRLOCK, 30,             10,             PASS,           CLIENT  }, 
354                 
355                 {13,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
356                 {13,    UNLOCK, 30,             10,             PASS,           CLIENT  }, 
357                 {13,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
358                 
359         /* Add new lock, differing types and processes, which completely overlap any of the locks in the list - 4,5,6 */
360                 {14,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
361                 {14,    WRLOCK, 30,             10,             PASS,           SERVER  }, 
362                 {14,    RDLOCK, 50,             10,             PASS,           SERVER  }, 
363                 /* The start is the same, end overlaps */
364                 {14,    RDLOCK, 30,             15,             FAIL,           CLIENT  },
365                 {14,    WRLOCK, 30,             15,             FAIL,           CLIENT  }, 
366                 /* The start is before, end is the same */
367                 {14,    RDLOCK, 25,             20,             FAIL,           CLIENT  }, 
368                 {14,    WRLOCK, 25,             20,             FAIL,           CLIENT  }, 
369                 /* Both start and end overlap */
370                 {14,    RDLOCK, 22,             26,             FAIL,           CLIENT  }, 
371                 {14,    WRLOCK, 22,             26,             FAIL,           CLIENT  }, 
372                 
373                 /* The start is the same, end overlaps */
374                 {14,    RDLOCK, 50,             15,             PASS,           CLIENT  },
375                 {14,    WRLOCK, 50,             17,             FAIL,           CLIENT  }, 
376                 /* The start is before, end is the same */
377                 {14,    RDLOCK, 45,             20,             PASS,           CLIENT  }, 
378                 {14,    WRLOCK, 43,             22,             FAIL,           CLIENT  }, 
379                 /* Both start and end overlap */
380                 {14,    RDLOCK, 42,             26,             PASS,           CLIENT  }, 
381                 {14,    WRLOCK, 41,             28,             FAIL,           CLIENT  }, 
382                 
383                 {14,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
384                 {14,    UNLOCK, 22,             26,             PASS,           SERVER  }, 
385                 {14,    UNLOCK, 42,             26,             PASS,           CLIENT  }, 
386
387         /* Add new lock, differing types and processes, which are completely overlaped by an old lock in the list - 7,8,10 */
388                 {15,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
389                 {15,    RDLOCK, 30,             10,             PASS,           SERVER  }, 
390                 {15,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
391                 /* The start is the same, end is in the middle of old lock */
392                 {15,    RDLOCK, 50,             5,              FAIL,           CLIENT  }, 
393                 {15,    WRLOCK, 50,             5,              FAIL,           CLIENT  }, 
394                 /* The start and end are in the middle of old lock */
395                 {15,    RDLOCK, 52,             6,              FAIL,           CLIENT  }, 
396                 {15,    WRLOCK, 52,             6,              FAIL,           CLIENT  }, 
397                 /* Start in the middle and end is the same */
398                 {15,    RDLOCK, 52,             8,              FAIL,           CLIENT  }, 
399                 {15,    WRLOCK, 52,             8,              FAIL,           CLIENT  }, 
400                 /* The start is the same, end is in the middle of old lock */
401                 {15,    RDLOCK, 30,             5,              PASS,           CLIENT  }, 
402                 {15,    WRLOCK, 30,             5,              FAIL,           CLIENT  }, 
403                 /* The start and end are in the middle of old lock */
404                 {15,    RDLOCK, 32,             6,              PASS,           CLIENT  }, 
405                 {15,    WRLOCK, 32,             6,              FAIL,           CLIENT  }, 
406                 /* Start in the middle and end is the same */
407                 {15,    RDLOCK, 32,             8,              PASS,           CLIENT  }, 
408                 {15,    WRLOCK, 32,             8,              FAIL,           CLIENT  }, 
409                 
410                 {15,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
411                 {15,    UNLOCK, 30,             10,             PASS,           SERVER  }, 
412                 {15,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
413         /* Add new lock, differing types and processes, which start before a lock in the list - 2,9 */
414                 {16,    RDLOCK, 10,             10,             PASS,           SERVER  }, 
415                 {16,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
416                 /* Start is before, end is the start of the old lock in list */
417                 {16,    RDLOCK, 5,              6,              PASS,           CLIENT  }, 
418                 {16,    WRLOCK, 5,              6,              FAIL,           CLIENT  }, 
419                 /* Start is before, end is in the middle of the old lock */
420                 {16,    RDLOCK, 5,              10,             PASS,           CLIENT  }, 
421                 {16,    WRLOCK, 5,              10,             FAIL,           CLIENT  }, 
422                 /* Start is before, end is the start of the old lock in list */
423                 {16,    RDLOCK, 45,             6,              FAIL,           CLIENT  }, 
424                 {16,    WRLOCK, 45,             6,              FAIL,           CLIENT  }, 
425                 /* Start is before, end is in the middle of the old lock */
426                 {16,    RDLOCK, 45,             10,             FAIL,           CLIENT  }, 
427                 {16,    WRLOCK, 45,             10,             FAIL,           CLIENT  }, 
428                 
429                 {16,    UNLOCK, 5,              15,             PASS,           CLIENT  }, 
430                 {16,    UNLOCK, 30,             10,             PASS,           SERVER  }, 
431                 {16,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
432
433         /* Add new lock, differing types and processes, which starts in the middle of a lock, and ends after - 11,12 */
434                 {17,    WRLOCK, 10,             10,             PASS,           SERVER  }, 
435                 {17,    RDLOCK, 30,             10,             PASS,           SERVER  }, 
436                 {17,    WRLOCK, 50,             10,             PASS,           SERVER  }, 
437                 /* Start in the middle, end after lock in list */
438                 {17,    WRLOCK, 35,             10,             FAIL,           CLIENT  }, 
439                 /* Start matches end of lock in list  */
440                 {17,    RDLOCK, 35,             10,             PASS,           CLIENT  }, 
441                 {17,    RDLOCK, 44,             2,              PASS,           CLIENT  }, 
442                 /* Start in the middle, end after lock in list */
443                 {17,    RDLOCK, 55,             10,             FAIL,           CLIENT  }, 
444                 {17,    WRLOCK, 55,             10,             FAIL,           CLIENT  }, 
445                 /* Start matches end of lock in list  */
446                 {17,    RDLOCK, 59,             5,              FAIL,           CLIENT  }, 
447                 {17,    WRLOCK, 59,             5,              FAIL,           CLIENT  }, 
448                 
449                 {17,    UNLOCK, 10,             10,             PASS,           SERVER  }, 
450                 {17,    UNLOCK, 30,             16,             PASS,           CLIENT  }, 
451                 {17,    UNLOCK, 50,             10,             PASS,           SERVER  }, 
452
453 /* SECTION 4: overlapping and EOF tests */
454         /* Acquire overlapping ranges */
455                 {18,    WRLOCK, 11,             7,              PASS,           SERVER  },
456                 {18,    WRLOCK, 13,             8,              FAIL,           CLIENT  },
457                 {18,    UNLOCK, 11,             7,              PASS,           SERVER  },
458         /* Acquire different ranges beyond EOF */
459                 {19,    WRLOCK, 10,             FILE_SIZE,      PASS,           SERVER  },
460                 {19,    WRLOCK, FILE_SIZE + 10, 10,             PASS,           CLIENT  },
461                 {19,    UNLOCK, 10,             FILE_SIZE,      PASS,           SERVER  },
462                 {19,    UNLOCK, FILE_SIZE + 10, 10,             PASS,           CLIENT  },
463         /* Acquire same range beyong EOF */
464                 {20,    WRLOCK, 10,             FILE_SIZE,      PASS,           SERVER, },
465                 {20,    WRLOCK, 10,             FILE_SIZE,      FAIL,           CLIENT, },
466                 {20,    UNLOCK, 10,             FILE_SIZE,      PASS,           SERVER, },
467         /* Acquire whole file lock */
468                 {21,    WRLOCK, 0,              0,              PASS,           SERVER, },
469                 {21,    WRLOCK, 0,              0,              FAIL,           CLIENT, },
470                 {21,    UNLOCK, 0,              0,              PASS,           SERVER, },
471         /* Acquire whole file lock, then range */
472                 {22,    WRLOCK, 0,              0,              PASS,           SERVER, },
473                 {22,    WRLOCK, 1,              5,              FAIL,           CLIENT, },
474                 {22,    UNLOCK, 0,              0,              PASS,           SERVER, },
475         /* Acquire non-overlapping read locks */
476                 {23,    RDLOCK, 1,              5,              PASS,           SERVER, },
477                 {23,    RDLOCK, 7,              6,              PASS,           CLIENT, },
478                 {23,    UNLOCK, 1,              5,              PASS,           SERVER, },
479                 {23,    UNLOCK, 7,              6,              PASS,           CLIENT, },
480         /* Acquire overlapping read locks */
481                 {24,    RDLOCK, 1,              5,              PASS,           SERVER, },
482                 {24,    RDLOCK, 2,              6,              PASS,           CLIENT, },
483                 {24,    UNLOCK, 1,              5,              PASS,           SERVER, },
484                 {24,    UNLOCK, 1,              7,              PASS,           CLIENT, },
485         /* Acquire non-overlapping read and write locks */
486                 {25,    RDLOCK, 1,              5,              PASS,           SERVER, },
487                 {25,    WRLOCK, 7,              6,              PASS,           CLIENT, },
488                 {25,    UNLOCK, 1,              5,              PASS,           SERVER, },
489                 {25,    UNLOCK, 7,              6,              PASS,           CLIENT, },
490         /* Acquire overlapping read and write locks */
491                 {26,    RDLOCK, 1,              5,              PASS,           SERVER, },
492                 {26,    WRLOCK, 2,              6,              FAIL,           CLIENT, },
493                 {26,    UNLOCK, 1,              5,              PASS,           SERVER, },
494         /* Acquire whole file lock, then close (without unlocking) */
495                 {27,    WRLOCK, 0,              0,              PASS,           SERVER, },
496                 {27,    WRLOCK, 1,              5,              FAIL,           CLIENT, },
497                 {27,    F_CLOSE,0,              0,              PASS,           SERVER, },
498                 {27,    WRLOCK, 1,              5,              PASS,           CLIENT, },
499                 {27,    F_OPEN, O_RDWR,         0,              PASS,           SERVER, },
500                 {27,    UNLOCK, 1,              5,              PASS,           CLIENT, },
501         /* Acquire two read locks, close one file and then reopen to check that first lock still exists */
502                 {28,    RDLOCK, 1,              5,              PASS,           SERVER, },
503                 {28,    RDLOCK, 1,              5,              PASS,           CLIENT, },
504                 {28,    F_CLOSE,0,              0,              PASS,           SERVER, },
505                 {28,    F_OPEN, O_RDWR,         0,              PASS,           SERVER, },
506                 {28,    WRLOCK, 0,              0,              FAIL,           SERVER, },
507                 {28,    UNLOCK, 1,              5,              PASS,           SERVER, },
508         /* Verify that F_GETLK for F_WRLCK doesn't require that file be opened for write */
509                 {29,    F_CLOSE, 0,             0,              PASS,           SERVER, },
510                 {29,    F_OPEN, O_RDONLY,       0,              PASS,           SERVER, },
511                 {29,    WRTEST, 0,              0,              PASS,           SERVER, },
512                 {29,    F_CLOSE,0,              0,              PASS,           SERVER, },
513                 {29,    F_OPEN, O_RDWR,         0,              PASS,           SERVER, },
514 #ifdef macosx
515         /* Close the opened file and open the file with SHLOCK, other client will try to open with SHLOCK too */
516                 {30,    F_CLOSE,0,              0,              PASS,           SERVER, },
517                 {30,    F_OPEN, O_RDWR|O_SHLOCK|O_NONBLOCK,     0,      PASS,           SERVER, },
518                 {30,    F_CLOSE,0,              0,              PASS,           CLIENT, },
519                 {30,    F_OPEN, O_RDWR|O_SHLOCK|O_NONBLOCK,     0,      PASS,           CLIENT, },
520         /* Close the opened file and open the file with SHLOCK, other client will try to open with EXLOCK */
521                 {31,    F_CLOSE,0,              0,              PASS,           SERVER, },
522                 {31,    F_CLOSE,0,              0,              PASS,           CLIENT, },
523                 {31,    F_OPEN, O_RDWR|O_SHLOCK|O_NONBLOCK,     0,      PASS,           SERVER, },
524                 {31,    F_OPEN, O_RDWR|O_EXLOCK|O_NONBLOCK,     0,      FAIL,           CLIENT, },
525         /* Close the opened file and open the file with EXLOCK, other client will try to open with EXLOCK too */
526                 {32,    F_CLOSE,0,              0,              PASS,           SERVER, },
527                 {32,    F_CLOSE,0,              0,              FAIL,           CLIENT, },
528                 {32,    F_OPEN, O_RDWR|O_EXLOCK|O_NONBLOCK,     0,      PASS,           SERVER, },
529                 {32,    F_OPEN, O_RDWR|O_EXLOCK|O_NONBLOCK,     0,      FAIL,           CLIENT, },
530                 {32,    F_CLOSE,0,              0,              PASS,           SERVER, },
531                 {32,    F_CLOSE,0,              0,              FAIL,           CLIENT, },
532                 {32,    F_OPEN, O_RDWR,         0,              PASS,           SERVER, },
533                 {32,    F_OPEN, O_RDWR,         0,              PASS,           CLIENT, },
534 #endif /* macosx */
535         /* indicate end of array */
536                 {0,0,0,0,0,SERVER},
537                 {0,0,0,0,0,CLIENT}
538         };
539
540 static struct {
541     int32_t             test;
542     int32_t             command;
543     int64_t             offset;
544     int64_t             length;
545     int32_t             result;
546     int32_t             index;
547     int32_t             error;
548     int32_t             padding; /* So mac and irix have the same size struct (bloody alignment) */
549 } ctl;
550
551
552 void
553 usage(void)
554 {
555     fprintf(stderr, "Usage: %s [options] sharedfile\n\
556 \n\
557 options:\n\
558   -p port       TCP/IP port number for client-server communication\n\
559   -d            enable debug tracing\n\
560   -n #          test number to run\n\
561   -h host       run as client and connect to server on remote host\n\
562                 [default run as server]\n", prog);
563     exit(1);
564 }
565
566 #define INIT_BUFSZ 512 
567
568 void
569 initialize(HANDLE fd)
570 {
571     char*       ibuf;
572     int         j=0;
573     int         nwrite;
574     int         offset = 0;
575     int         togo = FILE_SIZE;
576
577     ibuf = (char*)malloc(INIT_BUFSZ);
578     memset(ibuf, ':', INIT_BUFSZ);
579
580     SEEK(fd, 0L);
581     while (togo) {
582         offset+=j;
583         j = togo > INIT_BUFSZ ? INIT_BUFSZ : togo;
584
585         if ((nwrite = WRITE(fd, ibuf, j)) != j) {
586             if (nwrite < 0)
587                 perror("initialize write:");
588             else
589                 fprintf(stderr, "initialize: write() returns %d, not %d as expected\n", 
590                         nwrite, j);
591             exit(1);
592             /*NOTREACHED*/
593         }
594         togo -= j;
595     }
596 }
597
598
599 int do_open(int flag)
600 {
601     if ((f_fd = OPEN(filename, flag)) == INVALID_HANDLE) {
602         perror("shared file create");
603         return FAIL;
604         /*NOTREACHED*/
605     }
606
607     return PASS;
608 }
609
610 static int do_lock(int cmd, int type, int start, int length)
611 {
612     int ret;
613     int filedes = f_fd;
614     struct flock fl;
615
616     if(debug > 1) {
617         fprintf(stderr, "do_lock: cmd=%d type=%d start=%d, length=%d\n", cmd, type, start, length);
618     }
619
620     if (f_fd < 0)
621         return f_fd;
622     
623     fl.l_start = start;
624     fl.l_len = length;
625     fl.l_whence = SEEK_SET;
626     fl.l_pid = getpid();
627     fl.l_type = type;
628
629     errno = 0;
630
631     ret = fcntl(filedes, cmd, &fl);
632     saved_errno = errno;            
633
634     if(debug > 1 && ret)
635         fprintf(stderr, "do_lock: ret = %d, errno = %d (%s)\n", ret, errno, strerror(errno));
636
637     return(ret==0?PASS:FAIL);
638 }
639
640 int do_close(void)
641 {       
642     if(debug > 1) {
643         fprintf(stderr, "do_close\n");
644     }
645
646     errno =0;
647     CLOSE(f_fd);
648     f_fd = INVALID_HANDLE;
649
650     saved_errno = errno;            
651         
652     if (errno)
653         return FAIL;
654     return PASS;
655 }
656
657 void
658 send_ctl(void)
659 {
660     int         nwrite;
661
662     if (debug > 1) {
663         fprintf(stderr, "send_ctl: test=%d, command=%d offset=%"LL"d, length=%"LL"d, result=%d, error=%d\n", 
664                 ctl.test, ctl.command, (long long)ctl.offset, (long long)ctl.length,ctl.result, ctl.error);
665     }
666
667     ctl.test= bswap_uint32(ctl.test);
668     ctl.command = bswap_uint32(ctl.command);
669     ctl.offset = bswap_uint64(ctl.offset);
670     ctl.length = bswap_uint64(ctl.length);
671     ctl.result = bswap_uint32(ctl.result);
672     ctl.index= bswap_uint32(ctl.index);
673     ctl.error = bswap_uint32(ctl.error);
674     nwrite = SOCKET_WRITE(c_fd, (char*)&ctl, sizeof(ctl));
675
676     ctl.test= bswap_uint32(ctl.test);
677     ctl.command = bswap_uint32(ctl.command);
678     ctl.offset = bswap_uint64(ctl.offset);
679     ctl.length = bswap_uint64(ctl.length);
680     ctl.result = bswap_uint32(ctl.result);
681     ctl.index= bswap_uint32(ctl.index);
682     ctl.error= bswap_uint32(ctl.error);
683     if (nwrite != sizeof(ctl)) {
684         if (nwrite < 0)
685             perror("send_ctl: write");
686         else
687             fprintf(stderr, "send_ctl[%d]: write() returns %d, not %zu as expected\n", 
688                     ctl.test, nwrite, sizeof(ctl));
689         exit(1);
690         /*NOTREACHED*/
691     }
692 }
693
694 void recv_ctl(void)
695 {
696     int         nread;
697
698     if ((nread = SOCKET_READ(c_fd, (char*)&ctl, sizeof(ctl))) != sizeof(ctl)) {
699         if (nread < 0)
700             perror("recv_ctl: read");
701         else {
702             fprintf(stderr, "recv_ctl[%d]: read() returns %d, not %zu as expected\n", 
703                     ctl.test, nread, sizeof(ctl));
704             fprintf(stderr, "socket might has been closed by other locktest\n");
705         } 
706         exit(1);
707         /*NOTREACHED*/
708     }
709     ctl.test= bswap_uint32(ctl.test);
710     ctl.command = bswap_uint32(ctl.command);
711     ctl.offset = bswap_uint64(ctl.offset);
712     ctl.length = bswap_uint64(ctl.length);
713     ctl.result = bswap_uint32(ctl.result);
714     ctl.index= bswap_uint32(ctl.index);
715     ctl.error= bswap_uint32(ctl.error);
716
717     if (debug > 1) {
718         fprintf(stderr, "recv_ctl: test=%d, command=%d offset=%"LL"d, length=%"LL"d, result=%d, error=%d\n", 
719                 ctl.test, ctl.command, (long long)ctl.offset, (long long)ctl.length, ctl.result, ctl.error);
720     }
721 }
722
723 void
724 cleanup(void)
725 {
726     if (f_fd>=0)
727         CLOSE(f_fd);
728     
729     if (c_fd>=0)
730         SOCKET_CLOSE(c_fd);
731     
732     if (s_fd>=0)
733         SOCKET_CLOSE(s_fd);
734     
735     PLATFORM_CLEANUP();
736 }
737
738 int
739 main(int argc, char *argv[])
740 {
741     int         i, sts;
742     int         c;
743     struct sockaddr_in  myAddr;
744     struct linger       noLinger = {1, 0};
745     char        *host = NULL;
746     char        *endnum;
747     int         errflag = 0;
748     char        *p;
749     extern char *optarg;
750     extern int  optind;
751     int fail_count = 0;; 
752     
753     atexit(cleanup);
754     
755     PLATFORM_INIT();
756
757     /* trim command name of leading directory components */
758     prog = argv[0];
759     for (p = prog; *p; p++) {
760         if (*p == '/')
761             prog = p+1;
762     }
763
764     while ((c = getopt(argc, argv, "dn:h:p:?")) != EOF) {
765         switch (c) {
766
767         case 'd':       /* debug flag */
768             debug++;
769             break;
770
771         case 'h':       /* (server) hostname */
772             server = 0;
773             host = optarg;
774             break;
775
776         case 'n':
777             testnumber = atoi(optarg);
778             break;
779
780         case 'p':       /* TCP/IP port */
781             port = (int)strtol(optarg, &endnum, 10);
782             if (*endnum != '\0') {
783                 fprintf(stderr, "%s: -p argument must be a numeric\n", 
784                         prog);
785                 exit(1);
786                 /*NOTREACHED*/
787             }
788             break;
789
790         case '?':
791         default:
792             errflag++;
793             break;
794         }
795     }
796
797     if (errflag || optind != argc-1) {
798         usage();
799         /*NOTREACHED*/
800     }
801
802     filename=argv[optind];
803     if (do_open(O_RDWR) == FAIL)
804         exit(1);
805
806     setbuf(stderr, NULL);
807
808     if (server) {
809         int one = 1;
810         
811         s_fd = socket(AF_INET, SOCK_STREAM, 0);
812         if (s_fd == INVALID_SOCKET) {
813             perror("socket");
814             exit(1);
815             /*NOTREACHED*/
816         }
817         if (setsockopt(s_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) < 0) {
818             perror("setsockopt(nodelay)");
819             exit(1);
820             /*NOTREACHED*/
821         }
822         if (setsockopt(s_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one))<0) {
823             perror("setsockopt(reuseaddr)");
824             exit(1);
825             /*NOTREACHED*/
826         }
827 #ifdef SO_REUSEPORT
828         if (setsockopt(s_fd, SOL_SOCKET, SO_REUSEPORT, (char*)&one, sizeof(one))<0) {
829             perror("setsockopt(reuseport)");
830             exit(1);
831             /*NOTREACHED*/
832         }
833 #endif
834
835         memset(&myAddr, 0, sizeof(myAddr));
836         myAddr.sin_family = AF_INET;
837         myAddr.sin_addr.s_addr = htonl(INADDR_ANY);
838         myAddr.sin_port = htons((short)port);
839         sts = bind(s_fd, (struct sockaddr*)&myAddr, sizeof(myAddr));
840         if (sts < 0) {
841             perror("bind");
842             exit(1);
843             /*NOTREACHED*/
844         }
845
846         sts = listen(s_fd, 5);  /* Max. of 5 pending connection requests */
847         if (sts == -1) {
848             perror("listen");
849             exit(1);
850             /*NOTREACHED*/
851         }
852
853         if (port == 0) {
854                 socklen_t addr_len = sizeof(myAddr);
855
856                 if (getsockname(s_fd, &myAddr, &addr_len)) {
857                     perror("getsockname");
858                     exit(1);
859                 }
860
861                 port = ntohs(myAddr.sin_port);
862         }
863
864         printf("server port: %d\n", port);
865         fflush(stdout);
866
867         c_fd = accept(s_fd, NULL, NULL);
868         if (c_fd == INVALID_SOCKET) {
869             perror("accept");
870             exit(1);
871             /*NOTREACHED*/
872         }
873
874         if (debug) fprintf(stderr, "Client accepted\n");
875         SRAND(12345L);
876     }
877     else {
878         struct hostent  *servInfo;
879
880         if ((servInfo = gethostbyname(host)) == NULL) {
881             printf("Couldn't get hostbyname for %s", host);
882             if (h_errno == HOST_NOT_FOUND)
883                 printf(": host not found");
884             printf("\n");
885             exit(1);
886             /*NOTREACHED*/
887         }
888
889         c_fd = socket(AF_INET, SOCK_STREAM, 0);
890         if (c_fd == INVALID_SOCKET) {
891             perror("socket");
892             exit(1);
893             /*NOTREACHED*/
894         }
895         /* avoid 200 ms delay */
896         if (setsockopt(c_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)) < 0) {
897             perror("setsockopt(nodelay)");
898             exit(1);
899             /*NOTREACHED*/
900         }
901         /* Don't linger on close */
902         if (setsockopt(c_fd, SOL_SOCKET, SO_LINGER, (char *)&noLinger, sizeof(noLinger)) < 0) {
903             perror("setsockopt(nolinger)");
904             exit(1);
905             /*NOTREACHED*/
906         }
907
908         memset(&myAddr, 0, sizeof(myAddr));     /* Arrgh! &myAddr, not myAddr */
909         myAddr.sin_family = AF_INET;
910         memcpy(&myAddr.sin_addr, servInfo->h_addr, servInfo->h_length);
911         myAddr.sin_port = htons((short)port);
912
913         if (connect(c_fd, (struct sockaddr*)&myAddr, sizeof(myAddr)) < 0) {
914             perror("unable to connect");
915             fprintf(stderr, "Server might still initializing the shared file\n ");
916             exit(1);
917             /*NOTREACHED*/
918         }
919
920         if (debug) fprintf(stderr, "Connected to server\n");
921         SRAND(6789L);
922     }
923
924     if (server)
925         /* only server need do shared file */
926         initialize(f_fd);
927
928     /*
929      * TCP/IP connection to be established, safe to proceed.
930      *
931      * real work is in here ...
932      */
933     i = 0;
934 {
935     int index = 0;
936     int end = 0;
937     int result = 0;
938     int last_test = 0;
939     int test_count = 0;
940     int fail_flag = 0;
941     while(!end) {
942         if (server) {
943             if(testnumber > 0) {
944                 last_test = testnumber - 1;
945                 while(tests[index][TEST_NUM] != testnumber && tests[index][TEST_NUM] != 0) {
946                     index++;
947                 }
948             }
949             /* If we have a server command, deal with it */
950             if(tests[index][WHO] == SERVER) {
951                 if(debug>1)
952                     fprintf(stderr, "Got a server command (%d)\n", index);
953                 if(tests[index][TEST_NUM] == 0) {
954                     index++;
955                     continue;
956                 } 
957                 memset(&ctl, 0, sizeof(ctl));
958                 ctl.test = tests[index][TEST_NUM];
959
960                 if(tests[index][TEST_NUM] != 0) {
961                     switch(tests[index][COMMAND]) {
962                         case WRLOCK:
963                             result = do_lock(F_SETLK, F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
964                             break;
965                         case RDLOCK:
966                             result = do_lock(F_SETLK, F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
967                             break;
968                         case UNLOCK:
969                             result = do_lock(F_SETLK, F_UNLCK, tests[index][OFFSET], tests[index][LENGTH]);
970                             break;
971                         case F_CLOSE:
972                             result = do_close();
973                             break;
974                         case F_OPEN:
975                             result = do_open(tests[index][FLAGS]);
976                             break;
977                         case WRTEST:
978                             result = do_lock(F_GETLK, F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
979                             break;
980                         case RDTEST:
981                             result = do_lock(F_GETLK, F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
982                             break;
983                     }
984                     if( result != tests[index][RESULT]) {
985                         fail_flag++;
986                         /* We have a failure */
987                         if(debug)
988                             fprintf(stderr, "Server failure in test %d, while %sing using offset %lld, length %lld - err = %d:%s\n", 
989                                         ctl.test, tests[index][COMMAND]==WRLOCK?"write lock":
990                                                 tests[index][COMMAND]==RDLOCK?"read lock":
991                                                 tests[index][COMMAND]==UNLOCK?"unlock":
992                                                 tests[index][COMMAND]==F_OPEN?"open":"clos", 
993                                                 (long long)tests[index][OFFSET],
994                                                 (long long)tests[index][LENGTH],
995                                                 saved_errno, strerror(saved_errno));
996                         fprintf(stderr, "Server failure in %lld:%s\n",
997                                         (long long)tests[index][TEST_NUM],
998                                         descriptions[tests[index][TEST_NUM] - 1]);
999                     }
1000                 }
1001             /* else send it off to the client */
1002             } else if (tests[index][WHO] == CLIENT) {
1003                 if(tests[index][TEST_NUM] == 0) {
1004                     ctl.test = 0;
1005                     end=1;
1006                 } 
1007                 if(debug > 1)
1008                     fprintf(stderr, "Sending command to client (%d) - %s - %lld:%lld\n", 
1009                                         index, tests[index][COMMAND]==WRLOCK?"write lock":
1010                                         tests[index][COMMAND]==RDLOCK?"read lock":
1011                                         tests[index][COMMAND]==UNLOCK?"unlock": 
1012                                         tests[index][COMMAND]==F_OPEN?"open":"clos", 
1013                                         (long long)tests[index][OFFSET],
1014                                         (long long)tests[index][LENGTH]);
1015                 /* get the client to do something */
1016                 ctl.index = index;
1017                 send_ctl();
1018                 if(ctl.test != 0) {
1019                     /* Get the clients response */
1020                     recv_ctl();
1021                     /* this is the whether the test passed or failed,
1022                      * not what the command returned */
1023                     if( ctl.result == FAIL ) {
1024                         fail_flag++;
1025                         if(debug)
1026                             fprintf(stderr, "Client failure in test %d, while %sing using offset %lld, length %lld - err = %d:%s\n",
1027                                         ctl.test, ctl.command==WRLOCK?"write lock":
1028                                         ctl.command==RDLOCK?"read lock":
1029                                         ctl.command==UNLOCK?"unlock":
1030                                         ctl.command==F_OPEN?"open":"clos",
1031                                         (long long)ctl.offset, (long long)ctl.length,
1032                                         ctl.error, strerror(ctl.error));
1033                         fprintf(stderr, "Client failure in %lld:%s\n",
1034                                         (long long)tests[index][TEST_NUM],
1035                                         descriptions[tests[index][TEST_NUM] - 1]);
1036                     }
1037                 }
1038             }
1039             if(tests[index][TEST_NUM] != 0) {
1040                 if(last_test != tests[index][TEST_NUM]) {
1041                     test_count++;
1042                     if(fail_flag)
1043                         fail_count++;
1044                     fail_flag = 0;
1045
1046                 }
1047                 last_test = tests[index][TEST_NUM];
1048             }
1049                 
1050             index++;
1051         } else { /* CLIENT */
1052             if(debug > 2)
1053                 fprintf(stderr,"client: waiting...\n");
1054             /* wait for the server to do something */
1055             recv_ctl();
1056
1057             /* check for a client command */
1058             index = ctl.index;
1059             if (tests[index][WHO] != CLIENT) { 
1060                 fprintf(stderr, "not a client command index (%d)\n", index);
1061                 exit(1);
1062             }
1063                 
1064             if(ctl.test == 0) {
1065                 end = 1;
1066                 break;
1067             }
1068                 
1069
1070             ctl.command = tests[index][COMMAND];
1071             ctl.offset = tests[index][OFFSET];
1072             ctl.length = tests[index][LENGTH];
1073             switch(tests[index][COMMAND]) {
1074                 case WRLOCK:
1075                     result = do_lock(F_SETLK, F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
1076                     break;
1077                 case RDLOCK:
1078                     result = do_lock(F_SETLK, F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
1079                     break;
1080                 case UNLOCK:
1081                     result = do_lock(F_SETLK, F_UNLCK, tests[index][OFFSET], tests[index][LENGTH]);
1082                     break;
1083                 case F_CLOSE:
1084                     result = do_close();
1085                     break;
1086                 case F_OPEN:
1087                     result = do_open(tests[index][FLAGS]);
1088                     break;
1089                 case WRTEST:
1090                     result = do_lock(F_GETLK, F_WRLCK, tests[index][OFFSET], tests[index][LENGTH]);
1091                     break;
1092                 case RDTEST:
1093                     result = do_lock(F_GETLK, F_RDLCK, tests[index][OFFSET], tests[index][LENGTH]);
1094                     break;
1095             }
1096             if( result != tests[index][RESULT] ) {
1097                 if(debug)
1098                     fprintf(stderr,"Got %d, wanted %lld\n", result,
1099                                         (long long)tests[index][RESULT]);
1100                 ctl.result = FAIL;
1101                 ctl.error = saved_errno;
1102                 fail_count++;
1103             } else {
1104                 ctl.result = PASS;
1105             }
1106             if(debug > 2)
1107                 fprintf(stderr,"client: sending result to server (%d)\n", ctl.index);
1108             /* Send result to the server */
1109             send_ctl();
1110             if(tests[index][TEST_NUM] != 0) {
1111                 if(last_test != tests[index][TEST_NUM])
1112                     test_count++;
1113                 last_test = tests[index][TEST_NUM];
1114             }
1115         }
1116     }
1117     if(server)
1118         printf("%d tests run, %d failed\n", test_count, fail_count);
1119 }   
1120     
1121     exit(fail_count);
1122     /*NOTREACHED*/
1123 }
1124
1125