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