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