Example #1
0
/* 
 * Based on uio->uio_offset, get the name of the next directory entry,
 * if one exists.
 */
static
int
sfs_getdirentry(struct vnode *vv, struct uio *uio)
{
	struct sfs_vnode *sv;
	struct sfs_dir tsd;
        int nentries, slot, err;

	assert(uio->uio_iovec.iov_ubase != NULL);
	assert(uio->uio_rw == UIO_READ);

	sv = vv->vn_data;
	if(sv->sv_i.sfi_type != SFS_TYPE_DIR) return ENOTDIR;

	nentries = sfs_dir_nentries(sv);
	if(nentries == 0) return ENOENT;	

	/* Get slot of interest */
	if((uio->uio_offset % sizeof(struct sfs_dir)) <= 4){
		/* Use dir entry in which we are currently pointing to */
		slot = uio->uio_offset/sizeof(struct sfs_dir);
	} else{
		/* Use next dir entry */
		slot = uio->uio_offset/sizeof(struct sfs_dir) + 1;
	}

	while(slot < nentries){
		err = sfs_readdir(sv, &tsd, slot);
		if(err) return err;

		if(tsd.sfd_ino != SFS_NOINO) break;
		slot++;
	}

	if(slot >= nentries){
		/* EOF - just return */
		return 0;
	}
	
	/* Set things up and do the move */
	tsd.sfd_name[sizeof(tsd.sfd_name)-1] = 0;
	uio->uio_offset = 0;
	err = uiomove(tsd.sfd_name, sizeof(tsd.sfd_name), uio);
	if(err) return err;

	/* Reset offset */
	uio->uio_offset = ((slot + 1) * sizeof(struct sfs_dir));

	return 0;
}
Example #2
0
/*
 * Read a single filename from a directory into a uio.
 *
 */
 int
 sfs_getdirentry(struct vnode *v, struct uio *uio)
 {
 	struct sfs_vnode *sv = v->vn_data;
	struct sfs_dir tsd;
	int nentries = sfs_dir_nentries(sv);
	int result;

	vfs_biglock_acquire();

	while (uio->uio_offset <= nentries) {
		// Read directory entry
		result = sfs_readdir(sv, &tsd, uio->uio_offset);

		if (result) {
			vfs_biglock_release();
			return result;
		}

		if (tsd.sfd_ino != SFS_NOINO) {
			break;
		}

		uio->uio_offset ++;
	}

	// If we still don't have a result, there must be nothing left
	if (tsd.sfd_ino == SFS_NOINO) {
		vfs_biglock_release();
		return ENOMEM;
	}

	/* Ensure null termination, just in case */
	tsd.sfd_name[sizeof(tsd.sfd_name)-1] = 0;

	// Copy results to uio
	result = uiomove(tsd.sfd_name, strlen(tsd.sfd_name), uio);

	if (result) {
		vfs_biglock_release();
		return result;
	}

	uio->uio_offset ++;
 	vfs_biglock_release();
 	return 0;

 }
Example #3
0
static
int
sfs_dir_findname(struct sfs_vnode *sv, const char *name,
		    u_int32_t *ino, int *slot, int *emptyslot)
{
	struct sfs_dir tsd;
	int found = 0;
	int nentries = sfs_dir_nentries(sv);
	int i, result;

	/* For each slot... */
	for (i=0; i<nentries; i++) {

		/* Read the entry from that slot */
		result = sfs_readdir(sv, &tsd, i);
		if (result) {
			return result;
		}
		if (tsd.sfd_ino == SFS_NOINO) {
			/* Free slot - report it back if one was requested */
			if (emptyslot != NULL) {
				*emptyslot = i;
			}
		}
		else {
			/* Ensure null termination, just in case */
			tsd.sfd_name[sizeof(tsd.sfd_name)-1] = 0;
			if (!strcmp(tsd.sfd_name, name)) {

				/* Each name may legally appear only once... */
				assert(found==0);

				found = 1;
				if (slot != NULL) {
					*slot = i;
				}
				if (ino != NULL) {
					*ino = tsd.sfd_ino;
				}
			}
		}
	}

	return found ? 0 : ENOENT;
}
Example #4
0
/* Setup . and .. in root directory if this is the first mount */
int
sfs_setup_root(struct sfs_fs *sfs)
{
	struct fs *fs = &sfs->sfs_absfs;
	struct vnode *root_vv;
	struct sfs_vnode *root_sv;
	int result;

	root_vv = sfs_getroot(fs);
	root_sv = root_vv->vn_data;

	if(sfs_dir_nentries(root_sv) != 0){
		VOP_DECREF(root_vv);
		return 0;
	}

	result = sfs_dir_link(root_sv, ".", SFS_ROOT_LOCATION, NULL);
        if (result) {
                VOP_DECREF(root_vv);
                return result;
        }

        root_sv->sv_i.sfi_linkcount++;
        root_sv->sv_dirty = 1;

        result = sfs_dir_link(root_sv, "..", SFS_ROOT_LOCATION, NULL);
        if (result) {
                sfs_dir_unlink(root_sv, 0); /* Hope this doesn't fail?? */
                root_sv->sv_i.sfi_linkcount--;
                root_sv->sv_dirty = 1;
                VOP_DECREF(root_vv);
                return result;
        }

        root_sv->sv_i.sfi_linkcount++;
        root_sv->sv_dirty = 1;	

	/* Decrement reference that sfs_getroot incremented */
	VOP_DECREF(root_vv);

	return 0;
}
Example #5
0
/*
 * Create a link in a directory to the specified inode by number, with
 * the specified name, and optionally hand back the slot.
 */
static
int
sfs_dir_link(struct sfs_vnode *sv, const char *name, uint32_t ino, int *slot)
{
	int emptyslot = -1;
	int result;
	struct sfs_dir sd;

	/* Look up the name. We want to make sure it *doesn't* exist. */
	result = sfs_dir_findname(sv, name, NULL, NULL, &emptyslot);
	if (result!=0 && result!=ENOENT) {
		return result;
	}
	if (result==0) {
		return EEXIST;
	}

	if (strlen(name)+1 > sizeof(sd.sfd_name)) {
		return ENAMETOOLONG;
	}

	/* If we didn't get an empty slot, add the entry at the end. */
	if (emptyslot < 0) {
		emptyslot = sfs_dir_nentries(sv);
	}

	/* Set up the entry. */
	bzero(&sd, sizeof(sd));
	sd.sfd_ino = ino;
	strcpy(sd.sfd_name, name);

	/* Hand back the slot, if so requested. */
	if (slot) {
		*slot = emptyslot;
	}

	/* Write the entry. */
	return sfs_writedir(sv, &sd, emptyslot);
	
}
Example #6
0
int
sfs_getdirentry(struct vnode *v_node, struct uio *user_io)
{
	struct sfs_vnode *s_node = v_node->vn_data;
	struct sfs_dir sdir;

	int offset = user_io->uio_offset;

	vfs_biglock_acquire(); //acquire lock
	
	int nentries = sfs_dir_nentries(s_node);
	if (offset >= nentries) {
		vfs_biglock_release(); //release lock
		return ENOENT; //Error no entry
	}
	
	int result;
	while(1) {
		result = sfs_readdir(s_node, &sdir, user_io->uio_offset);
		if (result) {
			vfs_biglock_release(); //release lock
			return result; //return this result
		}

		if (sdir.sfd_ino == SFS_NOINO) { //if this sdir is the inode # for free dir entry
			offset++;
			if(offset >= nentries) {
				vfs_biglock_release(); //release lock
				return ENOENT; //error no entry
			}
			user_io->uio_offset++;
			continue;
		}
		break;
	}
	result = uiomove(sdir.sfd_name, strlen(sdir.sfd_name), user_io); //get the result
	user_io->uio_offset = offset + 1; //update uio offset
	vfs_biglock_release(); //release lock
	return 0; //and return
}
Example #7
0
static
int
sfs_rmdir(struct vnode *vv, const char *name){
	struct sfs_vnode *sv = vv->vn_data;
        struct sfs_vnode *victim;
	struct sfs_dir tsd;
        int slot, slot2, nentries;
        int result;

        /* Look for the directory and fetch a vnode for it. */
        result = sfs_lookonce(sv, name, &victim, &slot);
        if (result) {
                return result;
        }

	/* Make sure it's a directory and that only . and .. are left */
	if(victim->sv_i.sfi_type != SFS_TYPE_DIR){
		VOP_DECREF(&victim->sv_v);
		return ENOTDIR;
	}

	nentries = sfs_dir_nentries(victim);
	if(nentries != 2){
		slot2 = 2; 
		while(slot2 < nentries){
			/* Ensure all other entries are blank */
			result = sfs_readdir(victim, &tsd, slot2);
                	if(result){
				VOP_DECREF(&victim->sv_v);
				return result;
			}

                	if(tsd.sfd_ino != SFS_NOINO){
				VOP_DECREF(&victim->sv_v);
                                return ENOTEMPTY;
			}
                	slot2++;
		}	
	}

	/* Get rid of . and .. (should always be in slot 0 and 1) */
	result = sfs_dir_unlink(victim, 0);
	if(result){
		VOP_DECREF(&victim->sv_v);
		return result;
	}
	assert(victim->sv_i.sfi_linkcount > 0);
        victim->sv_i.sfi_linkcount--;
        victim->sv_dirty = 1;

	result = sfs_dir_unlink(victim, 1);
        if(result){
                VOP_DECREF(&victim->sv_v);
                return result;
        }       
	assert(sv->sv_i.sfi_linkcount > 0);
        sv->sv_i.sfi_linkcount--;
        sv->sv_dirty = 1;

        /* Erase its directory entry. */
        result = sfs_dir_unlink(sv, slot);
        if (result==0) {
                /* If we succeeded, decrement the link count. */
                assert(victim->sv_i.sfi_linkcount > 0);
                victim->sv_i.sfi_linkcount--;
                victim->sv_dirty = 1;
        }

        /* Discard the reference that sfs_lookonce got us */
        VOP_DECREF(&victim->sv_v);

	return result;
}
Example #8
0
/*
 * Get the full pathname for a file. This only needs to work on directories.
 * Since we don't support subdirectories, assume it's the root directory
 * and hand back the empty string. (The VFS layer takes care of the
 * device name, leading slash, etc.)
 */
static
int
sfs_namefile(struct vnode *vv, struct uio *uio)
{
	/* 
	 * 1. All you really have is inode number of directory passed in.
	 * 2. Get inode number of parent by reading directory slot 0 (..)
	 * 3. loadvnode of parent
	 * 4. Get our name by reading through parent directory for our inode
	 *    number
	 * 5. Add this name to string
	 * 6. Repeat 2 through 5 until we hit root
	 * 7. uiomove
	 *	Deal with reference counters as you need to, as loadvnode
	 *	increments refcount on vnode that we load. 
	 */
	
	struct sfs_vnode *sv = vv->vn_data;
	struct sfs_vnode *child_dir, *parent_dir;
	struct sfs_dir tsd;
	int err, nentries, slot;
	char to_add[SFS_NAMELEN + 1], pathname[(SFS_NAMELEN + 1) * SFS_DIR_DEPTH];
	
	/* If we're root, do nothing */
	if(sv->sv_ino == SFS_ROOT_LOCATION) return 0;

	child_dir = sv;
	VOP_INCREF(&child_dir->sv_v);

	while(1){
		err = sfs_readdir(child_dir, &tsd, 1);
        	if(err) return err;	

		assert(!strcmp(tsd.sfd_name, ".."));

		err = sfs_loadvnode(child_dir->sv_v.vn_fs->fs_data, tsd.sfd_ino, SFS_TYPE_INVAL, &parent_dir);
		if(err) return err;

		nentries = sfs_dir_nentries(parent_dir);
		slot = 2;
		while (slot < nentries){
			err = sfs_readdir(parent_dir, &tsd, slot);
        		if(err) return err;

			if(tsd.sfd_ino == child_dir->sv_ino) break;
                	slot++;
        	}

		/* 
	 	 * Doesn't make sense if we don't find our directory listed in our
	 	 * parent directory..
	 	 */
        	assert(slot < nentries);

		strcpy(to_add, tsd.sfd_name);
		strcat(to_add, "/");
		strcat(to_add, pathname);
		strcpy(pathname, to_add);
	
		VOP_DECREF(&child_dir->sv_v);
		if(parent_dir->sv_ino == SFS_ROOT_LOCATION){
			VOP_DECREF(&parent_dir->sv_v);
                        break;
		} else child_dir = parent_dir;
	}

	err = uiomove(pathname, strlen(pathname) + 1, uio);
	if(err) return err;

	return 0;
}
Example #9
0
/*
 * Called for getdirentry()
 *
 * Locking: gets/releases vnode lock.
 *
 * Requires up to 4 buffers.
 */
static
int
sfs_getdirentry(struct vnode *v, struct uio *uio)
{
	struct sfs_vnode *sv = v->vn_data;
	struct sfs_direntry tsd;
	off_t pos;
	int nentries;
	int result;

	KASSERT(uio->uio_offset >= 0);
	KASSERT(uio->uio_rw==UIO_READ);
	lock_acquire(sv->sv_lock);
	reserve_buffers(SFS_BLOCKSIZE);

	result = sfs_dinode_load(sv);
	if (result) {
		unreserve_buffers(SFS_BLOCKSIZE);
		lock_release(sv->sv_lock);
		return result;
	}

	result = sfs_dir_nentries(sv, &nentries);
	if (result) {
		sfs_dinode_unload(sv);
		unreserve_buffers(SFS_BLOCKSIZE);
		lock_release(sv->sv_lock);
		return result;
	}

	/* Use uio_offset as the slot index. */
	pos = uio->uio_offset;

	while (1) {
		if (pos >= nentries) {
			/* EOF */
			result = 0;
			break;
		}

		result = sfs_readdir(sv, pos, &tsd);
		if (result) {
			break;
		}

		pos++;

		if (tsd.sfd_ino == SFS_NOINO) {
			/* Blank entry */
			continue;
		}

		/* Ensure null termination, just in case */
		tsd.sfd_name[sizeof(tsd.sfd_name)-1] = 0;

		result = uiomove(tsd.sfd_name, strlen(tsd.sfd_name), uio);
		break;
	}

	sfs_dinode_unload(sv);

	unreserve_buffers(SFS_BLOCKSIZE);

	lock_release(sv->sv_lock);

	/* Update the offset the way we want it */
	uio->uio_offset = pos;

	return result;
}