Exemple #1
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;
}
Exemple #2
0
int
fdir_emptyp (fbuf *dir)
{
     DirPage0 *page0;
     unsigned npages;

     page0 = (DirPage0 *)fbuf_buf(dir);
     assert (page0);

     npages = ntohs(page0->header.pg_pgcount);

     return (npages == 1) && (page0->dheader.map[0] == 49);
}
Exemple #3
0
int
fdir_lookup (fbuf *the_fbuf, const VenusFid *dir,
	     const char *name, VenusFid *file)
{
     DirPage0 *page0;
     unsigned ind;

     page0 = (DirPage0 *)fbuf_buf(the_fbuf);
     assert (page0);
     ind = find_by_name (page0, name, file, dir);

     if (ind == 0)
	 return 0;
     else
	 return ENOENT;
}
Exemple #4
0
int
fdir_changefid (fbuf *the_fbuf,
		const char *name,
		const VenusFid *file)
{
    DirPage0 *page0;
    int ret;

    page0 = (DirPage0 *)fbuf_buf(the_fbuf);
    assert (page0);
    ret = update_fid_by_name (page0, name, file);

    if (ret == 0)
	return 0;
    else
	return ENOENT;
}
Exemple #5
0
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;
}
Exemple #6
0
static int
create_new_page (DirPage1 **ret_page,
		 fbuf *the_fbuf)
{
    int ret;
    DirPage1 *page1;
    size_t len = fbuf_len(the_fbuf);

    ret = fbuf_truncate (the_fbuf, len + AFSDIR_PAGESIZE);
    if (ret)
	return ret;

    page1 = (DirPage1 *)((char *)fbuf_buf(the_fbuf) + len);
    page1->header.pg_pgcount   = htons(0);
    page1->header.pg_tag       = htons(AFSDIRMAGIC);
    page1->header.pg_freecount = ENTRIESPERPAGE - 1;
    memset (page1->header.pg_bitmap, 0, sizeof(page1->header.pg_bitmap));
    set_used (page1, 0);
    *ret_page = page1;

    return 0;
}
Exemple #7
0
int
dir_remove_name (FCacheEntry *e, const char *filename,
		 fcache_cache_handle *cache_handle,
		 char *cache_name, size_t cache_name_sz)
{
    int ret;
    int fd;
    fbuf fb;
    struct stat sb;
    char *buf;
    char *p;
    size_t len;
    struct nnpfs_dirent *dp;
    struct nnpfs_dirent *last_dp;

    fcache_extra_file_name (e, cache_name, cache_name_sz);
    fd = open (cache_name, O_RDWR, 0);
    if (fd < 0)
	return errno;
    fcache_fhget (cache_name, cache_handle);
    if (fstat (fd, &sb) < 0) {
	ret = errno;
	close (fd);
	return ret;
    }
    len = sb.st_size;

    ret = fbuf_create (&fb, fd, len, FBUF_READ|FBUF_WRITE|FBUF_SHARED);
    if (ret) {
	close (fd);
	return ret;
    }
    last_dp = NULL;
    ret = ENOENT;
    for (p = buf = fbuf_buf (&fb); p < buf + len; p += dp->d_reclen) {

	dp = (struct nnpfs_dirent *)p;

	assert (dp->d_reclen > 0);

	if (strcmp (filename, dp->d_name) == 0) {
	    if (last_dp != NULL) {
		size_t off1, off2;
		unsigned len;

		/*
		 * d_reclen can be as largest (in worst case)
		 * DIRBLKSIZ, and may not cause the entry to cross a
		 * DIRBLKSIZ boundery.
		 */
		len = last_dp->d_reclen + dp->d_reclen;

                off1 = (char *)last_dp - buf;
                off2 = off1 + len;
		off1 /= DIRBLKSIZ;
		off2 /= DIRBLKSIZ;

		if (len < DIRBLKSIZ && off1 == off2)
		    last_dp->d_reclen = len;
	    }
	    dp->d_fileno = 0;
	    ret = 0;
	    break;
	}
	last_dp = dp;
    }
    fbuf_end (&fb);
    close (fd);
    return ret;
}
Exemple #8
0
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;
    }
}
Exemple #9
0
int
fdir_readdir (fbuf *the_fbuf,
	      fdir_readdir_func func,
	      void *arg,
	      VenusFid dir, 
	      uint32_t *offset)
{
     DirPage0 *page0;
     unsigned i, j;
     VenusFid fid;
     unsigned len = fbuf_len(the_fbuf);
     unsigned npages;
     unsigned first_slot;
     int ret;

     page0 = (DirPage0 *)fbuf_buf(the_fbuf);

     assert (page0);

     npages = ntohs(page0->header.pg_pgcount);

     if (npages < len / AFSDIR_PAGESIZE)
	 npages = len / AFSDIR_PAGESIZE;

     if (offset && *offset) {
	 i = *offset / ENTRIESPERPAGE;
	 first_slot = *offset % ENTRIESPERPAGE;

	 assert(i > 0 || first_slot >= 12);
     } else {
	 i = 0;
	 first_slot = 12;
     }

     for (; i < npages; ++i) {
	 DirPage1 *page = getpage (page0, i);

	 for (j = first_slot; j < ENTRIESPERPAGE - 1; ++j) {
	     if (first_slotp (page, j)) {
		 DirEntry *entry = &page->entry[j];

		 if (entry->flag != AFSDIR_FIRST)
		     continue;

		 fid.Cell       = dir.Cell;
		 fid.fid.Volume = dir.fid.Volume;
		 fid.fid.Vnode  = ntohl (entry->fid.Vnode);
		 fid.fid.Unique = ntohl (entry->fid.Unique);

		 ret = (*func)(&fid, entry->name, arg);
		 if (ret) {
		     if (ret > 0)
			 j++; /* look at next entry next time */
		     
		     goto done;
		 }
		 j += additional_entries (entry->name);
	     }
	 }
	 first_slot = 0;
     }

 done:
     if (offset)
	 *offset = i * ENTRIESPERPAGE + j;

     return 0;
}