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