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