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