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