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