Esempio n. 1
0
/* Removes any entry for NAME in DIR.
   Returns true if successful, false on failure,
   which occurs only if there is no file with the given NAME. */
bool
dir_remove (struct dir *dir, const char *name) 
{
  struct dir_entry e;
  struct inode *inode = NULL;
  bool success = false;
  off_t ofs;

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

  /* Find directory entry. */
  if (!lookup (dir, name, &e, &ofs))
    goto done;

  /* Open inode. */
  inode = inode_open (e.inode_sector);
  if (inode == NULL)
    goto done;

  /* Erase directory entry. */
  e.in_use = false;
  if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) 
    goto done;

  /* Remove inode. */
  inode_remove (inode);
  success = true;

 done:
  inode_close (inode);
  return success;
}
Esempio n. 2
0
int unregister_blockdriver(FAR const char *path)
{
  int ret;

  inode_semtake();
  ret = inode_remove(path);
  inode_semgive();
  return ret;
}
Esempio n. 3
0
/* Removes any entry for NAME in DIR.
   Returns true if successful, false on failure,
   which occurs only if there is no file with the given NAME. */
bool
dir_remove (struct dir *dir, const char *name) 
{
  struct dir_entry e;
  struct inode *inode = NULL;
  bool success = false;
  off_t ofs;

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

  //lock the directory for the rest of the lookup operation
  inode_lock(dir->inode);
  name = getfilename(name);

  /* Find directory entry. */
  if (!lookup (dir, name, &e, &ofs))
    goto done;

  /* Open inode. */
  inode = inode_open (e.inode_sector);
  if (inode == NULL)
    goto done;

  //if it is still open don't allow deletion
  if(inode_type(inode) == FILE_DIR) {
	//is file in use?
	if(inode_opencnt(inode) > 1)
		goto done;
	char * temp = (char *)malloc(sizeof(char) * (NAME_MAX + 1) );
	struct dir * dirtemp = dir_open(inode);
	//is dir empty?
	if (dir_readdir(dirtemp,temp)) {
		free(temp);
		dir_close(dirtemp);
		goto done;
	}
	free(temp);
	dir_close(dirtemp);	
  }

  /* Erase directory entry. */
  e.in_use = false;
  if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) 
    goto done;

  /* Remove inode. */
  inode_remove (inode);
  success = true;

 done:
  //unlock the directory
  inode_unlock(dir->inode);
  inode_close (inode);
  return success;
}
Esempio n. 4
0
/* Deletes NAME from DIR.
   Returns true if successful, false on failure,
   which occurs only if there is no file with the given NAME. */
bool
dir_remove (struct dir *dir, const char *name) 
{
  struct dir_entry e;
  struct inode *inode = NULL;
  bool success = false;
  off_t ofs;

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

  lock_acquire (&dir->l);

  /* Find directory entry. */
  if (!lookup (dir, name, &e, &ofs))
    goto done;

  /* Open inode. */
  inode = inode_open (e.inode_sector);
  if (inode == NULL)
    goto done;

  /* If directory, make sure it's empty */
  if (inode_is_directory (inode))
  {
    struct dir *inner = dir_open (inode_open (e.inode_sector));
    int size = dir_size (inner);
    dir_close (inner);
    if (size != 0)
      goto done;
  }

  /* Erase directory entry. */
  e.in_use = false;
  if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) 
    goto done;

  /* Remove inode. */
  success = inode_remove (inode);

done:
  lock_release (&dir->l);
  inode_close (inode);
  return success;
}
/* Removes any entry for NAME in DIR.
   Returns true if successful, false on failure,
   which occurs only if there is no file with the given NAME. */
bool
dir_remove (struct file *dir, const char *name) 
{
  ASSERT (file_is_dir (dir));
  struct dir_entry e;
  struct inode *inode = NULL;
  bool success = false;
  off_t ofs;
  int sector;

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

  bool locked = file_lock (dir);
  /* Find directory entry. */
  if ((sector = lookup (dir, name, &ofs, &e)) < 0)
    goto done;

  /* Open inode. */
  inode = inode_open (sector);
  if (inode == NULL)
    goto done;

  /* Erase directory entry. */
  e.in_use = false;
  if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) 
    goto done;

  /* Remove inode. */
  inode_remove (inode);
  success = true;

 done:
  if (locked) file_unlock (dir);
  if (inode)  inode_close (inode);
  return success;
}
Esempio n. 6
0
int unlink(FAR const char *pathname)
{
  FAR struct inode *inode;
  const char       *relpath = NULL;
  int               errcode;
  int               ret;

  /* Get an inode for this file */

  inode = inode_find(pathname, &relpath);
  if (!inode)
    {
      /* There is no inode that includes in this path */

      errcode = ENOENT;
      goto errout;
    }

#ifndef CONFIG_DISABLE_MOUNTPOINT
  /* Check if the inode is a valid mountpoint. */

  if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
    {
      /* Perform the unlink operation using the relative path at the
       * mountpoint.
       */

      if (inode->u.i_mops->unlink)
        {
          ret = inode->u.i_mops->unlink(inode, relpath);
          if (ret < 0)
            {
              errcode = -ret;
              goto errout_with_inode;
            }
        }
      else
        {
          errcode = ENOSYS;
          goto errout_with_inode;
        }
    }
  else
#endif

#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  /* If this is a "dangling" pseudo-file node (i.e., it has operations) then rm
   * should remove the node.
   */

  if (!INODE_IS_SPECIAL(inode) && inode->u.i_ops)
    {
      /* If this is a pseudo-file node (i.e., it has no operations)
       * then rmdir should remove the node.
       */

      if (inode->u.i_ops)
        {
          inode_semtake();

          /* Refuse to unlink the inode if it has children.  I.e., if it is
           * functioning as a directory and the directory is not empty.
           */

          if (inode->i_child != NULL)
            {
              errcode = ENOTEMPTY;
              inode_semgive();
              goto errout_with_inode;
            }

          /* Remove the old inode.  Because we hold a reference count on the
           * inode, it will not be deleted now.  It will be deleted when all
           * of the references to to the inode have been released (perhaps
           * when inode_release() is called below).  inode_remove() will
           * return -EBUSY to indicate that the inode was not deleted now.
           */

          ret = inode_remove(pathname);
          inode_semgive();

          if (ret < 0 && ret != -EBUSY)
            {
              errcode = -ret;
              goto errout_with_inode;
            }
        }
      else
        {
          errcode = EISDIR;
          goto errout_with_inode;
        }
    }
  else
#endif
    {
      errcode = ENXIO;
      goto errout_with_inode;
    }

  /* Successfully unlinked */

  inode_release(inode);
  return OK;

 errout_with_inode:
  inode_release(inode);
 errout:
  set_errno(errcode);
  return ERROR;
}
Esempio n. 7
0
int sem_unlink(FAR const char *name)
{
  FAR struct inode *inode;
  FAR const char *relpath = NULL;
  char fullpath[MAX_SEMPATH];
  int errcode;
  int ret;

  /* Get the full path to the semaphore */

  snprintf(fullpath, MAX_SEMPATH, CONFIG_FS_NAMED_SEMPATH "/%s", name);

  /* Get the inode for this semaphore. */

  sched_lock();
  inode = inode_find(fullpath, &relpath);
  if (!inode)
    {
      /* There is no inode that includes in this path */

      errcode = ENOENT;
      goto errout;
    }

  /* Verify that what we found is, indeed, a semaphore */

  if (!INODE_IS_NAMEDSEM(inode))
    {
      errcode = ENXIO;
      goto errout_with_inode;
    }

  /* Refuse to unlink the inode if it has children.  I.e., if it is
   * functioning as a directory and the directory is not empty.
   */

  inode_semtake();
  if (inode->i_child != NULL)
    {
      errcode = ENOTEMPTY;
      goto errout_with_semaphore;
    }

  /* Remove the old inode from the tree.  Because we hold a reference count
   * on the inode, it will not be deleted now.  This will set the
   * FSNODEFLAG_DELETED bit in the inode flags.
   */

  ret = inode_remove(fullpath);

  /* inode_remove() should always fail with -EBUSY because we hae a reference
   * on the inode.  -EBUSY means taht the inode was, indeed, unlinked but
   * thatis could not be freed because there are refrences.
   */

  DEBUGASSERT(ret >= 0 || ret == -EBUSY);
  UNUSED(ret);

  /* Now we do not release the reference count in the normal way (by calling
   * inode release.  Rather, we call sem_close().  sem_close will decrement
   * the reference count on the inode.  But it will also free the semaphore
   * if that reference count decrements to zero.  Since we hold one reference,
   * that can only occur if the semaphore is not in-use.
   */

  inode_semgive();
  ret = sem_close((FAR sem_t *)inode->u.i_nsem);
  sched_unlock();
  return ret;

errout_with_semaphore:
  inode_semgive();
errout_with_inode:
  inode_release(inode);
errout:
  set_errno(errcode);
  sched_unlock();
  return ERROR;
}
Esempio n. 8
0
int mount(const char *source, const char *target,
          const char *filesystemtype, unsigned long mountflags,
          const void *data)
{
#if defined(BDFS_SUPPORT) || defined(NONBDFS_SUPPORT)
#ifdef BDFS_SUPPORT
  FAR struct inode *blkdrvr_inode = NULL;
#endif
  FAR struct inode *mountpt_inode;
  FAR const struct mountpt_operations *mops;
  void *fshandle;
  int errcode;
  int status;

  /* Verify required pointer arguments */

  DEBUGASSERT(target && filesystemtype);

  /* Find the specified filesystem.  Try the block driver file systems first */

#ifdef BDFS_SUPPORT
  if ((mops = mount_findfs(g_bdfsmap, filesystemtype)) != NULL)
    {
      /* Make sure that a block driver argument was provided */

      DEBUGASSERT(source);

      /* Find the block driver */

      status = find_blockdriver(source, mountflags, &blkdrvr_inode);
      if (status < 0)
        {
           fdbg("Failed to find block driver %s\n", source);
           errcode = -status;
           goto errout;
        }
    }
  else
#endif /* BDFS_SUPPORT */
#ifdef NONBDFS_SUPPORT
  if ((mops = mount_findfs(g_nonbdfsmap, filesystemtype)) != NULL)
    {
    }
  else
#endif /* NONBDFS_SUPPORT */
    {
      fdbg("Failed to find file system %s\n", filesystemtype);
      errcode = ENODEV;
      goto errout;
    }

   /* Insert a dummy node -- we need to hold the inode semaphore
   * to do this because we will have a momentarily bad structure.
   */

  inode_semtake();
  mountpt_inode = inode_reserve(target);
  if (!mountpt_inode)
    {
      /* inode_reserve can fail for a couple of reasons, but the most likely
       * one is that the inode already exists.
       */

      fdbg("Failed to reserve inode\n");
      errcode = EBUSY;
      goto errout_with_semaphore;
    }

  /* Bind the block driver to an instance of the file system.  The file
   * system returns a reference to some opaque, fs-dependent structure
   * that encapsulates this binding.
   */

  if (!mops->bind)
    {
      /* The filesystem does not support the bind operation ??? */

      fdbg("Filesystem does not support bind\n");
      errcode = EINVAL;
      goto errout_with_mountpt;
    }

  /* Increment reference count for the reference we pass to the file system */

#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
  if (blkdrvr_inode)
#endif
    {
      blkdrvr_inode->i_crefs++;
    }
#endif

  /* On failure, the bind method returns -errorcode */

#ifdef BDFS_SUPPORT
  status = mops->bind(blkdrvr_inode, data, &fshandle);
#else
  status = mops->bind(NULL, data, &fshandle);
#endif
  if (status != 0)
  {
      /* The inode is unhappy with the blkdrvr for some reason.  Back out
       * the count for the reference we failed to pass and exit with an
       * error.
       */

      fdbg("Bind method failed: %d\n", status);
#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
      if (blkdrvr_inode)
#endif
        {
          blkdrvr_inode->i_crefs--;
        }
#endif
      errcode = -status;
      goto errout_with_mountpt;
  }

  /* We have it, now populate it with driver specific information. */

  INODE_SET_MOUNTPT(mountpt_inode);

  mountpt_inode->u.i_mops  = mops;
#ifdef CONFIG_FILE_MODE
  mountpt_inode->i_mode    = mode;
#endif
  mountpt_inode->i_private = fshandle;
  inode_semgive();

 /* We can release our reference to the blkdrver_inode, if the filesystem
  * wants to retain the blockdriver inode (which it should), then it must
  * have called inode_addref().  There is one reference on mountpt_inode
  * that will persist until umount() is called.
  */

#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
  if (blkdrvr_inode)
#endif
    {
      inode_release(blkdrvr_inode);
    }
#endif
  return OK;

  /* A lot of goto's!  But they make the error handling much simpler */

errout_with_mountpt:
  mountpt_inode->i_crefs = 0;
  inode_remove(target);
  inode_semgive();
#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
  if (blkdrvr_inode)
#endif
    {
       inode_release(blkdrvr_inode);
    }
#endif
  inode_release(mountpt_inode);
  goto errout;

errout_with_semaphore:
  inode_semgive();
#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
  if (blkdrvr_inode)
#endif
    {
      inode_release(blkdrvr_inode);
    }
#endif

errout:
  errno = errcode;
  return ERROR;

#else
  fdbg("No filesystems enabled\n");
  ernno = ENOSYS;
  return error;
#endif /* BDFS_SUPPORT || NONBDFS_SUPPORT */
}
Esempio n. 9
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;
}
Esempio n. 10
0
int rename(FAR const char *oldpath, FAR const char *newpath)
{
  FAR struct inode *oldinode;
  FAR struct inode *newinode;
  const char       *oldrelpath = NULL;
#ifndef CONFIG_DISABLE_MOUNTPOINT
  const char       *newrelpath = NULL;
#endif
  int               errcode;
  int               ret;

  /* Ignore paths that are interpreted as the root directory which has no name
   * and cannot be moved
   */

  if (!oldpath || *oldpath == '\0' || oldpath[0] != '/' ||
      !newpath || *newpath == '\0' || newpath[0] != '/')
    {
      return -EINVAL;
    }

  /* Get an inode that includes the oldpath */

  oldinode = inode_find(oldpath, &oldrelpath);
  if (!oldinode)
    {
      /* There is no inode that includes in this path */

      errcode = ENOENT;
      goto errout;
    }

#ifndef CONFIG_DISABLE_MOUNTPOINT
  /* Verify that the old inode is a valid mountpoint. */

  if (INODE_IS_MOUNTPT(oldinode) && oldinode->u.i_mops)
    {
      /* Get an inode for the new relpath -- it should like on the same
       * mountpoint
       */

      newinode = inode_find(newpath, &newrelpath);
      if (!newinode)
        {
          /* There is no mountpoint that includes in this path */

          errcode = ENOENT;
          goto errout_with_oldinode;
        }

      /* Verify that the two paths lie on the same mountpoint inode */

      if (oldinode != newinode)
        {
          errcode = EXDEV;
          goto errout_with_newinode;
        }

      /* Perform the rename operation using the relative paths
       * at the common mountpoint.
       */

      if (oldinode->u.i_mops->rename)
        {
          ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath);
          if (ret < 0)
            {
              errcode = -ret;
              goto errout_with_newinode;
            }
        }
      else
        {
          errcode = ENOSYS;
          goto errout_with_newinode;
        }

      /* Successfully renamed */

      inode_release(newinode);
    }
  else
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
    {
      /* Create a new, empty inode at the destination location.
       * NOTE that the new inode will be created with a reference count
       * of  zero.
       */

      inode_semtake();
      ret = inode_reserve(newpath, &newinode);
      if (ret < 0)
        {
          /* It is an error if a node at newpath already exists in the tree
           * OR if we fail to allocate memory for the new inode (and possibly
           * any new intermediate path segments).
           */

          inode_semgive();
          errcode = EEXIST;
          goto errout_with_oldinode;
        }

      /* Copy the inode state from the old inode to the newly allocated inode */

      newinode->i_child   = oldinode->i_child;   /* Link to lower level inode */
      newinode->i_flags   = oldinode->i_flags;   /* Flags for inode */
      newinode->u.i_ops   = oldinode->u.i_ops;   /* Inode operations */
#ifdef CONFIG_FILE_MODE
      newinode->i_mode    = oldinode->i_mode;    /* Access mode flags */
#endif
      newinode->i_private = oldinode->i_private; /* Per inode driver private data */

      /* We now have two copies of the inode.  One with a reference count of
       * zero (the new one), and one that may have multiple references
       * including one by this logic (the old one)
       *
       * Remove the old inode.  Because we hold a reference count on the
       * inode, it will not be deleted now.  It will be deleted when all of
       * the references to to the inode have been released (perhaps when
       * inode_release() is called below).  inode_remove() should return
       * -EBUSY to indicate that the inode was not deleted now.
       */

      ret = inode_remove(oldpath);
      if (ret < 0 && ret != -EBUSY)
        {
          /* Remove the new node we just recreated */

          (void)inode_remove(newpath);
          inode_semgive();

          errcode = -ret;
          goto errout_with_oldinode;
        }

      /* Remove all of the children from the unlinked inode */

      oldinode->i_child = NULL;
      inode_semgive();
    }
#else
    {
      errcode = ENXIO;
      goto errout;
    }
#endif

  /* Successfully renamed */

  inode_release(oldinode);
  return OK;

#ifndef CONFIG_DISABLE_MOUNTPOINT
errout_with_newinode:
  inode_release(newinode);
#endif
errout_with_oldinode:
  inode_release(oldinode);
errout:
  set_errno(errcode);
  return ERROR;
}
Esempio n. 11
0
int umount(const char *target)
{
  FAR struct inode *mountpt_inode;
  FAR struct inode *blkdrvr_inode = NULL;
  int errcode = OK;
  int status;

  /* Verify required pointer arguments */

  if (!target)
    {
      errcode = EFAULT;
      goto errout;
    }

  /* Find the mountpt */

  mountpt_inode = inode_find(target, NULL);
  if (!mountpt_inode)
    {
      errcode = ENOENT;
      goto errout;
    }

  /* Verify that the inode is a mountpoint */

  if (!INODE_IS_MOUNTPT(mountpt_inode))
    {
      errcode = EINVAL;
      goto errout_with_mountpt;
    }

  /* Unbind the block driver from the file system (destroying any fs
   * private data.
   */

  if (!mountpt_inode->u.i_mops->unbind)
    {
      /* The filesystem does not support the unbind operation ??? */

      errcode = EINVAL;
      goto errout_with_mountpt;
    }

  /* The unbind method returns the number of references to the
   * filesystem (i.e., open files), zero if the unbind was
   * performed, or a negated error code on a failure.
   */

  inode_semtake(); /* Hold the semaphore through the unbind logic */
  status = mountpt_inode->u.i_mops->unbind( mountpt_inode->i_private, &blkdrvr_inode);
  if (status < 0)
    {
      /* The inode is unhappy with the blkdrvr for some reason */

      errcode = -status;
      goto errout_with_semaphore;
    }
  else if (status > 0)
    {
      errcode = EBUSY;
      goto errout_with_semaphore;
    }

  /* Successfully unbound */

  mountpt_inode->i_private = NULL;

  /* Successfully unbound, remove the mountpoint inode from
   * the inode tree.  The inode will not be deleted yet because
   * there is still at least reference on it (from the mount)
   */

  status = inode_remove(target);
  inode_semgive();

  /* The return value of -EBUSY is normal (in fact, it should
   * not be OK)
   */

  if (status != OK && status != -EBUSY)
    {
      errcode = -status;
      goto errout_with_mountpt;
    }

  /* Release the mountpoint inode and any block driver inode
   * returned by the file system unbind above.  This should cause
   * the inode to be deleted (unless there are other references)
   */

  inode_release(mountpt_inode);

  /* Did the unbind method return a contained block driver */

  if (blkdrvr_inode)
    {
      inode_release(blkdrvr_inode);
    }

  return OK;

  /* A lot of goto's!  But they make the error handling much simpler */

errout_with_semaphore:
  inode_semgive();
errout_with_mountpt:
  inode_release(mountpt_inode);
  if (blkdrvr_inode)
    {
      inode_release(blkdrvr_inode);
    }
errout:
  set_errno(errcode);
  return ERROR;
}
Esempio n. 12
0
int umount2(FAR const char *target, unsigned int flags)
{
  FAR struct inode *mountpt_inode;
  FAR struct inode *blkdrvr_inode = NULL;
  struct inode_search_s desc;
  int errcode = OK;
  int ret;

  /* Verify required pointer arguments */

  if (!target)
    {
      errcode = EFAULT;
      goto errout;
    }

  /* Find the mountpt */

  SETUP_SEARCH(&desc, target, false);

  ret = inode_find(&desc);
  if (ret < 0)
    {
      errcode = ENOENT;
      goto errout_with_search;
    }

  /* Get the search results */

  mountpt_inode = desc.node;
  DEBUGASSERT(mountpt_inode != NULL);

  /* Verify that the inode is a mountpoint */

  if (!INODE_IS_MOUNTPT(mountpt_inode))
    {
      errcode = EINVAL;
      goto errout_with_mountpt;
    }

  /* Unbind the block driver from the file system (destroying any fs
   * private data.
   */

  if (!mountpt_inode->u.i_mops->unbind)
    {
      /* The filesystem does not support the unbind operation ??? */

      errcode = EINVAL;
      goto errout_with_mountpt;
    }

  /* The unbind method returns the number of references to the
   * filesystem (i.e., open files), zero if the unbind was
   * performed, or a negated error code on a failure.
   */

  inode_semtake(); /* Hold the semaphore through the unbind logic */
  ret = mountpt_inode->u.i_mops->unbind(mountpt_inode->i_private,
                                       &blkdrvr_inode, flags);
  if (ret < 0)
    {
      /* The inode is unhappy with the blkdrvr for some reason */

      errcode = -ret;
      goto errout_with_semaphore;
    }
  else if (ret > 0)
    {
      errcode = EBUSY;
      goto errout_with_semaphore;
    }

  /* Successfully unbound.  Convert the mountpoint inode to regular
   * pseudo-file inode.
   */


  mountpt_inode->i_flags  &= ~FSNODEFLAG_TYPE_MASK;
  mountpt_inode->i_private = NULL;
  mountpt_inode->u.i_mops  = NULL;

#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  /* If the node has children, then do not delete it. */

  if (mountpt_inode->i_child != NULL)
    {
       /* Just decrement the reference count (without deleting it) */

       DEBUGASSERT(mountpt_inode->i_crefs > 0);
       mountpt_inode->i_crefs--;
    }
  else
#endif
    {
      /* Remove the mountpoint inode from the inode tree.  The inode will
       * not be deleted yet because there is still at least reference on
       * it (from the mount)
       */

      ret = inode_remove(target);
      inode_semgive();

      /* The return value of -EBUSY is normal (in fact, it should
       * not be OK)
       */

      if (ret != OK && ret != -EBUSY)
        {
          errcode = -ret;
          goto errout_with_mountpt;
       }

      /* Release the mountpoint inode and any block driver inode
       * returned by the file system unbind above.  This should cause
       * the inode to be deleted (unless there are other references)
       */

      inode_release(mountpt_inode);
    }

  /* Did the unbind method return a contained block driver */

  if (blkdrvr_inode)
    {
      inode_release(blkdrvr_inode);
    }

  RELEASE_SEARCH(&desc);
  return OK;

  /* A lot of goto's!  But they make the error handling much simpler */

errout_with_semaphore:
  inode_semgive();

errout_with_mountpt:
  inode_release(mountpt_inode);
  if (blkdrvr_inode)
    {
      inode_release(blkdrvr_inode);
    }

errout_with_search:
  RELEASE_SEARCH(&desc);

errout:
  set_errno(errcode);
  return ERROR;
}
Esempio n. 13
0
int rmdir(FAR const char *pathname)
{
  FAR struct inode *inode;
  const char       *relpath = NULL;
  int               errcode;

  /* Get an inode for this file.  inode_find() automatically increments the
   * reference count on the inode if one is found.
   */

  inode = inode_find(pathname, &relpath);
  if (!inode)
    {
      /* There is no inode that includes in this path */

      errcode = ENOENT;
      goto errout;
    }

#ifndef CONFIG_DISABLE_MOUNTPOINT
  /* Check if the inode is a valid mountpoint. */

  if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
    {
      /* Perform the rmdir operation using the relative path
       * from the mountpoint.
       */

      if (inode->u.i_mops->rmdir)
        {
          int ret = inode->u.i_mops->rmdir(inode, relpath);
          if (ret < 0)
            {
              errcode = -ret;
              goto errout_with_inode;
            }
        }
      else
        {
          errcode = ENOSYS;
          goto errout_with_inode;
        }
    }
  else
#endif

#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  /* If this is a "dangling" pseudo-directory node (i.e., it has no operations)
   * then rmdir should remove the node.
   */

  if (!inode->u.i_ops)
    {
      int ret;

      /* If the directory inode has children, however, then it cannot be
       * removed.
       */

      if (inode->i_child)
        {
          errcode = ENOTEMPTY;
          goto errout_with_inode;
        }

      /* Remove the inode.  NOTE: Because we hold a reference count on the
       * inode, it will not be deleted now.  But probably when inode_release()
       * is called below.  inode_remove should return -EBUSY to indicate that
       * the inode was not deleted now.
       */

      inode_semtake();
      ret = inode_remove(pathname);
      inode_semgive();

      if (ret < 0 && ret != -EBUSY)
        {
          errcode = -ret;
          goto errout_with_inode;
        }
    }
  else
    {
      errcode = ENOTDIR;
      goto errout_with_inode;
    }
#else
    {
      errcode = ENXIO;
      goto errout_with_inode;
    }
#endif

  /* Successfully removed the directory */

  inode_release(inode);
  return OK;

errout_with_inode:
  inode_release(inode);
errout:
  set_errno(errcode);
  return ERROR;
}
Esempio n. 14
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;
}