Пример #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;
}
Пример #2
0
int
mdir_changefid(struct mnode *dir, const char *name, AFSFid fid) {
    fbuf the_fbuf;
    VenusFid vfid;
    int ret, saved_ret;
    int32_t len;

    assert (dir->flags.sbp);
    assert (dir->flags.fdp);

    vfid.Cell = 0;
    vfid.fid = fid;

    ret = fbuf_create (&the_fbuf, dir->fd, dir->sb.st_size,
		       FBUF_READ|FBUF_WRITE|FBUF_SHARED);
    if (ret)
	return ret;

    saved_ret = fdir_changefid (&the_fbuf, name, &vfid);

    if (ret == 0) {
	len = fbuf_len (&the_fbuf);
	mnode_update_size (dir, &len);
    }

    ret = fbuf_end (&the_fbuf);
    if (ret)
	return ret;
    
    return saved_ret;
}
Пример #3
0
int
mdir_mkdir (struct mnode *node,
	    AFSFid dot,
	    AFSFid dot_dot)
{
    fbuf the_fbuf;
    int ret, saved_ret;
    int32_t len;

    assert (node->flags.sbp);
    assert (node->flags.fdp);

    ret = fbuf_create (&the_fbuf, node->fd, node->sb.st_size,
		       FBUF_READ|FBUF_WRITE|FBUF_SHARED);
    if (ret)
	return ret;

    saved_ret = fdir_mkdir (&the_fbuf, dot, dot_dot);

    if (ret == 0) {
	len = fbuf_len (&the_fbuf);
	mnode_update_size (node, &len);
    }

    ret = fbuf_end (&the_fbuf);
    if (ret)
	return ret;
    
    return saved_ret;
}
Пример #4
0
int
mdir_remove (struct mnode *node,
	     const char *name)
{
    fbuf the_fbuf;
    int ret, saved_ret;
    int32_t len;

    assert (node->flags.sbp);
    assert (node->flags.fdp);

    ret = fbuf_create (&the_fbuf, node->fd, node->sb.st_size,
		       FBUF_READ|FBUF_WRITE|FBUF_SHARED);
    if (ret)
	return ret;

    saved_ret = fdir_remove (&the_fbuf, name, NULL);

    if (ret == 0) {
	len = fbuf_len (&the_fbuf);
	mnode_update_size (node, &len);
    }
    
    ret = fbuf_end (&the_fbuf);
    if (ret)
	return ret;
    
    return saved_ret;
}
Пример #5
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;
}
Пример #6
0
int
mdir_rename(struct mnode *dir1, const char *name1, int32_t *len1,
	    struct mnode *dir2, const char *name2, int32_t *len2)
{
    fbuf origfbuf;
    fbuf newfbuf;
    fbuf *newfbufP = &newfbuf;
    VenusFid child, origVFid;
    int ret, dirp;
    int same_dir = FALSE;
    
    origVFid.Cell = 0;
    origVFid.fid = dir1->fid;

    ret = fbuf_create (&origfbuf, dir1->fd, dir1->sb.st_size, 
		       FBUF_READ|FBUF_WRITE|FBUF_SHARED);
    if (ret)
	return ret;

    ret = fdir_lookup(&origfbuf, &origVFid, name1, &child);
    if (ret) {
	fbuf_end (&origfbuf);
	return ret;
    }

    dirp = afs_dir_p (child.fid.Vnode);

    if (dir1 == dir2) {
	newfbufP = &origfbuf;
	same_dir = TRUE;
    } else {
	ret = fbuf_create (&newfbuf, dir2->fd, 
			   dir2->sb.st_size, 
			   FBUF_READ|FBUF_WRITE|FBUF_SHARED);
	if (ret) {
	    fbuf_end (&origfbuf);
	    return ret;
	}
    }

    {
	VenusFid sentenced_file;
	VenusFid dir;

	dir.fid = dir2->fid;
	dir.Cell = 0;

	if (fdir_lookup(newfbufP, &dir, name2, &sentenced_file) == ENOENT) {
	    ret = fdir_creat (newfbufP, name2, child.fid);
	    if (ret)
		goto out1;

	} else {
	    if (afs_dir_p (sentenced_file.fid.Vnode) != dirp) { /* XXX check properly */
		ret = EISDIR;
		goto out1;
	    }
	    
	    if (dirp && fdir_emptyp(newfbufP) != TRUE) {
		ret = ENOTEMPTY;
		goto out1;
	    }
	    
	    ret = fdir_changefid(newfbufP, name2, &child);
	    if (ret)
		goto out1;
	}
    }
    
    ret = fdir_remove (&origfbuf, name1, NULL);
    if (ret == 0) {
	*len1 = fbuf_len (&origfbuf);
	if (!same_dir)
	    *len2 = fbuf_len (newfbufP);
    }

 out1:
    fbuf_end (&origfbuf);
    if (!same_dir) {
	fbuf_end (&newfbuf);
    }

    return ret;
}
Пример #7
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;
}