/* Reads the next directory entry in DIR and stores the name in
   NAME.  Returns true if successful, false if the directory
   contains no more entries. */
bool
dir_readdir (struct dir *dir, char name[NAME_MAX + 1])
{
  struct dir_entry e;

  while (inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e) 
    {
      dir->pos += sizeof e;
      if (e.in_use && strcmp(e.name,".") != 0 && strcmp(e.name,"..") != 0 )
        {
          strlcpy (name, e.name, NAME_MAX + 1);
          return true;
        } 
    }
  return false;
}
Exemple #2
0
bool dir_is_empty( struct dir *dir)
{
  struct dir_entry e;

  int pos = 0;

  while (inode_read_at (dir->inode, &e, sizeof e, pos) == sizeof e) 
    {
      pos += sizeof e;
      if (e.in_use)
        {
          if (strcmp(e.name,".")==0 || strcmp(e.name,"..")==0) continue;
          return false;
        } 
    }
  return true;
}
/* Adds a file named NAME to DIR, which must not already contain a
   file by that name.  The file's inode is in sector
   INODE_SECTOR.
   Returns true if successful, false on failure.
   Fails if NAME is invalid (i.e. too long) or a disk or memory
   error occurs. */
bool
dir_add (struct dir *dir, const char *name, block_sector_t inode_sector)
{
  struct dir_entry e;
  off_t ofs;
  bool success = false;

  name = getfilename(name);

  ASSERT (dir != NULL);
  ASSERT (name != NULL);

  /* Check NAME for validity. */
  if (*name == '\0' || strlen (name) > NAME_MAX) {
    return false;
  }
  //lock the directory for the operation
  inode_lock(dir->inode);

  /* Check that NAME is not in use. */
  if (lookup (dir, name, NULL, NULL))
    goto done;

  /* Set OFS to offset of free slot.
     If there are no free slots, then it will be set to the
     current end-of-file.
     
     inode_read_at() will only return a short read at end of file.
     Otherwise, we'd need to verify that we didn't get a short
     read due to something intermittent such as low memory. */
  for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
       ofs += sizeof e) 
    if (!e.in_use)
      break;

  /* Write slot. */
  e.in_use = true;
  strlcpy (e.name, name, sizeof e.name);
  e.inode_sector = inode_sector;
  success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e;

 done:
  //unlock the directory again
  inode_unlock(dir->inode);
  return success;
}
/* Adds a file named NAME to DIR, which must not already contain a
   file by that name.  The file's inode is in sector
   INODE_SECTOR.
   Returns true if successful, false on failure.
   Fails if NAME is invalid (i.e. too long) or a disk or memory
   error occurs. */
bool
dir_add (struct file *dir, const char *name, block_sector_t inode_sector)
{
  ASSERT (file_is_dir (dir));
  struct dir_entry e;
  size_t ofs;
  bool success = false;

  ASSERT (dir != NULL);
  ASSERT (name != NULL);

  /* Check NAME for validity. */
  if (*name == '\0' || strlen (name) > NAME_MAX)
    return false;

  bool locked = file_lock (dir);
  /* Check that NAME is not in use. */
  if (dir_lookup (dir, name) >= 0)
    goto done;

  /* Set OFS to offset of free slot.
     If there are no free slots, then it will be set to the
     current end-of-file.
     
     inode_read_at() will only return a short read at end of file.
     Otherwise, we'd need to verify that we didn't get a short
     read due to something intermittent such as low memory. */
  size_t dir_size = inode_length (dir->inode);
  for (ofs = 0; ofs < dir_size; ofs += sizeof e) 
    {
      inode_read_at (dir->inode, &e, sizeof e, ofs);
      if (!e.in_use)
        break;
    }

  /* Write slot. */
  e.in_use = true;
  strlcpy (e.name, name, sizeof e.name);
  e.inode_sector = inode_sector;
  success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e;

 done:
  if (locked) file_unlock (dir);
  return success;
}
Exemple #5
0
/* Returns the num of entries in this directory, EXCLUDING '.' and
   '..' */
static size_t
dir_size (struct dir *dir)
{
  struct dir_entry e;
  size_t ofs;
  size_t count = 0;

  ASSERT (dir != NULL);
  lock_acquire (&dir->l);
  for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
       ofs += sizeof e) 
  {
    if (e.in_use)
      count++;
  }
  lock_release (&dir->l);
  return count - 2;
}
Exemple #6
0
static struct directory *dir_get_root(struct block *d){
	struct inode *root_ino;
	struct directory *root;

	ASSERT(d != NULL);

	// get root inode
	root_ino = ext2_get_inode(d,EXT2_ROOT_INO);

	// allocate memory
	root = kmalloc(root_ino->i_size);
	if(root == NULL) return NULL;

	// read entire file
	inode_read_at(d,root_ino,root,root_ino->i_size,0);

	return root;
}
Exemple #7
0
/* Reads the next directory entry in DIR and stores the name in
   NAME.  Returns true if successful, false if the directory
   contains no more entries. */
bool
dir_readdir (struct dir *dir, char name[NAME_MAX + 1])
{
  struct dir_entry e;

  while (inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e) 
    {
      dir->pos += sizeof e;
      if (e.in_use)
        {
//          printf ("readdir name:%x, name:%s, pos:%d\n", name, e.name, dir->pos);
          strlcpy (name, e.name, NAME_MAX + 1);
 //         printf ("strlcpy end\n");
          return true;
        } 
    }
  return false;
}
Exemple #8
0
/* Reads the next directory entry in DIR and stores the name in
   NAME.  Returns true if successful, false if the directory
   contains no more entries. */
bool
dir_readdir (struct dir *dir, char name[NAME_MAX + 1])
{
  struct dir_entry e;

  bool result = false;
  lock_acquire (&dir->l);
  while (!result && 
      inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e) 
  {
    if (e.in_use)
    {
      strlcpy (name, e.name, NAME_MAX + 1);
      result = true;
    } 
    dir->pos += sizeof e;
  }
  lock_release (&dir->l);
  return result;
}
Exemple #9
0
/* Reads the next directory entry in DIR and stores the name in
   NAME.  Returns true if successful, false if the directory
   contains no more entries. */
bool
dir_readdir (struct dir *dir, char name[NAME_MAX + 1])
{
//  lock_acquire(&directory_lock);
  struct dir_entry e;
  bool success = false;

  while (inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e)
    {
      dir->pos += sizeof e;
      if (e.in_use)
        {
          strlcpy (name, e.name, NAME_MAX + 1);
//          return true;
          success = true;
        break;
        }
    }
//  lock_release(&directory_lock);
  return success;
}
Exemple #10
0
bool dir_readdir (struct dir *directory,
    char file [MAXIMUM_FILE_NAME_LENGTH + 1])
{
  struct dir_entry directory_element;
  bool success = false;
  acquire_inode_lock (directory->inode);

  while (inode_read_at (directory->inode, &directory_element,
      sizeof directory_element, directory->pos) == sizeof directory_element)
  {
    directory->pos += sizeof directory_element;
    if (directory_element.in_use)
    {
      strlcpy (file, directory_element.name,
          MAXIMUM_FILE_NAME_LENGTH + 1);
      success = true;
      break;
    }
  }
  release_inode_lock (directory->inode);
  return success;
}
Exemple #11
0
/* Searches DIR for a file with the given NAME.
   If successful, returns true, sets *EP to the directory entry
   if EP is non-null, and sets *OFSP to the byte offset of the
   directory entry if OFSP is non-null.
   otherwise, returns false and ignores EP and OFSP. */
static bool
lookup (const struct dir *dir, const char *name,
        struct dir_entry *ep, off_t *ofsp) 
{
  struct dir_entry e;
  size_t ofs;
  
  ASSERT (dir != NULL);
  ASSERT (name != NULL);

  for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
       ofs += sizeof e) 
    if (e.in_use && !strcmp (name, e.name)) 
      {
        if (ep != NULL)
          *ep = e;
        if (ofsp != NULL)
          *ofsp = ofs;
        return true;
      }
  return false;
}
/* Returns whether or not the given directory is empty (an empty directory is
   one in which the only entries are "." and "..").
   NOTE : Assumes the caller has already acquired a lock on the directory. */
bool
dir_is_empty (struct file *dir)
{
  ASSERT (file_is_dir (dir));
  
  /* Look through all the directory entries, counting up the entries that are
     in use. */
  size_t dir_size = inode_length (dir->inode);
  struct dir_entry e;
  size_t ofs;
  size_t entries = 0;
  for (ofs = 0; ofs < dir_size; ofs += sizeof e) 
    {
      inode_read_at (dir->inode, &e, sizeof e, ofs);
      if (e.in_use) entries++;
    }

  /* A directory should never have less than 2 entries. */
  ASSERT (entries >= 2);
  
  /* The directory is empty if it contains only "." and ".." - 2 entries. */
  return entries == 2;
}
Exemple #13
0
/*! Reads SIZE bytes from FILE into BUFFER, starting at offset FILE_OFS in the
    file.  Returns the number of bytes actually read, which may be less than
    SIZE if end of file is reached.  The file's current position is
    unaffected. */
off_t file_read_at(struct file *file, void *buffer, off_t size,
                   off_t file_ofs) {
    ASSERT(file != NULL);
    ASSERT(buffer != NULL);
    return inode_read_at(file->inode, buffer, size, file_ofs);
}
Exemple #14
0
/* Creates a file named NAME with the given INITIAL_SIZE.
   Returns true if successful, false otherwise.
   Fails if a file named NAME already exists,
   or if internal memory allocation fails. */
static bool
_filesys_create (const char *full_path, off_t initial_size,
                 bool is_dir)
{
    block_sector_t cwd = thread_current ()->cwd_sector;
    bool found = true;
    if (cwd != (block_sector_t) ROOT_DIR_SECTOR)
    {
        struct inode *curr = NULL;
        curr = inode_open (cwd);
        struct dir *p;
        p = dir_open (inode_open (curr->data.parent_dir_sector));
        struct dir_entry e;
        size_t ofs;
        ASSERT (p != NULL);
        found = false;
        for (ofs = 0;
                inode_read_at (p->inode, &e, sizeof e, ofs) == sizeof e;
                ofs += sizeof e)
        {
            if (e.inode_sector == cwd && e.in_use)
            {
                found = true;
                break;
            }
        }
    }
    if (!found)
        return false;

    char leaf_name[NAME_MAX + 1];
    if (!dir_get_leaf_name (full_path, leaf_name))
        return false;

    struct dir *parent_dir = dir_get_parent_dir (full_path);

    if (parent_dir == NULL)
        return false;

    block_sector_t inode_sector = 0;
    if (!free_map_allocate_one (&inode_sector))
    {
        dir_close (parent_dir);
        return false;
    }
    bool success = is_dir? dir_create (inode_sector, BLOCK_SECTOR_SIZE /
                                       sizeof (struct dir_entry)) :
                   inode_create (inode_sector, initial_size);
    if (!success)
    {
        free_map_release (inode_sector, 1);
        dir_close (parent_dir);
        return false;
    }
    if (!dir_add (parent_dir, leaf_name, inode_sector))
    {
        inode_remove (inode_open (inode_sector));
        free_map_release (inode_sector, 1);
        dir_close (parent_dir);
        return false;
    }
    dir_close (parent_dir);
    return true;
}
Exemple #15
0
bool dir_remove (struct dir *directory, const char *file)
{
  struct dir_entry directory_element_1, directory_element_2;
  struct inode *inode = NULL;
  bool present = false;
  off_t offset_1, offset_2;
  int count;

  ASSERT(directory != NULL);
  ASSERT(file != NULL);

  acquire_inode_lock (directory->inode);

  for (offset_2 = 0;
      inode_read_at (directory->inode, &directory_element_2,
          sizeof directory_element_2, offset_2) == sizeof directory_element_2;
      offset_2 += sizeof directory_element_2)
    if (directory_element_2.in_use
        && !strcmp (file, directory_element_2.name))
    {
      directory_element_1 = directory_element_2;
      offset_1 = offset_2;
      present = true;
    }

  if (!present)
  {
    inode_close (inode);
    release_inode_lock (directory->inode);
    return false;
  }
  inode = inode_open (directory_element_1.inode_sector);
  if (inode == NULL)
  {
    inode_close (inode);
    release_inode_lock (directory->inode);
    return false;
  }
  if (is_inode_dir (inode) && get_inode_open_cnt (inode) > 1)
  {
    inode_close (inode);
    release_inode_lock (directory->inode);
    return false;
  }
  if (is_inode_dir (inode) && !dir_is_empty (inode))
  {
    inode_close (inode);
    release_inode_lock (directory->inode);
    return false;
  }
  directory_element_1.in_use = false;
  offset_2 = inode_write_at (directory->inode, &directory_element_1,
      sizeof directory_element_1, offset_1);

  if (sizeof directory_element_1 != offset_2)
  {
    inode_close (inode);
    release_inode_lock (directory->inode);
    return false;
  }
  inode_remove (inode);
  inode_close (inode);
  release_inode_lock (directory->inode);
  return true;
}
Exemple #16
0
/* Reads SIZE bytes from FILE into BUFFER,
   starting at offset FILE_OFS in the file.
   Returns the number of bytes actually read,
   which may be less than SIZE if end of file is reached.
   The file's current position is unaffected. */
off_t
file_read_at (struct file *file, void *buffer, off_t size, off_t file_ofs) 
{
  return inode_read_at (file->inode, buffer, size, file_ofs);
}
Exemple #17
0
struct directory *dir_lookup(struct block *d, const char *path){
	char *path_copy, *token, *save_ptr;
	struct directory *cur,*next,*last,*file_ptr;
	struct directory *found = NULL;

	ASSERT(path != NULL);

	// copy path
	path_copy = kmalloc(strlen(path)+1);
	memcpy(path_copy,path,strlen(path)+1);
	
	// start from root
	last = NULL;
	cur = dir_get_root(d);
	ASSERT(cur != NULL);

	// search path
	for(token = strtok_r(path_copy,"/",&save_ptr); token != NULL;
		token = strtok_r(NULL,"/",&save_ptr)){
		// check if current directory is the same as the last
		if(cur == last) {
			file_ptr = NULL;
			break;
		}

		// look up current directory
		file_ptr = dir_lookup_current(cur,token);
		last = cur; //save current directory

		// if file is directory
		if(file_ptr != NULL && file_ptr->inode != 0 && file_ptr->file_type == EXT2_FT_DIR){
			// get file inode, it is temporary
			struct inode *file_ino = ext2_get_inode(d,file_ptr->inode);
			if(file_ino == NULL || (file_ino->i_mode & EXT2_S_IFDIR) == 0){
				file_ptr = NULL;
				if(file_ino != NULL) kfree(file_ino);
				break;
			}

			// read directory file
			next = kmalloc(file_ino->i_size);
			if(next == NULL) {
				file_ptr = NULL;
				kfree(file_ino);
				break;
			}
			inode_read_at(d,file_ino,next,file_ino->i_size,0);		

			// free temporary memory and switch directory
			kfree(file_ino);
			kfree(cur);
			cur = next;
		}
	}

	// file found
	if(file_ptr != NULL && file_ptr->inode != 0){
		found = kmalloc(sizeof(struct directory));
		memcpy(found,file_ptr,sizeof(struct directory));
	}
	
	kfree(cur);
	kfree(path_copy);
	return found;
}