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