Add proper per-file copyright notices/licenses and top-level license.
[bluesky.git] / TBBT / trace_play / sfs_3_vld.c
1 #ifndef lint
2 static char sfs_3_vldSid[] = "@(#)sfs_3_vld.c   2.1     97/10/23";
3 #endif
4
5 /*
6  *   Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
7  *      All rights reserved.
8  *              Standard Performance Evaluation Corporation (SPEC)
9  *              6585 Merchant Place, Suite 100
10  *              Warrenton, VA 20187
11  *
12  *      This product contains benchmarks acquired from several sources who
13  *      understand and agree with SPEC's goal of creating fair and objective
14  *      benchmarks to measure computer performance.
15  *
16  *      This copyright notice is placed here only to protect SPEC in the
17  *      event the source is misused in any manner that is contrary to the
18  *      spirit, the goals and the intent of SPEC.
19  *
20  *      The source code is provided to the user or company under the license
21  *      agreement for the SPEC Benchmark Suite for this product.
22  */
23
24 /*****************************************************************
25  *                                                               *
26  *      Copyright 1991,1992  Legato Systems, Inc.                *
27  *      Copyright 1991,1992  Auspex Systems, Inc.                *
28  *      Copyright 1991,1992  Data General Corporation            *
29  *      Copyright 1991,1992  Digital Equipment Corporation       *
30  *      Copyright 1991,1992  Interphase Corporation              *
31  *      Copyright 1991,1992  Sun Microsystems, Inc.              *
32  *                                                               *
33  *****************************************************************/
34
35 /*
36  * ------------------------------ sfs_3_vld.c ---------------------------
37  *
38  * Validation suite for sfs.
39  *
40  *.Exported_routines
41  *      void Validate_ops(int, char **)
42  *
43  *.Local_routines
44  *      void validate_init_rpc()
45  *      void validate_creation(void)
46  *      void validate_attributes(void)
47  *      void validate_read_write(void)
48  *      void validate_rename(void)
49  *      int compare_sattr(char *, char *, sattr3 *, fattr3 *)
50  *      int compare_fattr(char *, char *, fattr3 *, fattr3 *)
51  *      uint16_t sum(unsigned char *, int)
52  *      void validate_remove(void)
53  *      void validate_cleanup(void)
54  *      void validate_exit(void)
55  *      void verror(int, ValMsgType, char *, ...)
56  *
57  *.Revision History
58  *      11-Jul-94       ChakChung Ng    Created
59  */
60
61
62 /*
63  * -------------------------  Include Files  -------------------------
64  */
65
66 /*
67  * ANSI C headers
68  */
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <string.h>
72 #include <errno.h>
73 #include <stdarg.h>
74  
75 #include <unistd.h>
76
77 #include <sys/types.h>
78 #include <sys/stat.h>
79
80 #include "sfs_c_def.h"
81
82 extern struct hostent   *Server_hostent;
83
84 /*
85  * -----------------------  External Definitions  -----------------------
86  */
87
88 /* forward definitions for local routines */
89 /*
90  * validate options
91  * BATCH        - do complete pass of validation, reporting errors if any
92  * VERBOSE      - prints step-by-step validation actions being performed
93  * INTERACTIVE  - VERBOSE and if any errors encountered, ask to continue
94  *                validation or not.
95  */
96 #define VAL_BATCH       1
97 #define VAL_VERBOSE     2
98 #define VAL_INTERACTIVE 3
99
100 typedef enum {
101         I = 1,
102         W = 2,
103         E = 3
104 } ValMsgType;
105
106 #define NUMREGFILES     21
107 #define NUMDIRS         10
108 #define NUMLINKS        10
109 #define NUMSYMLINKS     10
110 #define NUMFILES        NUMREGFILES + NUMDIRS + NUMLINKS + NUMSYMLINKS
111 #define NUMFRAGS        8
112
113 static void val_op_null(void);
114 static void val_op_getattr(GETATTR3args *, GETATTR3res *);
115 static void val_op_setattr(SETATTR3args *, SETATTR3res *);
116 static void val_op_lookup(LOOKUP3args *, LOOKUP3res *);
117 static void val_op_access(ACCESS3args *, ACCESS3res *);
118 static void val_op_readlink(READLINK3args *, READLINK3res *);
119 static void val_op_read(READ3args *, READ3res *);
120 static void val_op_write(WRITE3args *, WRITE3res *);
121 static void val_op_create(CREATE3args *, CREATE3res *);
122 static void val_op_mkdir(MKDIR3args *, MKDIR3res *);
123 static void val_op_symlink(SYMLINK3args *, SYMLINK3res *);
124 static void val_op_mknod(MKNOD3args *, MKNOD3res *);
125 static void val_op_remove(REMOVE3args *, REMOVE3res *);
126 static void val_op_rmdir(RMDIR3args *, RMDIR3res *);
127 static void val_op_rename(RENAME3args *, RENAME3res *);
128 static void val_op_link(LINK3args *, LINK3res *);
129 static void val_op_readdir(READDIR3args *, READDIR3res *);
130 static void val_op_readdirplus(READDIRPLUS3args *, READDIRPLUS3res *);
131 static void val_op_fsstat(FSSTAT3args *, FSSTAT3res *);
132 static void val_op_fsinfo(FSINFO3args *, FSINFO3res *);
133 static void val_op_pathconf(PATHCONF3args *, PATHCONF3res *);
134 static void val_op_commit(COMMIT3args *, COMMIT3res *);
135
136 static void validate_init_rpc(void);
137 static void validate_exit(void);
138 static void validate_creation(void);
139 static void validate_attributes(void);
140 static void validate_read_write(void);
141 static void validate_rename(void);
142 static void validate_remove(void);
143 static void validate_cleanup(void);
144 static int compare_sattr(char *, char *, sattr3 *, fattr3 *);
145 static int compare_fattr(char *, char *, fattr3 *, fattr3 *);
146 static uint16_t sum(unsigned char *, int);
147 static void verror(int, ValMsgType, char *, ...);
148 static void create_3tmp_handles(void);
149 static void delete_3tmp_handles(void);
150
151 /*
152  * ----------------------  Static Declarations ----------------------
153  */
154
155 int Validate;
156
157 static int Validate_errors = 0;
158 static char Testdirname[SFS_MAXPATHLEN];    /* test dir component name */
159 /*
160  * packed structure to keep track of file status
161  */
162 struct sfs_fileinfo {
163     int file_found:1,   /* file has been found */
164         file_is_dup:1,  /* file has a duplicate */
165         pad:30;         /* pad the rest */
166 };
167
168 typedef struct sfs_fileinfo sfs_fileinfo;
169 /*
170  * This vector is used for readdirplus validation currently, but could be
171  * extended to keep track of other interesting pieces of information.
172  */
173 static sfs_fileinfo check_files[NUMFILES];
174
175 /*
176  * ----------------------  SFS Validation Suite  ----------------------
177  */
178
179 /*
180  * XXXXX Must make sure that we validate that all servers return back
181  * XXXXX All optional values
182  */
183 void
184 Validate_ops(
185     int         argc,
186     char *      argv[])
187 {
188     char *      valdir;
189     CLIENT *    mount_client_ptr;
190     int i;
191
192     if (argc > 1) {
193         verror(VAL_BATCH, E, "Can only validate one directory at a time.\n");
194         exit(1);
195     }
196
197     Num_io_files = NUMFILES;
198     Cur_uid = Real_uid;
199     nfs_version = NFS_V3;
200
201     if (argc == 0)
202         valdir = ".";
203     else
204         valdir = argv++[0];
205
206     (void) sprintf(Testdirname, "%s/validatedir", valdir);
207
208     do {
209         verror(VAL_BATCH, I, "validating sfs on \"%s\" directory ...\n",
210                 valdir);
211
212         init_fileinfo();
213         create_3tmp_handles();
214
215         /*
216          * need priv port to do following
217          */
218         mount_client_ptr = lad_getmnt_hand(valdir);
219         if (mount_client_ptr == NULL) {
220             exit(1);
221         }
222         validate_init_rpc();
223
224         /*
225          * should be all done doing priv port stuff
226          */
227         if (setuid(Real_uid) != 0) {
228            (void) fprintf(stderr,"%s: %s%s\n",
229                    sfs_Myname, "cannot perform setuid operation.\n",
230                    "Do `make install` as root.\n");
231         }
232
233         init_mount_point(0, valdir, mount_client_ptr);
234
235         /*
236          * initialize the check_file array
237          */
238         (void) memset((void *) check_files, '\0', sizeof(check_files));
239
240         verror(VAL_VERBOSE, I, "validating null operation ...\n");
241         val_op_null();
242
243         validate_creation();
244         validate_attributes();
245         validate_read_write();
246         validate_rename();
247         validate_remove();
248         argc--;
249         valdir = argv++[0];
250
251         /*
252          * Cleanup mount client handle
253          */
254         clnt_destroy(mount_client_ptr);
255
256         delete_3tmp_handles();
257         validate_cleanup();
258     } while (argc > 0);
259
260     validate_exit();
261
262 } /* Validate_ops */
263
264
265 /*
266  * allocate and initialize client handles
267  */
268 static void
269 validate_init_rpc(void)
270 {
271         NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
272                                         (uint32_t) NFS_PROGRAM,
273                                         (uint32_t) NFS_V3,
274                                         RPC_ANYSOCK, &Nfs_timers[0]);
275
276         if (NFS_client == ((CLIENT *) NULL)) { 
277                     verror(VAL_BATCH, E,
278                                 "portmap/nfsd server not responding\n"); 
279                     exit(1); 
280         }
281  
282         NFS_client->cl_auth = authunix_create(lad_hostname, Real_uid,
283                                       Cur_gid, 0, NULL);
284 } /* validate_init_rpc */
285
286
287 static void
288 validate_creation(void)
289 {
290     int                 filenum;
291     int                 target_filenum;
292     CREATE3args         argcr;
293     CREATE3res          repcr;
294     MKDIR3args          argmk;
295     MKDIR3res           repmk;
296     LINK3args           argln;
297     LINK3res            repln;
298     SYMLINK3args        argsl;
299     SYMLINK3res         repsl;
300     LOOKUP3args         arglp;
301     LOOKUP3res          replp;
302     READLINK3args       argrl;
303     READLINK3res        reprl;
304     char                sl_target_path[NFS_MAXPATHLEN];
305     char                sym_data[NFS_MAXPATHLEN];
306
307     for (filenum=0; filenum < NUMFILES ; filenum++) {
308
309         Cur_file_ptr = &Io_files[filenum];
310         sfs_gettime(&Cur_time);
311
312         if (filenum < NUMREGFILES) {
313
314             (void) sprintf(Cur_filename, Filespec, filenum);
315
316             /* regular file creation */
317             (void) memmove((char *) &argcr.where.dir, (char *) &Export_dir.fh3,
318                                 sizeof (nfs_fh3));
319             argcr.where.name = Cur_filename;
320             argcr.how.mode = UNCHECKED;
321             argcr.how.createhow3_u.obj_attributes.mode.set_it = TRUE;
322             argcr.how.createhow3_u.obj_attributes.mode.mode =
323                                                         (NFSMODE_REG | 0666);
324             argcr.how.createhow3_u.obj_attributes.uid.set_it = TRUE;
325             argcr.how.createhow3_u.obj_attributes.uid.uid = Cur_uid;
326             argcr.how.createhow3_u.obj_attributes.gid.set_it = TRUE;
327             argcr.how.createhow3_u.obj_attributes.gid.gid = Cur_gid;
328             argcr.how.createhow3_u.obj_attributes.atime.set_it = TRUE;
329             argcr.how.createhow3_u.obj_attributes.atime.atime.seconds =
330                                                         Cur_time.esec;
331             argcr.how.createhow3_u.obj_attributes.atime.atime.nseconds =
332                                                         Cur_time.usec * 1000;
333             argcr.how.createhow3_u.obj_attributes.mtime.set_it = TRUE;
334             argcr.how.createhow3_u.obj_attributes.mtime.mtime.seconds =
335                                                         Cur_time.esec;
336             argcr.how.createhow3_u.obj_attributes.mtime.mtime.nseconds =
337                                                         Cur_time.usec * 1000;
338             argcr.how.createhow3_u.obj_attributes.size.set_it = TRUE;
339             argcr.how.createhow3_u.obj_attributes.size.size._p._u =
340                                                         (uint32_t) 0;
341             argcr.how.createhow3_u.obj_attributes.size.size._p._l =
342                                                         (uint32_t) 0;
343
344             (void) memset((char *) &repcr.resok.obj.handle, '\0',
345                                                         sizeof (nfs_fh3));
346             verror(VAL_VERBOSE, I, "validating create file %s ...\n",
347                     Cur_filename);
348             val_op_create(&argcr, &repcr);
349
350             if (repcr.status == NFS3_OK) {
351                 Cur_file_ptr->state = Exists;
352                 (void) memmove((char *) &Cur_file_ptr->fh3,
353                                 (char *) &repcr.resok.obj.handle,
354                                 sizeof (nfs_fh3));
355                 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
356                 (void) memmove((char *) &Cur_file_ptr->attributes3,
357                                 (char *) &repcr.resok.obj_attributes.attr,
358                                 sizeof(Cur_file_ptr->attributes3));
359                 (void) compare_sattr(Ops[CREATE].name, Io_files[filenum].file_name,
360                                         &argcr.how.createhow3_u.obj_attributes,
361                                         &Cur_file_ptr->attributes3);
362             } else {
363                 Cur_file_ptr->state = Nonexistent;
364                 errno = (int)repcr.status;
365                 verror(VAL_BATCH, E, "create %s failed: %m\n",
366                           Cur_filename);
367                 /*
368                  * An error in file creation is fatal, because we use the
369                  * created files to validate the other operations.
370                  */
371                 validate_exit();
372             }
373
374         } else if (filenum < NUMREGFILES + NUMDIRS) {
375
376             (void) sprintf(Cur_filename, Dirspec, filenum - NUMREGFILES);
377
378             /* directory creation */
379             (void) memmove((char *) &argmk.where.dir, (char *) &Export_dir.fh3,
380                         sizeof (nfs_fh3));
381             argmk.where.name = Cur_filename;
382             argmk.attributes.mode.set_it = TRUE;
383             argmk.attributes.mode.mode = (NFSMODE_DIR | 0777);
384             argmk.attributes.uid.set_it = TRUE;
385             argmk.attributes.uid.uid = Cur_uid;
386             argmk.attributes.gid.set_it = TRUE;
387             argmk.attributes.gid.gid = Cur_gid;
388             argmk.attributes.size.set_it = FALSE;
389             argmk.attributes.size.size._p._u = (uint32_t) 0;
390             argmk.attributes.size.size._p._l = (uint32_t) 0;
391             argmk.attributes.atime.set_it = TRUE;
392             argmk.attributes.atime.atime.seconds = Cur_time.esec;
393             argmk.attributes.atime.atime.nseconds = Cur_time.usec * 1000;
394             argmk.attributes.mtime.set_it = TRUE;
395             argmk.attributes.mtime.mtime.seconds = Cur_time.esec;
396             argmk.attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
397
398             (void) memset((char *) &repmk.resok.obj.handle, '\0', sizeof (nfs_fh3));
399             verror(VAL_VERBOSE, I, "validating mkdir %s ...\n", Cur_filename);
400             val_op_mkdir(&argmk, &repmk);
401
402             if (repmk.status == NFS3_OK) {
403                 Cur_file_ptr->state = Exists;
404                 (void) memmove((char *) &Cur_file_ptr->fh3,
405                                 (char *) &repmk.resok.obj.handle,
406                                 sizeof (nfs_fh3));
407                 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
408                 (void) memmove((char *) &Cur_file_ptr->attributes3,
409                                 (char *) &repmk.resok.obj_attributes.attr,
410                                 sizeof(Cur_file_ptr->attributes3));
411                 (void) compare_sattr(Ops[MKDIR].name, Io_files[filenum].file_name,
412                                 &argmk.attributes, &Cur_file_ptr->attributes3);
413             } else {
414                 Cur_file_ptr->state = Nonexistent;
415                 verror(VAL_BATCH, W, "mkdir %s failed:%m\n", Cur_filename);
416             }
417
418         } else if (filenum < NUMREGFILES + NUMDIRS + NUMLINKS ) {
419
420             (void) sprintf(Cur_filename, Filespec, filenum - NUMDIRS);
421
422             /* hard link creation */
423             target_filenum = NUMFILES-NUMSYMLINKS-1-filenum;
424             (void) memmove((char *) &argln.file,
425                         (char *) &Io_files[target_filenum].fh3,
426                         sizeof (nfs_fh3));
427             (void) memmove((char *) &argln.link.dir, (char *) &Export_dir.fh3,
428                         sizeof (nfs_fh3));
429             argln.link.name = Cur_filename;
430
431             verror(VAL_VERBOSE, I, "validating link %s %s ...\n",
432                     Io_files[target_filenum].file_name, Cur_filename);
433             val_op_link(&argln, &repln);
434
435             if (repln.status == NFS3_OK) {
436                 Cur_file_ptr->state = Exists;
437                 (void) memmove((char *) &Cur_file_ptr->fh3,
438                                 (char *) &Io_files[target_filenum].fh3,
439                                 sizeof (nfs_fh3));
440                 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
441                 Cur_file_ptr->attributes3 = Io_files[target_filenum].attributes3;
442                 Io_files[target_filenum].attributes3.nlink++;
443                 Cur_file_ptr->attributes3.nlink++;
444             } else {
445                 Cur_file_ptr->state = Nonexistent;
446                 verror(VAL_BATCH, W, "link %s failed: %m\n", Cur_filename);
447                 exit(1);
448             }
449
450         } else {
451
452             (void) sprintf(Cur_filename, Symspec, filenum -
453                                         (NUMREGFILES + NUMDIRS + NUMLINKS));
454
455             /* symbolic link creation */
456             target_filenum = NUMFILES-1-filenum;
457             (void) memmove((char *) &argsl.where.dir, (char *) &Export_dir.fh3,
458                         sizeof (nfs_fh3));
459             argsl.where.name = Cur_filename;
460             (void) sprintf(sl_target_path,
461                            "./%s", Io_files[target_filenum].file_name);
462             argsl.symlink.symlink_attributes.size.set_it = TRUE;
463             argsl.symlink.symlink_attributes.size.size._p._u =
464                                         (uint32_t) 0;
465             argsl.symlink.symlink_attributes.size.size._p._l =
466                                         (uint32_t) strlen(sl_target_path);
467             argsl.symlink.symlink_data = sl_target_path;
468             argsl.symlink.symlink_attributes.mode.set_it = TRUE;
469             argsl.symlink.symlink_attributes.mode.mode = (NFSMODE_LNK | 0777);
470             argsl.symlink.symlink_attributes.uid.set_it = TRUE;
471             argsl.symlink.symlink_attributes.uid.uid = Cur_uid;
472             argsl.symlink.symlink_attributes.gid.set_it = TRUE;
473             argsl.symlink.symlink_attributes.gid.gid = Cur_gid;
474             argsl.symlink.symlink_attributes.atime.set_it = TRUE;
475             argsl.symlink.symlink_attributes.atime.atime.seconds =
476                                                         Cur_time.esec;
477             argsl.symlink.symlink_attributes.atime.atime.nseconds =
478                                                         Cur_time.usec * 1000;
479             argsl.symlink.symlink_attributes.mtime.set_it = TRUE;
480             argsl.symlink.symlink_attributes.mtime.mtime.seconds =
481                                                         Cur_time.esec;
482             argsl.symlink.symlink_attributes.mtime.mtime.nseconds =
483                                                         Cur_time.usec * 1000;
484
485             verror(VAL_VERBOSE, I, "validating symlink %s %s ...\n",
486                     sl_target_path, Cur_filename);
487             val_op_symlink(&argsl, &repsl);
488
489             if (repsl.status == NFS3_OK) {
490                 Cur_file_ptr->state = Exists;
491
492                 /* do a lookup to get file handle and attributes */
493                 (void) memmove((char *) &arglp.what.dir, (char *) &Export_dir.fh3,
494                                 sizeof (nfs_fh3));
495                 arglp.what.name = Cur_filename;
496                 (void) memset((char *) &replp.resok.object, '\0', sizeof (nfs_fh3));
497
498                 val_op_lookup(&arglp, &replp);
499
500                 if (replp.status == NFS3_OK) {
501                     (void) memmove((char *) &Cur_file_ptr->fh3,
502                                 (char *) &replp.resok.object,
503                                 sizeof (nfs_fh3));
504                     (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
505                     (void) memmove((char *) &Cur_file_ptr->attributes3,
506                                 (char *) &replp.resok.obj_attributes.attr,
507                                 sizeof (Cur_file_ptr->attributes3));
508                     (void) compare_sattr(Ops[SYMLINK].name,
509                                         Io_files[filenum].file_name,
510                                         &argsl.symlink.symlink_attributes,
511                                         &Cur_file_ptr->attributes3);
512                 } else {
513                     verror(VAL_BATCH, W, "lookup %s failed: %m\n",
514                             Cur_filename);
515                     continue;
516                 }
517
518                 /* validate readlink */
519                 (void) memmove((char *) &argrl.symlink,
520                                 (char *) &Cur_file_ptr->fh3,
521                                 sizeof (nfs_fh3));
522                 reprl.resok.data = sym_data;
523
524                 verror(VAL_VERBOSE, I, "validating readlink %s ...\n",
525                         Cur_filename);
526                 val_op_readlink(&argrl, &reprl);
527
528                 if (reprl.status == NFS3_OK) {
529                     if (strcmp(sl_target_path, sym_data)) {
530                         verror(VAL_BATCH, W,
531                             "readlink %s error, result = %s, should be %s\n",
532                             Cur_filename, reprl.resok.data,
533                             sl_target_path);
534                     }
535                 } else {
536                     verror(VAL_BATCH, W, "readlink %s failed:%m\n",
537                             Cur_filename);
538                 }
539
540             } else {
541                 Cur_file_ptr->state = Nonexistent;
542                 verror(VAL_BATCH, W, "symlink %s failed: %m\n", Cur_filename);
543             }
544         }
545     } /* end for each file */
546
547 } /* validate_creation */
548
549
550 static void
551 validate_attributes(void)
552 {
553     int                 filenum;
554     LOOKUP3args         arglp;
555     LOOKUP3res          replp;
556     GETATTR3args        argga;
557     GETATTR3res         repga;
558     SETATTR3args        argsa;
559     SETATTR3res         repsa;
560
561     /* validate fsstat */
562
563     /* validate lookup */
564     for (filenum = 0; filenum < NUMFILES; filenum++) {
565         (void) memmove((char *) &arglp.what.dir, (char *) &Export_dir.fh3,
566                         sizeof (nfs_fh3));
567         arglp.what.name = Io_files[filenum].file_name;
568         (void) memset((char *) &replp.resok.object, '\0', sizeof (nfs_fh3));
569
570         verror(VAL_VERBOSE, I, "validating lookup %s ...\n",
571                 Io_files[filenum].file_name);
572         val_op_lookup(&arglp, &replp);
573
574         if (replp.status == NFS3_OK) {
575             if (memcmp((char *) &(Io_files[filenum].fh3),
576                      (char *) &(replp.resok.object), sizeof (nfs_fh3))) {
577                 verror(VAL_BATCH, W, "lookup %s: file handle mismatch\n",
578                                 Io_files[filenum].file_name);
579                 exit(1);
580             }
581             (void) compare_fattr(Ops[LOOKUP].name, Io_files[filenum].file_name,
582                                         &Io_files[filenum].attributes3,
583                                         &replp.resok.obj_attributes.attr);
584         } else {
585             verror(VAL_BATCH, W, "lookup %s failed:%m\n",
586                     Io_files[filenum].file_name);
587         }
588     }
589
590     /* validate getattr */
591     for (filenum = 0; filenum < NUMFILES; filenum++) {
592         (void) memmove((char *) &argga.object,
593                         (char *) &Io_files[filenum].fh3,
594                         sizeof (nfs_fh3));
595
596         verror(VAL_VERBOSE, I, "validating getattr %s ...\n",
597                 Io_files[filenum].file_name);
598         val_op_getattr(&argga, &repga);
599
600         if (repga.status == NFS3_OK) {
601             (void) compare_fattr(Ops[GETATTR].name, Io_files[filenum].file_name,
602                           &Io_files[filenum].attributes3,
603                           &repga.resok.obj_attributes);
604         } else {
605             verror(VAL_BATCH, W, "getattr %s failed: %m\n",
606                     Io_files[filenum].file_name);
607         }
608     }
609
610     /*validate setattr */
611     for (filenum = 0; filenum < NUMFILES; filenum++) {
612         sfs_gettime(&Cur_time);
613         (void) memmove((char *) &argsa.object,
614                         (char *) &Io_files[filenum].fh3,
615                         sizeof (nfs_fh3));
616         argsa.new_attributes.mode.set_it = TRUE;
617         if (filenum >= NUMREGFILES && filenum < NUMREGFILES + NUMDIRS)
618           argsa.new_attributes.mode.mode = 0777;
619         else
620           argsa.new_attributes.mode.mode = 0666;
621         argsa.new_attributes.uid.set_it = FALSE;
622         argsa.new_attributes.uid.uid = 0;
623         argsa.new_attributes.gid.set_it = FALSE;
624         argsa.new_attributes.gid.gid = 0;
625         argsa.new_attributes.size.set_it = FALSE;
626         argsa.new_attributes.size.size._p._u = 0;
627         argsa.new_attributes.size.size._p._l = 0;
628         argsa.new_attributes.atime.set_it = TRUE;
629         argsa.new_attributes.atime.atime.seconds = Cur_time.esec;
630         argsa.new_attributes.atime.atime.nseconds = Cur_time.usec * 1000;
631         argsa.new_attributes.mtime.set_it = TRUE;
632         argsa.new_attributes.mtime.mtime.seconds = Cur_time.esec;
633         argsa.new_attributes.mtime.mtime.nseconds = Cur_time.usec * 1000;
634         argsa.guard.check = FALSE;
635
636         verror(VAL_VERBOSE, I, "validating setattr %s ...\n",
637                                 Io_files[filenum].file_name);
638         val_op_setattr(&argsa, &repsa);
639
640         if (repsa.status == NFS3_OK) {
641             (void) memmove((char *) &Io_files[filenum].attributes3,
642                                 (char *) &repsa.resok.obj_wcc.after.attr,
643                                 sizeof (Io_files[filenum].attributes3));
644             (void) compare_sattr(Ops[SETATTR].name, Io_files[filenum].file_name,
645                         &argsa.new_attributes, &repsa.resok.obj_wcc.after.attr);
646
647             (void) memmove((char *) &argga.object,
648                                 (char *) &Io_files[filenum].fh3,
649                                 sizeof (nfs_fh3));
650
651             val_op_getattr(&argga, &repga);
652
653             if (repga.status == NFS3_OK) {
654                 (void) compare_fattr(Ops[GETATTR].name, Io_files[filenum].file_name,
655                                                 &Io_files[filenum].attributes3,
656                                                 &repga.resok.obj_attributes);
657             } else {
658                 verror(VAL_BATCH, W, "getattr %s failed: %m\n",
659                         Io_files[filenum].file_name);
660             }
661         } else {
662             verror(VAL_BATCH, W, "setattr %s failed: %m\n",
663                     Io_files[filenum].file_name);
664             exit(1);
665         }
666     }
667
668 } /* validate_attributes */
669
670 #define WAITFOREOF 1
671 /*
672  * need to check if readdirplus returns a reasonable amount of data.
673  */
674 static void
675 val_rddirplus_retsize(uint32_t dircount, uint32_t maxcount,
676                       READDIRPLUS3resok *rp)
677 {
678     entryplus3 *esp;
679     static int eof_wait = 0;
680     int i;
681     int size = 0;
682     int tsize = 0;
683     int msize = 0;
684     double mpcnt = 0;
685
686     esp = rp->reply.entries;
687
688     for (i = 0; i < rp->count; i++) {
689             size += sizeof(esp[i].fileid);
690             size += strlen(esp[i].name) * sizeof(char);
691             size += sizeof(esp[i].cookie);
692             tsize += sizeof(esp[i].name_attributes);
693             tsize += sizeof(esp[i].name_handle.handle_follows);
694             tsize += esp[i].name_handle.handle.fh3_length * sizeof(char);
695     }
696
697     msize = size + tsize;
698     mpcnt = (double) msize / (double) maxcount * 100;
699
700     if (rp->reply.eof) {
701         verror(VAL_VERBOSE, I, "readdirplus on %s returned EOF.\n"
702     "\treceived %d bytes of directory information and %d bytes including\n"
703     "\tpost op attributes and filehandle.\n",
704                Testdirname, size, msize);
705     } else if (mpcnt < 80) {
706         eof_wait++;
707         if (eof_wait > WAITFOREOF) {
708             verror(VAL_BATCH, E,
709     "readdirplus on %s did not return a reasonable amount of data.\n"
710     "\treceived %d bytes. should receive close to %d bytes.\n",
711                    Testdirname, msize, maxcount);
712         } else {
713             verror(VAL_VERBOSE, I, "readdirplus on %s did not return EOF.\n"
714     "\treceived %d bytes of directory information and %d bytes including\n"
715     "\tpost op attributes and filehandle.\n",
716                    Testdirname, size, msize);
717         }
718     } else {
719         verror(VAL_VERBOSE, I, "readdirplus on %s did not return EOF.\n"
720     "\treceived %d bytes of directory information and %d bytes including\n"
721     "\tpost op attributes and filehandle.\n",
722                Testdirname, size, msize);
723     }    
724 }
725
726 static void
727 validate_read_write(void)
728 {
729     struct {
730         uint16_t  sum;                    /* checksum of data */
731         uint16_t  len;                    /* length of len and data */
732         char            data[DEFAULT_MAX_BUFSIZE - 2 * sizeof(uint16_t)];
733     } block;
734     WRITE3args          argwr;
735     WRITE3res           repwr;
736     READ3args           argrd;
737     READ3res            reprd;
738     READDIR3args        argdr;
739     READDIR3res         repdr;
740     READDIRPLUS3args    argdrp;
741     READDIRPLUS3res     repdrp;
742     int                 maxblks;
743     int                 maxfiles;
744     int                 i;
745     int                 numfiles;
746     int                 filenum;
747     int                 blocknum;
748     entry3              entry_stream[SFS_MAXDIRENTS];
749     entryplus3          entryplus_stream[SFS_MAXDIRENTS];
750
751     /* validate write */
752
753     /* get the maximum number of blocks sfs will write */
754     maxblks = Io_dist_ptr->max_bufs;
755     maxfiles = maxblks > NUMREGFILES ? NUMREGFILES : maxblks;
756
757     /* write maxblks - filenum + 1 blocks to each regular file */
758     argwr.offset._p._u = argwr.offset._p._l = (uint32_t) 0;
759     argwr.stable = FILE_SYNC;
760     argwr.data.data_val = (char *)&block;
761
762     for (blocknum = 0; blocknum <= maxblks ; blocknum++) {
763
764         for (i=0; i < sizeof(block.data); i++)
765             block.data[i] = (char)blocknum;
766
767         for (filenum=0; filenum < maxfiles; filenum++) {
768             /* Write fewer blocks to files with higher numbers. */
769             if (blocknum > (maxblks - filenum))
770                 break;
771
772             /* set the length field */
773             if (blocknum == (maxblks - filenum)) {
774                 block.len = ((maxfiles - filenum) *
775                         (Bytes_per_block/Kb_per_block)) - (sizeof(block.len) + 
776                                                            sizeof(block.sum));
777                 /*
778                  * XXX - write kludge.
779                  *
780                  * Writes must be less than 8K in
781                  * size or else the checksum will incur a buffer overflow
782                  */
783                 block.len = (block.len % DEFAULT_MAX_BUFSIZE) -
784                         (sizeof(block.len) + sizeof(block.sum));
785             } else {
786                 block.len = Bytes_per_block - (sizeof(block.len)
787                             + sizeof(block.sum));
788             }
789             block.sum = sum((unsigned char *) &block.len,
790                             (int)(block.len + sizeof(block.len)));
791
792             (void) memmove((char *) &argwr.file,
793                                 (char *) &Io_files[filenum].fh3,
794                                 sizeof (nfs_fh3));
795             argwr.data.data_len = block.len +
796                                   sizeof(block.len) + sizeof(block.sum);
797             argwr.count = argwr.data.data_len;
798
799             verror(VAL_VERBOSE, I,
800                     "validating write %d bytes @ offset %lu to %s ...\n",
801                     argwr.data.data_len, argwr.offset._p._l,
802                     Io_files[filenum].file_name);
803
804             val_op_write(&argwr, &repwr);
805
806             if (repwr.status == NFS3_OK) {
807                 (void) compare_fattr(Ops[WRITE].name, Io_files[filenum].file_name,
808                               &Io_files[filenum].attributes3,
809                               &repwr.resok.file_wcc.after.attr);
810                 Io_files[filenum].attributes3 = repwr.resok.file_wcc.after.attr;
811                 /*
812                  * XXX-bookeeping kludge.
813                  *
814                  * Need to update hardlink attributes, so readdirplus vali-
815                  * dation doesn't barf.  This is necessary because setattr was
816                  * validated on all the test files and the attributes in
817                  * Io_files[] were updated accordingly.  Since the write
818                  * op has been validated on just the regular files, we have to
819                  * make sure that the corresponding indexes in Io_files[] that
820                  * point to the hard links reflect the current file attributes.
821                  */
822                 if (filenum < NUMLINKS) {
823                     Io_files[NUMREGFILES+NUMDIRS+NUMLINKS-1-filenum].attributes3 = Io_files[filenum].attributes3;
824                 }
825
826             } else {
827                 verror(VAL_BATCH, W, "write %s failed: %m\n",
828                         Io_files[filenum].file_name);
829             }
830         }
831         argwr.offset._p._l += Bytes_per_block;
832     }
833
834     /* validate read */
835
836     for (filenum = 0; filenum < maxfiles; filenum++) {
837         (void) memmove((char *) &argrd.file,
838                         (char *) &Io_files[filenum].fh3,
839                         sizeof (nfs_fh3));
840         argrd.offset._p._u = argrd.offset._p._l = (uint32_t) 0;
841         argrd.count = 0;
842         reprd.resok.data.data_len = 0;
843         maxblks = Io_files[filenum].attributes3.size._p._l / Bytes_per_block;
844         for (blocknum = 0; blocknum <= maxblks; blocknum ++) {
845
846             if (argrd.count != reprd.resok.data.data_len) {
847                 argrd.count -= reprd.resok.data.data_len;
848                 reprd.resok.data.data_val = (char *)&block +
849                                         reprd.resok.data.data_len;
850                 blocknum--;
851             } else {
852                 if (blocknum < maxblks)
853                     argrd.count = Bytes_per_block;
854                 else
855                     argrd.count = (maxfiles - filenum)
856                                   * (Bytes_per_block/Kb_per_block);
857                 reprd.resok.data.data_val = (char *)&block;
858             }
859
860             verror(VAL_VERBOSE, I,
861                    "validating read %lu bytes @ offset %lu from %s ...\n",
862                     argrd.count, argrd.offset._p._l,
863                     Io_files[filenum].file_name);
864
865             val_op_read(&argrd, &reprd);
866
867             if (reprd.status == NFS3_OK) {
868                 (void) compare_fattr(Ops[READ].name, Io_files[filenum].file_name,
869                               &Io_files[filenum].attributes3,
870                               &reprd.resok.file_attributes.attr);
871                 Io_files[filenum].attributes3 = reprd.resok.file_attributes.attr;
872                 argrd.offset._p._l += reprd.resok.data.data_len;
873             } else {
874                 verror(VAL_BATCH, W, "read %s failed: %m\n",
875                         Io_files[filenum].file_name);
876             }
877
878             if ((argrd.count ==
879                 (block.sum != sum((unsigned char *) &block.len,
880                                   (int)(block.len + sizeof(block.len)))))) {
881                 verror(VAL_BATCH, W, "read %s checksum mismatch\n",
882                         Io_files[filenum].file_name);
883             }
884         }
885     }
886
887     /* validate readdir */
888     (void) memmove((char *) &argdr.dir, (char *) &Export_dir.fh3,
889                         sizeof (nfs_fh3));
890     argdr.cookie._p._l = argdr.cookie._p._u = (uint32_t) 0;
891     (void) memset((char *) argdr.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
892     argdr.count = DEFAULT_MAX_BUFSIZE;
893
894     do {
895         (void) memset((char *) entry_stream, '\0', sizeof (entry3) * SFS_MAXDIRENTS);
896         (void) memset((char *) &repdr, '\0', sizeof(repdr));
897         repdr.resok.count = SFS_MAXDIRENTS;
898         repdr.resok.reply.entries = entry_stream;
899         verror(VAL_VERBOSE, I, "validating readdir on %s ...\n", Testdirname);
900         val_op_readdir(&argdr, &repdr);
901
902
903         if (repdr.status == NFS3_OK) {
904             for (i = 0; i < repdr.resok.count; i++) {
905                 for (filenum = 0; filenum < NUMFILES; filenum++) {
906                     if (!strcmp(entry_stream[i].name, Io_files[filenum].file_name)) {                        if (entry_stream[i].fileid._p._l !=
907                                     Io_files[filenum].attributes3.fileid._p._l) {
908                             verror(VAL_BATCH, E,
909                                 "readdir %s error: file %s fileid mismatch\n",
910                                 Testdirname, entry_stream[i].name);
911                             verror(VAL_BATCH, W,
912                                 "   fileid: got = %lu, original = %lu\n",
913                                 entry_stream[i].fileid._p._l,
914                                 Io_files[filenum].attributes3.fileid._p._l);
915                         }
916                         /*
917                          * mark file as either found or dup
918                          */
919                         if (check_files[filenum].file_found &&
920                             !check_files[filenum].file_is_dup)
921                                 check_files[filenum].file_is_dup = 1;
922                         else
923                                 check_files[filenum].file_found = 1;
924                         break;
925                     }
926                 }
927             }
928         } else {
929             verror(VAL_BATCH, W, "readdir %s failed: %m\n", Testdirname);
930         }
931
932         argdr.cookie = entry_stream[repdr.resok.count-1].cookie;
933
934     } while (repdr.resok.reply.eof == 0);
935
936     /*
937      * check if any known files have not been found
938      */
939     for (i = 0; i < NUMFILES; i++) {
940         if (!check_files[i].file_found)
941                 verror(VAL_BATCH, E,
942                        "readdir %s error: file %s not found\n",
943                        Testdirname, Io_files[i].file_name);
944         else {
945                 if (check_files[i].file_is_dup)
946                     verror(VAL_BATCH, E,
947               "readdir %s error: file %s returned more than once\n",
948                            Testdirname, Io_files[i].file_name);
949         }
950     }
951
952     /* validate readdirplus */
953     (void) memset((void *) check_files, '\0', sizeof(check_files));
954
955     argdrp.cookie._p._l = argdrp.cookie._p._u = (uint32_t) 0;
956     (void) memmove((char *) &argdrp.dir, (char *) &Export_dir.fh3,
957                    sizeof (nfs_fh3));
958     (void) memset((char *) argdrp.cookieverf, '\0', NFS3_COOKIEVERFSIZE);
959     /*
960      * We validate readdirplus with dircount and maxcount both set at 8K.
961      * This is not the most efficient way, but this is how readdirplus is
962      * called in SFS.  With the numbers set as such, maxcount becomes the
963      * bottleneck and we will not get 8K worth of directory info.  What we
964      * should get is 8K worth which includes directory info plus post_op_
965      * attributes and filehandle.
966      */
967     argdrp.dircount = DEFAULT_MAX_BUFSIZE;
968     argdrp.maxcount = DEFAULT_MAX_BUFSIZE;
969     do {
970         (void) memset((char *) entryplus_stream, '\0',
971                       sizeof (entryplus_stream));
972
973         (void) memset((char *) &repdrp, '\0', sizeof(repdrp));
974         repdrp.resok.count = SFS_MAXDIRENTS;
975         repdrp.resok.reply.entries = entryplus_stream;
976
977         verror(VAL_VERBOSE, I, "validating readdirplus on %s ...\n",
978                 Testdirname);
979         val_op_readdirplus(&argdrp, &repdrp);
980
981         if (repdrp.status == NFS3_OK) {
982             verror(VAL_VERBOSE, I, "readdirplus found %d entries in %s...\n",
983                    repdrp.resok.count, Testdirname);
984             val_rddirplus_retsize(argdrp.dircount, argdrp.maxcount,
985                                   &repdrp.resok);
986             for (i = 0; i < repdrp.resok.count; i++) {
987                 for (filenum = 0; filenum < NUMFILES; filenum++) {
988                     if (!strcmp(entryplus_stream[i].name,
989                                 Io_files[filenum].file_name)) {
990                         if (entryplus_stream[i].fileid._p._l !=
991                             Io_files[filenum].attributes3.fileid._p._l) {
992                             verror(VAL_BATCH, E,
993                         "readdirplus %s error: file %s fileid mismatch\n",
994                                    Testdirname, entryplus_stream[i].name);
995                             verror(VAL_BATCH, W,
996                                 "   fileid: got = %lu, original = %lu\n",
997                                    entryplus_stream[i].fileid._p._l,
998                                    Io_files[filenum].attributes3.fileid._p._l);
999                         }
1000
1001                         /*
1002                          * mark file as either found or dup
1003                          */
1004                         if (check_files[filenum].file_found &&
1005                             !check_files[filenum].file_is_dup)
1006                                 check_files[filenum].file_is_dup = 1;
1007                         else
1008                                 check_files[filenum].file_found = 1;
1009
1010                         /*
1011                          * check to make sure post op attributes and
1012                          * file handle are returned.
1013                          */
1014                         if (!entryplus_stream[i].name_attributes.attributes)
1015                                 verror(VAL_BATCH, E,
1016                 "readdirplus %s warning: did not receive post op attributes for file %s\n\n",
1017                                        Testdirname, entryplus_stream[i].name);
1018                         else
1019                             (void) compare_fattr(Ops[READDIRPLUS].name,
1020                                                  Io_files[filenum].file_name,
1021                                                  &Io_files[filenum].attributes3,                                                 &entryplus_stream[i].name_attributes.attr);
1022
1023                         if (!entryplus_stream[i].name_handle.handle_follows)
1024                                 verror(VAL_BATCH, E,
1025                 "readdirplus %s warning: did not receive file handle for file %s\n\n",
1026                                        Testdirname, entryplus_stream[i].name);
1027                         else
1028                             if (memcmp((void *) &Io_files[filenum].fh3.fh3_u.data,
1029                                        (void *) &entryplus_stream[i].name_handle.handle.fh3_u.data, Io_files[filenum].fh3.fh3_length) != 0)
1030                                    verror(VAL_BATCH, E,
1031                 "readdirplus %s error: file %s, filehandles do not match\n\n",
1032                                           Testdirname, entryplus_stream[i].name);
1033                         break;
1034                     }
1035                 }
1036             }
1037         } else {
1038             verror(VAL_BATCH, W, "readdirplus %s failed: %m\n", Testdirname);
1039         }
1040         argdrp.cookie = entryplus_stream[repdrp.resok.count-1].cookie;
1041
1042     } while (repdrp.resok.reply.eof == 0);
1043     /*
1044      * check if any known files have not been found
1045      */
1046     for (i = 0; i < NUMFILES; i++) {
1047         if (!check_files[i].file_found)
1048                 verror(VAL_BATCH, E,
1049                        "readdirplus %s error: file %s not found\n",
1050                        Testdirname, Io_files[i].file_name);
1051         else {
1052                 if (check_files[i].file_is_dup)
1053                     verror(VAL_BATCH, E,
1054               "readdirplus %s error: file %s returned more than once\n",
1055                            Testdirname, Io_files[i].file_name);
1056         }
1057     }   
1058 } /* validate_read_write */
1059
1060
1061 static void
1062 validate_rename(void)
1063 {
1064     RENAME3args argrn;
1065     RENAME3res  reprn;
1066     int         filenum;
1067     char        newname[SFS_MAXNAMLEN];
1068     int         rncount = 0;
1069
1070     (void) memmove((char *) &argrn.from.dir, (char *) &Export_dir.fh3,
1071                         sizeof (nfs_fh3));
1072     (void) memmove((char *) &argrn.to.dir, (char *) &Export_dir.fh3,
1073                 sizeof (nfs_fh3));
1074
1075     for (filenum=0; filenum < NUMFILES; filenum++) {
1076         if (Io_files[filenum].state != Exists)
1077             continue;
1078
1079         rncount++;
1080         (void) sprintf(newname, "n%s", Io_files[filenum].file_name);
1081         argrn.from.name = Io_files[filenum].file_name;
1082         argrn.to.name = newname;
1083
1084         verror(VAL_VERBOSE, I, "validating rename %s %s ...\n",
1085                 argrn.from.name, argrn.to.name);
1086
1087         val_op_rename(&argrn, &reprn);
1088
1089         if (reprn.status == NFS3_OK) {
1090             (void) strcpy(Io_files[filenum].file_name, newname);
1091         } else {
1092             verror(VAL_BATCH, W, "rename %s to %s failed: %m\n",
1093                     Io_files[filenum].file_name, newname);
1094         }
1095
1096     }
1097
1098     if (!rncount) {
1099         verror(VAL_BATCH, E, "validate_rename: no files renamed\n");
1100         verror(VAL_BATCH, W, "    due to previous operation error\n");
1101     }
1102
1103 } /* validate_rename */
1104
1105
1106 static int
1107 compare_fattr(
1108     char *      op,
1109     char *      fname,
1110     fattr3 *     attr1,
1111     fattr3 *     attr2)
1112 {
1113     int         ret = TRUE;
1114     int         prev_warn = FALSE; /* -1 info warning */
1115     int         flag_error = FALSE;
1116
1117     if (attr1->type != attr2->type) {
1118         if (attr1->type == 0xFFFFFFFF) {
1119             prev_warn = TRUE;
1120             if (ret) {
1121                 verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1122                     fname, op);
1123             }
1124             verror(VAL_BATCH, I, "    type: current = %d, previous =  %d\n",
1125                    attr2->type, attr1->type);
1126             attr1->type = attr2->type;
1127             ret = FALSE;
1128         }
1129         else {
1130                 if (ret) {
1131                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1132                             fname, op);
1133                 }
1134                 verror(VAL_BATCH, E, "    type: current = %d, previous =  %d\n",
1135                         attr2->type, attr1->type);
1136                 ret = FALSE;
1137                 flag_error = TRUE;
1138         }
1139     }
1140
1141     if ((attr1->mode & NFSMODE_MASK) != (attr2->mode & NFSMODE_MASK)) {
1142         if (attr1->mode == (unsigned int)0xFFFFFFFF) {
1143                 prev_warn = TRUE;
1144                 if (ret) {
1145                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1146                                 fname, op);
1147                 }
1148                 verror(VAL_BATCH, I, "    mode: current = %7lo, previous =  %7lo\n",
1149                         attr2->mode, attr1->mode);
1150                 attr1->mode =  attr2->mode;
1151                 ret = FALSE;
1152         }
1153         else {
1154                 if (ret) {
1155                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1156                             fname, op);
1157                 }
1158                 verror(VAL_BATCH, E, "    mode: current = %7lo, previous =  %7lo\n",
1159                         attr2->mode, attr1->mode);
1160                 ret = FALSE;
1161                 flag_error = TRUE;
1162         }
1163     }
1164
1165     if (attr1->nlink != attr2->nlink) {
1166         if (attr1->nlink == (unsigned int)0xFFFFFFFF) {
1167                 prev_warn = TRUE;
1168                 if (ret) {
1169                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1170                                 fname, op);
1171                 }
1172                 verror(VAL_BATCH, I,
1173                         "    nlink: current = %lu, previous =  %lu\n",
1174                         attr2->nlink, attr1->nlink);
1175                 ret = FALSE;
1176                 attr1->nlink =  attr2->nlink;
1177         }
1178         else {
1179                 if (ret) {
1180                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1181                             fname, op);
1182                 }
1183                 verror(VAL_BATCH, E,
1184                         "    nlink: current = %lu, previous =  %lu\n",
1185                         attr2->nlink, attr1->nlink);
1186                 ret = FALSE;
1187                 flag_error = TRUE;
1188         }
1189     }
1190
1191
1192     /*
1193      * Check for user "nobody", UID -2, which may be untranslated from
1194      * sixteen-bit two's complement.
1195      */
1196     if (attr1->uid != attr2->uid && !((attr2->uid == (unsigned int)0xFFFFFFFE ||
1197         attr2->uid == 65534) && attr1->uid ==0)) {
1198         if (attr1->uid == (unsigned int)0xFFFFFFFF) {
1199                 prev_warn = TRUE;
1200                 if (ret) {
1201                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1202                                 fname, op);
1203                 }
1204                 verror(VAL_BATCH, I,
1205                         "    uid: current = %lu, previous =  %lu\n",
1206                         attr2->uid, attr1->uid);
1207                 attr1->uid =  attr2->uid;
1208                 ret = FALSE;
1209         }
1210         else {
1211                 if (ret) {
1212                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1213                             fname, op);
1214                 }
1215                 verror(VAL_BATCH, E,
1216                         "    uid: current = %lu, previous =  %lu\n",
1217                         attr2->uid, attr1->uid);
1218                 ret = FALSE;
1219                 flag_error = TRUE;
1220         }
1221     }
1222
1223     if (attr1->gid != attr2->gid && attr2->gid != 0) {
1224 /*
1225     if (attr1->gid != attr2->gid) {
1226 */
1227         if (attr1->gid == (unsigned int)0xFFFFFFFF) {
1228                 prev_warn = TRUE;
1229                 if (ret) {
1230                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1231                                 fname, op);
1232                 }
1233                 verror(VAL_BATCH, I,
1234                         "    gid: current = %lu, previous =  %lu\n",
1235                         attr2->gid, attr1->gid);
1236                 attr1->gid =  attr2->gid;
1237                 ret = FALSE;
1238         }
1239         else {
1240                 if (ret) {
1241                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1242                             fname, op);
1243                 }
1244                 verror(VAL_BATCH, E,
1245                         "    gid: current = %lu, previous =  %lu\n",
1246                         attr2->gid, attr1->gid);
1247                 ret = FALSE;
1248                 flag_error = TRUE;
1249         }
1250     }
1251
1252     if (attr1->size._p._l != attr2->size._p._l) {
1253         if (strcmp(op, Ops[WRITE].name)) {
1254             if (attr1->size._p._l == (unsigned int)0xFFFFFFFF) {
1255                 prev_warn = TRUE;
1256                 if (ret) {
1257                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1258                                 fname, op);
1259                 }
1260                 verror(VAL_BATCH, I,
1261                         "    size: current = %lu, previous =  %lu\n",
1262                         attr2->size._p._l, attr1->size._p._l);
1263                 attr1->size._p._l =  attr2->size._p._l;
1264                 ret = FALSE;
1265             }
1266             else {
1267                 if (ret) {
1268                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1269                             fname, op);
1270                 }
1271                 verror(VAL_BATCH, E,
1272                         "    size: current = %lu, previous =  %lu\n",
1273                         attr2->size._p._l, attr1->size._p._l);
1274                 ret = FALSE;
1275                 flag_error = TRUE;
1276             }
1277         }
1278     }
1279
1280     /* compare rdev only if type == NFCHR or NFBLK */
1281     if ((attr1->type == NF3CHR || attr1->type == NF3BLK) &&
1282                         (attr1->rdev.specdata1 != attr2->rdev.specdata1 ||
1283                         attr1->rdev.specdata2 != attr2->rdev.specdata2)) {
1284         if (attr1->rdev.specdata1 == (unsigned int)0xFFFFFFFF) {
1285              prev_warn = TRUE;
1286              if (ret) {
1287                      verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1288                              fname, op);
1289              }
1290              verror(VAL_BATCH, I,
1291                         "    rdev: current = %lu %lu, previous =  %lu %lu\n",
1292                         attr2->rdev.specdata1, attr2->rdev.specdata2,
1293                         attr1->rdev.specdata1, attr1->rdev.specdata2);
1294              attr1->rdev.specdata1 =  attr2->rdev.specdata1;
1295              attr1->rdev.specdata2 =  attr2->rdev.specdata2;
1296              ret = FALSE;
1297         }
1298         else {
1299              if (ret) {
1300                      verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1301                          fname, op);
1302              }
1303              verror(VAL_BATCH, E,
1304                         "    rdev: current = %lu %lu, previous =  %lu %lu\n",
1305                         attr2->rdev.specdata1, attr2->rdev.specdata2,
1306                         attr1->rdev.specdata1, attr1->rdev.specdata2);
1307              ret = FALSE;
1308              flag_error = TRUE;
1309         }
1310     }
1311
1312     if (attr1->fsid._p._l != attr2->fsid._p._l) {
1313         if (attr1->fsid._p._l == (unsigned int)0xFFFFFFFF) {
1314              prev_warn = TRUE;
1315              if (ret) {
1316                      verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1317                              fname, op);
1318              }
1319              verror(VAL_BATCH, I, "    fsid: current = %lu, previous =  %lu\n",
1320                      attr2->fsid._p._l, attr1->fsid._p._l);
1321              attr1->fsid._p._l =  attr2->fsid._p._l;
1322              ret = FALSE;
1323         }
1324         else {
1325              if (ret) {
1326                      verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1327                          fname, op);
1328              }
1329              verror(VAL_BATCH, E, "    fsid: current = %lu, previous =  %lu\n",
1330                      attr2->fsid._p._l, attr1->fsid._p._l);
1331              ret = FALSE;
1332                 flag_error = TRUE;
1333         }
1334     }
1335
1336     if (attr1->fileid._p._l != attr2->fileid._p._l) {
1337         if (attr1->fileid._p._l == (unsigned int)0xFFFFFFFF) {
1338              prev_warn = TRUE;
1339              if (ret) {
1340                      verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1341                              fname, op);
1342              }
1343              verror(VAL_BATCH, I,
1344                         "    fileid: current = %lu, previous =  %lu\n",
1345                         attr2->fileid._p._l, attr1->fileid._p._l);
1346              attr1->fileid._p._l =  attr2->fileid._p._l;
1347              ret = FALSE;
1348         }
1349         else {
1350              if (ret) {
1351                      verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1352                          fname, op);
1353              }
1354              verror(VAL_BATCH, E,
1355                         "    fileid: current = %lu, previous =  %lu\n",
1356                      attr2->fileid._p._l, attr1->fileid._p._l);
1357              ret = FALSE;
1358                 flag_error = TRUE;
1359         }
1360     }
1361
1362     if (prev_warn) {
1363         verror(VAL_BATCH, I,
1364                 "\n        Warning: the previous value of a field is -1,\n");
1365         verror(VAL_BATCH, I,
1366                 "        this resulted from an unused field returned by\n");
1367         verror(VAL_BATCH, I,
1368                 "        the previous operation on this file/directory.\n");
1369         verror(VAL_BATCH, I,
1370             "        The current value is now stored for future comparison\n\n");
1371     }
1372
1373     if (flag_error)
1374         verror(VAL_BATCH, W,"\n");
1375
1376     return(flag_error);
1377
1378 } /* ckompare_fattr */
1379
1380
1381 uint32_t sattr_types[8] =       {
1382                           0000000,              /* NF3NON */
1383                           0100000,              /* NF3REG */
1384                           0040000,              /* NF3DIR */
1385                           0060000,              /* NF3BLK */
1386                           0020000,              /* NF3CHR */
1387                           0120000,              /* NF3LNK */
1388                           0140000,              /* NF3SOCK */
1389                           0010000 };            /* NF3FIFO */
1390 static int
1391 compare_sattr(
1392     char *      op,
1393     char *      fname,
1394     sattr3 *    attr1,
1395     fattr3 *    attr2)
1396 {
1397     int         ret = TRUE;
1398     char        msg[80];
1399
1400     msg[0] = '\0';
1401
1402 #ifdef notyet
1403     if (attr1->mode.mode.set_it == TRUE &&
1404         (((attr1->mode.mode & NFSTYPE_FMT) != sattr_types[attr2->type]) &&
1405         ((attr1->mode.mode & NFSTYPE_FMT) != sattr_types[0]) ||
1406         ((attr1->mode.mode & NFSMODE_FMT) != (attr2->mode & NFSMODE_FMT)))) {
1407         if (ret) {
1408             verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1409                                                 fname, op);
1410
1411         }
1412         verror(VAL_BATCH, E, "    mode: returned = %7o, specified = %7o\n",
1413                                 attr1->mode.mode, attr2->mode);
1414         ret = FALSE;
1415     }
1416 #endif
1417
1418     /*
1419      * Check for user "nobody", UID -2, which may be untranslated from
1420      * sixteen-bit two's complement.
1421      */
1422     if (attr1->uid.set_it == TRUE && attr1->uid.uid != attr2->uid &&
1423                         !((attr2->uid == (unsigned int)0xFFFFFFFE ||
1424                                                 attr2->uid == 65534) &&
1425                                                 attr1->uid.uid == 0)) {
1426         if (ret) {
1427             verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1428                                                 fname, op);
1429         }
1430         if (attr1->uid.uid == 0)
1431             (void) strcat(msg," (is root UID mapped to other UID?)");
1432         verror(VAL_BATCH, E, "    uid: returned = %lu, specified = %lu %s\n",
1433                                 attr2->uid, attr1->uid.uid, msg);
1434         ret = FALSE;
1435     }
1436
1437     if (attr1->gid.set_it == TRUE && attr1->gid.gid != attr2->gid &&
1438                                                         attr2->gid != 0) {
1439 /*
1440    if (attr1->gid.set_it == TRUE && attr1->gid != attr2->gid) {
1441 */
1442         if (ret) {
1443             verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1444                     fname, op);
1445         }
1446         verror(VAL_BATCH, E, "    gid: returned = %lu, specified = %lu\n",
1447                 attr2->gid, attr1->gid.gid);
1448         ret = FALSE;
1449     }
1450
1451     if (attr1->size.set_it == TRUE &&
1452                                 attr1->size.size._p._l != attr2->size._p._l) {
1453         if (ret) {
1454             verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1455                     fname, op);
1456         }
1457         verror(VAL_BATCH, E, "    size: returned = %lu, specified = %lu\n",
1458                 attr2->size._p._l, attr1->size.size._p._l);
1459         ret = FALSE;
1460     }
1461
1462     if (!ret)
1463         verror(VAL_BATCH, W,"\n");
1464
1465     return(ret);
1466
1467 } /* compare_sattr */
1468
1469
1470 /*
1471  * Return the BSD checksum of buf[0..len-1]
1472  */
1473 static uint16_t
1474 sum(
1475     unsigned char *     buf,
1476     int                 len)
1477 {
1478     uint16_t      cksum;
1479
1480     cksum = 0;
1481     for (; len--; buf++) {
1482         if (cksum & 01)
1483             cksum = (cksum >> 1) + 0x8000;
1484         else
1485             cksum >>= 1;
1486         cksum += (uint16_t) *buf;
1487         cksum &= 0xFFFF;
1488     }
1489     return(cksum);
1490
1491 } /* sum */
1492
1493
1494 static void
1495 validate_remove(void)
1496 {
1497     REMOVE3args argrm;
1498     REMOVE3res  reprm;
1499     RMDIR3args  argrd;
1500     RMDIR3res   reprd;
1501     LOOKUP3args arglp;
1502     LOOKUP3res  replp;
1503     nfsstat3    reply;
1504     int         filenum;
1505     char *      op;
1506
1507     for (filenum = 0; filenum < NUMFILES; filenum++) {
1508
1509         if (Io_files[filenum].state != Exists)
1510             continue;
1511
1512         if (Io_files[filenum].attributes3.type == NF3DIR) {
1513             op = Ops[RMDIR].name;
1514             verror(VAL_VERBOSE, I, "validating rmdir %s ...\n",
1515                     Io_files[filenum].file_name);
1516
1517             (void) memmove((char *) &argrd.object.dir,
1518                                 (char *) &Export_dir.fh3,
1519                                 sizeof (nfs_fh3));
1520             argrd.object.name = Io_files[filenum].file_name;
1521             val_op_rmdir(&argrd, &reprd);
1522             reply = reprd.status;
1523         } else {
1524             op = Ops[REMOVE].name;
1525             verror(VAL_VERBOSE, I, "validating remove %s ...\n",
1526                     Io_files[filenum].file_name);
1527
1528             (void) memmove((char *) &argrm.object.dir, (char *) &Export_dir.fh3,
1529                                 sizeof (nfs_fh3));
1530             argrm.object.name = Io_files[filenum].file_name;
1531             val_op_remove(&argrm, &reprm);
1532             reply = reprm.status;
1533         }
1534
1535         if (reply == NFS3_OK) {
1536             /* make sure the file is removed from the directory */
1537             (void) memmove((char *) &arglp.what.dir, (char *) &Export_dir.fh3,
1538                                 sizeof (nfs_fh3));
1539             arglp.what.name = Io_files[filenum].file_name;
1540             val_op_lookup(&arglp, &replp);
1541
1542             if (replp.status == NFS3ERR_NOENT) {
1543                 Io_files[filenum].state = Nonexistent;
1544             } else if (replp.status == NFS3_OK) {
1545                 verror(VAL_BATCH, W, "%s %s: file not removed\n",
1546                        op, Io_files[filenum].file_name);
1547             } else {
1548                 verror(VAL_BATCH, W, "lookup %s failed: %m\n",
1549                        Io_files[filenum].file_name);
1550
1551             }
1552         } else {
1553             verror(VAL_BATCH, W, "%s %s failed: %m\n", op,
1554                     Io_files[filenum].file_name);
1555         }
1556
1557     }
1558
1559 } /* validate_remove */
1560
1561
1562 static void
1563 validate_cleanup(void)
1564 {
1565     free(Io_files);
1566     free(Non_io_files);
1567     free(Dirs);
1568     free(Symlinks);
1569     clnt_destroy(NFS_client);
1570 } /* validate_cleanup */
1571
1572
1573 static void
1574 validate_exit(void)
1575 {
1576     if (!Validate_errors) {
1577         verror(VAL_BATCH, I, "validation completed successfully.\n");
1578         exit(0);
1579     } else {
1580         verror(VAL_BATCH, I, "validation terminated with errors\n");
1581         exit(1);
1582     }
1583
1584 } /* validate_exit */
1585
1586
1587 /* PRINTFLIKE3 */ 
1588 static void
1589 verror(
1590     int         opt,
1591     ValMsgType  msgtype,
1592     char *      fmt,
1593     ...)
1594 {
1595     va_list     ap;
1596     char        buf[1024];
1597     char *      bp = buf;
1598     char *      fp;
1599     char *      sp;
1600     int         repeat;
1601
1602     va_start(ap, fmt);
1603
1604     /*
1605      * Expand the "%m" format character into the descriptive string
1606      * for the current value of errno.  Printf handles the other "%"
1607      * formatting characters.
1608      */
1609     if (Validate >= opt) {
1610         for (fp = fmt; *fp; fp++) {
1611             if (*fp == '%' && fp[1] == 'm') {
1612                 if ((sp = strerror(errno)) == NULL) {
1613                     (void) sprintf(bp, "unknown error %d", errno);
1614                 } else {
1615                     (void) strcpy(bp, sp);
1616                 }
1617                 bp = buf + strlen(buf);
1618                 fp++;
1619             } else {
1620                 *bp++ = *fp;
1621             }
1622         }
1623         *bp = '\0';
1624         (void) vfprintf(stderr, buf, ap);
1625     }
1626     va_end(ap);
1627
1628     if (msgtype != I)
1629         Validate_errors++;
1630
1631     if (msgtype == W && Validate == VAL_INTERACTIVE) {
1632         repeat = 1;
1633         while (repeat) {
1634             char ans[80];
1635
1636             (void) fprintf(stderr, "continue? (y or n)  ");
1637             if (!fgets(ans,80,stdin)) {
1638                 (void) fprintf(stderr, "\n");
1639                 continue;
1640             }
1641             if (ans[0] == 'n' || ans[0] == 'N') {
1642                 validate_exit();
1643                 exit(1);
1644             } else if (ans[0] == 'y' || ans[0] == 'Y') {
1645                 repeat = 0;
1646                 break;
1647             }
1648         }
1649     }
1650
1651 } /* verror */
1652
1653
1654 static void
1655 val_op_null(void)
1656 {
1657         int rpc_stat;
1658  
1659         /* CONSTCOND */
1660         while (1) {
1661             rpc_stat = clnt_call(NFS_client, NFSPROC3_NULL, 
1662                 xdr_void, (char *)0, xdr_void, (char *)0, 
1663                 Nfs_timers[Ops[NULLCALL].call_class]);
1664             if (rpc_stat == RPC_SUCCESS)
1665                 break;
1666             if (rpc_stat != RPC_TIMEDOUT) {
1667                 clnt_perror(NFS_client, "null");
1668                 Validate_errors++;
1669                 validate_exit();
1670             }
1671         }
1672 }
1673
1674 static void
1675 val_op_getattr(GETATTR3args *args, GETATTR3res *reply)
1676 {
1677         int rpc_stat;
1678  
1679         /* CONSTCOND */
1680         while (1) {
1681             rpc_stat = clnt_call(NFS_client, NFSPROC3_GETATTR, 
1682                 xdr_GETATTR3args, (char *)args, xdr_GETATTR3res, (char *)reply, 
1683                 Nfs_timers[Ops[GETATTR].call_class]);
1684             if (rpc_stat == RPC_SUCCESS)
1685                 break;
1686             if (rpc_stat != RPC_TIMEDOUT) {
1687                 clnt_perror(NFS_client, "getattr");
1688                 Validate_errors++;
1689                 validate_exit();
1690             }
1691         }
1692 }
1693
1694 static void
1695 val_op_setattr(SETATTR3args *args, SETATTR3res *reply)
1696 {
1697         int rpc_stat;
1698  
1699         /* CONSTCOND */
1700         while (1) {
1701             rpc_stat = clnt_call(NFS_client, NFSPROC3_SETATTR, 
1702                 xdr_SETATTR3args, (char *)args, xdr_SETATTR3res, (char *)reply, 
1703                 Nfs_timers[Ops[SETATTR].call_class]);
1704             if (rpc_stat == RPC_SUCCESS)
1705                 break;
1706             if (rpc_stat != RPC_TIMEDOUT) {
1707                 clnt_perror(NFS_client, "setattr");
1708                 Validate_errors++;
1709                 validate_exit();
1710             }
1711         }
1712 }
1713
1714 static void
1715 val_op_lookup(LOOKUP3args *args, LOOKUP3res *reply)
1716 {
1717         int rpc_stat;
1718  
1719         /* CONSTCOND */
1720         while (1) {
1721             rpc_stat = clnt_call(NFS_client, NFSPROC3_LOOKUP, 
1722                 xdr_LOOKUP3args, (char *)args, xdr_LOOKUP3res, (char *)reply, 
1723                 Nfs_timers[Ops[LOOKUP].call_class]);
1724             if (rpc_stat == RPC_SUCCESS)
1725                 break;
1726             if (rpc_stat != RPC_TIMEDOUT) {
1727                 clnt_perror(NFS_client, "lookup");
1728                 Validate_errors++;
1729                 validate_exit();
1730             }
1731         }
1732 }
1733
1734 static void
1735 val_op_access(ACCESS3args *args, ACCESS3res *reply)
1736 {
1737         int rpc_stat;
1738  
1739         /* CONSTCOND */
1740         while (1) {
1741             rpc_stat = clnt_call(NFS_client, NFSPROC3_ACCESS, 
1742                 xdr_ACCESS3args, (char *)args, xdr_ACCESS3res, (char *)reply, 
1743                 Nfs_timers[Ops[ACCESS].call_class]);
1744             if (rpc_stat == RPC_SUCCESS)
1745                 break;
1746             if (rpc_stat != RPC_TIMEDOUT) {
1747                 clnt_perror(NFS_client, "access");
1748                 Validate_errors++;
1749                 validate_exit();
1750             }
1751         }
1752 }
1753
1754 static void
1755 val_op_readlink(READLINK3args *args, READLINK3res *reply)
1756 {
1757         int rpc_stat;
1758  
1759         /* CONSTCOND */
1760         while (1) {
1761             rpc_stat = clnt_call(NFS_client, NFSPROC3_READLINK, 
1762                 xdr_READLINK3args, (char *)args, xdr_READLINK3res, (char *)reply, 
1763                 Nfs_timers[Ops[READLINK].call_class]);
1764             if (rpc_stat == RPC_SUCCESS)
1765                 break;
1766             if (rpc_stat != RPC_TIMEDOUT) {
1767                 clnt_perror(NFS_client, "readlink");
1768                 Validate_errors++;
1769                 validate_exit();
1770             }
1771         }
1772 }
1773
1774 static void
1775 val_op_read(READ3args *args, READ3res *reply)
1776 {
1777         int rpc_stat;
1778  
1779         /* CONSTCOND */
1780         while (1) {
1781             rpc_stat = clnt_call(NFS_client, NFSPROC3_READ, 
1782                 xdr_READ3args, (char *)args, xdr_READ3res, (char *)reply, 
1783                 Nfs_timers[Ops[READ].call_class]);
1784             if (rpc_stat == RPC_SUCCESS)
1785                 break;
1786             if (rpc_stat != RPC_TIMEDOUT) {
1787                 clnt_perror(NFS_client, "read");
1788                 Validate_errors++;
1789                 validate_exit();
1790             }
1791         }
1792 }
1793
1794 static void
1795 val_op_write(WRITE3args *args, WRITE3res *reply)
1796 {
1797         int rpc_stat;
1798  
1799         /* CONSTCOND */
1800         while (1) {
1801             rpc_stat = clnt_call(NFS_client, NFSPROC3_WRITE, 
1802                 xdr_WRITE3args, (char *)args, xdr_WRITE3res, (char *)reply, 
1803                 Nfs_timers[Ops[WRITE].call_class]);
1804             if (rpc_stat == RPC_SUCCESS)
1805                 break;
1806             if (rpc_stat != RPC_TIMEDOUT) {
1807                 clnt_perror(NFS_client, "write");
1808                 Validate_errors++;
1809                 validate_exit();
1810             }
1811         }
1812 }
1813
1814 static void
1815 val_op_create(CREATE3args *args, CREATE3res *reply)
1816 {
1817         int rpc_stat;
1818  
1819         /* CONSTCOND */
1820         while (1) {
1821             rpc_stat = clnt_call(NFS_client, NFSPROC3_CREATE, 
1822                 xdr_CREATE3args, (char *)args, xdr_CREATE3res, (char *)reply, 
1823                 Nfs_timers[Ops[CREATE].call_class]);
1824             if (rpc_stat == RPC_SUCCESS)
1825                 break;
1826             if (rpc_stat != RPC_TIMEDOUT) {
1827                 clnt_perror(NFS_client, "create");
1828                 Validate_errors++;
1829                 validate_exit();
1830             }
1831         }
1832 }
1833
1834 static void
1835 val_op_mkdir(MKDIR3args *args, MKDIR3res *reply)
1836 {
1837         int rpc_stat;
1838  
1839         /* CONSTCOND */
1840         while (1) {
1841             rpc_stat = clnt_call(NFS_client, NFSPROC3_MKDIR, 
1842                 xdr_MKDIR3args, (char *)args, xdr_MKDIR3res, (char *)reply, 
1843                 Nfs_timers[Ops[MKDIR].call_class]);
1844             if (rpc_stat == RPC_SUCCESS)
1845                 break;
1846             if (rpc_stat != RPC_TIMEDOUT) {
1847                 clnt_perror(NFS_client, "mkdir");
1848                 Validate_errors++;
1849                 validate_exit();
1850             }
1851         }
1852 }
1853
1854 static void
1855 val_op_symlink(SYMLINK3args *args, SYMLINK3res *reply)
1856 {
1857         int rpc_stat;
1858  
1859         /* CONSTCOND */
1860         while (1) {
1861             rpc_stat = clnt_call(NFS_client, NFSPROC3_SYMLINK, 
1862                 xdr_SYMLINK3args, (char *)args, xdr_SYMLINK3res, (char *)reply, 
1863                 Nfs_timers[Ops[SYMLINK].call_class]);
1864             if (rpc_stat == RPC_SUCCESS)
1865                 break;
1866             if (rpc_stat != RPC_TIMEDOUT) {
1867                 clnt_perror(NFS_client, "symlink");
1868                 Validate_errors++;
1869                 validate_exit();
1870             }
1871         }
1872 }
1873
1874 static void
1875 val_op_mknod(MKNOD3args *args, MKNOD3res *reply)
1876 {
1877         int rpc_stat;
1878  
1879         /* CONSTCOND */
1880         while (1) {
1881             rpc_stat = clnt_call(NFS_client, NFSPROC3_MKNOD, 
1882                 xdr_MKNOD3args, (char *)args, xdr_MKNOD3res, (char *)reply, 
1883                 Nfs_timers[Ops[MKNOD].call_class]);
1884             if (rpc_stat == RPC_SUCCESS)
1885                 break;
1886             if (rpc_stat != RPC_TIMEDOUT) {
1887                 clnt_perror(NFS_client, "mknod");
1888                 Validate_errors++;
1889                 validate_exit();
1890             }
1891         }
1892 }
1893
1894 static void
1895 val_op_remove(REMOVE3args *args, REMOVE3res *reply)
1896 {
1897         int rpc_stat;
1898  
1899         /* CONSTCOND */
1900         while (1) {
1901             rpc_stat = clnt_call(NFS_client, NFSPROC3_REMOVE, 
1902                 xdr_REMOVE3args, (char *)args, xdr_REMOVE3res, (char *)reply, 
1903                 Nfs_timers[Ops[REMOVE].call_class]);
1904             if (rpc_stat == RPC_SUCCESS)
1905                 break;
1906             if (rpc_stat != RPC_TIMEDOUT) {
1907                 clnt_perror(NFS_client, "remove");
1908                 Validate_errors++;
1909                 validate_exit();
1910             }
1911         }
1912 }
1913
1914 static void
1915 val_op_rmdir(RMDIR3args *args, RMDIR3res *reply)
1916 {
1917         int rpc_stat;
1918  
1919         /* CONSTCOND */
1920         while (1) {
1921             rpc_stat = clnt_call(NFS_client, NFSPROC3_RMDIR, 
1922                 xdr_RMDIR3args, (char *)args, xdr_RMDIR3res, (char *)reply, 
1923                 Nfs_timers[Ops[RMDIR].call_class]);
1924             if (rpc_stat == RPC_SUCCESS)
1925                 break;
1926             if (rpc_stat != RPC_TIMEDOUT) {
1927                 clnt_perror(NFS_client, "rmdir");
1928                 Validate_errors++;
1929                 validate_exit();
1930             }
1931         }
1932 }
1933
1934 static void
1935 val_op_rename(RENAME3args *args, RENAME3res *reply)
1936 {
1937         int rpc_stat;
1938  
1939         /* CONSTCOND */
1940         while (1) {
1941             rpc_stat = clnt_call(NFS_client, NFSPROC3_RENAME, 
1942                 xdr_RENAME3args, (char *)args, xdr_RENAME3res, (char *)reply, 
1943                 Nfs_timers[Ops[RENAME].call_class]);
1944             if (rpc_stat == RPC_SUCCESS)
1945                 break;
1946             if (rpc_stat != RPC_TIMEDOUT) {
1947                 clnt_perror(NFS_client, "rename");
1948                 Validate_errors++;
1949                 validate_exit();
1950             }
1951         }
1952 }
1953
1954 static void
1955 val_op_link(LINK3args *args, LINK3res *reply)
1956 {
1957         int rpc_stat;
1958  
1959         /* CONSTCOND */
1960         while (1) {
1961             rpc_stat = clnt_call(NFS_client, NFSPROC3_LINK, 
1962                 xdr_LINK3args, (char *)args, xdr_LINK3res, (char *)reply, 
1963                 Nfs_timers[Ops[LINK].call_class]);
1964             if (rpc_stat == RPC_SUCCESS)
1965                 break;
1966             if (rpc_stat != RPC_TIMEDOUT) {
1967                 clnt_perror(NFS_client, 
1968                     "link");
1969                 Validate_errors++;
1970                 validate_exit();
1971             }
1972         }
1973 }
1974
1975 static void
1976 val_op_readdir(READDIR3args *args, READDIR3res *reply)
1977 {
1978         int rpc_stat;
1979  
1980         /* CONSTCOND */
1981         while (1) {
1982             rpc_stat = clnt_call(NFS_client, NFSPROC3_READDIR, 
1983                 xdr_READDIR3args, (char *)args, xdr_READDIR3res, (char *)reply, 
1984                 Nfs_timers[Ops[READDIR].call_class]);
1985             if (rpc_stat == RPC_SUCCESS)
1986                 break;
1987             if (rpc_stat != RPC_TIMEDOUT) {
1988                 clnt_perror(NFS_client, "readdir");
1989                 Validate_errors++;
1990                 validate_exit();
1991             }
1992         }
1993 }
1994
1995 static void
1996 val_op_readdirplus(READDIRPLUS3args *args, READDIRPLUS3res *reply)
1997 {
1998         int rpc_stat;
1999  
2000         /* CONSTCOND */
2001         while (1) {
2002             rpc_stat = clnt_call(NFS_client,
2003                 NFSPROC3_READDIRPLUS, xdr_READDIRPLUS3args, (char *)args, 
2004                 xdr_READDIRPLUS3res, (char *)reply, 
2005                 Nfs_timers[Ops[READDIRPLUS].call_class]);
2006             if (rpc_stat == RPC_SUCCESS)
2007                 break;
2008             if (rpc_stat != RPC_TIMEDOUT) {
2009                 clnt_perror(NFS_client,
2010                     "readdirplus");
2011                 Validate_errors++;
2012                 validate_exit();
2013             }
2014         }
2015 }
2016
2017 static void
2018 val_op_fsstat(FSSTAT3args *args, FSSTAT3res *reply)
2019 {
2020         int rpc_stat;
2021  
2022         /* CONSTCOND */
2023         while (1) {
2024             rpc_stat = clnt_call(NFS_client, NFSPROC3_FSSTAT, 
2025                 xdr_FSSTAT3args, (char *)args, xdr_FSSTAT3res, (char *)reply, 
2026                 Nfs_timers[Ops[FSSTAT].call_class]);
2027             if (rpc_stat == RPC_SUCCESS)
2028                 break;
2029             if (rpc_stat != RPC_TIMEDOUT) {
2030                 clnt_perror(NFS_client, "fsstat");
2031                 Validate_errors++;
2032                 validate_exit();
2033             }
2034         }
2035 }
2036
2037 static void
2038 val_op_fsinfo(FSINFO3args *args, FSINFO3res *reply)
2039 {
2040         int rpc_stat;
2041  
2042         /* CONSTCOND */
2043         while (1) {
2044             rpc_stat = clnt_call(NFS_client, NFSPROC3_FSINFO, 
2045                 xdr_FSINFO3args, (char *)args, xdr_FSINFO3res, (char *)reply, 
2046                 Nfs_timers[Ops[FSINFO].call_class]);
2047             if (rpc_stat == RPC_SUCCESS)
2048                 break;
2049             if (rpc_stat != RPC_TIMEDOUT) {
2050                 clnt_perror(NFS_client, "fsinfo");
2051                 Validate_errors++;
2052                 validate_exit();
2053             }
2054         }
2055 }
2056
2057 static void
2058 val_op_pathconf(PATHCONF3args *args, PATHCONF3res *reply)
2059 {
2060         int rpc_stat;
2061  
2062         /* CONSTCOND */
2063         while (1) {
2064             rpc_stat = clnt_call(NFS_client, NFSPROC3_PATHCONF, 
2065                 xdr_PATHCONF3args, (char *)args, xdr_PATHCONF3res, (char *)reply, 
2066                 Nfs_timers[Ops[PATHCONF].call_class]);
2067             if (rpc_stat == RPC_SUCCESS)
2068                 break;
2069             if (rpc_stat != RPC_TIMEDOUT) {
2070                 clnt_perror(NFS_client, "pathconf");
2071                 Validate_errors++;
2072                 validate_exit();
2073             }
2074         }
2075 }
2076
2077 static void
2078 val_op_commit(COMMIT3args *args, COMMIT3res *reply)
2079 {
2080         int rpc_stat;
2081  
2082         /* CONSTCOND */
2083         while (1) {
2084             rpc_stat = clnt_call(NFS_client, NFSPROC3_COMMIT, 
2085                 xdr_COMMIT3args, (char *)args, xdr_COMMIT3res, (char *)reply, 
2086                 Nfs_timers[Ops[COMMIT].call_class]);
2087             if (rpc_stat == RPC_SUCCESS)
2088                 break;
2089             if (rpc_stat != RPC_TIMEDOUT) {
2090                 clnt_perror(NFS_client, "commit");
2091                 Validate_errors++;
2092                 validate_exit();
2093             }
2094         }
2095 }
2096
2097 static void
2098 create_3tmp_handles(void)
2099 {
2100         int filenum;
2101         for (filenum = 0; filenum < NUMFILES; filenum++) {
2102
2103                 if(Io_files[filenum].fh_data == (sfs_fh_data *)0)
2104                 {
2105                         Io_files[filenum].fh_data = 
2106                                         calloc(1,sizeof(sfs_fh_data));
2107                         Io_files[filenum].attributes2.type = NFNON;
2108                         Io_files[filenum].attributes3.type = NF3NON;
2109                 }
2110         }
2111 }
2112
2113 static void
2114 delete_3tmp_handles(void)
2115 {
2116         int filenum;
2117         for (filenum = 0; filenum < NUMFILES; filenum++) {
2118
2119                 if(Io_files[filenum].fh_data != (sfs_fh_data *)0)
2120                 {
2121                         free(Io_files[filenum].fh_data);
2122                         Io_files[filenum].fh_data= (sfs_fh_data *)0;
2123                 }
2124         }
2125 }
2126 /* sfs_3_vld.c */