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