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