Import TBBT (NFS trace replay).
[bluesky.git] / TBBT / trace_play / sfs_2_vld.c
1 #ifndef lint
2 static char sfs_c_vldSid[] = "@(#)sfs_2_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_c_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 *, sattr *, fattr *)
50  *      int compare_fattr(char *, char *, fattr *, fattr *)
51  *      uint16_t sum(unsigned char *, uint_t)
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  *      04-Dec-91       Keith           Define string.h for SYSV/SVR4.
59  *      25-Jun-91       Wiryaman        Created
60  */
61
62
63 /*
64  * -------------------------  Include Files  -------------------------
65  */
66
67 /*
68  * ANSI C headers
69  */
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <errno.h>
74 #include <stdarg.h>
75
76 #include <sys/types.h>
77 #include <sys/stat.h> 
78  
79 #include <unistd.h>
80
81 #include "sfs_c_def.h"
82
83 extern struct hostent   *Server_hostent;
84
85 /*
86  * -----------------------  External Definitions  -----------------------
87  */
88
89 /* forward definitions for local routines */
90 /*
91  * validate options
92  * BATCH        - do complete pass of validation, reporting errors if any
93  * VERBOSE      - prints step-by-step validation actions being performed
94  * INTERACTIVE  - VERBOSE and if any errors encountered, ask to continue
95  *                validation or not.
96  */
97 #define VAL_BATCH       1
98 #define VAL_VERBOSE     2
99 #define VAL_INTERACTIVE 3
100
101 typedef enum {
102         I = 1,
103         W = 2,
104         E = 3
105 } ValMsgType;
106
107 #define NUMREGFILES     7
108 #define NUMDIRS         5
109 #define NUMLINKS        5
110 #define NUMSYMLINKS     5
111 #define NUMFILES        NUMREGFILES + NUMDIRS + NUMLINKS + NUMSYMLINKS
112 #define NUMFRAGS        8
113
114 static void validate_init_rpc(void);
115 static void validate_exit(void);
116 static void validate_creation(void);
117 static void validate_attributes(void);
118 static void validate_read_write(void);
119 static void validate_rename(void);
120 static void validate_remove(void);
121 static void validate_cleanup(void);
122 static int compare_sattr(char *, char *, sattr *, fattr *);
123 static int compare_fattr(char *, char *, fattr *, fattr *);
124 static uint16_t sum(unsigned char *, uint_t);
125 static void verror(int, ValMsgType, char *, ...);
126
127 static void val_op_null(void);
128 static void val_op_getattr(fhandle_t *, attrstat *);
129 static void val_op_setattr(sattrargs *, attrstat *);
130 static void val_op_lookup(diropargs *, diropres *);
131 static void val_op_readlink(fhandle_t *, readlinkres *);
132 static void val_op_read(readargs *, readres *);
133 static void val_op_write(writeargs *, attrstat *);
134 static void val_op_create(createargs *, diropres *);
135 static void val_op_remove(diropargs *, nfsstat *);
136 static void val_op_rename(renameargs *, nfsstat *);
137 static void val_op_link(linkargs *, nfsstat *);
138 static void val_op_symlink(symlinkargs *, nfsstat *);
139 static void val_op_mkdir(mkdirargs *, diropres *);
140 static void val_op_rmdir(diropargs *, nfsstat *);
141 static void val_op_readdir(readdirargs *, readdirres *);
142 static void val_op_statfs(fhandle_t *, statfsres *);
143 static void create_tmp_handles(void);
144 static void delete_tmp_handles(void);
145
146 /*
147  * ----------------------  Static Declarations ----------------------
148  */
149
150 int Validate;
151
152 static int Validate_errors = 0;
153 static char Testdirname[SFS_MAXPATHLEN];    /* test dir component name */
154
155 /*
156  * ----------------------  SFS Validation Suite  ----------------------
157  */
158
159 void
160 Validate_ops(
161     int         argc,
162     char *      argv[])
163 {
164     char *      valdir;
165     CLIENT *    mount_client_ptr;
166
167     if (argc > 1) {
168         verror(VAL_BATCH, E, "Can only validate one directory at a time.\n");
169         exit(1);
170     }
171
172     Num_io_files = NUMFILES;
173     Cur_uid = Real_uid;
174     nfs_version = NFS_VERSION;
175
176     if (argc == 0)
177         valdir = ".";
178     else
179         valdir = argv++[0];
180
181     (void) sprintf(Testdirname, "%s/validatedir", valdir);
182
183     do {
184         verror(VAL_BATCH, I, "validating sfs on \"%s\" directory ...\n",
185                 valdir);
186
187         init_fileinfo();
188         create_tmp_handles();
189
190         /*
191          * need priv port to do following
192          */
193         mount_client_ptr = lad_getmnt_hand(valdir);
194         if (mount_client_ptr == NULL) {
195             exit(1);
196         }
197         validate_init_rpc();
198
199         /*
200          * should be all done doing priv port stuff
201          */
202         if (setuid(Real_uid) != 0) {
203            (void) fprintf(stderr,"%s: %s%s\n",
204                    sfs_Myname, "cannot perform setuid operation.\n",
205                    "Do `make install` as root.\n");
206         }
207
208         init_mount_point(0, valdir, mount_client_ptr);
209         verror(VAL_VERBOSE, I, "validating null operation ...\n");
210         val_op_null();
211
212         validate_creation();
213         validate_attributes();
214         validate_read_write();
215         validate_rename();
216         validate_remove();
217         argc--;
218         valdir = argv++[0];
219
220         /*
221          * Cleanup mount client handle
222          */
223         clnt_destroy(mount_client_ptr);
224
225         delete_tmp_handles();
226         validate_cleanup();
227
228     } while (argc > 0);
229
230     validate_exit();
231
232 } /* Validate_ops */
233
234
235 /*
236  * allocate and initialize client handles
237  */
238 static void
239 validate_init_rpc(void)
240 {
241         NFS_client = lad_clnt_create(Tcp? 1: 0, Server_hostent,
242                                         (uint32_t) NFS_PROGRAM,
243                                         (uint32_t) NFS_VERSION,
244                                         RPC_ANYSOCK, &Nfs_timers[0]);
245  
246         if (NFS_client == ((CLIENT *) NULL)) { 
247                 verror(VAL_BATCH, E, "portmap/nfsd server not responding\n"); 
248                 exit(1); 
249         }
250  
251         NFS_client->cl_auth = authunix_create(lad_hostname, Real_uid,
252                                       Cur_gid, 0, NULL);
253 } /* validate_init_rpc */
254
255
256 static void
257 validate_creation(void)
258 {
259     int                 filenum;
260     int                 target_filenum;
261     diropargs           arglp;
262     createargs          argcr;
263     mkdirargs           argmk;
264     linkargs            argln;
265     symlinkargs         argsl;
266     char                sl_target_path[NFS_MAXPATHLEN];
267     diropres            reply;
268     readlinkres         rlreply;
269     char                sym_data[NFS_MAXPATHLEN];
270
271     for (filenum=0; filenum < NUMFILES ; filenum++) {
272
273         Cur_file_ptr = &Io_files[filenum];
274         sfs_gettime(&Cur_time);
275
276         if (filenum < NUMREGFILES) {
277
278             (void) sprintf(Cur_filename, Filespec, filenum);
279
280             /* regular file creation */
281             argcr.attributes.mode= (NFSMODE_REG | 0666);
282             argcr.attributes.uid = Cur_uid;
283             argcr.attributes.gid = Cur_gid;
284             argcr.attributes.atime.seconds = (unsigned int) Cur_time.esec;
285             argcr.attributes.atime.useconds = (unsigned int) Cur_time.usec;
286             argcr.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
287             argcr.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
288             argcr.attributes.size = 0;
289             (void) memmove((char *) &argcr.where.dir, (char *) &Export_dir.fh2,
290                         NFS_FHSIZE);
291             argcr.where.name = Cur_filename;
292
293             verror(VAL_VERBOSE, I, "validating create file %s ...\n",
294                                         Cur_filename);
295             val_op_create(&argcr, &reply);
296
297             if (reply.status == NFS_OK) {
298                 Cur_file_ptr->state = Exists;
299                 (void) memmove((char *) &Cur_file_ptr->fh2,
300                         (char *) &reply.diropres_u.diropres.file, NFS_FHSIZE);
301                 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
302                 (void) memmove((char *) &Cur_file_ptr->attributes2,
303                                 (char *) &reply.diropres_u.diropres.attributes,
304                                 sizeof(Cur_file_ptr->attributes2));
305                 (void) compare_sattr(Ops[CREATE].name, Io_files[filenum].file_name,
306                             &argcr.attributes, &Cur_file_ptr->attributes2);
307             } else {
308                 Cur_file_ptr->state = Nonexistent;
309                 errno = (int)reply.status;
310                 verror(VAL_BATCH, E, "create %s failed: %m\n", Cur_filename);
311                 /*
312                  * An error in file creation is fatal, because we use the
313                  * created files to validate the other operations.
314                  */
315                 validate_exit();
316             }
317
318         } else if (filenum < NUMREGFILES + NUMDIRS) {
319
320             (void) sprintf(Cur_filename, Dirspec, filenum);
321
322             /* directory creation */
323             argmk.attributes.mode= (NFSMODE_DIR | 0777);
324             argmk.attributes.uid = Cur_uid;
325             argmk.attributes.gid = Cur_gid;
326             argmk.attributes.size = 0xFFFFFFFF;
327             argmk.attributes.atime.seconds = (unsigned int) Cur_time.esec;
328             argmk.attributes.atime.useconds = (unsigned int) Cur_time.usec;
329             argmk.attributes.mtime.seconds = (unsigned int) Cur_time.esec;
330             argmk.attributes.mtime.useconds = (unsigned int) Cur_time.usec;
331             (void) memmove((char *) &argmk.where.dir, (char *) &Export_dir.fh2,
332                         NFS_FHSIZE);
333             argmk.where.name = Cur_filename;
334
335             verror(VAL_VERBOSE, I, "validating mkdir %s ...\n", Cur_filename);
336             val_op_mkdir(&argmk, &reply);
337
338             if (reply.status == NFS_OK) {
339                 Cur_file_ptr->state = Exists;
340                 (void) memmove((char *) &Cur_file_ptr->fh2,
341                         (char *) &reply.diropres_u.diropres.file,
342                         NFS_FHSIZE);
343                 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
344                 (void) memmove((char *) &Cur_file_ptr->attributes2,
345                                 (char *) &reply.diropres_u.diropres.attributes,
346                                 sizeof(Cur_file_ptr->attributes2));
347                 (void) compare_sattr(Ops[MKDIR].name, Io_files[filenum].file_name,
348                                 &argmk.attributes, &Cur_file_ptr->attributes2);
349             } else {
350                 Cur_file_ptr->state = Nonexistent;
351                 verror(VAL_BATCH, W, "mkdir %s failed:%m\n", Cur_filename);
352             }
353
354         } else if(filenum < NUMREGFILES + NUMDIRS + NUMLINKS ) {
355
356             (void) sprintf(Cur_filename, Filespec, filenum);
357
358             /* hard link creation */
359             target_filenum = NUMFILES-NUMSYMLINKS-1-filenum;
360             (void) memmove((char *) &argln.from,
361                         (char *) &Io_files[target_filenum].fh2, NFS_FHSIZE);
362             (void) memmove((char *) &argln.to.dir, (char *) &Export_dir.fh2,
363                         NFS_FHSIZE);
364             argln.to.name = Cur_filename;
365
366             verror(VAL_VERBOSE, I, "validating link %s %s ...\n",
367                                 Io_files[target_filenum].file_name, Cur_filename);
368             val_op_link(&argln, &reply.status);
369
370             if (reply.status == NFS_OK) {
371                 Cur_file_ptr->state = Exists;
372                 (void) memmove((char *) &Cur_file_ptr->fh2,
373                         (char *) &Io_files[target_filenum].fh2,
374                         NFS_FHSIZE);
375                 (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
376                 Cur_file_ptr->attributes2 = Io_files[target_filenum].attributes2;
377                 Io_files[target_filenum].attributes2.nlink++;
378                 Cur_file_ptr->attributes2.nlink++;
379             } else {
380                 Cur_file_ptr->state = Nonexistent;
381                 verror(VAL_BATCH, W, "link %s failed: %m\n", Cur_filename);
382             }
383
384         } else {
385
386             (void) sprintf(Cur_filename, Symspec, filenum);
387
388             /* symbolic link creation */
389             target_filenum = NUMFILES-1-filenum;
390             (void) memmove((char *) &argsl.from.dir, (char *) &Export_dir.fh2,
391                         NFS_FHSIZE);
392             argsl.from.name = Cur_filename;
393             (void) sprintf(sl_target_path,
394                            "./%s", Io_files[target_filenum].file_name);
395             argsl.attributes.size = strlen(sl_target_path);
396             argsl.to = sl_target_path;
397             argsl.attributes.mode = (NFSMODE_LNK | 0777);
398             argsl.attributes.uid = Cur_uid;
399             argsl.attributes.gid = Cur_gid;
400             argsl.attributes.atime.seconds = (unsigned int)Cur_time.esec;
401             argsl.attributes.atime.useconds = (unsigned int)Cur_time.usec;
402             argsl.attributes.mtime.seconds = (unsigned int)Cur_time.esec;
403             argsl.attributes.mtime.useconds = (unsigned int)Cur_time.usec;
404
405             verror(VAL_VERBOSE, I, "validating symlink %s %s ...\n",
406                                         sl_target_path, Cur_filename);
407             val_op_symlink(&argsl, &reply.status);
408
409             if (reply.status == NFS_OK) {
410                 Cur_file_ptr->state = Exists;
411
412                 /* do a lookup to get file handle and attributes */
413                 (void) memmove((char *) &arglp.dir, (char *) &Export_dir.fh2,
414                         NFS_FHSIZE);
415                 arglp.name = Cur_filename;
416
417                 val_op_lookup(&arglp, &reply);
418
419                 if (reply.status == NFS_OK) {
420                     (void) memmove((char *) &Cur_file_ptr->fh2,
421                         (char *) &reply.diropres_u.diropres.file, NFS_FHSIZE);
422                     (void) strcpy(Cur_file_ptr->file_name, Cur_filename);
423                     Cur_file_ptr->attributes2 =
424                                         reply.diropres_u.diropres.attributes;
425                     (void) compare_sattr(Ops[SYMLINK].name,
426                                         Io_files[filenum].file_name,
427                                         &argsl.attributes,
428                                         &Cur_file_ptr->attributes2);
429                 } else {
430                     verror(VAL_BATCH, W, "lookup %s failed: %m\n",
431                                                 Cur_filename);
432                     continue;
433                 }
434
435                 /* validate readlink */
436                 rlreply.readlinkres_u.data = sym_data;
437
438                 verror(VAL_VERBOSE, I, "validating readlink %s ...\n",
439                                                 Cur_filename);
440                 val_op_readlink(&Cur_file_ptr->fh2, &rlreply);
441
442                 if (rlreply.status == NFS_OK) {
443                     sym_data[rlreply.readlinkres_u.len] = '\0';
444                     if (strcmp(sl_target_path, sym_data)) {
445                         verror(VAL_BATCH, W,
446                             "readlink %s error, result = %s, should be %s\n",
447                             Cur_filename, rlreply.readlinkres_u.data,
448                             sl_target_path);
449                     }
450                 } else {
451                     verror(VAL_BATCH, W, "readlink %s failed:%m\n",
452                             Cur_filename);
453                 }
454
455             } else {
456                 Cur_file_ptr->state = Nonexistent;
457                 verror(VAL_BATCH, W, "symlink %s failed: %m\n",
458                         Cur_filename);
459             }
460         }
461     } /* end for each file */
462
463 } /* validate_creation */
464
465
466 static void
467 validate_attributes(void)
468 {
469     int                 filenum;
470     diropargs           arglp;
471     diropres            lreply;
472     fhandle_t           fh;
473     sattrargs           argsa;
474     attrstat            areply;
475
476     /* validate fsstat */
477
478     /* validate lookup */
479     for (filenum = 0; filenum < NUMFILES; filenum++) {
480         (void) memmove((char *) &arglp.dir, (char *) &Export_dir.fh2,
481                         NFS_FHSIZE);
482         arglp.name = Io_files[filenum].file_name;
483
484         verror(VAL_VERBOSE, I, "validating lookup %s ...\n",
485                 Io_files[filenum].file_name);
486         val_op_lookup(&arglp, &lreply);
487
488         if (lreply.status == NFS_OK) {
489             if (memcmp((char *) &(Io_files[filenum].fh2),
490                      (char *) &(lreply.diropres_u.diropres.file),
491                         NFS_FHSIZE)) {
492                 verror(VAL_BATCH, W, "lookup %s: file handle mismatch\n",
493                         Io_files[filenum].file_name);
494             }
495             (void) compare_fattr(Ops[LOOKUP].name, Io_files[filenum].file_name,
496                           &Io_files[filenum].attributes2,
497                           &lreply.diropres_u.diropres.attributes);
498         } else {
499             verror(VAL_BATCH, W, "lookup %s failed:%m\n",
500                     Io_files[filenum].file_name);
501         }
502     }
503
504     /* validate getattr */
505     for (filenum = 0; filenum < NUMFILES; filenum++) {
506         (void) memmove((char *) &fh, (char *) &Io_files[filenum].fh2,
507                         NFS_FHSIZE);
508
509         verror(VAL_VERBOSE, I, "validating getattr %s ...\n",
510                 Io_files[filenum].file_name);
511         val_op_getattr(&fh, &areply);
512
513         if (areply.status == NFS_OK) {
514             (void) compare_fattr(Ops[GETATTR].name, Io_files[filenum].file_name,
515                           &Io_files[filenum].attributes2,
516                           &areply.attrstat_u.attributes);
517         } else {
518             verror(VAL_BATCH, W, "getattr %s failed: %m\n",
519                     Io_files[filenum].file_name);
520         }
521     }
522
523     /*validate setattr */
524     for (filenum = 0; filenum < NUMFILES; filenum++) {
525         sfs_gettime(&Cur_time);
526         if (filenum >= NUMREGFILES && filenum < NUMREGFILES + NUMDIRS)
527           argsa.attributes.mode= 0777;
528         else
529           argsa.attributes.mode= 0666;
530         argsa.attributes.uid  = 0xFFFFFFFF;
531         argsa.attributes.gid  = 0xFFFFFFFF;
532         argsa.attributes.size = 0xFFFFFFFF;
533         argsa.attributes.atime.seconds =  (unsigned int)Cur_time.esec;
534         argsa.attributes.atime.useconds = (unsigned int)Cur_time.usec;
535         argsa.attributes.mtime.seconds =  (unsigned int)Cur_time.esec;
536         argsa.attributes.mtime.useconds = (unsigned int)Cur_time.usec;
537         (void) memmove((char *) &argsa.file, (char *) &Io_files[filenum].fh2,
538                         NFS_FHSIZE);
539
540         verror(VAL_VERBOSE, I, "validating setattr %s ...\n",
541                 Io_files[filenum].file_name);
542         val_op_setattr(&argsa, &areply);
543
544         if (areply.status == NFS_OK) {
545             if (argsa.attributes.mode != areply.attrstat_u.attributes.mode){
546                 argsa.attributes.mode |=
547                         (Io_files[filenum].attributes2.mode & NFSMODE_FMT);
548                 argsa.attributes.mode &= Io_files[filenum].attributes2.mode;
549             }
550             Io_files[filenum].attributes2 = areply.attrstat_u.attributes;
551             (void) compare_sattr(Ops[SETATTR].name, Io_files[filenum].file_name,
552                           &argsa.attributes, &areply.attrstat_u.attributes);
553
554             val_op_getattr(&argsa.file, &areply);
555
556             if (areply.status == NFS_OK) {
557                 (void) compare_fattr(Ops[GETATTR].name, Io_files[filenum].file_name,
558                               &Io_files[filenum].attributes2,
559                               &areply.attrstat_u.attributes);
560             } else {
561                 verror(VAL_BATCH, W, "getattr %s failed: %m\n",
562                         Io_files[filenum].file_name);
563             }
564         } else {
565             verror(VAL_BATCH, W, "setattr %s failed: %m\n",
566                     Io_files[filenum].file_name);
567         }
568     }
569
570 } /* validate_attributes */
571
572
573 static void
574 validate_read_write(void)
575 {
576     struct {
577         uint16_t  sum;                    /* checksum of data */
578         uint16_t  len;                    /* length of len and data */
579         char            data[DEFAULT_MAX_BUFSIZE - 2 * sizeof(uint16_t)];
580     } block;
581     writeargs           argwr;
582     attrstat            wrreply;
583     readargs            argrd;
584     readres             rdreply;
585     int                 maxblks;
586     int                 maxfiles;
587     uint_t              i;
588     int                 numfiles;
589     int                 filenum;
590     int                 blocknum;
591     readdirargs         argrdir;
592     readdirres          rdirreply;
593     int                 entry_cnt = 9;
594     entry               entry_stream[9];
595     char                name_stream[9 * SFS_MAXNAMLEN];
596
597     /* validate write */
598
599     /* get the maximum number of blocks sfs will write */
600     maxblks = Io_dist_ptr->max_bufs;
601     maxfiles = maxblks > NUMREGFILES ? NUMREGFILES : maxblks;
602
603     /* write maxblks - filenum + 1 blocks to each regular file */
604     argwr.offset = 0;
605     argwr.beginoffset = 0; /* unused */
606     argwr.totalcount = 0; /* unused */
607     argwr.data.data_val = (char *)&block;
608
609     for (blocknum = 0; blocknum <= maxblks ; blocknum++) {
610
611         for (i=0; i < sizeof(block.data); i++)
612             block.data[i] = (char)blocknum;
613
614         for (filenum=0; filenum < maxfiles; filenum++) {
615
616             /* Write fewer blocks to files with higher numbers. */
617             if (blocknum > (maxblks - filenum))
618                 break;
619
620             /* set the length field */
621             if (blocknum == (maxblks - filenum)) {
622                 block.len = ((maxfiles - filenum) *
623                             (Bytes_per_block/Kb_per_block)) - (sizeof(block.len)
624                              + sizeof(block.sum));
625             } else {
626                 block.len = Bytes_per_block - (sizeof(block.len)
627                             + sizeof(block.sum));
628             }
629             block.sum = sum((unsigned char *) &block.len,
630                             block.len + sizeof(block.len));
631
632             (void) memmove((char *) &argwr.file,
633                         (char *) &Io_files[filenum].fh2, NFS_FHSIZE);
634             argwr.data.data_len = block.len +
635                                   sizeof(block.len) + sizeof(block.sum);
636
637             verror(VAL_VERBOSE, I,
638                     "validating write %d bytes @ offset %d to %s ...\n",
639                     argwr.data.data_len, argwr.offset,
640                     Io_files[filenum].file_name);
641
642             val_op_write(&argwr, &wrreply);
643
644             if (wrreply.status == NFS_OK) {
645                 (void) compare_fattr(Ops[WRITE].name, Io_files[filenum].file_name,
646                               &Io_files[filenum].attributes2,
647                               &wrreply.attrstat_u.attributes);
648                 Io_files[filenum].attributes2 = wrreply.attrstat_u.attributes;
649             } else {
650                 verror(VAL_BATCH, W, "write %s failed: %m\n",
651                         Io_files[filenum].file_name);
652             }
653         }
654         argwr.offset += Bytes_per_block;
655     }
656
657     /* validate read */
658
659     for (filenum = 0; filenum < maxfiles; filenum++) {
660         (void) memmove((char *) &argrd.file, (char *) &Io_files[filenum].fh2,
661                         NFS_FHSIZE);
662         argrd.offset = 0;
663         argrd.count = 0;
664         rdreply.readres_u.reply.data.data_len = 0;
665         maxblks = Io_files[filenum].attributes2.size / Bytes_per_block;
666         for (blocknum = 0; blocknum <= maxblks; blocknum ++) {
667
668             if (argrd.count != rdreply.readres_u.reply.data.data_len) {
669                 argrd.count -= rdreply.readres_u.reply.data.data_len;
670                 rdreply.readres_u.reply.data.data_val = (char *)&block +
671                                         rdreply.readres_u.reply.data.data_len;
672                 blocknum--;
673             } else {
674                 if (blocknum < maxblks)
675                     argrd.count = Bytes_per_block;
676                 else
677                     argrd.count = (maxfiles - filenum)
678                                   * (Bytes_per_block/Kb_per_block);
679                 rdreply.readres_u.reply.data.data_val = (char *)&block;
680             }
681             argrd.totalcount = argrd.count; /* unused */
682
683             verror(VAL_VERBOSE, I,
684                    "validating read %d bytes @ offset %d from %s ...\n",
685                     argrd.count, argrd.offset,
686                     Io_files[filenum].file_name);
687
688             val_op_read(&argrd, &rdreply);
689
690             if (rdreply.status == NFS_OK) {
691                 (void) compare_fattr(Ops[READ].name, Io_files[filenum].file_name,
692                               &Io_files[filenum].attributes2,
693                               &rdreply.readres_u.reply.attributes);
694                 Io_files[filenum].attributes2 =
695                                         rdreply.readres_u.reply.attributes;
696                 argrd.offset += rdreply.readres_u.reply.data.data_len;
697             } else {
698                 verror(VAL_BATCH, W, "read %s failed: %m\n",
699                         Io_files[filenum].file_name);
700             }
701
702             if (argrd.count ==
703                 (block.sum != sum((unsigned char *) &block.len,
704                                   block.len + sizeof(block.len)))) {
705                 verror(VAL_BATCH, W, "read %s checksum mismatch\n",
706                         Io_files[filenum].file_name);
707             }
708         }
709     }
710
711     /* validate readdir */
712     numfiles = 0;
713
714     (void) memmove((char *) &argrdir.dir, (char *) &Export_dir.fh2, NFS_FHSIZE);
715     (void) memset((char *) argrdir.cookie, '\0', NFS_COOKIESIZE);
716     argrdir.count = DEFAULT_MAX_BUFSIZE;
717
718     (void) memset((char *) &rdirreply, '\0', sizeof(rdirreply));
719     rdirreply.readdirres_u.reply.max_entries = entry_cnt;
720     rdirreply.readdirres_u.reply.entries = entry_stream;
721     for (i = 0; i < entry_cnt; i++) {
722         entry_stream[i].name = &name_stream[i * SFS_MAXNAMLEN];
723     }
724
725     do {
726         verror(VAL_VERBOSE, I, "validating readdir %d entries of %s ...\n",
727                 rdirreply.readdirres_u.reply.max_entries, Testdirname);
728         val_op_readdir(&argrdir, &rdirreply);
729
730         if (rdirreply.status == NFS_OK) {
731             for (i = 0; i < rdirreply.readdirres_u.reply.max_entries; i++) {
732                 numfiles++;
733                 entry_stream[i].name[entry_stream[i].name_len] = '\0';
734                 if (!entry_stream[i].valid) {
735                     verror(VAL_BATCH, W,
736                           "readdir %s error: entry %d (%s) is marked invalid\n",
737                             Testdirname, i, entry_stream[i].name);
738                 }
739                 if ((!strcmp(entry_stream[i].name, ".")) ||
740                     (!strcmp(entry_stream[i].name, "..")) ) {
741                     numfiles--;
742                     continue;
743                 }
744                 for (filenum = 0; filenum < NUMFILES; filenum++) {
745                     if (!strcmp(entry_stream[i].name, Io_files[filenum].file_name)) {
746                         if (entry_stream[i].fileid !=
747                                     Io_files[filenum].attributes2.fileid) {
748                             verror(VAL_BATCH, E,
749                                   "readdir %s error: file %s fileid mismatch\n",
750                                     Testdirname, entry_stream[i].name);
751
752                             verror(VAL_BATCH, W,
753                                    "   fileid: got = %d, original = %d\n",
754                                     entry_stream[i].fileid,
755                                     Io_files[filenum].attributes2.fileid);
756                         }
757                         break;
758                     }
759                 }
760                 if (filenum == NUMFILES) {
761                     verror(VAL_BATCH, W,
762                "readdir %s error: file \"%s\" was not created within sfs\n",
763                             Testdirname, entry_stream[i].name);
764                 }
765             }
766
767             if (i < entry_cnt && entry_stream[i].valid) {
768                 verror(VAL_BATCH, W,
769                         "readdir %s error: valid entries exceeded maximum\n",
770                         Testdirname);
771             }
772
773         } else {
774             verror(VAL_BATCH, W, "readdir %s failed: %m\n", Testdirname);
775         }
776
777         (void) memmove((char *)argrdir.cookie,
778         (char *)entry_stream[rdirreply.readdirres_u.reply.max_entries-1].cookie,
779                         NFS_COOKIESIZE);
780
781     } while (rdirreply.readdirres_u.reply.eof == 0);
782
783     if (numfiles != NUMFILES) {
784         verror(VAL_BATCH, W,
785                         "readdir %s error: the number of files found\n\
786 does not match with the number of files created within sfs\n", Testdirname);
787     }
788
789 } /* validate_read_write */
790
791
792 static void
793 validate_rename(void)
794 {
795     renameargs  argrn;
796     nfsstat     rnreply;
797     int         filenum;
798     char        newname[SFS_MAXNAMLEN];
799     int         rncount = 0;
800
801     (void) memmove((char *) &argrn.from.dir, (char *) &Export_dir.fh2, NFS_FHSIZE);
802     (void) memmove((char *) &argrn.to.dir, (char *) &Export_dir.fh2, NFS_FHSIZE);
803
804     for (filenum=0; filenum < NUMFILES; filenum++) {
805         if (Io_files[filenum].state != Exists)
806             continue;
807
808         rncount++;
809         (void) sprintf(newname, "n%s", Io_files[filenum].file_name);
810         argrn.from.name = Io_files[filenum].file_name;
811         argrn.to.name = newname;
812
813         verror(VAL_VERBOSE, I, "validating rename %s %s ...\n",
814                 argrn.from.name, argrn.to.name);
815
816         val_op_rename(&argrn, &rnreply);
817
818         if (rnreply == NFS_OK) {
819             (void) strcpy(Io_files[filenum].file_name, newname);
820         } else {
821             verror(VAL_BATCH, W, "rename %s to %s failed: %m\n",
822                     Io_files[filenum].file_name, newname);
823         }
824
825     }
826
827     if (!rncount) {
828         verror(VAL_BATCH, E, "validate_rename: no files renamed\n");
829         verror(VAL_BATCH, W, "    due to previous operation error\n");
830     }
831
832 } /* validate_rename */
833
834
835 static int
836 compare_fattr(
837     char *      op,
838     char *      fname,
839     fattr *     attr1,
840     fattr *     attr2)
841 {
842     int         ret = TRUE;
843     int         prev_warn = FALSE; /* -1 info warning */
844     int         flag_error = FALSE;
845
846     if (attr1->type != attr2->type) {
847         if (attr1->type == 0xFFFFFFFF) {
848             prev_warn = TRUE;
849             if (ret) {
850                 verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
851                     fname, op);
852             }
853             verror(VAL_BATCH, I, "    type: current = %d, previous =  %d\n",
854                    attr2->type, attr1->type);
855             attr1->type = attr2->type;
856             ret = FALSE;
857         }
858         else {
859                 if (ret) {
860                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
861                             fname, op);
862                 }
863                 verror(VAL_BATCH, E, "    type: current = %d, previous =  %d\n",
864                         attr2->type, attr1->type);
865                 ret = FALSE;
866                 flag_error = TRUE;
867         }
868     }
869
870     if ((attr1->mode & NFSMODE_MASK) != (attr2->mode & NFSMODE_MASK)) {
871         if (attr1->mode == (unsigned int)0xFFFFFFFF) {
872                 prev_warn = TRUE;
873                 if (ret) {
874                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
875                                 fname, op);
876                 }
877                 verror(VAL_BATCH, I, "    mode: current = %7o, previous =  %7o\n",
878                         attr2->mode, attr1->mode);
879                 attr1->mode =  attr2->mode;
880                 ret = FALSE;
881         }
882         else {
883                 if (ret) {
884                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
885                             fname, op);
886                 }
887                 verror(VAL_BATCH, E, "    mode: current = %d, previous =  %d\n",
888                         attr2->mode, attr1->mode);
889                 ret = FALSE;
890                 flag_error = TRUE;
891         }
892     }
893
894     if (attr1->nlink != attr2->nlink) {
895         if (attr1->nlink == (unsigned int)0xFFFFFFFF) {
896                 prev_warn = TRUE;
897                 if (ret) {
898                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
899                                 fname, op);
900                 }
901                 verror(VAL_BATCH, I, "    nlink: current = %d, previous =  %d\n",
902                         attr2->nlink, attr1->nlink);
903                 attr1->nlink =  attr2->nlink;
904                 ret = FALSE;
905         }
906         else {
907                 if (ret) {
908                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
909                             fname, op);
910                 }
911                 verror(VAL_BATCH, E, "    nlink: current = %d, previous =  %d\n",
912                         attr2->nlink, attr1->nlink);
913                 ret = FALSE;
914                 flag_error = TRUE;
915         }
916     }
917
918
919     /*
920      * Check for user "nobody", UID -2, which may be untranslated from
921      * sixteen-bit two's complement.
922      */
923     if (attr1->uid != attr2->uid && !((attr2->uid == (unsigned int)0xFFFFFFFE ||
924         attr2->uid == 65534) && attr1->uid ==0)) {
925         if (attr1->uid == (unsigned int)0xFFFFFFFF) {
926                 prev_warn = TRUE;
927                 if (ret) {
928                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
929                                 fname, op);
930                 }
931                 verror(VAL_BATCH, I, "    uid: current = %d, previous =  %d\n",
932                         attr2->uid, attr1->uid);
933                 attr1->uid =  attr2->uid;
934                 ret = FALSE;
935         }
936         else {
937                 if (ret) {
938                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
939                             fname, op);
940                 }
941                 verror(VAL_BATCH, E, "    uid: current = %d, previous =  %d\n",
942                         attr2->uid, attr1->uid);
943                 ret = FALSE;
944                 flag_error = TRUE;
945         }
946     }
947
948     if (attr1->gid != attr2->gid && attr2->gid != 0) {
949 /*
950     if (attr1->gid != attr2->gid) {
951 */
952         if (attr1->gid == (unsigned int)0xFFFFFFFF) {
953                 prev_warn = TRUE;
954                 if (ret) {
955                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
956                                 fname, op);
957                 }
958                 verror(VAL_BATCH, I, "    gid: current = %d, previous =  %d\n",
959                         attr2->gid, attr1->gid);
960                 attr1->gid =  attr2->gid;
961                 ret = FALSE;
962         }
963         else {
964                 if (ret) {
965                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
966                             fname, op);
967                 }
968                 verror(VAL_BATCH, E, "    gid: current = %d, previous =  %d\n",
969                         attr2->gid, attr1->gid);
970                 ret = FALSE;
971                 flag_error = TRUE;
972         }
973     }
974
975     if (attr1->size != attr2->size) {
976         if (strcmp(op, Ops[WRITE].name)) {
977             if (attr1->size == (unsigned int)0xFFFFFFFF) {
978                 prev_warn = TRUE;
979                 if (ret) {
980                         verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
981                                 fname, op);
982                 }
983                 verror(VAL_BATCH, I, "    size: current = %d, previous =  %d\n",
984                         attr2->size, attr1->size);
985                 attr1->size =  attr2->size;
986                 ret = FALSE;
987             }
988             else {
989                 if (ret) {
990                         verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
991                             fname, op);
992                 }
993                 verror(VAL_BATCH, E, "    size: current = %d, previous =  %d\n",
994                         attr2->size, attr1->size);
995                 ret = FALSE;
996                 flag_error = TRUE;
997             }
998         }
999     }
1000
1001     if (attr1->blocksize != attr2->blocksize) {
1002         if (attr1->blocksize == (unsigned int)0xFFFFFFFF) {
1003              prev_warn = TRUE;
1004              if (ret) {
1005                      verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1006                              fname, op);
1007              }
1008              verror(VAL_BATCH, I, "    blocksize: current = %d, previous =  %d\n",
1009                      attr2->blocksize, attr1->blocksize);
1010              attr1->blocksize =  attr2->blocksize;
1011              ret = FALSE;
1012         }
1013         else {
1014              if (ret) {
1015                      verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1016                          fname, op);
1017              }
1018              verror(VAL_BATCH, E, "    blocksize: current = %d, previous =  %d\n",
1019                      attr2->blocksize, attr1->blocksize);
1020              ret = FALSE;
1021                 flag_error = TRUE;
1022         }
1023     }
1024
1025
1026     /* compare rdev only if type == NFCHR or NFBLK */
1027     if ((attr1->type == NFCHR || attr1->type == NFBLK) &&
1028         attr1->rdev != attr2->rdev) {
1029         if (attr1->rdev == (unsigned int)0xFFFFFFFF) {
1030              prev_warn = TRUE;
1031              if (ret) {
1032                      verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1033                              fname, op);
1034              }
1035              verror(VAL_BATCH, I, "    rdev: current = %d, previous =  %d\n",
1036                      attr2->rdev, attr1->rdev);
1037              attr1->rdev =  attr2->rdev;
1038              ret = FALSE;
1039         }
1040         else {
1041              if (ret) {
1042                      verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1043                          fname, op);
1044              }
1045              verror(VAL_BATCH, E, "    rdev: current = %d, previous =  %d\n",
1046                      attr2->rdev, attr1->rdev);
1047              ret = FALSE;
1048                 flag_error = TRUE;
1049         }
1050     }
1051
1052
1053     /*
1054      * The NFS specification does not require that the number of blocks
1055      * associated with a file remain constant.  Certain file systems
1056      * may pre-allocate more blocks than necessary then trim them
1057      * back ("garbage collect") or even blow holes in files that have
1058      * all zero blocks.
1059      * We must check that we never get back -1.
1060      */
1061     if (attr1->blocks != attr2->blocks) {
1062         if (strcmp(op, Ops[WRITE].name)) {
1063             if (attr1->blocks == (unsigned int)0xFFFFFFFF) {
1064                  prev_warn = TRUE;
1065                  if (ret) {
1066                      verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1067                              fname, op);
1068                  }
1069                 verror(VAL_BATCH, I, "    blocks: current = %d, previous =  %d\n",
1070                          attr2->blocks, attr1->blocks);
1071                  attr1->blocks =  attr2->blocks;
1072                  ret = FALSE;
1073             }
1074         }
1075     }
1076
1077
1078     if (attr1->fsid != attr2->fsid) {
1079         if (attr1->fsid == (unsigned int)0xFFFFFFFF) {
1080              prev_warn = TRUE;
1081              if (ret) {
1082                      verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1083                              fname, op);
1084              }
1085              verror(VAL_BATCH, I, "    fsid: current = %d, previous =  %d\n",
1086                      attr2->fsid, attr1->fsid);
1087              attr1->fsid =  attr2->fsid;
1088              ret = FALSE;
1089         }
1090         else {
1091              if (ret) {
1092                      verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1093                          fname, op);
1094              }
1095              verror(VAL_BATCH, E, "    fsid: current = %d, previous =  %d\n",
1096                      attr2->fsid, attr1->fsid);
1097              ret = FALSE;
1098                 flag_error = TRUE;
1099         }
1100     }
1101
1102     if (attr1->fileid != attr2->fileid) {
1103         if (attr1->fileid == (unsigned int)0xFFFFFFFF) {
1104              prev_warn = TRUE;
1105              if (ret) {
1106                      verror(VAL_BATCH, I, "%s: %s attribute mismatch\n",
1107                              fname, op);
1108              }
1109              verror(VAL_BATCH, I, "    fileid: current = %d, previous =  %d\n",
1110                      attr2->fileid, attr1->fileid);
1111              attr1->fileid =  attr2->fileid;
1112              ret = FALSE;
1113         }
1114         else {
1115              if (ret) {
1116                      verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1117                          fname, op);
1118              }
1119              verror(VAL_BATCH, E, "    fileid: current = %d, previous =  %d\n",
1120                      attr2->fileid, attr1->fileid);
1121              ret = FALSE;
1122                 flag_error = TRUE;
1123         }
1124     }
1125
1126     if (prev_warn) {
1127         verror(VAL_BATCH, I,
1128                 "\n        Warning: the previous value of a field is -1,\n");
1129         verror(VAL_BATCH, I,
1130                 "        this resulted from an unused field returned by\n");
1131         verror(VAL_BATCH, I,
1132                 "        the previous operation on this file/directory.\n");
1133         verror(VAL_BATCH, I,
1134             "        The current value is now stored for future comparison\n\n");
1135     }
1136
1137     if (flag_error)
1138         verror(VAL_BATCH, W,"\n");
1139
1140     return(flag_error);
1141
1142 } /* ckompare_fattr */
1143
1144
1145 static int
1146 compare_sattr(
1147     char *      op,
1148     char *      fname,
1149     sattr *     attr1,
1150     fattr *     attr2)
1151 {
1152     int         ret = TRUE;
1153     char        msg[80];
1154
1155     msg[0] = '\0';
1156
1157     if (attr1->mode != (unsigned int)0xFFFFFFFF &&
1158         (attr1->mode & NFSMODE_MASK) != (attr2->mode & NFSMODE_MASK)) {
1159         if (ret) {
1160             verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1161                     fname, op);
1162
1163         }
1164         verror(VAL_BATCH, E, "    mode: returned = %7o, specified = %7o\n",
1165                 attr2->mode, attr1->mode);
1166         ret = FALSE;
1167     }
1168
1169     /*
1170      * Check for user "nobody", UID -2, which may be untranslated from
1171      * sixteen-bit two's complement.
1172      */
1173     if (attr1->uid != (unsigned int)0xFFFFFFFF && attr1->uid != attr2->uid &&
1174                 !((attr2->uid == (unsigned int)0xFFFFFFFE ||
1175                 attr2->uid == 65534) &&
1176                         attr1->uid == 0)) {
1177         if (ret) {
1178             verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1179                     fname, op);
1180         }
1181         if (attr1->uid == 0)
1182             (void) strcat(msg," (is root UID mapped to other UID?)");
1183         verror(VAL_BATCH, E, "    uid: returned = %d, specified = %d %s\n",
1184                 attr2->uid, attr1->uid, msg);
1185         ret = FALSE;
1186     }
1187     if (attr1->gid != (unsigned int)0xFFFFFFFF &&
1188                         attr1->gid != attr2->gid &&
1189                         attr2->gid != 0) {
1190 /*
1191    if (attr1->gid != 0xFFFFFFFF && attr1->gid != attr2->gid) {
1192 */
1193         if (ret) {
1194             verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1195                     fname, op);
1196         }
1197         verror(VAL_BATCH, E, "    gid: returned = %d, specified = %d\n",
1198                 attr2->gid, attr1->gid);
1199         ret = FALSE;
1200     }
1201
1202     if (attr1->size != (unsigned int)0xFFFFFFFF &&
1203                         attr1->size != attr2->size) {
1204         if (ret) {
1205             verror(VAL_BATCH, E, "%s: %s attribute mismatch\n",
1206                     fname, op);
1207         }
1208         verror(VAL_BATCH, E, "    size: returned = %d, specified = %d\n",
1209                 attr2->size, attr1->size);
1210         ret = FALSE;
1211     }
1212
1213     if (!ret)
1214         verror(VAL_BATCH, W,"\n");
1215
1216     return(ret);
1217
1218 } /* compare_sattr */
1219
1220
1221 /*
1222  * Return the BSD checksum of buf[0..len-1]
1223  */
1224 static uint16_t
1225 sum(
1226     unsigned char *     buf,
1227     uint_t              len)
1228 {
1229     uint16_t      cksum;
1230
1231     cksum = 0;
1232     for (; len--; buf++) {
1233         if (cksum & 1)
1234             cksum = (cksum >> 1) + 0x8000;
1235         else
1236             cksum >>= 1;
1237         cksum += (uint16_t) *buf;
1238         cksum &= 0xFFFF;
1239     }
1240     return(cksum);
1241 } /* sum */
1242
1243
1244 static void
1245 validate_remove(void)
1246 {
1247     diropargs   args;
1248     nfsstat     reply;
1249     diropres    lreply;
1250     int         filenum;
1251     char *      op;
1252
1253     (void) memmove((char *) &args.dir, (char *) &Export_dir.fh2, NFS_FHSIZE);
1254
1255     for (filenum = 0; filenum < NUMFILES; filenum++) {
1256
1257         if (Io_files[filenum].state != Exists)
1258             continue;
1259
1260         args.name = Io_files[filenum].file_name;
1261
1262         if (Io_files[filenum].attributes2.type == NFDIR) {
1263             op = Ops[RMDIR].name;
1264             verror(VAL_VERBOSE, I, "validating rmdir %s ...\n",
1265                     args.name);
1266             val_op_rmdir(&args, &reply);
1267         } else {
1268             op = Ops[REMOVE].name;
1269             verror(VAL_VERBOSE, I, "validating remove %s ...\n",
1270                     args.name);
1271             val_op_remove(&args, &reply);
1272         }
1273
1274         if (reply == NFS_OK) {
1275             /* make sure the file is removed from the directory */
1276             val_op_lookup(&args, &lreply);
1277
1278             if (lreply.status == NFSERR_NOENT) {
1279                 Io_files[filenum].state = Nonexistent;
1280             } else if (lreply.status == NFS_OK) {
1281                 verror(VAL_BATCH, W, "%s %s: file not removed\n",
1282                        op, Io_files[filenum].file_name);
1283             } else {
1284                 verror(VAL_BATCH, W, "lookup %s failed: %m\n",
1285                        Io_files[filenum].file_name);
1286
1287             }
1288         } else {
1289             verror(VAL_BATCH, W, "%s %s failed: %m\n", op,
1290                     Io_files[filenum].file_name);
1291         }
1292
1293     }
1294
1295 } /* validate_remove */
1296
1297
1298 static void
1299 validate_cleanup(void)
1300 {
1301     free(Io_files);
1302     free(Non_io_files);
1303     free(Dirs);
1304     free(Symlinks);
1305     clnt_destroy(NFS_client);
1306
1307 } /* validate_cleanup */
1308
1309
1310 static void
1311 validate_exit(void)
1312 {
1313     if (!Validate_errors) {
1314         verror(VAL_BATCH, I, "validation completed successfully.\n");
1315         exit(0);
1316     } else {
1317         verror(VAL_BATCH, I, "validation terminated with errors\n");
1318         exit(1);
1319     }
1320
1321 } /* validate_exit */
1322
1323
1324 /* PRINTFLIKE3 */
1325 static void
1326 verror(
1327     int         opt,
1328     ValMsgType  msgtype,
1329     char *      fmt,
1330     ...)
1331 {
1332     va_list     ap;
1333     char        buf[1024];
1334     char *      bp = buf;
1335     char *      fp;
1336     int         repeat;
1337     char *      sp;
1338
1339     va_start(ap, fmt);
1340
1341     /*
1342      * Expand the "%m" format character into the descriptive string
1343      * for the current value of errno.  Printf handles the other "%"
1344      * formatting characters.
1345      */
1346     if (Validate >= opt) {
1347         for (fp = fmt; *fp; fp++) {
1348             if (*fp == '%' && fp[1] == 'm') {
1349                 if ((sp = strerror(errno)) == NULL) {
1350                     (void) sprintf(bp, "unknown error %d", errno);
1351                 } else {
1352                     (void) strcpy(bp, sp);
1353                 }
1354                 bp = buf + strlen(buf);
1355                 fp++;
1356             } else {
1357                 *bp++ = *fp;
1358             }
1359         }
1360         *bp = '\0';
1361         (void) vprintf(buf, ap);
1362     }
1363     va_end(ap);
1364
1365     if (msgtype != I)
1366         Validate_errors++;
1367
1368     if (msgtype == W && Validate == VAL_INTERACTIVE) {
1369         repeat = 1;
1370         while (repeat) {
1371             char ans[80];
1372
1373             (void) fprintf(stderr, "continue? (y or n)  ");
1374             if (!fgets(ans,80,stdin)) {
1375                 (void) fprintf(stderr, "\n");
1376                 continue;
1377             }
1378             if (ans[0] == 'n' || ans[0] == 'N') {
1379                 validate_exit();
1380                 exit(1);
1381             } else if (ans[0] == 'y' || ans[0] == 'Y') {
1382                 repeat = 0;
1383                 break;
1384             }
1385         }
1386     }
1387
1388 } /* verror */
1389
1390
1391 static void
1392 val_op_null(void)
1393 {
1394         int rpc_stat;
1395
1396         /* CONSTCOND */
1397         while (1) {
1398             rpc_stat = clnt_call(NFS_client, NFSPROC_NULL, 
1399                 xdr_void, (char *)0, xdr_void, (char *)0, 
1400                 Nfs_timers[Ops[NULLCALL].call_class]);
1401             if (rpc_stat == RPC_SUCCESS)
1402                 break;
1403             if (rpc_stat != RPC_TIMEDOUT) {
1404                 clnt_perror(NFS_client, "null");
1405                 Validate_errors++;
1406                 validate_exit();
1407             }
1408         }
1409 }
1410
1411 static void
1412 val_op_getattr(fhandle_t *args, attrstat *reply)
1413 {
1414         int rpc_stat;
1415
1416         /* CONSTCOND */
1417         while (1) {
1418             rpc_stat = clnt_call(NFS_client, NFSPROC_GETATTR, 
1419             xdr_getattr, (char *)args, xdr_getattr, (char *)reply, 
1420             Nfs_timers[Ops[GETATTR].call_class]);
1421             if (rpc_stat == RPC_SUCCESS)
1422                 break;
1423             if (rpc_stat != RPC_TIMEDOUT) {
1424                 clnt_perror(NFS_client, "getattr");
1425                 Validate_errors++;
1426                 validate_exit();
1427             }
1428         }
1429 }
1430
1431 static void
1432 val_op_setattr(sattrargs *args, attrstat *reply)
1433 {
1434         int rpc_stat;
1435
1436         /* CONSTCOND */
1437         while (1) {
1438             rpc_stat = clnt_call(NFS_client, NFSPROC_SETATTR, 
1439                 xdr_setattr, (char *)args, xdr_setattr, (char *)reply, 
1440                 Nfs_timers[Ops[SETATTR].call_class]);
1441             if (rpc_stat == RPC_SUCCESS)
1442                 break;
1443             if (rpc_stat != RPC_TIMEDOUT) {
1444                 clnt_perror(NFS_client, "setattr");
1445                 Validate_errors++;
1446                 validate_exit();
1447             }
1448         }
1449 }
1450
1451 static void
1452 val_op_lookup(diropargs *args, diropres *reply)
1453 {
1454         int rpc_stat;
1455
1456         /* CONSTCOND */
1457         while (1) {
1458             rpc_stat = clnt_call(NFS_client, NFSPROC_LOOKUP, 
1459                 xdr_lookup, (char *)args, xdr_lookup, (char *)reply, 
1460                 Nfs_timers[Ops[LOOKUP].call_class]);
1461             if (rpc_stat == RPC_SUCCESS)
1462                 break;
1463             if (rpc_stat != RPC_TIMEDOUT) {
1464                 clnt_perror(NFS_client, "lookup");
1465                 Validate_errors++;
1466                 validate_exit();
1467             }
1468         }
1469 }
1470
1471 static void
1472 val_op_readlink(fhandle_t *args, readlinkres *reply)
1473 {
1474         int rpc_stat;
1475
1476         /* CONSTCOND */
1477         while (1) {
1478             rpc_stat = clnt_call(NFS_client, NFSPROC_READLINK, 
1479                 xdr_readlink, (char *)args, xdr_readlink, (char *)reply, 
1480                 Nfs_timers[Ops[READLINK].call_class]);
1481             if (rpc_stat == RPC_SUCCESS)
1482                 break;
1483             if (rpc_stat != RPC_TIMEDOUT) {
1484                 clnt_perror(NFS_client, "readlink");
1485                 Validate_errors++;
1486                 validate_exit();
1487             }
1488         }
1489 }
1490
1491 static void
1492 val_op_read(readargs *args, readres *reply)
1493 {
1494         int rpc_stat;
1495
1496         /* CONSTCOND */
1497         while (1) {
1498             rpc_stat = clnt_call(NFS_client, NFSPROC_READ, 
1499                 xdr_read, (char *)args, xdr_read, (char *)reply, 
1500                 Nfs_timers[Ops[READ].call_class]);
1501             if (rpc_stat == RPC_SUCCESS)
1502                 break;
1503             if (rpc_stat != RPC_TIMEDOUT) {
1504                 clnt_perror(NFS_client, "read");
1505                 Validate_errors++;
1506                 validate_exit();
1507             }
1508         }
1509 }
1510
1511 static void
1512 val_op_write(writeargs *args, attrstat *reply)
1513 {
1514         int rpc_stat;
1515
1516         /* CONSTCOND */
1517         while (1) {
1518             rpc_stat = clnt_call(NFS_client,
1519                 NFSPROC_WRITE, xdr_write, (char *)args, xdr_write, (char *)reply,
1520                 Nfs_timers[Ops[WRITE].call_class]);
1521
1522             if (rpc_stat == RPC_SUCCESS)
1523                 break;
1524             if (rpc_stat != RPC_TIMEDOUT) {
1525                     clnt_perror(NFS_client, "write");
1526                     Validate_errors++;
1527                     validate_exit();
1528             }
1529         }
1530 }
1531
1532 static void
1533 val_op_create(createargs *args, diropres *reply)
1534 {
1535         int rpc_stat;
1536
1537         /* CONSTCOND */
1538         while (1) {
1539             rpc_stat = clnt_call(NFS_client,
1540             NFSPROC_CREATE, xdr_create, (char *)args, xdr_create, (char *)reply, 
1541             Nfs_timers[Ops[CREATE].call_class]);
1542             if (rpc_stat == RPC_SUCCESS)
1543                 break;
1544             if (rpc_stat != RPC_TIMEDOUT) {
1545                 clnt_perror(NFS_client, "create");
1546                 Validate_errors++;
1547                 validate_exit();
1548             }
1549         }
1550 }
1551
1552 static void
1553 val_op_remove(diropargs *args, nfsstat *reply)
1554 {
1555         int rpc_stat;
1556
1557         /* CONSTCOND */
1558         while (1) {
1559             rpc_stat = clnt_call(NFS_client,
1560                 NFSPROC_REMOVE, xdr_remove, (char *)args, xdr_remove, (char *)reply, 
1561                 Nfs_timers[Ops[REMOVE].call_class]);
1562             if (rpc_stat == RPC_SUCCESS)
1563                 break;
1564             if (rpc_stat != RPC_TIMEDOUT) {
1565                 clnt_perror(NFS_client, "remove");
1566                 Validate_errors++;
1567                 validate_exit();
1568             }
1569         }
1570 }
1571
1572 static void
1573 val_op_rename(renameargs *args, nfsstat *reply)
1574 {
1575         int rpc_stat;
1576
1577         /* CONSTCOND */
1578         while (1) {
1579             rpc_stat = clnt_call(NFS_client, NFSPROC_RENAME, 
1580                 xdr_rename, (char *)args, xdr_rename, (char *)reply, 
1581                 Nfs_timers[Ops[RENAME].call_class]);
1582             if (rpc_stat == RPC_SUCCESS)
1583                 break;
1584             if (rpc_stat != RPC_TIMEDOUT) {
1585                 clnt_perror(NFS_client, "rename");
1586                 Validate_errors++;
1587                 validate_exit();
1588             }
1589         }
1590 }
1591
1592 static void
1593 val_op_link(linkargs *args, nfsstat *reply)
1594 {
1595         int rpc_stat;
1596
1597         /* CONSTCOND */
1598         while (1) {
1599             rpc_stat = clnt_call(NFS_client, NFSPROC_LINK, 
1600                 xdr_link, (char *)args, xdr_link, (char *)reply, 
1601                 Nfs_timers[Ops[LINK].call_class]);
1602             if (rpc_stat == RPC_SUCCESS)
1603                 break;
1604             if (rpc_stat != RPC_TIMEDOUT) {
1605                 clnt_perror(NFS_client, "link");
1606                 Validate_errors++;
1607                 validate_exit();
1608             }
1609         }
1610 }
1611
1612 static void
1613 val_op_symlink(symlinkargs *args, nfsstat *reply)
1614 {
1615         int rpc_stat;
1616
1617         /* CONSTCOND */
1618         while (1) {
1619             rpc_stat = clnt_call(NFS_client, NFSPROC_SYMLINK, 
1620                 xdr_symlink, (char *)args, xdr_symlink, (char *)reply, 
1621                 Nfs_timers[Ops[SYMLINK].call_class]);
1622             if (rpc_stat == RPC_SUCCESS)
1623                 break;
1624             if (rpc_stat != RPC_TIMEDOUT) {
1625                 clnt_perror(NFS_client, "symlink");
1626                 Validate_errors++;
1627                 validate_exit();
1628             }
1629         }
1630 }
1631
1632 static void
1633 val_op_mkdir(mkdirargs *args, diropres *reply)
1634 {
1635         int rpc_stat;
1636
1637         /* CONSTCOND */
1638         while (1) {
1639             rpc_stat = clnt_call(NFS_client, NFSPROC_MKDIR, 
1640                 xdr_mkdir, (char *)args, xdr_mkdir, (char *)reply, 
1641                 Nfs_timers[Ops[MKDIR].call_class]);
1642             if (rpc_stat == RPC_SUCCESS)
1643                 break;
1644             if (rpc_stat != RPC_TIMEDOUT) {
1645                 clnt_perror(NFS_client, "mkdir");
1646                 Validate_errors++;
1647                 validate_exit();
1648             }
1649         }
1650 }
1651
1652 static void
1653 val_op_rmdir(diropargs *args, nfsstat *reply)
1654 {
1655         int rpc_stat;
1656
1657         /* CONSTCOND */
1658         while (1) {
1659             rpc_stat = clnt_call(NFS_client, NFSPROC_RMDIR, 
1660                 xdr_rmdir, (char *)args, xdr_rmdir, (char *)reply, 
1661                 Nfs_timers[Ops[RMDIR].call_class]);
1662             if (rpc_stat == RPC_SUCCESS)
1663                 break;
1664             if (rpc_stat != RPC_TIMEDOUT) {
1665                 clnt_perror(NFS_client, "rmdir");
1666                 Validate_errors++;
1667                 validate_exit();
1668             }
1669         }
1670 }
1671
1672 static void
1673 val_op_readdir(readdirargs *args, readdirres *reply)
1674 {
1675         int rpc_stat;
1676
1677         /* CONSTCOND */
1678         while (1) {
1679             rpc_stat = clnt_call(NFS_client, NFSPROC_READDIR, 
1680                 xdr_readdir, (char *)args, xdr_readdir, (char *)reply, 
1681                 Nfs_timers[Ops[READDIR].call_class]);
1682             if (rpc_stat == RPC_SUCCESS)
1683                 break;
1684             if (rpc_stat != RPC_TIMEDOUT) {
1685                 clnt_perror(NFS_client, "readdir");
1686                 Validate_errors++;
1687                 validate_exit();
1688             }
1689         }
1690 }
1691
1692 static void
1693 val_op_statfs(fhandle_t *args, statfsres *reply)
1694 {
1695         int rpc_stat;
1696
1697         /* CONSTCOND */
1698         while (1) {
1699             rpc_stat = clnt_call(NFS_client, NFSPROC_STATFS, 
1700                 xdr_statfs, (char *)args, xdr_statfs, (char *)reply, 
1701                 Nfs_timers[Ops[FSSTAT].call_class]);
1702             if (rpc_stat == RPC_SUCCESS)
1703                 break;
1704             if (rpc_stat != RPC_TIMEDOUT) {
1705                 clnt_perror(NFS_client, "statfs");
1706                 Validate_errors++;
1707                 validate_exit();
1708             }
1709         }
1710 }
1711 static void
1712 create_tmp_handles(void)
1713 {
1714         int filenum;
1715         for (filenum = 0; filenum < NUMFILES; filenum++) {
1716
1717                 if(Io_files[filenum].fh_data == (sfs_fh_data *)0)
1718                 {
1719                         Io_files[filenum].fh_data = 
1720                                         calloc(1,sizeof(sfs_fh_data));
1721                         Io_files[filenum].attributes2.type = NFNON;
1722                         Io_files[filenum].attributes3.type = NF3NON;
1723                 }
1724         }
1725 }
1726
1727 static void
1728 delete_tmp_handles()
1729 {
1730         int filenum;
1731         for (filenum = 0; filenum < NUMFILES; filenum++) {
1732
1733                 if(Io_files[filenum].fh_data != (sfs_fh_data *)0)
1734                 {
1735                         free(Io_files[filenum].fh_data);
1736                         Io_files[filenum].fh_data=(sfs_fh_data *)0;
1737                 }
1738         }
1739 }
1740
1741
1742
1743
1744
1745
1746
1747