Code cleanup for vlserver
[openafs.git] / src / vlserver / vlclient.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13
14 #include <afs/stds.h>
15 #include <sys/types.h>
16 #ifdef HAVE_TIME_H
17 #include <time.h>
18 #endif
19 #ifdef HAVE_FCNTL_H
20 #include <fcntl.h>
21 #endif
22 #ifdef AFS_NT40_ENV
23 #include <winsock2.h>
24 #include <WINNT/afsevent.h>
25 #endif
26 #ifdef HAVE_SYS_TIME_H
27 #include <sys/time.h>
28 #endif
29 #ifdef HAVE_SYS_FILE_H
30 #include <sys/file.h>
31 #endif
32 #ifdef HAVE_NETDB_H
33 #include <netdb.h>
34 #endif
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
37 #endif
38 #include <stdio.h>
39 #include <string.h>
40
41 #include <afs/afsutil.h>
42 #include <rx/xdr.h>
43 #include <rx/rx.h>
44 #include <rx/rx_globals.h>
45 #include <rx/rxkad.h>
46 #include <afs/cellconfig.h>
47 #include <afs/keys.h>
48 #include <afs/cmd.h>
49 #include <lock.h>
50 #include <ubik.h>
51 #include "vlserver.h"
52
53 void fill_listattributes_entry(struct VldbListByAttributes *, char **, int);
54 void display_listattributes_entry(struct VldbListByAttributes *,int);
55 void display_entry(struct vldbentry *, int);
56 void display_entryN(struct nvldbentry *, int);
57 void display_update_entry(struct VldbUpdateEntry *, int);
58 void dump_stats(vldstats *, vital_vlheader *);
59 void GetArgs(char *, char **, int *);
60 void print_usage(void);
61 void fill_entry(struct vldbentry *, char **, int);
62 void fill_update_entry(struct VldbUpdateEntry *, char **, int);
63
64 #define VL_NUMBER_OPCODESX      34
65 static char *opcode_names[VL_NUMBER_OPCODESX] = {
66     "CreateEntry",
67     "DeleteEntry",
68     "GetEntryByID",
69     "GetEntryByName",
70     "GetNewVolumeId",
71     "ReplaceEntry",
72     "UpdateEntry",
73     "SetLock",
74     "ReleaseLock",
75     "ListEntry",
76     "ListAttributes",
77     "LinkedList",
78     "GetStats",
79     "Probe",
80     "GetAddrs",
81     "ChangeAddr",
82     "CreateEntryN",
83     "GetEntryByIDN",
84     "GetEntryByNameN",
85     "ReplaceEntryN",
86     "ListEntryN",
87     "ListAttributesN",
88     "LinkedListN",
89     "UpdateeEntryByName",
90     "CreateEntryU",
91     "GetEntryByIDU",
92     "GetEntryByNameU",
93     "ReplaceEntryU",
94     "ListEntryU",
95     "ListAttributesU",
96     "LinkedListU",
97     "RegisterAddr",
98     "GetAddrsU",
99     "ListAttributesN2"
100 };
101
102 struct Vlent {
103     struct Vlent *next;
104     afs_int32 rwid;
105     afs_int32 roid;
106     afs_int32 baid;
107     char name[64];
108 };
109
110 #define NVOLS   1000
111 #define ALLOCNT 50000
112 struct Vlent *VLa[NVOLS];
113 #define VHash(avol)     ((avol)&(NVOLS-1))
114 struct Vlent *VL, *SVL;
115 int VLcnt = 0;
116 struct ubik_client *cstruct;
117 struct rx_connection *serverconns[MAXSERVERS];
118 char confdir[AFSDIR_PATH_MAX];
119 char *(args[50]);
120
121 struct Vlent *
122 GetVolume(int vol, struct vldbentry *entry)
123 {
124     register int i;
125     register struct Vlent *vl;
126
127     if (!vol)
128         return NULL;
129     i = VHash(vol);
130     for (vl = VLa[i]; vl; vl = vl->next) {
131         if ((vl->rwid == vol && vol != entry->volumeId[0])
132             || (vl->roid == vol && vol != entry->volumeId[1])
133             || (vl->baid == vol && vol != entry->volumeId[2])) {
134             return vl;
135         }
136     }
137     VL->rwid = entry->volumeId[0];
138     VL->roid = entry->volumeId[1];
139     VL->baid = entry->volumeId[2];
140     strcpy(entry->name, VL->name);
141     VL->next = VLa[i];
142     VLa[i] = VL;
143     if (VLcnt++ > ALLOCNT) {    /* XXXX FIX XXXXXXXXX */
144         printf("Too many entries (> %d)\n", ALLOCNT);
145         exit(1);
146     }
147     VL++;
148     return NULL;
149 }
150
151 /* Almost identical's to pr_Initialize in vlserver/pruser.c */
152 afs_int32
153 vl_Initialize(int auth, char *confDir, int server, char *cellp)
154 {
155     return ugen_ClientInit(auth?0:1, confDir, cellp, 0,
156                           &cstruct, NULL, "vl_Initialize", rxkad_clear, 
157                           MAXSERVERS, AFSCONF_VLDBSERVICE, 50, server,
158                           htons(AFSCONF_VLDBPORT), USER_SERVICE_ID);
159 }
160
161 /* return host address in network byte order */
162 afs_int32
163 GetServer(char *aname)
164 {
165     register struct hostent *th;
166     afs_int32 addr;
167     int b1, b2, b3, b4;
168     register afs_int32 code;
169
170     code = sscanf(aname, "%d.%d.%d.%d", &b1, &b2, &b3, &b4);
171     if (code == 4) {
172         addr = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
173         return htonl(addr);     /* convert to network order (128 in byte 0) */
174     }
175     th = gethostbyname(aname);
176     if (!th)
177         return 0;
178     memcpy(&addr, th->h_addr, sizeof(addr));
179     return addr;
180 }
181
182
183 static int
184 handleit(struct cmd_syndesc *as, void *arock)
185 {
186     register struct cmd_item *ti;
187     register afs_int32 code, server = 0, sawserver = 0;
188     afs_int32 id, voltype;
189     struct vldbentry entry;
190     char *cellp = 0;
191     struct VldbUpdateEntry updateentry;
192     struct VldbListByAttributes listbyattributes;
193     int noAuth = 1;             /* Default is authenticated connections */
194
195     if ((ti = as->parms[0].items))      /* -cellpath <dir> */
196         strcpy(confdir, ti->data);
197     if (as->parms[1].items)     /* -server */
198         strcpy(confdir, AFSDIR_SERVER_ETC_DIRPATH);
199     if (as->parms[2].items)     /* -noauth */
200         noAuth = 0;
201     if ((ti = as->parms[3].items)) {    /* -host */
202         server = GetServer(ti->data);
203         if (server == 0) {
204             printf("server '%s' not found in host table\n", ti->data);
205             exit(1);
206         }
207         sawserver = 1;
208     }
209     if (!sawserver && noAuth && (!(ti = as->parms[4].items))) {
210         printf
211             ("Must also specify the -cell' option along with -host for authenticated conns\n");
212         exit(1);
213     }
214     if ((ti = as->parms[4].items)) {    /* -cell */
215         cellp = ti->data;
216     }
217     if ((code = vl_Initialize(noAuth, confdir, server, cellp))) {
218         printf("Couldn't initialize vldb library (code=%d).\n", code);
219         exit(1);
220     }
221
222     if (as->parms[5].items) {   /* -gstats */
223         vldstats stats;
224         vital_vlheader vital_header;
225         code = ubik_VL_GetStats(cstruct, 0, &stats, &vital_header);
226         if (!code)
227             dump_stats(&stats, &vital_header);
228         exit(0);
229     }
230
231     while (1) {
232         char line[500];
233         int nargs, releasetype;
234         memset(&entry, 0, sizeof(entry));
235         memset(&updateentry, 0, sizeof(updateentry));
236         memset(&listbyattributes, 0, sizeof(listbyattributes));
237         printf("vl> ");
238         if (fgets(line, 499, stdin) == NULL) {
239             printf("\n");
240             exit(0);
241         } else {
242             char *oper, *vname;
243             register char **argp = args;
244             GetArgs(line, argp, &nargs);
245             oper = &argp[0][0];
246             ++argp, --nargs;
247             if (!strcmp(oper, "cr")) {
248                 fill_entry(&entry, argp, nargs);
249                 display_entry(&entry, 0);
250                 code = ubik_VL_CreateEntry(cstruct, 0, &entry);
251                 printf("return code is %d\n", code);
252             } else if (!strcmp(oper, "rm")) {
253                 sscanf(&(*argp)[0], "%d", &id);
254                 ++argp, --nargs;
255                 sscanf(&(*argp)[0], "%d", &voltype);
256                 code = ubik_VL_DeleteEntry(cstruct, 0, id, voltype);
257                 printf("return code is %d\n", code);
258             } else if (!strcmp(oper, "re")) {
259                 sscanf(&(*argp)[0], "%d", &id);
260                 ++argp, --nargs;
261                 sscanf(&(*argp)[0], "%d", &voltype);
262                 ++argp, --nargs;
263                 sscanf(&(*argp)[0], "%d", &releasetype);
264                 ++argp, --nargs;
265                 fill_entry(&entry, argp, nargs);
266                 display_entry(&entry, 0);
267                 code =
268                     ubik_VL_ReplaceEntry(
269                     cstruct, 0, id, voltype,
270                               &entry, releasetype);
271                 printf("return code is %d\n", code);
272             } else if (!strcmp(oper, "up")) {
273                 sscanf(&(*argp)[0], "%d", &id);
274                 ++argp, --nargs;
275                 sscanf(&(*argp)[0], "%d", &voltype);
276                 ++argp, --nargs;
277                 sscanf(&(*argp)[0], "%d", &releasetype);
278                 ++argp, --nargs;
279                 fill_update_entry(&updateentry, argp, nargs);
280                 display_update_entry(&updateentry, 0);
281                 code =
282                     ubik_VL_UpdateEntry(cstruct, 0, id, voltype,
283                               &updateentry, releasetype);
284                 printf("return code is %d\n", code);
285             } else if (!strcmp(oper, "ls")) {
286                 afs_int32 index, count, next_index;
287                 for (index = 0; 1; index = next_index) {
288                     memset(&entry, 0, sizeof(entry));
289                     code =
290                         ubik_VL_ListEntry(cstruct, 0, index, &count,
291                                   &next_index, &entry);
292                     if (code) {
293                         printf("VL_ListEntry returned code = %d\n", code);
294                         break;
295                     }
296                     if (!next_index)
297                         break;
298                     display_entry(&entry, 0);
299                 }
300             } else if (!strcmp(oper, "ldups")) {
301                 afs_int32 index, count, num = 0, num1 = 0, next_index;
302                 struct Vlent *vl1;
303
304                 VL = SVL =
305                     (struct Vlent *)malloc(ALLOCNT * sizeof(struct Vlent));
306                 if (VL == NULL) {
307                     printf("Can't allocate memory...\n");
308                     exit(1);
309                 }
310                 printf("Enumerating all entries in vldb...\n");
311                 for (index = 0; 1; index = next_index) {
312                     memset(&entry, 0, sizeof(entry));
313                     code =
314                         ubik_VL_ListEntry(cstruct, 0, index, &count,
315                                   &next_index, &entry);
316                     if (code) {
317                         printf("VL_ListEntry returned code = %d\n", code);
318                         break;
319                     }
320                     if (!next_index)
321                         break;
322                     num++;
323                     if ((vl1 = GetVolume(entry.volumeId[0], &entry))) {
324                         num1++;
325                         printf
326                             ("Duplicate entry is found for RW vol %u: [RW %u, RO %u, BA %u, name=%s]\n",
327                              entry.volumeId[0], vl1->rwid, vl1->roid,
328                              vl1->baid, vl1->name);
329                     }
330                     if ((vl1 = GetVolume(entry.volumeId[1], &entry))) {
331                         num1++;
332                         printf
333                             ("Duplicate entry is found for RO vol %u: [RW %u, RO %u, BA %u, name=%s]\n",
334                              entry.volumeId[1], vl1->rwid, vl1->roid,
335                              vl1->baid, vl1->name);
336                     }
337                     if ((vl1 = GetVolume(entry.volumeId[2], &entry))) {
338                         num1++;
339                         printf
340                             ("Duplicate entry is found for BA vol %u: [RW %u, RO %u, BA %u, name=%s]\n",
341                              entry.volumeId[2], vl1->rwid, vl1->roid,
342                              vl1->baid, vl1->name);
343                     }
344                     /*display_entry(&entry, 0); */
345                 }
346                 printf("(%d vldb entries found - %d duplicates)\n", num,
347                        num1);
348             } else if (!strcmp(oper, "checkhash")) {
349                 int index, count, num = 0, num1 = 0, num2 = 0, num3 =
350                     0, num31 = 0, num4 = 0, num41 = 0, next_index;
351                 struct vldbentry tentry;
352
353                 VL = SVL =
354                     (struct Vlent *)malloc(ALLOCNT * sizeof(struct Vlent));
355                 if (VL == NULL) {
356                     printf("Can't allocate memory...\n");
357                     exit(1);
358                 }
359                 printf("Volumes not found in main hash tables in vldb...\n");
360                 for (index = 0; 1; index = next_index) {
361                     memset(&entry, 0, sizeof(entry));
362                     code =
363                         ubik_VL_ListEntry(cstruct, 0, index, &count,
364                                   &next_index, &entry);
365                     if (code) {
366                         printf("VL_ListEntry returned code = %d\n", code);
367                         break;
368                     }
369                     if (!next_index)
370                         break;
371                     num++;
372                     code =
373                         ubik_VL_GetEntryByNameO(cstruct, 0, entry.name,
374                                   &tentry);
375                     if (code == VL_NOENT) {
376                         num1++;
377                         printf("\tVolume %s %d (not in namehash)\n",
378                                entry.name, entry.volumeId[RWVOL]);
379                     }
380                     code =
381                         ubik_VL_GetEntryByID(cstruct, 0,
382                                   entry.volumeId[RWVOL], RWVOL, &tentry);
383                     if (code == VL_NOENT) {
384                         num2++;
385                         printf("\tVolume %s %d (not in rwid hash)\n",
386                                entry.name, entry.volumeId[RWVOL]);
387                     }
388                     if (entry.volumeId[BACKVOL]) {
389                         code =
390                             ubik_VL_GetEntryByID(cstruct, 0,
391                                       entry.volumeId[BACKVOL], BACKVOL,
392                                       &tentry);
393                         num31++;
394                         if (code == VL_NOENT) {
395                             num3++;
396                             printf("\tVolume %s %d (not in backup id hash)\n",
397                                    entry.name, entry.volumeId[BACKVOL]);
398                         }
399                     }
400                     if (entry.volumeId[ROVOL]) {
401                         code =
402                             ubik_VL_GetEntryByID(cstruct, 0,
403                                       entry.volumeId[ROVOL], ROVOL, &tentry);
404                         num41++;
405                         if (code == VL_NOENT) {
406                             num4++;
407                             printf("\tVolume %s %d (not in RO id hash)\n",
408                                    entry.name, entry.volumeId[ROVOL]);
409                         }
410                     }
411                 }
412                 printf
413                     ("\nTotal vldb entries %d\nTotal volumes %d (%d rw, %d backup, %d ro)\n",
414                      num, num + num31 + num41, num, num31, num41);
415                 printf
416                     ("\n\t%d didn't hash properly by name\n\t%d didn't hash properly by rw volid\n",
417                      num1, num2);
418                 printf
419                     ("\t%d didn't hash properly by backup volid (out of %d)\n\t%d didn't hash properly by ro volid (out of %d)\n",
420                      num3, num31, num4, num41);
421             } else if (!strcmp(oper, "fixhash")) {
422                 int index, count, num = 0, num1 = 0, num2 = 0, next_index, x =
423                     0;
424                 struct vldbentry tentry;
425
426                 VL = SVL =
427                     (struct Vlent *)malloc(ALLOCNT * sizeof(struct Vlent));
428                 if (VL == NULL) {
429                     printf("Can't allocate memory...\n");
430                     exit(1);
431                 }
432                 printf
433                     ("Volumes not found in main hash tables in vldb will be fixed...\n");
434                 memset(&updateentry, 0, sizeof(updateentry));
435                 for (index = 0; 1; index = next_index) {
436                     /* FIXME: n2 is never changed for some reason */
437                     int n1 = 0, n2 = 0, n3 = 0, n4 = 0;
438                     memset(&entry, 0, sizeof(entry));
439                     code =
440                         ubik_VL_ListEntry(cstruct, 0, index, &count,
441                                   &next_index, &entry);
442                     if (code) {
443                         printf("VL_ListEntry returned code = %d\n", code);
444                         break;
445                     }
446                     if (!next_index)
447                         break;
448                     num++;
449                     code =
450                         ubik_VL_GetEntryByNameO(cstruct, 0, entry.name,
451                                   &tentry);
452                     if (code == VL_NOENT) {
453                         num1++;
454                         n1 = 1;
455                         updateentry.Mask = VLUPDATE_VOLNAMEHASH;
456                         printf("\tVolume %s %d (not in namehash)\n",
457                                entry.name, entry.volumeId[RWVOL]);
458                         code =
459                             ubik_VL_UpdateEntry(cstruct, 0,
460                                       entry.volumeId[RWVOL], -1, &updateentry,
461                                       0);
462                         if (code) {
463                             x++;
464                             printf("\tFailed to update volume %s (err=%d)\n",
465                                    entry.name, code);
466                         }
467                     }
468                     code =
469                         ubik_VL_GetEntryByID(cstruct, 0,
470                                   entry.volumeId[RWVOL], RWVOL, &tentry);
471                     if (code == VL_NOENT) {
472                         num1++;
473                         num2++;
474                         updateentry.Mask = VLUPDATE_RWID;
475                         updateentry.spares3 = entry.volumeId[RWVOL];
476                         printf("\tVolume %s %d (not in rw id hash)\n",
477                                entry.name, entry.volumeId[RWVOL]);
478                         code =
479                             ubik_VL_UpdateEntryByName(cstruct, 0,
480                                       entry.name, &updateentry, 0);
481                         if (code) {
482                             printf("\tFailed to update volume %s (err=%d)\n",
483                                    entry.name, code);
484                             x++;
485                         }
486                         x++;
487                     }
488                     if (entry.volumeId[BACKVOL] && !n2) {
489                         code =
490                             ubik_VL_GetEntryByID(cstruct, 0,
491                                       entry.volumeId[BACKVOL], BACKVOL,
492                                       &tentry);
493                         if (code == VL_NOENT) {
494                             n3 = 1;
495                             num1++;
496                             updateentry.Mask = VLUPDATE_BACKUPID;
497                             updateentry.BackupId = entry.volumeId[BACKVOL];
498                             printf("\tVolume %s %d (not in backup id hash)\n",
499                                    entry.name, entry.volumeId[BACKVOL]);
500                             code =
501                                 ubik_VL_UpdateEntry(cstruct, 0,
502                                           entry.volumeId[RWVOL], -1,
503                                           &updateentry, 0);
504                             if (code) {
505                                 printf
506                                     ("\tFailed to update volume %s (err=%d)\n",
507                                      entry.name, code);
508                                 x++;
509                             }
510                         }
511                     }
512                     if (entry.volumeId[ROVOL && !n2]) {
513                         code =
514                             ubik_VL_GetEntryByID(cstruct, 0,
515                                       entry.volumeId[ROVOL], ROVOL, &tentry);
516                         if (code == VL_NOENT) {
517                             n4 = 1;
518                             num1++;
519                             updateentry.Mask = VLUPDATE_READONLYID;
520                             updateentry.ReadOnlyId = entry.volumeId[ROVOL];
521                             printf("\tVolume %s %d (not in RO id hash)\n",
522                                    entry.name, entry.volumeId[ROVOL]);
523                             code =
524                                 ubik_VL_UpdateEntry(cstruct, 0,
525                                           entry.volumeId[RWVOL], -1,
526                                           &updateentry, 0);
527                             if (code) {
528                                 printf
529                                     ("\tFailed to update volume %s (err=%d)\n",
530                                      entry.name, code);
531                                 x++;
532                             }
533                         }
534                     }
535                 }
536                 printf
537                     ("\nTotal vldb entries found %d:\n\t%d entries didn't hash properly and are fixed except %d that need to be handled manually\n",
538                      num, num1, x);
539             } else if (!strcmp(oper, "la")) {
540                 int nentries = 0, i;
541                 bulkentries entries;
542                 struct vldbentry *entry;
543
544                 memset(&entries, 0, sizeof(entries));
545                 fill_listattributes_entry(&listbyattributes, argp, nargs);
546                 display_listattributes_entry(&listbyattributes, 0);
547                 code =
548                     ubik_VL_ListAttributes(cstruct, 0,
549                               &listbyattributes, &nentries, &entries);
550                 if (code) {
551                     printf("VL_ListAttributes returned code = %d\n", code);
552                     continue;
553                 }
554                 entry = (struct vldbentry *)entries.bulkentries_val;
555                 for (i = 0; i < nentries; i++, entry++)
556                     display_entry(entry, 0);
557                 if (entries.bulkentries_val)
558                     free((char *)entries.bulkentries_val);
559             } else if (!strcmp(oper, "lan2")) {
560                 int nentries, i, si, nsi, t = 0;
561                 nbulkentries entries;
562                 struct nvldbentry *entry;
563                 char name[64];
564
565                 /* The volume name to search for (supports wildcarding) */
566                 if (nargs > 0) {
567                     strcpy(name, argp[0]);
568                     ++argp, --nargs;
569                 } else {
570                     strcpy(name, "");
571                 }
572
573                 fill_listattributes_entry(&listbyattributes, argp, nargs);
574                 display_listattributes_entry(&listbyattributes, 0);
575                 printf("Wildcard VolName: '%s'\n", name);
576
577                 for (si = 0; si != -1; si = nsi) {
578                     nentries = 0;
579                     memset(&entries, 0, sizeof(entries));
580                     code =
581                         ubik_VL_ListAttributesN2(cstruct, 0,
582                                   &listbyattributes, name, si, &nentries,
583                                   &entries, &nsi);
584                     if (code) {
585                         printf("VL_ListAttributesN2 returned code = %d\n",
586                                code);
587                         break;
588                     }
589
590                     t += nentries;
591                     entry = (struct nvldbentry *)entries.nbulkentries_val;
592                     for (i = 0; i < nentries; i++, entry++)
593                         display_entryN(entry, 0);
594                     if (entries.nbulkentries_val)
595                         free((char *)entries.nbulkentries_val);
596                 }
597                 printf("--- %d volumes ---\n", t);
598             } else if (!strcmp(oper, "ln")) {
599                 int netries;
600                 vldb_list linkedvldbs;
601                 vldblist vllist, vllist1;
602
603                 fill_listattributes_entry(&listbyattributes, argp, nargs);
604                 display_listattributes_entry(&listbyattributes, 0);
605                 memset(&linkedvldbs, 0, sizeof(vldb_list));
606                 code =
607                     ubik_VL_LinkedList(cstruct, 0, &listbyattributes,
608                               &netries, &linkedvldbs);
609                 if (code) {
610                     printf("VL_LinkedList returned code = %d\n", code);
611                     continue;
612                 }
613                 printf("Found %d entr%s\n", netries,
614                        (netries == 1 ? "y" : "ies"));
615                 for (vllist = linkedvldbs.node; vllist; vllist = vllist1) {
616                     vllist1 = vllist->next_vldb;
617                     display_entry((struct vldbentry *) &vllist->VldbEntry, 0);
618                     free(vllist);
619                 }
620             } else if (!strcmp(oper, "lnn")) {
621                 int netries;
622                 nvldb_list linkedvldbs;
623                 nvldblist vllist, vllist1;
624
625                 fill_listattributes_entry(&listbyattributes, argp, nargs);
626                 display_listattributes_entry(&listbyattributes, 0);
627                 memset(&linkedvldbs, 0, sizeof(vldb_list));
628                 code =
629                     ubik_VL_LinkedListN(cstruct, 0, &listbyattributes,
630                               &netries, &linkedvldbs);
631                 if (code) {
632                     printf("VL_LinkedList returned code = %d\n", code);
633                     continue;
634                 }
635                 printf("Found %d entr%s\n", netries,
636                        (netries == 1 ? "y" : "ies"));
637                 for (vllist = linkedvldbs.node; vllist; vllist = vllist1) {
638                     vllist1 = vllist->next_vldb;
639                     display_entry((struct vldbentry *)&vllist->VldbEntry, 0);
640                     free((char *)vllist);
641                 }
642             } else if (!strcmp(oper, "di")) {
643                 sscanf(&(*argp)[0], "%d", &id);
644                 ++argp, --nargs;
645                 sscanf(&(*argp)[0], "%d", &voltype);
646                 code =
647                     ubik_VL_GetEntryByID(cstruct, 0, id, voltype,
648                               &entry);
649                 display_entry(&entry, code);
650                 printf("return code is %d.\n", code);
651             } else if (!strcmp(oper, "rmnh")) {
652                 sscanf(&(*argp)[0], "%d", &id);
653                 ++argp, --nargs;
654                 sscanf(&(*argp)[0], "%d", &voltype);
655                 code =
656                     ubik_VL_GetEntryByID(cstruct, 0, id, voltype,
657                               &entry);
658                 display_entry(&entry, code);
659                 memset(&updateentry, 0, sizeof(updateentry));
660                 updateentry.Mask = VLUPDATE_VOLNAMEHASH;
661                 printf("\tRehashing namehash table for %s (%d)\n", entry.name,
662                        entry.volumeId[RWVOL]);
663                 code =
664                     ubik_VL_UpdateEntry(cstruct, 0,
665                               entry.volumeId[RWVOL], -1, &updateentry, 0);
666                 if (code) {
667                     printf("\tFailed to update volume %s (err=%d)\n",
668                            entry.name, code);
669                 }
670                 printf("return code is %d.\n", code);
671             } else if (!strcmp(oper, "undelete")) {
672                 afs_int32 index, count, next_index;
673
674                 memset(&updateentry, 0, sizeof(updateentry));
675                 sscanf(&(*argp)[0], "%d", &id);
676                 ++argp, --nargs;
677                 sscanf(&(*argp)[0], "%d", &voltype);
678                 if (voltype < 0 && voltype > 2) {
679                     printf("Illegal voltype; must be 0, 1 or 2\n");
680                     continue;
681                 }
682                 printf("Searching vldb for volume %d...\n", id);
683                 for (index = 0; 1; index = next_index) {
684                     memset(&entry, 0, sizeof(entry));
685                     code =
686                         ubik_VL_ListEntry(cstruct, 0, index, &count,
687                                   &next_index, &entry);
688                     if (code) {
689                         printf("VL_ListEntry returned code = %d\n", code);
690                         break;
691                     }
692                     if (!next_index)
693                         break;
694                     if (entry.volumeId[voltype] == id) {
695                         printf("\nThe current contents of the vldb for %d:\n",
696                                id);
697                         display_entry(&entry, 0);
698
699                         if (entry.flags & VLDELETED) {
700                             updateentry.Mask = VLUPDATE_FLAGS;
701                             updateentry.flags = entry.flags;
702                             updateentry.flags &= ~VLDELETED;
703                             printf
704                                 ("\tUndeleting vldb entry for vol %d (%s)\n",
705                                  id, entry.name);
706                             code =
707                                 ubik_VL_UpdateEntry(cstruct, 0, id, -1,
708                                           &updateentry, 0);
709                             if (code) {
710                                 printf
711                                     ("\tFailed to update volume %s (err=%d)\n",
712                                      entry.name, code);
713                             }
714                         } else {
715                             printf("Entry not deleted; ignored\n");
716                         }
717                         break;
718                     }
719                 }
720             } else if (!strcmp(oper, "dn")) {
721                 vname = &argp[0][0];
722                 code =
723                     ubik_VL_GetEntryByNameO(cstruct, 0, vname, &entry);
724                 display_entry(&entry, code);
725                 printf("return code is %d.\n", code);
726             } else if (!strcmp(oper, "nv")) {
727                 unsigned int newvolid;
728                 sscanf(&(*argp)[0], "%d", &id);
729                 code =
730                     ubik_VL_GetNewVolumeId(cstruct, 0, id, &newvolid);
731                 if (!code)
732                     printf("Current Max volid is (in hex):0x%x\n", newvolid);
733                 printf("return code is %d\n", code);
734             } else if (!strcmp(oper, "gs")) {
735                 vldstats stats;
736                 vital_vlheader vital_header;
737                 code =
738                     ubik_VL_GetStats(cstruct, 0, &stats, &vital_header);
739                 if (!code)
740                     dump_stats(&stats, &vital_header);
741                 printf("return code is %d.\n", code);
742             } else if (!strcmp(oper, "ga")) {
743                 int nentries, i;
744                 afs_uint32 *addrp;
745                 bulkaddrs addrs;
746                 struct VLCallBack vlcb;
747
748                 addrs.bulkaddrs_val = 0;
749                 addrs.bulkaddrs_len = 0;
750                 code = ubik_VL_GetAddrs(cstruct, 0, 0 /*Handle */ ,
751                                  0 /*spare2 */ , &vlcb,
752                                  &nentries, &addrs);
753                 if (code) {
754                     printf("VL_GetAddrs returned code = %d\n", code);
755                     continue;
756                 }
757                 addrp = addrs.bulkaddrs_val;
758                 for (i = 0; i < nentries; i++, addrp++) {
759                     if ((*addrp & 0xff000000) == 0xff000000)
760                         printf("[0x%x %u] (special multi-homed entry)\n",
761                                *addrp, *addrp);
762                     else
763                         printf("[0x%x %u] %s\n", *addrp, *addrp,
764                                hostutil_GetNameByINet(ntohl(*addrp)));
765                 }
766                 free((char *)addrs.bulkaddrs_val);
767             } else if (!strcmp(oper, "gau")) {
768                 int nentries, i, j;
769                 afs_uint32 *addrp;
770                 bulkaddrs addrs;
771                 struct VLCallBack vlcb;
772
773                 addrs.bulkaddrs_val = 0;
774                 addrs.bulkaddrs_len = 0;
775                 code = ubik_VL_GetAddrs(cstruct, 0, 0 /*Handle */ ,
776                                  0 /*spare2 */ , &vlcb,
777                                  &nentries, &addrs);
778                 if (code) {
779                     printf("VL_GetAddrs returned code = %d\n", code);
780                     continue;
781                 }
782                 addrp = addrs.bulkaddrs_val;
783                 for (i = 0; i < nentries; i++, addrp++) {
784                     if ((*addrp & 0xff000000) == 0xff000000) {
785                         int mhnentries, unique;
786                         struct in_addr hostAddr;
787                         afs_uint32 *mhaddrp;
788                         bulkaddrs mhaddrs;
789                         ListAddrByAttributes attrs;
790                         afsUUID uuid;
791
792                         printf("[0x%x %u] (special multi-homed entry)\n",
793                                *addrp, *addrp);
794                         attrs.Mask = VLADDR_INDEX;
795                         mhaddrs.bulkaddrs_val = 0;
796                         mhaddrs.bulkaddrs_len = 0;
797                         attrs.index = *addrp & 0x00ffffff;
798
799                         code =
800                             ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid,
801                                       &unique, &mhnentries, &mhaddrs);
802                         if (code) {
803                             printf("VL_GetAddrsU returned code = %d\n", code);
804                             continue;
805                         }
806                         printf
807                             ("   [%d]: uuid[%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x]\n   addrunique=%d, ip address(es):\n",
808                              attrs.index, uuid.time_low, uuid.time_mid,
809                              uuid.time_hi_and_version,
810                              uuid.clock_seq_hi_and_reserved,
811                              uuid.clock_seq_low, uuid.node[0], uuid.node[1],
812                              uuid.node[2], uuid.node[3], uuid.node[4],
813                              uuid.node[5], unique);
814                         mhaddrp = mhaddrs.bulkaddrs_val;
815                         for (j = 0; j < mhnentries; j++) {
816                             mhaddrp[j] = ntohl(mhaddrp[j]);
817                             hostAddr.s_addr = mhaddrp[j];
818                             printf("\t%s (%s)\n", inet_ntoa(hostAddr),
819                                    hostutil_GetNameByINet(mhaddrp[j]));
820                         }
821                         if (mhaddrs.bulkaddrs_val)
822                             free((char *)mhaddrs.bulkaddrs_val);
823                     } else {
824                         printf("[0x%x %u] %s\n", *addrp, *addrp,
825                                hostutil_GetNameByINet(ntohl(*addrp)));
826                     }
827                 }
828                 free((char *)addrs.bulkaddrs_val);
829             } else if (!strcmp(oper, "mhc")) {
830                 afs_int32 serveraddrs[MAXSERVERID + 1][VL_MAXIPADDRS_PERMH];
831                 afs_int32 serveraddrtype[MAXSERVERID + 1];
832                 int nentries1, nentries2, i, j, x, y, unique, found;
833                 afs_uint32 *addrp1, *addrp2;
834                 bulkaddrs addrs1, addrs2;
835                 struct VLCallBack vlcb;
836                 ListAddrByAttributes attrs;
837                 afsUUID uuid;
838                 afs_int32 base, index;
839
840                 for (i = 0; i < MAXSERVERID + 1; i++) {
841                     serveraddrtype[i] = 0;
842                     for (j = 0; j < VL_MAXIPADDRS_PERMH; j++)
843                         serveraddrs[i][j] = 0;
844                 }
845
846                 /* Collect a list of all registered IP addresses */
847                 addrs1.bulkaddrs_val = 0;
848                 addrs1.bulkaddrs_len = 0;
849                 code =
850                     ubik_VL_GetAddrs(cstruct, 0, 0, 0, &vlcb,
851                               &nentries1, &addrs1);
852                 if (code) {
853                     printf("VL_GetAddrs returned code = %d\n", code);
854                     continue;
855                 }
856                 addrp1 = addrs1.bulkaddrs_val;
857                 for (i = 0; i < nentries1; i++, addrp1++) {
858                     if ((*addrp1 & 0xff000000) != 0xff000000) {
859                         serveraddrs[i][0] = ntohl(*addrp1);
860                         serveraddrtype[i] = 1;
861                     } else {
862                         /* It's multihomed. Get all of its addresses */
863                         serveraddrtype[i] = 2;
864                         base = (*addrp1 >> 16) & 0xff;
865                         index = *addrp1 & 0xffff;
866
867                         addrs2.bulkaddrs_val = 0;
868                         addrs2.bulkaddrs_len = 0;
869                         attrs.Mask = VLADDR_INDEX;
870                         attrs.index = (base * VL_MHSRV_PERBLK) + index;
871                         code =
872                             ubik_VL_GetAddrsU(cstruct, 0, &attrs, &uuid,
873                                       &unique, &nentries2, &addrs2);
874                         if (code) {
875                             printf("VL_GetAddrsU returned code = %d\n", code);
876                             break;
877                         }
878
879                         addrp2 = addrs2.bulkaddrs_val;
880                         for (j = 0; j < nentries2; j++) {
881                             serveraddrs[i][j] = ntohl(addrp2[j]);
882                         }
883                         free((char *)addrs2.bulkaddrs_val);
884                     }
885
886                     if (nargs) {
887                         if (serveraddrtype[i] == 1) {
888                             printf("%u\n", serveraddrs[i][0]);
889                         } else {
890                             printf("[");
891                             for (j = 0; j < VL_MAXIPADDRS_PERMH; j++)
892                                 if (serveraddrs[i][j])
893                                     printf(" %u", serveraddrs[i][j]);
894                             printf(" ]\n");
895                         }
896                     }
897                 }
898                 free((char *)addrs1.bulkaddrs_val);
899
900                 /* Look for any duplicates */
901                 for (i = 0; i < MAXSERVERID + 1; i++) {
902                     if (!serveraddrtype[i])
903                         continue;
904                     for (j = 0; j < VL_MAXIPADDRS_PERMH; j++) {
905                         if (!serveraddrs[i][j])
906                             continue;
907
908                         found = 0;
909                         for (x = i + 1; x < MAXSERVERID + 1; x++) {
910                             if (!serveraddrtype[x])
911                                 continue;
912                             for (y = 0; y < VL_MAXIPADDRS_PERMH; y++) {
913                                 if (!serveraddrs[x][y])
914                                     continue;
915                                 if (serveraddrs[i][j] == serveraddrs[x][y]) {
916                                     serveraddrs[x][y] = 0;
917                                     found++;
918                                 }
919                             }
920                         }
921                         if (found) {
922                             printf
923                                 ("Found %d entries of IP address %u (0x%x)\n",
924                                  found + 1, serveraddrs[i][j],
925                                  serveraddrs[i][j]);
926                         }
927                     }
928                 }
929
930                /*----------------------------------------*/
931
932             } else if (!strcmp(oper, "regaddr")) {
933                 int i;
934                 afs_uint32 *addrp, tad;
935                 bulkaddrs addrs;
936                 afsUUID uuid;
937
938                 memset(&uuid, 0, sizeof(uuid));
939                 sscanf(&(*argp)[0], "%d", &i);
940                 ++argp, --nargs;
941                 memcpy(uuid.node, &i, sizeof(i));
942
943                 if (nargs < 0 || nargs > 16) {
944                     printf("Illegal # entries = %d\n", nargs);
945                     continue;
946                 }
947                 addrp = (afs_uint32 *) malloc(20 * 4);
948                 addrs.bulkaddrs_val = addrp;
949                 addrs.bulkaddrs_len = nargs;
950                 while (nargs > 0) {
951                     sscanf(&(*argp)[0], "%d", &tad);
952                     *addrp++ = tad;
953                     ++argp, --nargs;
954                 }
955                 code =
956                     ubik_VL_RegisterAddrs(cstruct, 0, &uuid,
957                               0 /*spare */ , &addrs);
958                 if (code) {
959                     printf("VL_RegisterAddrs returned code = %d\n", code);
960                     continue;
961                 }
962             } else if (!strcmp(oper, "ca")) {
963                 struct hostent *h1, *h2;
964                 afs_uint32 a1, a2;
965
966                 printf("changing %s", *argp);
967                 h1 = hostutil_GetHostByName(&(*argp)[0]);
968                 if (!h1) {
969                     printf("cmdebug: can't resolve address for host %s",
970                            *argp);
971                     continue;
972                 }
973                 memcpy(&a1, (afs_int32 *) h1->h_addr, sizeof(afs_uint32));
974
975                 ++argp, --nargs;
976                 printf(" to %s\n", *argp);
977                 h2 = hostutil_GetHostByName(&(*argp)[0]);
978                 if (!h2) {
979                     printf("cmdebug: can't resolve address for host %s",
980                            *argp);
981                     continue;
982                 }
983                 memcpy(&a2, (afs_int32 *) h2->h_addr, sizeof(afs_uint32));
984
985                 printf("changing 0x%x to 0x%x\n", ntohl(a1), ntohl(a2));
986                 code =
987                     ubik_VL_ChangeAddr(cstruct, 0, ntohl(a1),
988                               ntohl(a2));
989                 if (code) {
990                     printf("VL_ChangeAddr returned code = %d\n", code);
991                     continue;
992                 }
993             } else if (!strcmp(oper, "caid")) {
994                 afs_uint32 a1, a2;
995
996                 sscanf(&(*argp)[0], "%d", &a1);
997                 printf("changing %d (0x%x)", a1, a1);
998                 ++argp, --nargs;
999                 sscanf(&(*argp)[0], "%d", &a2);
1000                 printf(" to %d (0x%x)\n", a2, a2);
1001                 code = ubik_VL_ChangeAddr(cstruct, 0, a1, a2);
1002                 if (code) {
1003                     printf("VL_ChangeAddr returned code = %d\n", code);
1004                     continue;
1005                 }
1006             } else if ((!strcmp(oper, "?")) || !strcmp(oper, "h"))
1007                 print_usage();
1008             else if ((!strcmp(oper, "q")) || !strcmp(oper, "quit"))
1009                 exit(0);
1010             else {
1011                 printf("Unknown oper!\n");
1012             }
1013         }
1014     }
1015 }
1016
1017
1018 #include "AFS_component_version_number.c"
1019
1020 int
1021 main(int argc, char **argv)
1022 {
1023     register struct cmd_syndesc *ts;
1024     afs_int32 code;
1025
1026     strcpy(confdir, AFSDIR_CLIENT_ETC_DIRPATH);
1027     ts = cmd_CreateSyntax("initcmd", handleit, NULL, "initialize the program");
1028     cmd_AddParm(ts, "-cellpath", CMD_LIST, CMD_OPTIONAL,
1029                 "Cell configuration directory");
1030     cmd_AddParm(ts, "-server", CMD_LIST, CMD_OPTIONAL,
1031                 "Use the cell config in /usr/afs/etc (default /usr/vice/etc)");
1032     cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL,
1033                 "Run it without authentication");
1034     cmd_AddParm(ts, "-host", CMD_LIST, CMD_OPTIONAL,
1035                 "vldb server to talk to");
1036     cmd_AddParm(ts, "-cell", CMD_LIST, CMD_OPTIONAL,
1037                 "cellname '-host' belongs to (required for auth conns)");
1038     cmd_AddParm(ts, "-getstats", CMD_FLAG, CMD_OPTIONAL,
1039                 "print vldb statistics (non interactive)");
1040     code = cmd_Dispatch(argc, argv);
1041     exit(code);
1042 }
1043
1044
1045 void
1046 fill_entry(struct vldbentry *entry, char **argp, int nargs)
1047 {
1048     char *name;
1049     int i;
1050
1051     name = &argp[0][0];
1052     ++argp, --nargs;
1053     sscanf(&(*argp)[0], "%d", &entry->spares3);
1054     ++argp, --nargs;
1055     sscanf(&(*argp)[0], "%d", &entry->nServers);
1056     strcpy(entry->name, name);
1057     for (i = 0; i < entry->nServers; i++) {
1058         ++argp, --nargs;
1059         sscanf(&(*argp)[0], "%u", &entry->serverNumber[i]);
1060     }
1061     for (i = 0; i < entry->nServers; i++) {
1062         ++argp, --nargs;
1063         sscanf(&(*argp)[0], "%d", &entry->serverPartition[i]);
1064     }
1065     for (i = 0; i < entry->nServers; i++) {
1066         ++argp, --nargs;
1067         sscanf(&(*argp)[0], "%d", &entry->serverFlags[i]);
1068     }
1069     for (i = 0; i < MAXTYPES; i++) {
1070         ++argp, --nargs;
1071         sscanf(&(*argp)[0], "%u", &entry->volumeId[i]);
1072     }
1073     ++argp, --nargs;
1074     sscanf(&(*argp)[0], "%d", &entry->flags);
1075     ++argp, --nargs;
1076     sscanf(&(*argp)[0], "%u", &entry->cloneId);
1077 }
1078
1079 void
1080 fill_update_entry(struct VldbUpdateEntry *entry, char **argp, int nargs)
1081 {
1082     int i, Mask;
1083     char *name;
1084
1085     entry->Mask = 0;
1086     name = &argp[0][0];
1087     if (strcmp(name, "null")) {
1088         strcpy(entry->name, name);
1089         entry->Mask |= VLUPDATE_VOLUMENAME;
1090     }
1091     ++argp, --nargs;
1092     sscanf(&(*argp)[0], "%d", &entry->flags);
1093     if (entry->flags != -1)
1094         entry->Mask |= VLUPDATE_FLAGS;
1095     ++argp, --nargs;
1096     sscanf(&(*argp)[0], "%u", &entry->cloneId);
1097     if (entry->flags != -1)
1098         entry->Mask |= VLUPDATE_CLONEID;
1099     ++argp, --nargs;
1100     sscanf(&(*argp)[0], "%u", &entry->ReadOnlyId);
1101     if (entry->ReadOnlyId != -1)
1102         entry->Mask |= VLUPDATE_READONLYID;
1103     ++argp, --nargs;
1104     sscanf(&(*argp)[0], "%u", &entry->BackupId);
1105     if (entry->BackupId != -1)
1106         entry->Mask |= VLUPDATE_BACKUPID;
1107     ++argp, --nargs;
1108     sscanf(&(*argp)[0], "%d", &entry->nModifiedRepsites);
1109     if (entry->nModifiedRepsites != -1)
1110         entry->Mask |= VLUPDATE_REPSITES;
1111     for (i = 0; i < entry->nModifiedRepsites; i++) {
1112         ++argp, --nargs;
1113         sscanf(&(*argp)[0], "%x", &Mask);
1114         ++argp, --nargs;
1115         sscanf(&(*argp)[0], "%u", &entry->RepsitesTargetServer[i]);
1116         ++argp, --nargs;
1117         sscanf(&(*argp)[0], "%d", &entry->RepsitesTargetPart[i]);
1118         if (Mask & VLUPDATE_REPS_DELETE)
1119             entry->RepsitesMask[i] |= VLUPDATE_REPS_DELETE;
1120         if (Mask & VLUPDATE_REPS_MODSERV) {
1121             ++argp, --nargs;
1122             sscanf(&(*argp)[0], "%u", &entry->RepsitesNewServer[i]);
1123             entry->RepsitesMask[i] |= VLUPDATE_REPS_MODSERV;
1124         } else if (Mask & VLUPDATE_REPS_MODPART) {
1125             ++argp, --nargs;
1126             sscanf(&(*argp)[0], "%d", &entry->RepsitesNewPart[i]);
1127             entry->RepsitesMask[i] |= VLUPDATE_REPS_MODPART;
1128         } else if (Mask & VLUPDATE_REPS_MODFLAG) {
1129             ++argp, --nargs;
1130             sscanf(&(*argp)[0], "%d", &entry->RepsitesNewFlags[i]);
1131             entry->RepsitesMask[i] |= VLUPDATE_REPS_MODFLAG;
1132         } else if (Mask & VLUPDATE_REPS_ADD) {
1133             ++argp, --nargs;
1134             sscanf(&(*argp)[0], "%u", &entry->RepsitesNewServer[i]);
1135             ++argp, --nargs;
1136             sscanf(&(*argp)[0], "%d", &entry->RepsitesNewPart[i]);
1137             ++argp, --nargs;
1138             sscanf(&(*argp)[0], "%d", &entry->RepsitesNewFlags[i]);
1139             entry->RepsitesMask[i] |= VLUPDATE_REPS_ADD;
1140         }
1141     }
1142 }
1143
1144 void
1145 fill_listattributes_entry(struct VldbListByAttributes *entry, char **argp,
1146                           int nargs)
1147 {
1148     entry->Mask = 0;
1149
1150     if (nargs <= 0)
1151         return;
1152     entry->server = ntohl(GetServer(argp[0]));
1153     sscanf(&(*argp)[0], "%d", &entry->server);
1154     if (entry->server != 0)
1155         entry->Mask |= VLLIST_SERVER;
1156     ++argp, --nargs;
1157
1158     if (nargs <= 0)
1159         return;
1160     sscanf(&(*argp)[0], "%d", &entry->partition);
1161     if (entry->partition != -1)
1162         entry->Mask |= VLLIST_PARTITION;
1163     ++argp, --nargs;
1164
1165     if (nargs <= 0)
1166         return;
1167     sscanf(&(*argp)[0], "%d", &entry->volumeid);
1168     if (entry->volumeid != -1)
1169         entry->Mask |= VLLIST_VOLUMEID;
1170     ++argp, --nargs;
1171
1172     if (nargs <= 0)
1173         return;
1174     sscanf(&(*argp)[0], "%d", &entry->flag);
1175     if (entry->flag != -1)
1176         entry->Mask |= VLLIST_FLAG;
1177 }
1178
1179 void
1180 display_listattributes_entry(struct VldbListByAttributes *entry, int error)
1181 {
1182     if (error)
1183         return;
1184     printf("\nList entry values (Mask=%x)\n", entry->Mask);
1185     if (entry->Mask & VLLIST_SERVER)
1186         printf("\tServer: %d.%d.%d.%d\n", (entry->server >> 24) & 0xff,
1187                (entry->server >> 16) & 0xff, (entry->server >> 8) & 0xff,
1188                (entry->server) & 0xff);
1189     if (entry->Mask & VLLIST_PARTITION)
1190         printf("\tPartition: %d\n", entry->partition);
1191     if (entry->Mask & VLLIST_VOLUMEID)
1192         printf("\tVolumeId: %u\n", entry->volumeid);
1193     if (entry->Mask & VLLIST_FLAG)
1194         printf("\tFlag: %x\n", entry->flag);
1195 }
1196
1197
1198 #define volumetype_string(type) (type == RWVOL? "read/write":type == ROVOL? "readonly":type == BACKVOL? "backup":"unknown")
1199
1200 void
1201 display_entry(struct vldbentry *entry, int error)
1202 {
1203     int i;
1204
1205     if (error)
1206         return;
1207     printf("\nEntry for volume name: %s, volid=%u (flags=%X) are:\n",
1208            entry->name, entry->volumeId[RWVOL], entry->flags);
1209     printf("ParentID=%u, ReadOnlyID=%u, backupID=%u, CloneId=%u ",
1210            entry->volumeId[0], entry->volumeId[1], entry->volumeId[2],
1211            entry->cloneId);
1212     printf("nServers=%d\n", entry->nServers);
1213     printf("ServerNumber\tServerPart\tserverFlag\n");
1214     for (i = 0; i < entry->nServers; i++)
1215         printf("%12u\t%10d\t%10x\n", entry->serverNumber[i],
1216                entry->serverPartition[i], entry->serverFlags[i]);
1217 }
1218
1219 void
1220 display_entryN(struct nvldbentry *entry, int error)
1221 {
1222     int i, et, ei;
1223
1224     if (error)
1225         return;
1226     printf("\nEntry for volume name: %s, volid=%u (flags=%X) are:\n",
1227            entry->name, entry->volumeId[RWVOL], entry->flags);
1228     printf("ParentID=%u, ReadOnlyID=%u, backupID=%u, CloneId=%u ",
1229            entry->volumeId[0], entry->volumeId[1], entry->volumeId[2],
1230            entry->cloneId);
1231     printf("nServers=%d\n", entry->nServers);
1232     printf("ServerNumber\tServerPart\tserverFlag\n");
1233     ei = entry->matchindex & 0xffff;
1234     et = (entry->matchindex >> 16) & 0xffff;
1235     for (i = 0; i < entry->nServers; i++) {
1236         printf("%12u\t%10d\t%10x", entry->serverNumber[i],
1237                entry->serverPartition[i], entry->serverFlags[i]);
1238         if (i == ei) {
1239             printf(" <--- %s", (et == 4) ? "RW" : ((et == 8) ? "BK" : "RO"));
1240         }
1241         printf("\n");
1242     }
1243 }
1244
1245 void
1246 display_update_entry(struct VldbUpdateEntry *entry, int error)
1247 {
1248     int i;
1249
1250     if (error)
1251         return;
1252     printf("\nUpdate entry values (Mask=%x)\n", entry->Mask);
1253     if (entry->Mask & VLUPDATE_VOLUMENAME)
1254         printf("\tNew name: %s\n", entry->name);
1255     if (entry->Mask & VLUPDATE_FLAGS)
1256         printf("\tNew flags: %X\n", entry->flags);
1257     if (entry->Mask & VLUPDATE_CLONEID)
1258         printf("\tNew CloneId: %X\n", entry->cloneId);
1259     if (entry->Mask & VLUPDATE_READONLYID)
1260         printf("\tNew RO id: %d\n", entry->ReadOnlyId);
1261     if (entry->Mask & VLUPDATE_BACKUPID)
1262         printf("\tNew BACKUP id: %d\n", entry->BackupId);
1263     if (entry->Mask & VLUPDATE_REPSITES) {
1264         printf("\tRepsites info:\n");
1265         printf("\tFlag\tTServer\tTPart\tNServer\tNPart\tNFlag\n");
1266         for (i = 0; i < entry->nModifiedRepsites; i++) {
1267             printf("\t%4x\t%7u\t%5d", entry->RepsitesMask[i],
1268                    entry->RepsitesTargetServer[i],
1269                    entry->RepsitesTargetPart[i]);
1270             if ((entry->RepsitesMask[i] & VLUPDATE_REPS_ADD)
1271                 || (entry->RepsitesMask[i] & VLUPDATE_REPS_MODSERV))
1272                 printf("\t%7u", entry->RepsitesNewServer[i]);
1273             else
1274                 printf("\t-------");
1275             if ((entry->RepsitesMask[i] & VLUPDATE_REPS_ADD)
1276                 || (entry->RepsitesMask[i] & VLUPDATE_REPS_MODPART))
1277                 printf("\t%5d", entry->RepsitesNewPart[i]);
1278             else
1279                 printf("\t-----");
1280             if ((entry->RepsitesMask[i] & VLUPDATE_REPS_ADD)
1281                 || (entry->RepsitesMask[i] & VLUPDATE_REPS_MODFLAG))
1282                 printf("\t%5x\n", entry->RepsitesNewFlags[i]);
1283             else
1284                 printf("\t-----\n");
1285         }
1286     }
1287 }
1288
1289 void
1290 dump_stats(vldstats *stats, vital_vlheader *vital_header)
1291 {
1292     int i;
1293     char strg[30];
1294     time_t start_time = stats->start_time;
1295
1296     afs_ctime(&start_time, strg, sizeof(strg));
1297     strg[strlen(strg) - 1] = 0;
1298     printf("Dynamic statistics stats (starting time: %s):\n", strg);
1299     printf("OpcodeName\t# Requests\t# Aborts\n");
1300     for (i = 0; i < VL_NUMBER_OPCODESX; i++)
1301         printf("%10s\t%10d\t%8d\n", opcode_names[i], stats->requests[i],
1302                stats->aborts[i]);
1303     printf("\nVldb header stats (version=%d)\n",
1304            ntohl(vital_header->vldbversion));
1305     printf("headersize=%d, allocs=%d, frees=%d, MaxVolid=%X\n",
1306            ntohl(vital_header->headersize), ntohl(vital_header->allocs),
1307            ntohl(vital_header->frees), ntohl(vital_header->MaxVolumeId));
1308     for (i = 0; i < MAXTYPES; i++)
1309         printf("total %s entries=%d\n", volumetype_string(i),
1310                ntohl(vital_header->totalEntries[i]));
1311 }
1312
1313 void
1314 GetArgs(char *line, char **args, int *nargs)
1315 {
1316     *nargs = 0;
1317     while (*line) {
1318         register char *last = line;
1319         while (*line == ' ')
1320             line++;
1321         if (*last == ' ')
1322             *last = 0;
1323         if (!*line)
1324             break;
1325         *args++ = line, (*nargs)++;
1326         while (*line && *line != ' ')
1327             line++;
1328     }
1329 }
1330
1331 void
1332 print_usage(void)
1333 {
1334     printf("Valid Commands:\n");
1335
1336     printf("   CreateEntry:\n");
1337     printf
1338         ("\tcr <vname> <vtype> <#S> <Saddr1>.<Saddrn> <Spart1>.<Spartn> <Sflag1>.<Sflagn> <Volid1-3> <flag>\n");
1339
1340     printf("   DeleteEntry:\n");
1341     printf("\trm <volid> <voltype>\n");
1342
1343     printf("   ReplaceEntry:\n");
1344     printf("\tre <volid> <voltype> <New vldb entry ala 'cr'>\n");
1345
1346     printf("   UpdateEntry:\n");
1347     printf
1348         ("\tup <volid> <voltype> <vname> <vtype> <#AddSer> [<Saddr1>.<Saddrn> <Spart1>.<Spartn> <Sflag1>.<Sflagn>] <Volid1-3> <flag>\n");
1349
1350     printf("   ListEntry:\n");
1351     printf("\tls\n");
1352
1353     printf("   Find duplicate entries of a volume\n");
1354     printf("\tldups\n");
1355
1356     printf("   For each vlentry, find it by name, RW id, BK id, and RO id\n");
1357     printf("\tcheckhash\n");
1358
1359     printf
1360         ("   UpdateEntry (update the volname, RW id, BK id, RO id hashes):\n");
1361     printf("\tfixhash\n");
1362
1363     printf("   ListAttributes:\n");
1364     printf("\tla [server] [partition] [volumeid] [flag]\n");
1365
1366     printf("   ListAttributesN2:\n");
1367     printf("\tlan2 [volname] [server] [partition] [volumeid] [flag]\n");
1368
1369     printf("   GetEntryByID:\n");
1370     printf("\tdi <volid> <voltype>\n");
1371
1372     printf("   UpdateEntry (refresh namehash table):\n");
1373     printf("\trmnh <volid> <voltype>\n");
1374
1375     printf("   GetEntryByName:\n");
1376     printf("\tdn <volname> <voltype>\n");
1377
1378     printf("   UpdateEntry (undelete a vol entry):\n");
1379     printf("\tundelete <volid> <voltype>\n");
1380 /*
1381  *  printf("  LinkedList\n");
1382  *  printf("\t:ln [server] [partition] [volumeid] [flag]\n");
1383  *
1384  *  printf("  LinkedListN\n");
1385  *  printf("\t:lnn [server] [partition] [volumeid] [flag]\n");
1386  */
1387     printf("   GetNewVoumeId:\n");
1388     printf("\tnv <bump-count>\n");
1389
1390     printf("   GetStats:\n");
1391     printf("\tgs\n");
1392
1393     printf("   ChangeAddr:\n");
1394     printf("\tca <oldmachname> <newmachname>\n");
1395
1396 /*
1397  *  printf("   ChangeAddr\n");
1398  *  printf("\t:caid <oldaddr> <newaddr>\n");
1399  */
1400     printf("   GetAddrs:\n");
1401     printf("\tga\n");
1402
1403     printf("   GetAddrsU:\n");
1404     printf("\tgau\n");
1405
1406     printf("   RegisterAddrs:\n");
1407     printf("\tregaddr uuidNumber <ip1 .. ipn>\n");
1408
1409     printf("\tmisc: q, quit, ?, h\n");
1410 }