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