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