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