int fdir_mkdir (fbuf *the_fbuf, AFSFid dot, AFSFid dot_dot) { DirPage0 *page0; DirPage1 *page; int ind; int i; int tmp; int ret; ret = create_new_page (&page, the_fbuf); if (ret) return ret; page0 = (DirPage0 *)fbuf_buf(the_fbuf); memset (&page0->dheader, 0, sizeof(page0->dheader)); tmp = ENTRIESPERPAGE - (sizeof(PageHeader) + sizeof(DirHeader)) / sizeof(DirEntry); page0->header.pg_freecount = tmp; page0->dheader.map[0] = tmp; page0->header.pg_pgcount = htons(1); for (i = 0; i < 13; ++i) set_used (page, i); assert (page0->dheader.hash[hashentry(".")] == 0); ind = add_to_page (page0, page, 0, ".", dot, 0); assert (ind >= 0); page0->dheader.hash[hashentry(".")] = htons(ind + 1); assert (page0->dheader.hash[hashentry("..")] == 0); ind = add_to_page (page0, page, 0, "..", dot_dot, 0); assert (ind >= 0); page0->dheader.hash[hashentry("..")] = htons(ind + 1); return 0; }
int fdir_creat (fbuf *dir, const char *name, AFSFid fid) { int ret; int i; unsigned npages; DirPage0 *page0; DirPage1 *page; int ind = 0; unsigned hash_value, next; assert (dir->len != 0); page0 = (DirPage0 *)fbuf_buf(dir); assert (page0); npages = ntohs(page0->header.pg_pgcount); if (npages < fbuf_len(dir) / AFSDIR_PAGESIZE) npages = fbuf_len(dir) / AFSDIR_PAGESIZE; if (find_entry (page0, name)) return EEXIST; hash_value = hashentry (name); next = page0->dheader.hash[hash_value]; for (i = 0; i < npages; ++i) { page = getpage (page0, i); ind = add_to_page (page0, page, i, name, fid, next); if (ind >= 0) break; } if (i == npages) { ret = create_new_page (&page, dir); if (ret) return ret; page0 = (DirPage0 *)fbuf_buf(dir); page0->header.pg_pgcount = htons(npages + 1); if (i < MAXPAGES) page0->dheader.map[i] = ENTRIESPERPAGE - 1; ind = add_to_page (page0, page, i, name, fid, next); assert (ind >= 0); } ind += i * ENTRIESPERPAGE; page0->dheader.hash[hash_value] = htons(ind + 1); return 0; }
static DirEntry * find_entry(DirPage0 *page0, const char *name) { DirEntry *entry; unsigned short i; for (i = ntohs(page0->dheader.hash[hashentry (name)]); i != 0; i = ntohs(entry->next)) { entry = getentry (page0, (unsigned short)(i - 1)); if (strcmp (entry->name, name) == 0) return entry; } return NULL; }
static int check_dir (const char *filename) { struct stat statbuf; int fd; fbuf the_fbuf; DirPage0 *page0; unsigned i, j; unsigned ind; unsigned len; int ret = 0; unsigned npages = 0; unsigned page_entry_count; unsigned hash_entry_count; unsigned noverfill; uint8_t **my_bitmaps = NULL; fd = open (filename, O_RDONLY | O_BINARY, 0); if (fd < 0) err (1, "open %s", filename); if (fstat (fd, &statbuf) < 0) err (1, "stat %s", filename); len = statbuf.st_size; if (len == 0) errx (1, "length == 0"); if (len % AFSDIR_PAGESIZE != 0) errx (1, "length %% AFSDIR_PAGESIZE != 0"); ret = fbuf_create (&the_fbuf, fd, len, FBUF_READ|FBUF_PRIVATE); if (ret) err (1, "fbuf_create"); page0 = (DirPage0 *)(the_fbuf.buf); printf ("size = %u, pages = %u, pgcount = %u\n", len, len / AFSDIR_PAGESIZE, ntohs(page0->header.pg_pgcount)); if (len / AFSDIR_PAGESIZE != ntohs(page0->header.pg_pgcount)) { ret = 1; goto out; } npages = len / AFSDIR_PAGESIZE; my_bitmaps = malloc (npages * sizeof(*my_bitmaps)); if (my_bitmaps == NULL) err (1, "malloc %lu", (unsigned long)npages * sizeof(*my_bitmaps)); printf ("map: "); for (i = 0; i < min(npages, MAXPAGES); ++i) { printf ("%u ", page0->dheader.map[i]); } printf ("\n"); page_entry_count = 0; for (i = 0; i < npages; ++i) { PageHeader *ph = (PageHeader *)((char *)page0 + i * AFSDIR_PAGESIZE); int start; size_t sz = ENTRIESPERPAGE / 8 * sizeof(*my_bitmaps[i]); my_bitmaps[i] = malloc (sz); if (my_bitmaps[i] == NULL) err (1, "malloc %lu", (unsigned long)sz); memset (my_bitmaps[i], 0, sz); if (ph->pg_tag != htons(AFSDIRMAGIC)) { printf ("page %d: wrong tag: %u\n", i, htons(ph->pg_tag)); ret = 1; goto out; } printf ("page %d: count = %u, tag = %u, freecount = %u\n", i, ntohs(ph->pg_pgcount), htons(ph->pg_tag), ph->pg_freecount); if (i == 0) { if (ph->pg_freecount != 51) { printf ("freecount should be 51!\n"); ret = 1; goto out; } if (ntohs(ph->pg_pgcount) != npages) { printf ("pgcount should be %u!\n", npages); ret = 1; goto out; } } else { if (ph->pg_freecount != 63) { printf ("freecount should be 63!\n"); ret = 1; goto out; } if (ntohs(ph->pg_pgcount) != 0) { printf ("pgcount should be 0!\n"); ret = 1; goto out; } } if (i == 0) start = 13; else start = 1; for (j = start; j < ENTRIESPERPAGE; ++j) { if (ph->pg_bitmap[j / 8] & (1 << (j % 8))) ++page_entry_count; } } printf ("page entry count = %u\n", page_entry_count); hash_entry_count = 0; noverfill = 0; for (i = 0; i < ADIRHASHSIZE; ++i) { const DirEntry *entry; for(ind = ntohs(page0->dheader.hash[i]); ind; ind = ntohs(entry->next)) { DirPage1 *page_n; int len; unsigned off; unsigned pageno; entry = getentry (page0, ind - 1); if (verbose) printf ("%s - %ld.%ld\n", entry->name, (long)ntohl(entry->fid.Vnode), (long)ntohl(entry->fid.Unique)); if (hashentry (entry->name) != i) printf ("wrong name here? hash = %u, name = *%s*\n", i, entry->name); pageno = (ind) / ENTRIESPERPAGE; off = (ind) % ENTRIESPERPAGE; page_n = (DirPage1 *)((char *)page0 + AFSDIR_PAGESIZE * pageno); if (!(page_n->header.pg_bitmap[off / 8] & (1 << (off % 8)))) { printf ("page %d: off %u not set\n", (ind - 1) / ENTRIESPERPAGE, off); } my_bitmaps[pageno][off / 8] |= (1 << (off % 8)); len = strlen(entry->name); while (len > 15) { len -= sizeof(DirEntry); ++noverfill; ++off; my_bitmaps[pageno][off / 8] |= (1 << (off % 8)); } ++hash_entry_count; } } for (i = 0; i < npages; ++i) { DirPage1 *page_n; int j; unsigned unused; if (i == 0) unused = 13; else unused = 1; for (j = 0; j < unused; ++j) my_bitmaps[i][j / 8] |= (1 << (j % 8)); page_n = (DirPage1 *)((char *)page0 + AFSDIR_PAGESIZE * i); if (memcmp (my_bitmaps[i], page_n->header.pg_bitmap, sizeof(my_bitmaps[i])) != 0) { printf ("page %i: bitmaps differ\n" "actual: ", i); for (j = 0; j < ENTRIESPERPAGE / 8; ++j) printf ("%02x ", page_n->header.pg_bitmap[j]); printf ("\n" "calculated: "); for (j = 0; j < ENTRIESPERPAGE / 8; ++j) printf ("%02x ", my_bitmaps[i][j]); printf ("\n"); } } printf ("hash entry count = %u, noverfill = %u, sum = %u\n", hash_entry_count, noverfill, hash_entry_count + noverfill); if (hash_entry_count + noverfill != page_entry_count) ret = 1; out: fbuf_end (&the_fbuf); close (fd); if (my_bitmaps) { for (i = 0; i < npages; ++i) free (my_bitmaps[i]); free (my_bitmaps); } return ret; }
int fdir_remove (fbuf *dir, const char *name, AFSFid *fid) { int i; unsigned len = dir->len; DirPage0 *page0; DirPage1 *page; unsigned hash_value; DirEntry *entry = NULL; DirEntry *prev_entry; unsigned pageno; int found; unsigned npages; page0 = (DirPage0 *)fbuf_buf(dir); npages = ntohs(page0->header.pg_pgcount); if (npages < len / AFSDIR_PAGESIZE) npages = len / AFSDIR_PAGESIZE; hash_value = hashentry (name); i = ntohs(page0->dheader.hash[hash_value]); found = i == 0; prev_entry = NULL; while (!found) { entry = getentry (page0, i - 1); if (strcmp (entry->name, name) == 0) { found = TRUE; } else { i = ntohs(entry->next); if (i == 0) found = TRUE; prev_entry = entry; } } if (i == 0) return ENOENT; else { if (fid) { fid->Vnode = ntohl(entry->fid.Vnode); fid->Unique = ntohl(entry->fid.Unique); } if (prev_entry == NULL) page0->dheader.hash[hash_value] = entry->next; else prev_entry->next = entry->next; pageno = (i - 1) / ENTRIESPERPAGE; page = getpage (page0, pageno); remove_from_page (page0, page, pageno, (i - 1) % ENTRIESPERPAGE); if (pageno == npages - 1 && is_page_empty (page0, pageno)) { do { len -= AFSDIR_PAGESIZE; --pageno; --npages; } while(is_page_empty(page0, pageno)); page0->header.pg_pgcount = htons(npages); fbuf_truncate (dir, len); } return 0; } }