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