auth-cleanup-20070208
[openafs.git] / src / tviced / state_analyzer.c
1 /*
2  * Copyright 2006, Sine Nomine Associates 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 /*
11  * demand attach fs
12  * fileserver state serialization
13  *
14  * state analyzer
15  */
16
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20 RCSID
21     ("$Header$");
22
23 #include <stdio.h>
24 #include <errno.h>
25 #include <sys/file.h>
26 #include <netdb.h>
27 #include <netinet/in.h>
28 #include <time.h>
29
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #else
33 #ifdef HAVE_STRINGS_H
34 #include <strings.h>
35 #endif
36 #endif
37
38 #include <afs/stds.h>
39 #include <rx/xdr.h>
40 #include <afs/assert.h>
41 #include <lwp.h>
42 #include <lock.h>
43 #include <afs/afsint.h>
44 #include <afs/rxgen_consts.h>
45 #include <afs/nfs.h>
46 #include <afs/errors.h>
47 #include <afs/ihandle.h>
48 #include <afs/vnode.h>
49 #include <afs/volume.h>
50 #ifdef AFS_ATHENA_STDENV
51 #include <krb.h>
52 #endif
53 #include <afs/acl.h>
54 #include <afs/ptclient.h>
55 #include <afs/prs_fs.h>
56 #include <afs/afsutil.h>
57 #include <rx/rx.h>
58 #include <afs/cellconfig.h>
59 #include <stdlib.h>
60 #include "../util/afsutil_prototypes.h"
61 #include "../viced/viced.h"
62 #include "../viced/host.h"
63 #include "../viced/callback.h"
64 #include "serialize_state.h"
65 #include <fcntl.h>
66 #include <sys/types.h>
67 #include <sys/stat.h>
68 #include <sys/mman.h>
69 #include <unistd.h>
70
71 /*@+fcnmacros +macrofcndecl@*/
72 #ifdef O_LARGEFILE
73 #ifdef S_SPLINT_S
74 extern off64_t afs_lseek(int FD, off64_t O, int F);
75 #endif /*S_SPLINT_S */
76 #define afs_lseek(FD, O, F)     lseek64(FD, (off64_t)(O), F)
77 #define afs_stat                stat64
78 #define afs_fstat               fstat64
79 #define afs_open                open64
80 #define afs_fopen               fopen64
81 #define afs_mmap                mmap64
82 #ifdef AFS_AIX_ENV
83 extern void * mmap64();  /* ugly hack since aix build env appears to be somewhat broken */
84 #endif
85 #else /* !O_LARGEFILE */
86 #ifdef S_SPLINT_S
87 extern off_t afs_lseek(int FD, off_t O, int F);
88 #endif /*S_SPLINT_S */
89 #define afs_lseek(FD, O, F)     lseek(FD, (off_t)(O), F)
90 #define afs_stat                stat
91 #define afs_fstat               fstat
92 #define afs_open                open
93 #define afs_fopen               fopen
94 #define afs_mmap                mmap
95 #endif /* !O_LARGEFILE */
96 /*@=fcnmacros =macrofcndecl@*/
97
98
99 #ifndef AFS_DEMAND_ATTACH_FS
100 int
101 main (int argc, char ** argv)
102 {
103     fprintf(stderr, "%s is only supported for demand attach fileservers\n",
104             argv[0] ? argv[0] : "state analyzer");
105     return 1;
106 }
107 #else /* AFS_DEMAND_ATTACH_FS */
108
109 static void usage(char * prog);
110 static int openFile(char * path);
111 static void initState(void);
112
113 static void banner(void);
114 static void prompt(void);
115
116 static void print_help(void);
117 static void print_global_help(void);
118 static void print_h_help(void);
119 static void print_fe_help(void);
120 static void print_cb_help(void);
121
122 static void dump_hdr(void);
123 static void dump_h_hdr(void);
124 static void dump_cb_hdr(void);
125
126 static void dump_cb_timeout(void);
127 static void dump_cb_fehash(void);
128
129 static void dump_all_hes(void);
130 static void dump_all_fes(void);
131 static void dump_all_cbs(void);
132
133 static void dump_he(afs_uint32 idx);
134 static void dump_fe(afs_uint32 idx);
135 static void dump_cb(afs_uint32 idx);
136 static void dump_this_he(void);
137 static void dump_this_fe(void);
138 static void dump_this_cb(void);
139 static void dump_next_he(void);
140 static void dump_next_fe(void);
141 static void dump_next_cb(void);
142 static void dump_prev_he(void);
143 static void dump_prev_fe(void);
144 static void dump_prev_cb(void);
145 static void dump_first_he(void);
146 static void dump_first_fe(void);
147 static void dump_first_cb(void);
148 static void dump_last_he(void);
149 static void dump_last_fe(void);
150 static void dump_last_cb(void);
151 static void dump_he_hdr(void);
152 static void dump_he_entry(void);
153 static void dump_he_interfaces(void);
154 static void dump_he_hcps(void);
155 static void dump_fe_hdr(void);
156 static void dump_fe_entry(void);
157 static void dump_cb_entry(void);
158
159 static void hexdump_map(afs_uint32 offset, afs_uint32 len);
160
161 static int get_hdr(void);
162 static int get_h_hdr(void);
163 static int get_cb_hdr(void);
164 static int get_cb_timeout_hdr(void);
165 static int get_cb_timeout(void);
166 static int get_cb_fehash_hdr(void);
167 static int get_cb_fehash(void);
168 static int get_he(afs_uint32 idx);
169 static int get_he_hdr(void);
170 static int get_he_entry(void);
171 static int get_fe(afs_uint32 idx);
172 static int get_fe_hdr(void);
173 static int get_fe_entry(void);
174 static int get_cb(afs_uint32 idx);
175 static int get_cb_entry(void);
176
177 static int find_fe_by_index(afs_uint32 idx);
178 static int find_cb_by_index(afs_uint32 idx);
179 static int find_fe_by_fid(afs_uint32 vol, afs_uint32 vn, afs_uint32 uniq);
180
181
182 static int dump_fd = -1;
183 static void * map = NULL;
184 static size_t map_len;
185
186 static struct {
187     struct fs_state_header hdr;
188     struct host_state_header h_hdr;
189     struct callback_state_header cb_hdr;
190     struct callback_state_timeout_header timeout_hdr;
191     struct callback_state_fehash_header fehash_hdr;
192     afs_uint32 * timeout;
193     afs_uint32 * fehash;
194
195     /* pointers into the memory map */
196     void * hdr_p;
197     void * h_hdr_p;
198     void * cb_hdr_p;
199     void * timeout_hdr_p;
200     void * timeout_p;
201     void * fehash_hdr_p;
202     void * fehash_p;
203
204     byte hdr_valid;
205     byte h_hdr_valid;
206     byte cb_hdr_valid;
207     byte timeout_hdr_valid;
208     byte fehash_hdr_valid;
209 } hdrs;
210
211 static struct {
212     void * fh;
213     void * cursor;
214     void * ifp;
215     void * hcps;
216     struct host_state_entry_header hdr;
217     struct hostDiskEntry he;
218     afs_uint32 idx;
219     byte hdr_valid;
220     byte he_valid;
221 } he_cursor;
222
223 static struct {
224     void ** cursor;
225 } he_cache;
226
227 static struct {
228     void * ffe;
229     void * cursor;
230     void * fcb;
231     struct callback_state_entry_header hdr;
232     struct FEDiskEntry fe;
233     afs_uint32 idx;
234     byte hdr_valid;
235     byte fe_valid;
236 } fe_cursor;
237
238 static struct {
239     void ** cursor;
240 } fe_cache;
241
242 static struct {
243     void * cursor;
244     struct CBDiskEntry cb;
245     afs_uint32 idx;
246     byte cb_valid;
247 } cb_cursor;
248
249 static struct {
250     void ** cursor;
251 } cb_cache;
252
253 static void
254 usage(char * prog)
255 {
256     fprintf(stderr, "usage: %s [<state dump file>]\n");
257 }
258
259 int
260 main(int argc, char ** argv)
261 {
262     banner();
263
264     if (argc > 2 || (argc == 2 && !strcmp(argv[1], "-h"))) {
265         usage(argv[0]);
266         return 1;
267     }
268
269     initState();
270
271     if (argc > 1) {
272         if (openFile(argv[1]))
273             return 1;
274     } else {
275         if (openFile(AFSDIR_SERVER_FSSTATE_FILEPATH))
276             return 1;
277     }
278
279     prompt();
280     return 0;
281 }
282
283
284 static int
285 openFile(char * path)
286 {
287     int ret = 0;
288     struct afs_stat status;
289     
290     dump_fd = afs_open(path, O_RDWR);
291     if (dump_fd == -1) {
292         fprintf(stderr, "dump file '%s' failed to open\n", path);
293         ret = 1;
294         goto done;
295     }
296
297     printf("opened dump file '%s'\n", path);
298
299     if (afs_fstat(dump_fd, &status) == -1) {
300         fprintf(stderr, "failed to stat file\n");
301         ret = 1;
302         goto done;
303     }
304
305     map_len = status.st_size;
306
307     map = afs_mmap(NULL, map_len, PROT_READ, MAP_SHARED, dump_fd, 0);
308     if (map == MAP_FAILED) {
309         fprintf(stderr, "failed to mmap file\n");
310         ret = 1;
311         goto done;
312     }
313
314     printf("mapped %d bytes at 0x%x\n", map_len, map);
315
316  done:
317     if (ret) {
318         if (map) {
319             munmap(map, map_len);
320             map = NULL;
321         }
322         if (dump_fd != -1) {
323             close(dump_fd);
324             dump_fd = -1;
325         }
326     }
327     return ret;
328 }
329
330 static void
331 initState(void)
332 {
333     hdrs.hdr_valid = hdrs.h_hdr_valid = hdrs.cb_hdr_valid = 0;
334     he_cursor.cursor = fe_cursor.cursor = cb_cursor.cursor = NULL;
335     he_cursor.fh = fe_cursor.ffe = fe_cursor.fcb = NULL;
336     he_cache.cursor = fe_cache.cursor = NULL;
337 }
338
339 static void
340 banner(void)
341 {
342     fprintf(stderr, "demand attach fs\n");
343     fprintf(stderr, "fileserver state analyzer\n");
344     fprintf(stderr, "version 0.1\n");
345 }
346
347 #define PROGNAME "fs state analyzer"
348
349 static void
350 prompt(void)
351 {
352     char input[256];
353     char prev_input[256];
354     char * tok = NULL;
355     afs_uint32 x, y, z;
356     enum {
357         PR_GLOBAL_MODE,
358         PR_H_MODE,
359         PR_FE_MODE,
360         PR_CB_MODE
361     } mode = PR_GLOBAL_MODE, next_mode;
362
363     next_mode = mode;
364     input[0] = prev_input[0] = '\0';
365
366     while (1) {
367         if (!tok) {
368             switch(mode) {
369             case PR_GLOBAL_MODE:
370                 printf(PROGNAME "> ");
371                 break;
372             case PR_H_MODE:
373                 printf(PROGNAME ": h(%d)> ", he_cursor.idx);
374                 break;
375             case PR_FE_MODE:
376                 printf(PROGNAME ": fe(%d)> ", fe_cursor.idx);
377                 break;
378             case PR_CB_MODE:
379                 printf(PROGNAME ": fe(%d):cb(%d)> ", fe_cursor.idx, cb_cursor.idx);
380                 break;
381             default:
382                 fprintf(stderr, "prompt state broken; aborting\n");
383                 return;
384             }
385             gets(input);
386
387             if (!strcmp(input, "")) {
388                 /* repeat last command */
389                 if (!strcmp(prev_input, "")) {
390                     continue;
391                 }
392                 strlcpy(input, prev_input, sizeof(input));
393             } else {
394                 /* save command for repetition */
395                 strlcpy(prev_input, input, sizeof(prev_input));
396             }
397
398             tok = strtok(input, " \t");
399         }
400         while (tok && !strcmp(tok, ";")) {
401             tok = strtok(NULL, "; \t");
402         }
403
404         if (!tok) {
405             continue;
406         }
407
408         if (!strcasecmp(tok, "exit")) {
409             return;
410         } else if (!strcasecmp(tok, "quit")) {
411             switch(mode) {
412             case PR_CB_MODE:
413                 next_mode = PR_FE_MODE;
414                 break;
415             case PR_FE_MODE:
416             case PR_H_MODE:
417                 next_mode = PR_GLOBAL_MODE;
418                 break;
419             default:
420                 return;
421             }
422         } else if (!strcasecmp(tok, "h")) {
423             tok = strtok(NULL, " \t");
424             mode = PR_H_MODE;
425             if (!tok) {
426                 next_mode = mode;
427             }
428             continue;
429         } else if (!strcasecmp(tok, "fe")) {
430             tok = strtok(NULL, " \t");
431             mode = PR_FE_MODE;
432             if (!tok) {
433                 next_mode = mode;
434             }
435             continue;
436         } else if (!strcasecmp(tok, "fs")) {
437             tok = strtok(NULL, " \t");
438             mode = PR_GLOBAL_MODE;
439             if (!tok) {
440                 next_mode = mode;
441             }
442             continue;
443         } else if (!strcasecmp(tok, "cb")) {
444             tok = strtok(NULL, " \t");
445             mode = PR_CB_MODE;
446             if (!tok) {
447                 next_mode = mode;
448             }
449             continue;
450         } else if (!strcasecmp(tok, "help")) {
451             switch(mode) {
452             case PR_H_MODE:
453                 print_h_help();
454                 break;
455             case PR_FE_MODE:
456                 print_fe_help();
457                 break;
458             case PR_CB_MODE:
459                 print_cb_help();
460                 break;
461             default:
462                 print_global_help();
463             }
464             print_help();
465         } else if (!strcasecmp(tok, "hexdump")) {
466             tok = strtok(NULL, " \t");
467             if (!tok) {
468                 hexdump_map(0, map_len);
469                 continue;
470             }
471             if (sscanf(tok, "%u", &x) != 1) {
472                 fprintf(stderr, "hexdump parse error 1\n");
473                 tok = NULL;
474                 continue;
475             }
476             tok = strtok(NULL, " \t");
477             if (!tok) {
478                 hexdump_map(x, map_len - x);
479                 continue;
480             }
481             if (sscanf(tok, "%u", &y) != 1) {
482                 fprintf(stderr, "hexdump parse error 2\n");
483                 continue;
484             }
485             hexdump_map(x,y);
486         } else if (!strcasecmp(tok, "hdr")) {
487             switch(mode) {
488             case PR_H_MODE:
489                 dump_h_hdr();
490                 break;
491             case PR_FE_MODE:
492                 dump_cb_hdr();
493                 break;
494             case PR_CB_MODE:
495                 dump_this_fe();
496                 break;
497             default:
498                 dump_hdr();
499             }
500         } else if (!strcasecmp(tok, "this")) {
501             switch(mode) {
502             case PR_H_MODE:
503                 dump_this_he();
504                 break;
505             case PR_FE_MODE:
506                 dump_this_fe();
507                 break;
508             case PR_CB_MODE:
509                 dump_this_cb();
510                 break;
511             default:
512                 fprintf(stderr, "command not valid for this mode\n");
513             }
514         } else if (!strcasecmp(tok, "next")) {
515             switch(mode) {
516             case PR_H_MODE:
517                 dump_next_he();
518                 break;
519             case PR_FE_MODE:
520                 dump_next_fe();
521                 break;
522             case PR_CB_MODE:
523                 dump_next_cb();
524                 break;
525             default:
526                 fprintf(stderr, "command not valid for this mode\n");
527             }
528         } else if (!strcasecmp(tok, "prev")) {
529             switch(mode) {
530             case PR_H_MODE:
531                 dump_prev_he();
532                 break;
533             case PR_FE_MODE:
534                 dump_prev_fe();
535                 break;
536             case PR_CB_MODE:
537                 dump_prev_cb();
538                 break;
539             default:
540                 fprintf(stderr, "command not valid for this mode\n");
541             }
542         } else if (!strcasecmp(tok, "first")) {
543             switch(mode) {
544             case PR_H_MODE:
545                 dump_first_he();
546                 break;
547             case PR_FE_MODE:
548                 dump_first_fe();
549                 break;
550             case PR_CB_MODE:
551                 dump_first_cb();
552                 break;
553             default:
554                 fprintf(stderr, "command not valid for this mode\n");
555             }
556         } else if (!strcasecmp(tok, "last")) {
557             switch(mode) {
558             case PR_H_MODE:
559                 dump_last_he();
560                 break;
561             case PR_FE_MODE:
562                 dump_last_fe();
563                 break;
564             case PR_CB_MODE:
565                 dump_last_cb();
566                 break;
567             default:
568                 fprintf(stderr, "command not valid for this mode\n");
569             }
570         } else if (!strcasecmp(tok, "dump")) {
571             switch(mode) {
572             case PR_H_MODE:
573                 dump_all_hes();
574                 break;
575             case PR_FE_MODE:
576                 dump_all_fes();
577                 break;
578             case PR_CB_MODE:
579                 dump_all_cbs();
580                 break;
581             default:
582                 fprintf(stderr, "command not valid for this mode\n");
583             }
584         } else if (!strcasecmp(tok, "find")) {
585             tok = strtok(NULL, " \t");
586             if (!tok || strcasecmp(tok, "by")) {
587                 tok = NULL;
588                 fprintf(stderr, "find syntax error 1 (%s)\n", 
589                         (tok) ? tok : "nil");
590                 continue;
591             }
592             tok = strtok(NULL, " \t");
593             if (!tok) {
594                 fprintf(stderr, "find syntax error 2\n");
595                 continue;
596             }
597             switch(mode) {
598             case PR_H_MODE:
599                 fprintf(stderr, "not implemented yet\n");
600                 break;
601             case PR_FE_MODE:
602                 if (!strcasecmp(tok, "index")) {
603                     tok = strtok(NULL, " \t");
604                     if (!tok || sscanf(tok, "%u", &x) != 1) {
605                         tok = NULL;
606                         fprintf(stderr, "find syntax error 3\n");
607                         continue;
608                     }
609                     if (find_fe_by_index(x)) {
610                         fprintf(stderr, "find returned no results\n");
611                     }
612                 } else if (!strcasecmp(tok, "fid")) {
613                     tok = strtok(NULL, "(), \t");
614                     if (!tok || sscanf(tok, "%u", &x) != 1) {
615                         tok = NULL;
616                         fprintf(stderr, "find syntax error 4\n");
617                         continue;
618                     }
619                     tok = strtok(NULL, "(), \t");
620                     if (!tok || sscanf(tok, "%u", &y) != 1) {
621                         tok = NULL;
622                         fprintf(stderr, "find syntax error 5\n");
623                         continue;
624                     }
625                     tok = strtok(NULL, "(), \t");
626                     if (!tok || sscanf(tok, "%u", &z) != 1) {
627                         tok = NULL;
628                         fprintf(stderr, "find syntax error 6\n");
629                         continue;
630                     }
631                     if (find_fe_by_fid(x,y,z)) {
632                         fprintf(stderr, "find returned no results\n");
633                     }
634                 } else {
635                     fprintf(stderr, "unsupported filter type\n");
636                 }
637                 break;
638             case PR_CB_MODE:
639                 if (!strcasecmp(tok, "index")) {
640                     tok = strtok(NULL, " \t");
641                     if (!tok || sscanf(tok, "%u", &x) != 1) {
642                         tok = NULL;
643                         fprintf(stderr, "find syntax error 3\n");
644                         continue;
645                     }
646                     if (find_cb_by_index(x)) {
647                         fprintf(stderr, "find returned no results\n");
648                     }
649                 } else {
650                     fprintf(stderr, "unsupported filter type\n");
651                 }
652                 break;
653             default:
654                 fprintf(stderr, "find not supported for this menu\n");
655             }
656         } else if (!strcspn(tok, "0123456789")) {
657             if (sscanf(tok, "%u", &x) == 1) {
658                 switch(mode) {
659                 case PR_H_MODE:
660                     dump_he(x);
661                     break;
662                 case PR_FE_MODE:
663                     dump_fe(x);
664                     break;
665                 case PR_CB_MODE:
666                     dump_cb(x);
667                     break;
668                 default:
669                     fprintf(stderr, "command not available from this menu\n");
670                 }
671             } else {
672                 fprintf(stderr, "input parse error ('%s')\n", tok);
673             }
674         } else if (mode == PR_FE_MODE) {
675             if (!strcmp(tok, "timeout")) {
676                 dump_cb_timeout();
677             } else if (!strcmp(tok, "hash")) {
678                 dump_cb_fehash();
679             }
680         } else {
681             fprintf(stderr, "unknown command\n");
682         }
683         tok = strtok(NULL, " \t");
684         mode = next_mode;
685     }
686 }
687
688 static void
689 print_help(void)
690 {
691     printf("\th <...>  -- host menu commands\n");
692     printf("\tfe <...> -- FileEntry menu commands\n");
693     printf("\tcb <...> -- CallBack menu commands\n");
694     printf("\thexdump [<offset> [<len>]]\n\t\t -- hex dump the raw data\n");
695     printf("\tquit     -- quit this menu\n");
696     printf("\texit     -- exit the debugger\n");
697     printf("\thelp     -- this help message\n");
698 }
699
700 static void
701 print_global_help(void)
702 {
703     printf("\thdr      -- display the fs_state_header struct\n");
704 }
705
706 static void
707 print_h_help(void)
708 {
709     printf("\thdr      -- display the host_state_header struct\n");
710     printf("\tfirst    -- display the first host\n");
711     printf("\tprev     -- display the previous host\n");
712     printf("\tthis     -- display this host\n");
713     printf("\tnext     -- display the next host\n");
714     printf("\tlast     -- display the last host\n");
715     printf("\tdump     -- display all hosts\n");
716 }
717
718 static void
719 print_fe_help(void)
720 {
721     printf("\thdr      -- display the callback_state_header struct\n");
722     printf("\tfirst    -- display the first FE\n");
723     printf("\tprev     -- display the previous FE\n");
724     printf("\tthis     -- display this FE\n");
725     printf("\tnext     -- display the next FE\n");
726     printf("\tlast     -- display the last FE\n");
727     printf("\tdump     -- display all FEs\n");
728     printf("\ttimeout  -- display the timeout queue heads\n");
729     printf("\thash   -- display the file entry hash buckets\n");
730     printf("\tfind by index <id>\n\t\t -- find an fe by its array index\n");
731     printf("\tfind by fid <(vol,vnode,unique)>\n\t\t -- find an fe by its AFSFid\n");
732 }
733
734 static void
735 print_cb_help(void)
736 {
737     printf("\thdr      -- display the callback_state_entry_header struct\n");
738     printf("\tfirst    -- display the first CB\n");
739     printf("\tprev     -- display the previous CB\n");
740     printf("\tthis     -- display this CB\n");
741     printf("\tnext     -- display the next CB\n");
742     printf("\tlast     -- display the last CB\n");
743     printf("\tdump     -- display all CBs\n");
744 }
745
746 #define DPFTB0 "\t"
747 #define DPFTB1 "\t\t"
748 #define DPFTB2 "\t\t\t"
749
750 #define DPFOFF(addr) \
751     do { \
752         char * _p = (char *)addr; \
753         char * _m = (char *)map; \
754         printf("loading structure from address 0x%x (offset %u)\n", \
755                addr, _p-_m); \
756     } while (0)
757
758 /* structs */
759 #define DPFSO(T, name) printf(T "%s = {\n", name)
760 #define DPFSO0(name) DPFSO(DPFTB0, name)
761 #define DPFSO1(name) DPFSO(DPFTB1, name)
762 #define DPFSC(T) printf(T "}\n")
763 #define DPFSC0 DPFSC(DPFTB0)
764 #define DPFSC1 DPFSC(DPFTB1)
765
766 /* arrays */
767 #define DPFAO(T1, T2, name) printf(T1 "%s =\n" T2 "{ ", name)
768 #define DPFAO0(name) DPFAO(DPFTB0, DPFTB1, name)
769 #define DPFAO1(name) DPFAO(DPFTB1, DPFTB2, name)
770 #define DPFAC0 printf(" }\n")
771 #define DPFAC1 DPFAC0
772 #define DPFA1 printf(DPFTB1 "  ")
773 #define DPFA2 printf(DPFTB2 "  ")
774 #define DPFAN printf("\n")
775 #define DPFALE(type, var) printf("%" type, var)
776 #define DPFAE(type, var) printf("%" type ",\t", var)
777
778 /* normal vars */
779 #define DPFV(T, name, type, var) printf(T "%s = %" type "\n", name, var)
780 #define DPFV1(name, type, var) DPFV(DPFTB1, name, type, var)
781 #define DPFV2(name, type, var) DPFV(DPFTB2, name, type, var)
782
783 /* hex */
784 #define DPFX(T, name, var) printf(T "%s = 0x%x\n", name, var)
785 #define DPFX1(name, var) DPFX(DPFTB1, name, var)
786 #define DPFX2(name, var) DPFX(DPFTB2, name, var)
787
788 /* strings */
789 #define DPFS(T, name, var) printf(T "%s = \"%s\"\n", name, var)
790 #define DPFS1(name, var) DPFS(DPFTB1, name, var)
791 #define DPFS2(name, var) DPFS(DPFTB2, name, var)
792
793 /* time */
794 #define DPFT(T, name, var) \
795     do { \
796         char * last; \
797         printf(T "%s = \"%s\"\n", name, strtok_r(ctime(&(var)), "\r\n", &last)); \
798     } while(0)
799 #define DPFT1(name, var) DPFT(DPFTB1, name, var)
800 #define DPFT2(name, var) DPFT(DPFTB2, name, var)
801
802 static void
803 dump_hdr(void)
804 {
805     char uuid_str[40];
806     afs_uint32 hi, lo;
807
808     if (get_hdr())
809         return;
810
811     DPFOFF(map);
812     DPFSO0("fs_state_header");
813     DPFSO1("stamp");
814     DPFX2("magic", hdrs.hdr.stamp.magic);
815     DPFV2("version", "u", hdrs.hdr.stamp.version);
816     DPFSC1;
817     DPFT1("timestamp", hdrs.hdr.timestamp);
818     DPFV1("sys_name", "u", hdrs.hdr.sys_name);
819
820     afsUUID_to_string(&hdrs.hdr.server_uuid, uuid_str, sizeof(uuid_str));
821     DPFS1("server_uuid", uuid_str);
822     DPFV1("valid", "d", hdrs.hdr.valid);
823     DPFV1("endianness", "d", hdrs.hdr.endianness);
824     DPFV1("stats_detailed", "d", hdrs.hdr.stats_detailed);
825
826     SplitInt64(hdrs.hdr.h_offset, hi, lo);
827     DPFSO1("h_offset");
828     DPFV2("hi", "u", hi);
829     DPFV2("lo", "u", lo);
830     DPFSC1;
831
832     SplitInt64(hdrs.hdr.cb_offset, hi, lo);
833     DPFSO1("cb_offset");
834     DPFV2("hi", "u", hi);
835     DPFV2("lo", "u", lo);
836     DPFSC1;
837
838     DPFS1("server_version_string", hdrs.hdr.server_version_string);
839     DPFSC0;
840
841     if (hdrs.hdr.stamp.magic != FS_STATE_MAGIC) {
842         fprintf(stderr, "* magic check failed\n");
843     }
844     if (hdrs.hdr.stamp.version != FS_STATE_VERSION) {
845         fprintf(stderr, "* version check failed\n");
846     }
847 }
848
849 static void
850 dump_h_hdr(void)
851 {
852     if (get_h_hdr())
853         return;
854
855     DPFOFF(hdrs.h_hdr_p);
856     DPFSO0("host_state_header");
857     DPFSO1("stamp");
858     DPFX2("magic", hdrs.h_hdr.stamp.magic);
859     DPFV2("version", "u", hdrs.h_hdr.stamp.version);
860     DPFSC1;
861     DPFV1("records", "u", hdrs.h_hdr.records);
862     DPFV1("index_max", "u", hdrs.h_hdr.index_max);
863     DPFSC0;
864
865     if (hdrs.h_hdr.stamp.magic != HOST_STATE_MAGIC) {
866         fprintf(stderr, "* magic check failed\n");
867     }
868     if (hdrs.h_hdr.stamp.version != HOST_STATE_VERSION) {
869         fprintf(stderr, "* version check failed\n");
870     }
871 }
872
873 static void
874 dump_cb_hdr(void)
875 {
876     afs_uint32 hi, lo;
877
878     if (get_cb_hdr())
879         return;
880
881     DPFOFF(hdrs.cb_hdr_p);
882     DPFSO0("callback_state_header");
883     DPFSO1("stamp");
884     DPFX2("magic", hdrs.cb_hdr.stamp.magic);
885     DPFV2("version", "u", hdrs.cb_hdr.stamp.version);
886     DPFSC1;
887     DPFV1("nFEs", "u", hdrs.cb_hdr.nFEs);
888     DPFV1("nCBs", "u", hdrs.cb_hdr.nCBs);
889     DPFV1("fe_max", "u", hdrs.cb_hdr.fe_max);
890     DPFV1("cb_max", "u", hdrs.cb_hdr.cb_max);
891     DPFV1("tfirst", "d", hdrs.cb_hdr.tfirst);
892
893     SplitInt64(hdrs.cb_hdr.timeout_offset, hi, lo);
894     DPFSO1("timeout_offset");
895     DPFV2("hi", "u", hi);
896     DPFV2("lo", "u", lo);
897     DPFSC1;
898
899     SplitInt64(hdrs.cb_hdr.fehash_offset, hi, lo);
900     DPFSO1("fehash_offset");
901     DPFV2("hi", "u", hi);
902     DPFV2("lo", "u", lo);
903     DPFSC1;
904
905     SplitInt64(hdrs.cb_hdr.fe_offset, hi, lo);
906     DPFSO1("fe_offset");
907     DPFV2("hi", "u", hi);
908     DPFV2("lo", "u", lo);
909     DPFSC1;
910
911     DPFSC0;
912
913     if (hdrs.cb_hdr.stamp.magic != CALLBACK_STATE_MAGIC) {
914         fprintf(stderr, "* magic check failed\n");
915     }
916     if (hdrs.cb_hdr.stamp.version != CALLBACK_STATE_VERSION) {
917         fprintf(stderr, "* version check failed\n");
918     }
919 }
920
921 static void
922 dump_cb_timeout(void)
923 {
924     int i;
925
926     if (get_cb_hdr())
927         return;
928
929     if (get_cb_timeout_hdr())
930         return;
931
932     if (get_cb_timeout())
933         return;
934
935     DPFOFF(hdrs.timeout_hdr_p);
936     DPFSO0("callback_state_timeout_header");
937     DPFX1("magic", hdrs.timeout_hdr.magic);
938     DPFV1("len", "u", hdrs.timeout_hdr.len);
939     DPFV1("records", "u", hdrs.timeout_hdr.records);
940     DPFSC0;
941
942     if (hdrs.timeout_hdr.magic != CALLBACK_STATE_TIMEOUT_MAGIC) {
943         fprintf(stderr, "* magic check failed\n");
944     }
945
946     DPFOFF(hdrs.timeout_p);
947     DPFAO0("timeout");
948     for (i = 0; i < 127; i++) {
949         DPFAE("u", hdrs.timeout[i]);
950         if ((i % 8) == 7) {
951             DPFAN;
952             DPFA1;
953         }
954     }
955     DPFALE("u", hdrs.timeout[127]);
956     DPFAC0;
957 }
958
959 static void
960 dump_cb_fehash(void)
961 {
962     int i;
963
964     if (get_cb_hdr())
965         return;
966
967     if (get_cb_fehash_hdr())
968         return;
969
970     if (get_cb_fehash())
971         return;
972
973     DPFOFF(hdrs.fehash_hdr_p);
974     DPFSO0("callback_state_fehash_header");
975     DPFX1("magic", hdrs.fehash_hdr.magic);
976     DPFV1("len", "u", hdrs.fehash_hdr.len);
977     DPFV1("records", "u", hdrs.fehash_hdr.records);
978     DPFSC0;
979
980     if (hdrs.fehash_hdr.magic != CALLBACK_STATE_FEHASH_MAGIC) {
981         fprintf(stderr, "* magic check failed\n");
982     }
983
984     DPFOFF(hdrs.fehash_p);
985     DPFAO0("fehash");
986     for (i = 0; i < hdrs.fehash_hdr.records - 1; i++) {
987         DPFAE("u", hdrs.fehash[i]);
988         if ((i % 8) == 7) {
989             DPFAN;
990             DPFA1;
991         }
992     }
993     DPFALE("u", hdrs.fehash[hdrs.fehash_hdr.records-1]);
994     DPFAC0;
995 }
996
997 static void
998 dump_all_hes(void)
999 {
1000     int i;
1001
1002     if (get_h_hdr()) {
1003         fprintf(stderr, "error getting host_state_header\n");
1004         return;
1005     }
1006
1007     for (i = 0; i < hdrs.h_hdr.records; i++) {
1008         dump_he(i);
1009     }
1010 }
1011
1012 static void
1013 dump_all_fes(void)
1014 {
1015     int i;
1016
1017     if (get_cb_hdr()) {
1018         fprintf(stderr, "error getting callback_state_header\n");
1019         return;
1020     }
1021
1022     for (i = 0; i < hdrs.cb_hdr.nFEs; i++) {
1023         dump_fe(i);
1024     }
1025 }
1026
1027 static void
1028 dump_all_cbs(void)
1029 {
1030     int i;
1031
1032     if (get_fe_hdr()) {
1033         fprintf(stderr, "error getting callback_state_entry_header\n");
1034         return;
1035     }
1036
1037     for (i = 0; i < fe_cursor.hdr.nCBs; i++) {
1038         dump_cb(i);
1039     }
1040 }
1041
1042 static void
1043 dump_he(afs_uint32 idx)
1044 {
1045     if (get_he(idx)) {
1046         fprintf(stderr, "error getting he %d\n", idx);
1047         return;
1048     }
1049
1050     DPFOFF(he_cursor.cursor);
1051     dump_he_hdr();
1052     dump_he_entry();
1053     dump_he_interfaces();
1054     dump_he_hcps();
1055 }
1056
1057 static void
1058 dump_fe(afs_uint32 idx)
1059 {
1060     if (get_fe(idx)) {
1061         fprintf(stderr, "error getting fe %d\n", idx);
1062         return;
1063     }
1064
1065     DPFOFF(fe_cursor.cursor);
1066     dump_fe_hdr();
1067     dump_fe_entry();
1068 }
1069
1070 static void
1071 dump_cb(afs_uint32 idx)
1072 {
1073     if (get_cb(idx)) {
1074         fprintf(stderr, "error getting cb %d\n", idx);
1075         return;
1076     }
1077
1078     DPFOFF(cb_cursor.cursor);
1079     dump_cb_entry();
1080 }
1081
1082 static void
1083 dump_this_he(void)
1084 {
1085     dump_he(he_cursor.idx);
1086 }
1087
1088 static void
1089 dump_this_fe(void)
1090 {
1091     dump_fe(fe_cursor.idx);
1092 }
1093
1094 static void
1095 dump_this_cb(void)
1096 {
1097     dump_cb(cb_cursor.idx);
1098 }
1099
1100 static void
1101 dump_next_he(void)
1102 {
1103     if (get_h_hdr()) {
1104         fprintf(stderr, "error getting host_state_header\n");
1105         return;
1106     }
1107
1108     if ((he_cursor.idx + 1) >= hdrs.h_hdr.records) {
1109         fprintf(stderr, "no more HEs\n");
1110         return;
1111     }
1112     
1113     dump_he(he_cursor.idx+1);
1114 }
1115
1116 static void
1117 dump_next_fe(void)
1118 {
1119     if (get_cb_hdr()) {
1120         fprintf(stderr, "error getting callback_state_header\n");
1121         return;
1122     }
1123
1124     if ((fe_cursor.idx + 1) >= hdrs.cb_hdr.nFEs) {
1125         fprintf(stderr, "no more FEs\n");
1126         return;
1127     }
1128     
1129     dump_fe(fe_cursor.idx+1);
1130 }
1131
1132 static void
1133 dump_next_cb(void)
1134 {
1135     if (get_fe_hdr()) {
1136         fprintf(stderr, "error getting callback_state_entry_header\n");
1137         return;
1138     }
1139
1140     if ((cb_cursor.idx + 1) >= fe_cursor.hdr.nCBs) {
1141         fprintf(stderr, "no more CBs\n");
1142         return;
1143     }
1144     
1145     dump_cb(cb_cursor.idx+1);
1146 }
1147
1148 static void
1149 dump_prev_he(void)
1150 {
1151     if (!he_cursor.idx) {
1152         fprintf(stderr, "no more HEs\n");
1153         return;
1154     }
1155     
1156     dump_he(he_cursor.idx-1);
1157 }
1158
1159 static void
1160 dump_prev_fe(void)
1161 {
1162     if (!fe_cursor.idx) {
1163         fprintf(stderr, "no more FEs\n");
1164         return;
1165     }
1166     
1167     dump_fe(fe_cursor.idx-1);
1168 }
1169
1170 static void
1171 dump_prev_cb(void)
1172 {
1173     if (!cb_cursor.idx) {
1174         fprintf(stderr, "no more CBs\n");
1175         return;
1176     }
1177     
1178     dump_cb(cb_cursor.idx-1);
1179 }
1180
1181 static void
1182 dump_first_fe(void)
1183 {
1184     if (get_cb_hdr()) {
1185         fprintf(stderr, "error getting callback_state_header\n");
1186         return;
1187     }
1188
1189     if (!hdrs.cb_hdr.nFEs) {
1190         fprintf(stderr, "no FEs present\n");
1191         return;
1192     }
1193     
1194     dump_fe(0);
1195 }
1196
1197 static void
1198 dump_first_he(void)
1199 {
1200     if (get_h_hdr()) {
1201         fprintf(stderr, "error getting host_state_header\n");
1202         return;
1203     }
1204
1205     if (!hdrs.h_hdr.records) {
1206         fprintf(stderr, "no HEs present\n");
1207         return;
1208     }
1209     
1210     dump_he(0);
1211 }
1212
1213 static void
1214 dump_first_cb(void)
1215 {
1216     if (get_fe_hdr()) {
1217         fprintf(stderr, "error getting callback_state_entry_header\n");
1218         return;
1219     }
1220
1221     if (!fe_cursor.hdr.nCBs) {
1222         fprintf(stderr, "no CBs present\n");
1223         return;
1224     }
1225     
1226     dump_cb(0);
1227 }
1228
1229 static void
1230 dump_last_he(void)
1231 {
1232     if (get_h_hdr()) {
1233         fprintf(stderr, "error getting host_state_header\n");
1234         return;
1235     }
1236
1237     if (!hdrs.h_hdr.records) {
1238         fprintf(stderr, "no HEs present\n");
1239         return;
1240     }
1241     
1242     dump_he(hdrs.h_hdr.records-1);
1243 }
1244
1245 static void
1246 dump_last_fe(void)
1247 {
1248     if (get_cb_hdr()) {
1249         fprintf(stderr, "error getting callback_state_header\n");
1250         return;
1251     }
1252
1253     if (!hdrs.cb_hdr.nFEs) {
1254         fprintf(stderr, "no FEs present\n");
1255         return;
1256     }
1257     
1258     dump_fe(hdrs.cb_hdr.nFEs-1);
1259 }
1260
1261 static void
1262 dump_last_cb(void)
1263 {
1264     if (get_fe_hdr()) {
1265         fprintf(stderr, "error getting callback_state_entry_header\n");
1266         return;
1267     }
1268
1269     if (!fe_cursor.hdr.nCBs) {
1270         fprintf(stderr, "no CBs present\n");
1271         return;
1272     }
1273
1274     dump_cb(fe_cursor.hdr.nCBs-1);
1275 }
1276
1277 static void
1278 dump_he_hdr(void)
1279 {
1280     DPFSO0("host_state_entry_header");
1281     DPFX1("magic", he_cursor.hdr.magic);
1282     DPFV1("len", "u", he_cursor.hdr.len);
1283     DPFV1("interfaces", "u", he_cursor.hdr.interfaces);
1284     DPFV1("hcps", "u", he_cursor.hdr.hcps);
1285     DPFSC0;
1286
1287     if (he_cursor.hdr.magic != HOST_STATE_ENTRY_MAGIC) {
1288         fprintf(stderr, "* magic check failed\n");
1289     }
1290 }
1291
1292 static void
1293 dump_he_entry(void)
1294 {
1295     DPFSO0("hostDiskEntry");
1296     DPFS1("host", afs_inet_ntoa(he_cursor.he.host));
1297     DPFV1("port", "u", he_cursor.he.port);
1298     DPFX1("hostFlags", he_cursor.he.hostFlags);
1299     DPFV1("Console", "u", he_cursor.he.Console);
1300     DPFV1("hcpsfailed", "u", he_cursor.he.hcpsfailed);
1301     DPFV1("hcps_valid", "u", he_cursor.he.hcps_valid);
1302     if (hdrs.hdr.stats_detailed) {
1303 #ifdef FS_STATS_DETAILED
1304         DPFV1("InSameNetwork", "u", he_cursor.he.InSameNetwork);
1305 #else
1306         DPFV1("InSameNetwork", "u", he_cursor.he.padding1[0]);
1307 #endif
1308     }
1309     DPFV1("hcps_len", "u", he_cursor.he.hcps_len);
1310     DPFT1("LastCall", he_cursor.he.LastCall);
1311     DPFT1("ActiveCall", he_cursor.he.ActiveCall);
1312     DPFT1("cpsCall", he_cursor.he.cpsCall);
1313     DPFV1("cblist", "u", he_cursor.he.cblist);
1314     DPFV1("index", "u", he_cursor.he.index);
1315     DPFSC0;
1316 }
1317
1318 static void
1319 dump_he_interfaces(void)
1320 {
1321     char temp_str[40];
1322     struct Interface * ifp;
1323     int len, i;
1324
1325     if (!he_cursor.hdr.interfaces)
1326         return;
1327
1328     len = sizeof(struct Interface) + ((he_cursor.hdr.interfaces-1)*sizeof(struct AddrPort));
1329     ifp = (struct Interface *) malloc(len);
1330     assert(ifp != NULL);
1331
1332     memcpy(ifp, he_cursor.ifp, len);
1333
1334     DPFSO0("Interface");
1335     DPFV1("numberOfInterfaces", "u", ifp->numberOfInterfaces);
1336
1337     afsUUID_to_string(&ifp->uuid, temp_str, sizeof(temp_str));
1338     DPFS1("uuid", temp_str);
1339     for (i = 0; i < he_cursor.hdr.interfaces; i++) {
1340         snprintf(temp_str, sizeof(temp_str), "interface[%d]", i);
1341         DPFSO1(temp_str);
1342         DPFS2("addr", afs_inet_ntoa(ifp->interface[i].addr));
1343         DPFV2("port", "u", ifp->interface[i].port);
1344         DPFSC1;
1345     }
1346
1347     DPFSC0;
1348
1349     if (he_cursor.hdr.interfaces != ifp->numberOfInterfaces) {
1350         fprintf(stderr, "* interface count mismatch between header and Interface struct\n");
1351     }
1352     free(ifp);
1353 }
1354
1355 static void
1356 dump_he_hcps(void)
1357 {
1358     char temp_str[40];
1359     afs_int32 * hcps;
1360     int len, i;
1361
1362     if (!he_cursor.hdr.hcps)
1363         return;
1364
1365     len = (he_cursor.hdr.hcps)*sizeof(afs_uint32);
1366     hcps = (afs_int32 *) malloc(len);
1367     assert(hcps != NULL);
1368     memcpy(hcps, he_cursor.hcps, len);
1369
1370     DPFSO0("hcps");
1371     DPFAO1("prlist_val");
1372     for (i = 0; i < he_cursor.hdr.hcps - 1; i++) {
1373         DPFAE("d", hcps[i]);
1374         if ((i % 8) == 7) {
1375             DPFAN;
1376             DPFA2;
1377         }
1378     }
1379     DPFALE("d", hcps[he_cursor.hdr.hcps-1]);
1380     DPFAC1;
1381     DPFSC0;
1382     free(hcps);
1383 }
1384
1385 static void
1386 dump_fe_hdr(void)
1387 {
1388     DPFSO0("callback_state_entry_header");
1389     DPFX1("magic", fe_cursor.hdr.magic);
1390     DPFV1("len", "u", fe_cursor.hdr.len);
1391     DPFV1("nCBs", "u", fe_cursor.hdr.nCBs);
1392     DPFSC0;
1393
1394     if (fe_cursor.hdr.magic != CALLBACK_STATE_ENTRY_MAGIC) {
1395         fprintf(stderr, "* magic check failed\n");
1396     }
1397 }
1398
1399 static void
1400 dump_fe_entry(void)
1401 {
1402     DPFSO0("FEDiskEntry");
1403     DPFSO1("fe");
1404     DPFV2("vnode", "u", fe_cursor.fe.fe.vnode);
1405     DPFV2("unique", "u", fe_cursor.fe.fe.unique);
1406     DPFV2("volid", "u", fe_cursor.fe.fe.volid);
1407     DPFV2("fnext", "u", fe_cursor.fe.fe.fnext);
1408     DPFV2("ncbs", "u", fe_cursor.fe.fe.ncbs);
1409     DPFV2("firstcb", "u", fe_cursor.fe.fe.firstcb);
1410     DPFV2("status", "u", fe_cursor.fe.fe.status);
1411     DPFSC1;
1412     DPFV1("index", "u", fe_cursor.fe.index);
1413     DPFSC0;
1414 }
1415
1416 static void
1417 dump_cb_entry(void)
1418 {
1419     DPFSO0("CBDiskEntry");
1420     DPFSO1("cb");
1421     DPFV2("cnext", "u", cb_cursor.cb.cb.cnext);
1422     DPFV2("fhead", "u", cb_cursor.cb.cb.fhead);
1423     DPFV2("thead", "u", (afs_uint32)cb_cursor.cb.cb.thead);
1424     DPFV2("status", "u", (afs_uint32)cb_cursor.cb.cb.status);
1425     DPFV2("hhead", "u", cb_cursor.cb.cb.hhead);
1426     DPFV2("tprev", "u", cb_cursor.cb.cb.tprev);
1427     DPFV2("tnext", "u", cb_cursor.cb.cb.tnext);
1428     DPFV2("hprev", "u", cb_cursor.cb.cb.hprev);
1429     DPFV2("hnext", "u", cb_cursor.cb.cb.hnext);
1430     DPFSC1;
1431     DPFV1("index", "u", cb_cursor.cb.index);
1432     DPFSC0;
1433 }
1434
1435 #define DPFHMS printf("  ")
1436 #define DPFHS printf("    ")
1437 #define DPFHN(offset) printf("\n%u\t", offset)
1438 #define DPFHD(x) printf("%02X  ", x)
1439 #define DPFHE printf("\n")
1440
1441 static void
1442 hexdump_map(afs_uint32 offset, afs_uint32 len)
1443 {
1444     int i;
1445     unsigned char * p = (unsigned char *)map;
1446     afs_uint32 c32;
1447
1448     if (!len)
1449         return;
1450
1451     if ((offset + len) > map_len) {
1452         fprintf(stderr, "offset + length exceeds memory map size (%u > %u)\n",
1453                 offset+len, map_len);
1454         return;
1455     }
1456
1457     p += offset;
1458     DPFOFF(p);
1459     DPFHN(offset);
1460
1461     for (i = offset % 16; i > 0; i--) {
1462         DPFHS;
1463     }
1464
1465     for (i=0; i < len; i++, p++, offset++) {
1466         if (!(offset % 16)) {
1467             DPFHN(offset);
1468         } else if (!(offset % 8)) {
1469             DPFHMS;
1470         }
1471         DPFHD(*p);
1472     }
1473     DPFHE;
1474 }
1475
1476 static int
1477 get_hdr(void)
1478 {
1479     if (!hdrs.hdr_valid) {
1480         if (map_len < sizeof(struct fs_state_header)) {
1481             fprintf(stderr, "corrupt state dump: fs_state_header larger than memory map\n");
1482             return 1;
1483         }
1484         memcpy(&hdrs.hdr, map, sizeof(hdrs.hdr));
1485         hdrs.hdr_p = map;
1486         hdrs.hdr_valid = 1;
1487     }
1488     return 0;
1489 }
1490
1491 static int
1492 get_h_hdr(void)
1493 {
1494     char * buf;
1495     afs_uint32 hi, lo;
1496
1497     if (hdrs.h_hdr_valid)
1498         return 0;
1499
1500     if (get_hdr())
1501         return 1;
1502
1503     SplitInt64(hdrs.hdr.h_offset, hi, lo);
1504
1505     if (hi) {
1506         fprintf(stderr, "hi offset bits set in h_offset; can't get host_state_header\n");
1507         return 1;
1508     }
1509     if ((lo >= map_len) || 
1510         ((lo + sizeof(struct host_state_header)) > map_len) ||
1511         (lo + sizeof(struct host_state_header) < lo)) {
1512         fprintf(stderr, "h_offset puts host_state_header beyond end of memory map\n");
1513         return 1;
1514     }
1515
1516     buf = (char *) map;
1517     buf += lo;
1518     memcpy(&hdrs.h_hdr, buf, sizeof(struct host_state_header));
1519     hdrs.h_hdr_p = buf;
1520     buf += sizeof(struct host_state_header);
1521     he_cursor.fh = (void *)buf;
1522     return 0;
1523 }
1524
1525 static int
1526 get_cb_hdr(void)
1527 {
1528     char * buf;
1529     afs_uint32 hi, lo;
1530
1531     if (hdrs.cb_hdr_valid)
1532         return 0;
1533
1534     if (get_hdr())
1535         return 1;
1536
1537     SplitInt64(hdrs.hdr.cb_offset, hi, lo);
1538
1539     if (hi) {
1540         fprintf(stderr, "hi offset bits set in cb_offset; can't get callback_state_header\n");
1541         return 1;
1542     }
1543     if ((lo >= map_len) || 
1544         ((lo + sizeof(struct callback_state_header)) > map_len) ||
1545         (lo + sizeof(struct callback_state_header) < lo)) {
1546         fprintf(stderr, "cb_offset puts callback_state_header beyond end of memory map\n");
1547         return 1;
1548     }
1549
1550     buf = (char *) map;
1551     buf += lo;
1552     memcpy(&hdrs.cb_hdr, buf, sizeof(struct callback_state_header));
1553     hdrs.cb_hdr_p = buf;
1554     hdrs.cb_hdr_valid = 1;
1555
1556     SplitInt64(hdrs.cb_hdr.fe_offset, hi, lo);
1557
1558     if (hi) {
1559         fprintf(stderr, "hi offset bits set in fe_offset; can't get callback_state_entry_header\n");
1560         return 1;
1561     }
1562     hi = lo + (hdrs.cb_hdr.nFEs * (sizeof(struct callback_state_entry_header) +
1563                                   sizeof(struct FEDiskEntry)) +
1564                hdrs.cb_hdr.nCBs * sizeof(struct CBDiskEntry));
1565     if ((hi > map_len) ||
1566         (lo > hi)) {
1567         fprintf(stderr, "fe_offset puts callback_state_entry_header beyond end of memory map\n");
1568         return 1;
1569     }
1570
1571     buf = (char *) map;
1572     buf += lo;
1573     fe_cursor.ffe = (void *)buf;
1574
1575     return 0;
1576 }
1577
1578 static int
1579 get_cb_timeout_hdr(void)
1580 {
1581     char * buf;
1582     afs_uint32 hi, lo;
1583
1584     if (hdrs.timeout_hdr_valid)
1585         return 0;
1586
1587     if (get_cb_hdr())
1588         return 1;
1589
1590     SplitInt64(hdrs.cb_hdr.timeout_offset, hi, lo);
1591
1592     if (hi) {
1593         fprintf(stderr, "hi offset bits set in timeout_offset; can't get callback_state_timeout_header\n");
1594         return 1;
1595     }
1596     if ((lo >= map_len) || 
1597         ((lo + sizeof(struct callback_state_timeout_header)) > map_len) ||
1598         (lo + sizeof(struct callback_state_timeout_header) < lo)) {
1599         fprintf(stderr, "timeout_offset puts callback_state_timeout_header beyond end of memory map\n");
1600         return 1;
1601     }
1602
1603     buf = (char *) map;
1604     buf += lo;
1605     memcpy(&hdrs.timeout_hdr, buf, sizeof(struct callback_state_timeout_header));
1606     hdrs.timeout_hdr_p = buf;
1607     hdrs.timeout_hdr_valid = 1;
1608     buf += sizeof(struct callback_state_timeout_header);
1609     hdrs.timeout_p = buf;
1610
1611     return 0;
1612 }
1613
1614 static int
1615 get_cb_timeout(void)
1616 {
1617     char * buf;
1618
1619     if (hdrs.timeout)
1620         return 0;
1621
1622     if (get_cb_timeout_hdr())
1623         return 1;
1624
1625     hdrs.timeout = (afs_uint32 *) calloc(hdrs.timeout_hdr.records, sizeof(afs_uint32));
1626     assert(hdrs.timeout != NULL);
1627     memcpy(hdrs.timeout, hdrs.timeout_p, hdrs.timeout_hdr.records * sizeof(afs_uint32));
1628     return 0;
1629 }
1630
1631 static int
1632 get_cb_fehash_hdr(void)
1633 {
1634     char * buf;
1635     afs_uint32 hi, lo;
1636
1637     if (hdrs.fehash_hdr_valid)
1638         return 0;
1639
1640     if (get_cb_hdr())
1641         return 1;
1642
1643     SplitInt64(hdrs.cb_hdr.fehash_offset, hi, lo);
1644
1645     if (hi) {
1646         fprintf(stderr, "hi offset bits set in fehash_offset; can't get callback_state_fehash_header\n");
1647         return 1;
1648     }
1649     if ((lo >= map_len) || 
1650         ((lo + sizeof(struct callback_state_fehash_header)) > map_len) ||
1651         (lo + sizeof(struct callback_state_fehash_header) < lo)) {
1652         fprintf(stderr, "timeout_offset puts callback_state_fehash_header beyond end of memory map\n");
1653         return 1;
1654     }
1655
1656     buf = (char *) map;
1657     buf += lo;
1658     memcpy(&hdrs.fehash_hdr, buf, sizeof(struct callback_state_fehash_header));
1659     hdrs.fehash_hdr_p = buf;
1660     hdrs.fehash_hdr_valid = 1;
1661     buf += sizeof(struct callback_state_fehash_header);
1662     hdrs.fehash_p = buf;
1663
1664     return 0;
1665 }
1666
1667 static int
1668 get_cb_fehash(void)
1669 {
1670     char * buf;
1671
1672     if (hdrs.fehash)
1673         return 0;
1674
1675     if (get_cb_fehash_hdr())
1676         return 1;
1677
1678     hdrs.fehash = (afs_uint32 *) calloc(hdrs.fehash_hdr.records, sizeof(afs_uint32));
1679     assert(hdrs.fehash != NULL);
1680     memcpy(hdrs.fehash, hdrs.fehash_p, hdrs.fehash_hdr.records * sizeof(afs_uint32));
1681     return 0;
1682 }
1683
1684 static int
1685 get_he(afs_uint32 idx)
1686 {
1687     int i;
1688     char * p;
1689
1690     if (get_h_hdr())
1691         return 1;
1692
1693     if (idx >= hdrs.h_hdr.records)
1694         return 1;
1695
1696     if (he_cursor.idx == idx && he_cursor.hdr_valid && he_cursor.he_valid)
1697         return 0;
1698
1699     he_cursor.hdr_valid = he_cursor.he_valid = 0;
1700
1701     if (he_cache.cursor == NULL) {
1702         he_cache.cursor = (void **) calloc(hdrs.h_hdr.records, sizeof(void *));
1703         assert(he_cache.cursor != NULL);
1704     }
1705
1706     if (idx && he_cache.cursor[idx-1] == NULL) {
1707         for (i = 0; i < idx; i++) {
1708             if (he_cache.cursor[i] == NULL) {
1709                 get_he(i);
1710             }
1711         }
1712     }
1713
1714     if (!idx) {
1715         he_cursor.cursor = he_cursor.fh;
1716     } else if (he_cursor.cursor == he_cache.cursor[idx-1]) {
1717         p = (char *)he_cursor.cursor;
1718         p += he_cursor.hdr.len;
1719         he_cursor.cursor = (void *)p;
1720     } else {
1721         he_cursor.cursor = he_cache.cursor[idx-1];
1722         if (get_he_hdr())
1723             return 1;
1724         p = (char *)he_cursor.cursor;
1725         p += he_cursor.hdr.len;
1726         he_cursor.cursor = (void *)p;
1727     }
1728
1729     he_cursor.idx = idx;
1730     he_cache.cursor[idx] = he_cursor.cursor;
1731
1732     if (get_he_hdr())
1733         return 1;
1734     if (get_he_entry())
1735         return 1;
1736
1737     return 0;
1738 }
1739
1740 static int
1741 get_he_hdr(void)
1742 {
1743     memcpy(&he_cursor.hdr, he_cursor.cursor, sizeof(struct host_state_entry_header));
1744     he_cursor.hdr_valid = 1;
1745     return 0;
1746 }
1747
1748 static int
1749 get_he_entry(void)
1750 {
1751     char * p;
1752
1753     if (!he_cursor.hdr_valid) {
1754         if (get_he_hdr()) {
1755             return 1;
1756         }
1757     }
1758
1759     p = (char *) he_cursor.cursor;
1760     p += sizeof(struct host_state_entry_header);
1761
1762     memcpy(&he_cursor.he, p, sizeof(struct hostDiskEntry));
1763
1764     he_cursor.he_valid = 1;
1765     p += sizeof(struct hostDiskEntry);
1766     he_cursor.ifp = (void *)p;
1767     if (he_cursor.hdr.interfaces) {
1768         p += sizeof(struct Interface) + ((he_cursor.hdr.interfaces-1)*sizeof(struct AddrPort));
1769         he_cursor.hcps = (void *)p;
1770     } else {
1771         he_cursor.hcps = he_cursor.ifp;
1772     }
1773     return 0;
1774 }
1775
1776 static int
1777 get_fe(afs_uint32 idx)
1778 {
1779     int i;
1780     char * p;
1781
1782     cb_cursor.cb_valid = 0;
1783
1784     if (get_cb_hdr())
1785         return 1;
1786
1787     if (idx >= hdrs.cb_hdr.nFEs)
1788         return 1;
1789
1790     if (fe_cursor.idx == idx && fe_cursor.hdr_valid && fe_cursor.fe_valid)
1791         return 0;
1792
1793     fe_cursor.hdr_valid = fe_cursor.fe_valid = 0;
1794
1795     if (fe_cache.cursor == NULL) {
1796         fe_cache.cursor = (void **) calloc(hdrs.cb_hdr.nFEs, sizeof(void *));
1797         assert(fe_cache.cursor != NULL);
1798     }
1799
1800     if (idx && fe_cache.cursor[idx-1] == NULL) {
1801         for (i = 0; i < idx; i++) {
1802             if (fe_cache.cursor[i] == NULL) {
1803                 get_fe(i);
1804             }
1805         }
1806     }
1807
1808     if (!idx) {
1809         fe_cursor.cursor = fe_cursor.ffe;
1810     } else if (fe_cursor.cursor == fe_cache.cursor[idx-1]) {
1811         p = (char *)fe_cursor.cursor;
1812         p += fe_cursor.hdr.len;
1813         fe_cursor.cursor = (void *)p;
1814     } else {
1815         fe_cursor.cursor = fe_cache.cursor[idx-1];
1816         if (get_fe_hdr())
1817             return 1;
1818         p = (char *)fe_cursor.cursor;
1819         p += fe_cursor.hdr.len;
1820         fe_cursor.cursor = (void *)p;
1821     }
1822
1823     fe_cursor.idx = idx;
1824     fe_cache.cursor[idx] = fe_cursor.cursor;
1825
1826     if (get_fe_hdr())
1827         return 1;
1828     if (get_fe_entry())
1829         return 1;
1830
1831     return 0;
1832 }
1833
1834 static int
1835 get_fe_hdr(void)
1836 {
1837     memcpy(&fe_cursor.hdr, fe_cursor.cursor, sizeof(struct callback_state_entry_header));
1838     fe_cursor.hdr_valid = 1;
1839     return 0;
1840 }
1841
1842 static int
1843 get_fe_entry(void)
1844 {
1845     char * p;
1846
1847     if (!fe_cursor.hdr_valid) {
1848         if (get_fe_hdr()) {
1849             return 1;
1850         }
1851     }
1852
1853     p = (char *) fe_cursor.cursor;
1854     p += sizeof(struct callback_state_entry_header);
1855
1856     memcpy(&fe_cursor.fe, p, sizeof(struct FEDiskEntry));
1857
1858     fe_cursor.fe_valid = 1;
1859     p += sizeof(struct FEDiskEntry);
1860     fe_cursor.fcb = (void *)p;
1861     return 0;
1862 }
1863
1864 static int
1865 get_cb(afs_uint32 idx)
1866 {
1867     int i;
1868     char * p;
1869
1870     if (get_fe(fe_cursor.idx))
1871         return 1;
1872
1873     if (idx >= fe_cursor.hdr.nCBs)
1874         return 1;
1875
1876     if (idx == cb_cursor.idx && cb_cursor.cb_valid)
1877         return 0;
1878
1879     cb_cursor.cb_valid = 0;
1880
1881     p = (char *)fe_cursor.fcb;
1882     p += idx * sizeof(struct CBDiskEntry);
1883     cb_cursor.cursor = (void *)p;
1884
1885     cb_cursor.idx = idx;
1886
1887     if (get_cb_entry())
1888         return 1;
1889
1890     return 0;
1891 }
1892
1893 static int
1894 get_cb_entry(void)
1895 {
1896     memcpy(&cb_cursor.cb, cb_cursor.cursor, sizeof(struct CBDiskEntry));
1897     cb_cursor.cb_valid = 1;
1898     return 0;
1899 }
1900
1901 static int
1902 find_he_by_index(afs_uint32 idx)
1903 {
1904     int i;
1905
1906     if (get_h_hdr()) {
1907         return 1;
1908     }
1909
1910     for (i = 0; i < hdrs.h_hdr.records; i++) {
1911         if (get_he(i)) {
1912             fprintf(stderr, "error getting he %d\n", i);
1913             return 1;
1914         }
1915         if (he_cursor.he.index == idx)
1916             break;
1917     }
1918
1919     if (i < hdrs.h_hdr.records) {
1920         dump_this_he();
1921         return 0;
1922     }
1923     return 1;
1924 }
1925
1926 static int
1927 find_fe_by_index(afs_uint32 idx)
1928 {
1929     int i;
1930
1931     if (get_cb_hdr()) {
1932         return 1;
1933     }
1934
1935     for (i = 0; i < hdrs.cb_hdr.nFEs; i++) {
1936         if (get_fe(i)) {
1937             fprintf(stderr, "error getting fe %d\n", i);
1938             return 1;
1939         }
1940         if (fe_cursor.fe.index == idx)
1941             break;
1942     }
1943
1944     if (i < hdrs.cb_hdr.nFEs) {
1945         dump_this_fe();
1946         return 0;
1947     }
1948     return 1;
1949 }
1950
1951 static int
1952 find_fe_by_fid(afs_uint32 volid, afs_uint32 vnode, afs_uint32 unique)
1953 {
1954     int i;
1955
1956     if (get_cb_hdr()) {
1957         return 1;
1958     }
1959
1960     for (i = 0; i < hdrs.cb_hdr.nFEs; i++) {
1961         if (get_fe(i)) {
1962             fprintf(stderr, "error getting fe %d\n", i);
1963             return 1;
1964         }
1965         if ((fe_cursor.fe.fe.unique == unique) &&
1966             (fe_cursor.fe.fe.volid == volid) &&
1967             (fe_cursor.fe.fe.vnode == vnode))
1968             break;
1969     }
1970
1971     if (i < hdrs.cb_hdr.nFEs) {
1972         dump_this_fe();
1973         return 0;
1974     }
1975     return 1;
1976 }
1977
1978 static int
1979 find_cb_by_index(afs_uint32 idx)
1980 {
1981     int i;
1982
1983     if (get_fe_hdr()) {
1984         return 1;
1985     }
1986
1987     for (i = 0; i < fe_cursor.hdr.nCBs; i++) {
1988         if (get_cb(i)) {
1989             fprintf(stderr, "error getting cb %d\n", i);
1990             return 1;
1991         }
1992         if (cb_cursor.cb.index == idx)
1993             break;
1994     }
1995
1996     if (i < fe_cursor.hdr.nCBs) {
1997         dump_this_cb();
1998         return 0;
1999     }
2000     return 1;
2001 }
2002
2003 #endif /* AFS_DEMAND_ATTACH_FS */