use a cell that actually exists
[arla.git] / arlad / afsdir_check.c
blob745951f7ea1e39058af91487e2276c32c0ad28fe
1 /*
2 * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
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
31 * SUCH DAMAGE.
35 * Check a directory in afs format.
38 #include "arla_local.h"
39 #include <getarg.h>
41 RCSID("$Id$");
43 static int local_help_flag;
44 static int verbose = 0;
47 * Hash the filename of one entry.
50 static unsigned
51 hashentry (const char *entry)
53 int s = 0, h;
55 while (*entry)
56 s = s * 173 + *entry++;
57 h = s & (ADIRHASHSIZE - 1);
58 if (h == 0)
59 return h;
60 else if( s < 0 )
61 h = ADIRHASHSIZE - h;
62 return h;
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,
72 unsigned short num)
74 DirPage1 *page;
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);
83 exit (1);
85 return &page->entry[num % ENTRIESPERPAGE];
88 static int
89 check_dir (const char *filename)
91 struct stat statbuf;
92 int fd;
93 fbuf the_fbuf;
94 DirPage0 *page0;
95 unsigned i, j;
96 unsigned ind;
97 unsigned len;
98 int ret = 0;
99 int utf8_dir = 0;
100 unsigned npages = 0;
101 unsigned page_entry_count;
102 unsigned hash_entry_count;
103 unsigned noverfill;
104 uint8_t **my_bitmaps = NULL;
106 fd = open (filename, O_RDONLY | O_BINARY, 0);
107 if (fd < 0)
108 err (1, "open %s", filename);
110 if (fstat (fd, &statbuf) < 0)
111 err (1, "stat %s", filename);
113 len = statbuf.st_size;
115 if (len == 0)
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);
122 if (ret)
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)) {
132 ret = 1;
133 goto out;
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));
142 printf ("map: ");
143 for (i = 0; i < min(npages, MAXPAGES); ++i) {
144 printf ("%u ", page0->dheader.map[i]);
146 printf ("\n");
148 page_entry_count = 0;
150 if (page0->header.pg_tag == htons(AFSDIRMAGIC_UTF8))
151 utf8_dir = 1;
153 for (i = 0; i < npages; ++i) {
154 PageHeader *ph = (PageHeader *)((char *)page0 + i * AFSDIR_PAGESIZE);
155 int start;
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));
168 ret = 1;
169 goto out;
171 printf ("page %d: count = %u, tag = %u, freecount = %u\n",
172 i, ntohs(ph->pg_pgcount), htons(ph->pg_tag), ph->pg_freecount);
173 if (i == 0) {
174 if (utf8_dir) {
175 if (ph->pg_freecount != 19) {
176 printf ("freecount should be 19!\n");
177 ret = 1;
178 goto out;
180 } else {
181 if (ph->pg_freecount != 51) {
182 printf ("freecount should be 51!\n");
183 ret = 1;
184 goto out;
187 if (ntohs(ph->pg_pgcount) != npages) {
188 printf ("pgcount should be %u!\n", npages);
189 ret = 1;
190 goto out;
192 } else {
193 if (ph->pg_freecount != 63) {
194 printf ("freecount should be 63!\n");
195 ret = 1;
196 goto out;
198 if (ntohs(ph->pg_pgcount) != 0) {
199 printf ("pgcount should be 0!\n");
200 ret = 1;
201 goto out;
205 if (i == 0)
206 start = 13;
207 else
208 start = 1;
210 for (j = start; j < ENTRIESPERPAGE; ++j) {
211 if (ph->pg_bitmap[j / 8] & (1 << (j % 8)))
212 ++page_entry_count;
216 printf ("page entry count = %u\n", page_entry_count);
218 hash_entry_count = 0;
219 noverfill = 0;
221 for (i = 0; i < ADIRHASHSIZE; ++i) {
222 const DirEntry *entry;
224 for(ind = ntohs(page0->dheader.hash[i]);
225 ind;
226 ind = ntohs(entry->next)) {
227 DirPage1 *page_n;
228 int len;
229 unsigned off;
230 unsigned pageno;
231 const char *name;
233 entry = getentry (page0, ind - 1);
235 name = entry->name;
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;
245 if (verbose)
246 printf ("%s - %ld.%ld\n",
247 name,
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",
253 i, entry->name);
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);
269 while (len > 15) {
270 len -= sizeof(DirEntry);
271 ++noverfill;
272 ++off;
273 my_bitmaps[pageno][off / 8] |= (1 << (off % 8));
276 ++hash_entry_count;
280 for (i = 0; i < npages; ++i) {
281 DirPage1 *page_n;
282 int j;
283 unsigned unused;
285 if (i == 0) {
286 unused = 13;
287 if (utf8_dir)
288 unused += 32;
290 else
291 unused = 1;
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"
301 "actual: ", i);
302 for (j = 0; j < ENTRIESPERPAGE / 8; ++j)
303 printf ("%02x ", page_n->header.pg_bitmap[j]);
304 printf ("\n"
305 "calculated: ");
306 for (j = 0; j < ENTRIESPERPAGE / 8; ++j)
307 printf ("%02x ", my_bitmaps[i][j]);
308 printf ("\n");
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)
317 ret = 1;
319 out:
320 fbuf_end (&the_fbuf);
321 close (fd);
322 if (my_bitmaps) {
323 for (i = 0; i < npages; ++i)
324 free (my_bitmaps[i]);
325 free (my_bitmaps);
327 return ret;
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,
334 NULL, NULL},
337 static void
338 usage (int ret)
340 arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "[file]");
341 exit (ret);
345 main(int argc, char **argv)
347 int optind = 0;
349 if (getarg (args, sizeof(args)/sizeof(*args), argc, argv, &optind))
350 usage (1);
352 argc -= optind;
353 argv += optind;
355 if (local_help_flag)
356 usage (0);
358 if (argc != 1)
359 usage (1);
361 return check_dir (argv[0]);