2 * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Check a directory in afs format.
38 #include "arla_local.h"
43 static int local_help_flag
;
44 static int verbose
= 0;
47 * Hash the filename of one entry.
51 hashentry (const char *entry
)
56 s
= s
* 173 + *entry
++;
57 h
= s
& (ADIRHASHSIZE
- 1);
66 * Return the entry in the directory given the number.
67 * The directory must be contiounsly in memory after page0.
70 static const DirEntry
*
71 getentry (DirPage0
*page0
,
76 page
= (DirPage1
*)((char *)page0
+
77 AFSDIR_PAGESIZE
* (num
/ ENTRIESPERPAGE
));
78 if (page
->header
.pg_tag
!= htons(AFSDIRMAGIC
) &&
79 page
->header
.pg_tag
!= htons(AFSDIRMAGIC_UTF8
))
81 printf ("Bad magic (%d) != %d in directory\n",
82 ntohs(page
->header
.pg_tag
), AFSDIRMAGIC
);
85 return &page
->entry
[num
% ENTRIESPERPAGE
];
89 check_dir (const char *filename
)
101 unsigned page_entry_count
;
102 unsigned hash_entry_count
;
104 uint8_t **my_bitmaps
= NULL
;
106 fd
= open (filename
, O_RDONLY
| O_BINARY
, 0);
108 err (1, "open %s", filename
);
110 if (fstat (fd
, &statbuf
) < 0)
111 err (1, "stat %s", filename
);
113 len
= statbuf
.st_size
;
116 errx (1, "length == 0");
118 if (len
% AFSDIR_PAGESIZE
!= 0)
119 errx (1, "length %% AFSDIR_PAGESIZE != 0");
121 ret
= fbuf_create (&the_fbuf
, fd
, len
, FBUF_READ
|FBUF_PRIVATE
);
123 err (1, "fbuf_create");
125 page0
= (DirPage0
*)(the_fbuf
.buf
);
127 printf ("size = %u, pages = %u, pgcount = %u\n",
128 len
, len
/ AFSDIR_PAGESIZE
,
129 ntohs(page0
->header
.pg_pgcount
));
131 if (len
/ AFSDIR_PAGESIZE
!= ntohs(page0
->header
.pg_pgcount
)) {
136 npages
= len
/ AFSDIR_PAGESIZE
;
138 my_bitmaps
= malloc (npages
* sizeof(*my_bitmaps
));
139 if (my_bitmaps
== NULL
)
140 err (1, "malloc %lu", (unsigned long)npages
* sizeof(*my_bitmaps
));
143 for (i
= 0; i
< min(npages
, MAXPAGES
); ++i
) {
144 printf ("%u ", page0
->dheader
.map
[i
]);
148 page_entry_count
= 0;
150 if (page0
->header
.pg_tag
== htons(AFSDIRMAGIC_UTF8
))
153 for (i
= 0; i
< npages
; ++i
) {
154 PageHeader
*ph
= (PageHeader
*)((char *)page0
+ i
* AFSDIR_PAGESIZE
);
156 size_t sz
= ENTRIESPERPAGE
/ 8 * sizeof(*my_bitmaps
[i
]);
158 my_bitmaps
[i
] = malloc (sz
);
159 if (my_bitmaps
[i
] == NULL
)
160 err (1, "malloc %lu", (unsigned long)sz
);
162 memset (my_bitmaps
[i
], 0, sz
);
164 if (ph
->pg_tag
!= htons(AFSDIRMAGIC
) &&
165 ph
->pg_tag
!= htons(AFSDIRMAGIC_UTF8
))
167 printf ("page %d: wrong tag: %u\n", i
, htons(ph
->pg_tag
));
171 printf ("page %d: count = %u, tag = %u, freecount = %u\n",
172 i
, ntohs(ph
->pg_pgcount
), htons(ph
->pg_tag
), ph
->pg_freecount
);
175 if (ph
->pg_freecount
!= 19) {
176 printf ("freecount should be 19!\n");
181 if (ph
->pg_freecount
!= 51) {
182 printf ("freecount should be 51!\n");
187 if (ntohs(ph
->pg_pgcount
) != npages
) {
188 printf ("pgcount should be %u!\n", npages
);
193 if (ph
->pg_freecount
!= 63) {
194 printf ("freecount should be 63!\n");
198 if (ntohs(ph
->pg_pgcount
) != 0) {
199 printf ("pgcount should be 0!\n");
210 for (j
= start
; j
< ENTRIESPERPAGE
; ++j
) {
211 if (ph
->pg_bitmap
[j
/ 8] & (1 << (j
% 8)))
216 printf ("page entry count = %u\n", page_entry_count
);
218 hash_entry_count
= 0;
221 for (i
= 0; i
< ADIRHASHSIZE
; ++i
) {
222 const DirEntry
*entry
;
224 for(ind
= ntohs(page0
->dheader
.hash
[i
]);
226 ind
= ntohs(entry
->next
)) {
233 entry
= getentry (page0
, ind
- 1);
237 if (entry
->flag
& AFSDIR_UTFENT
) {
238 const DirEntry2
*direntry2
= (DirEntry2
*)
239 (((const char *)entry
) + (entry
->length
<< 2));
240 printf("len %d\n", entry
->length
);
241 printf("raw_offset %x\n", direntry2
->raw_offset
);
242 name
= ((const char *)entry
) + direntry2
->raw_offset
;
246 printf ("%s - %ld.%ld\n",
248 (long)ntohl(entry
->fid
.Vnode
),
249 (long)ntohl(entry
->fid
.Unique
));
251 if (hashentry (entry
->name
) != i
)
252 printf ("wrong name here? hash = %u, name = *%s*\n",
255 pageno
= (ind
) / ENTRIESPERPAGE
;
256 off
= (ind
) % ENTRIESPERPAGE
;
258 page_n
= (DirPage1
*)((char *)page0
259 + AFSDIR_PAGESIZE
* pageno
);
261 if (!(page_n
->header
.pg_bitmap
[off
/ 8] & (1 << (off
% 8)))) {
262 printf ("page %d: off %u not set\n",
263 (ind
- 1) / ENTRIESPERPAGE
, off
);
266 my_bitmaps
[pageno
][off
/ 8] |= (1 << (off
% 8));
268 len
= strlen(entry
->name
);
270 len
-= sizeof(DirEntry
);
273 my_bitmaps
[pageno
][off
/ 8] |= (1 << (off
% 8));
280 for (i
= 0; i
< npages
; ++i
) {
293 for (j
= 0; j
< unused
; ++j
)
294 my_bitmaps
[i
][j
/ 8] |= (1 << (j
% 8));
296 page_n
= (DirPage1
*)((char *)page0
+ AFSDIR_PAGESIZE
* i
);
298 if (memcmp (my_bitmaps
[i
],
299 page_n
->header
.pg_bitmap
, sizeof(my_bitmaps
[i
])) != 0) {
300 printf ("page %i: bitmaps differ\n"
302 for (j
= 0; j
< ENTRIESPERPAGE
/ 8; ++j
)
303 printf ("%02x ", page_n
->header
.pg_bitmap
[j
]);
306 for (j
= 0; j
< ENTRIESPERPAGE
/ 8; ++j
)
307 printf ("%02x ", my_bitmaps
[i
][j
]);
313 printf ("hash entry count = %u, noverfill = %u, sum = %u\n",
314 hash_entry_count
, noverfill
, hash_entry_count
+ noverfill
);
316 if (hash_entry_count
+ noverfill
!= page_entry_count
)
320 fbuf_end (&the_fbuf
);
323 for (i
= 0; i
< npages
; ++i
)
324 free (my_bitmaps
[i
]);
330 static struct getargs args
[] = {
331 {"verbose", 'v', arg_flag
, &verbose
,
332 "run in test mode", NULL
},
333 {"help", 0, arg_flag
, &local_help_flag
,
340 arg_printusage (args
, sizeof(args
)/sizeof(*args
), NULL
, "[file]");
345 main(int argc
, char **argv
)
349 if (getarg (args
, sizeof(args
)/sizeof(*args
), argc
, argv
, &optind
))
361 return check_dir (argv
[0]);