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