Beispiel #1
0
int find_blockdriver(FAR const char *pathname, int mountflags, FAR struct inode **ppinode)
{
  FAR struct inode *inode;
  int ret = 0; /* Assume success */

  /* Sanity checks */
#ifdef CONFIG_DEBUG
  if (!pathname || !ppinode)
    {
      ret = -EINVAL;
      goto errout;
    }
#endif

  /* Find the inode registered with this pathname */

  inode = inode_find(pathname, NULL);
  if (!inode)
    {
      fdbg("Failed to find %s\n", pathname);
      ret = -ENOENT;
      goto errout;
    }

  /* Verify that the inode is a block driver. */

  if (!INODE_IS_BLOCK(inode))
    { 
      fdbg("%s is not a block driver\n", pathname);
      ret = -ENOTBLK;
      goto errout_with_inode;
   }

  /* Make sure that the inode supports the requested access */

  if (!inode->u.i_bops || !inode->u.i_bops->read ||
      (!inode->u.i_bops->write && (mountflags & MS_RDONLY) == 0))
    {
      fdbg("%s does not support requested access\n", pathname);
      ret = -EACCES;
      goto errout_with_inode;
    }

  *ppinode = inode;
  return OK;

errout_with_inode:
  inode_release(inode);
errout:
  return ret;
}
Beispiel #2
0
int inode_stat(FAR struct inode *inode, FAR struct stat *buf)
{
	DEBUGASSERT(inode != NULL && buf != NULL);

	memset(buf, 0, sizeof(*buf));

	if (INODE_IS_SPECIAL(inode)) {
#if defined(CONFIG_FS_NAMED_SEMAPHORES)
		if (INODE_IS_NAMEDSEM(inode)) {
			buf->st_mode = S_IFSEM;
		} else
#endif
#if !defined(CONFIG_DISABLE_MQUEUE)
		if (INODE_IS_MQUEUE(inode)) {
			buf->st_mode = S_IFMQ;
		} else
#endif
		{
		}
	} else if (inode->u.i_ops != NULL) {
		/* Determine read/write privileges based on the existence of read
		 * and write methods.
		 */
		if (inode->u.i_ops->read) {
			buf->st_mode = S_IROTH | S_IRGRP | S_IRUSR;
		}
		if (inode->u.i_ops->write) {
			buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR;
		}
		/* Determine the type of the inode */
		if (INODE_IS_MOUNTPT(inode)) {
			buf->st_mode |= S_IFDIR;
		} else if (INODE_IS_BLOCK(inode)) {
			/* What is if also has child inodes? */
			buf->st_mode |= S_IFBLK;
		} else /* if (INODE_IS_DRIVER(inode)) */ {
			/* What is it if it also has child inodes? */
			buf->st_mode |= S_IFCHR;
		}
	} else {
		/* If it has no operations, then it must just be a intermediate
		 * node in the inode tree. It is something like a directory.
		 * We'll say that all pseudo-directories are read-able but not
		 * write-able.
		 */
		buf->st_mode |= S_IFDIR | S_IROTH | S_IRGRP | S_IRUSR;
	}

	return OK;
}
Beispiel #3
0
static inline int statpseudo(FAR struct inode *inode, FAR struct stat *buf)
{
  /* Most of the stat entries just do not apply */

  memset(buf, 0, sizeof(struct stat) );
  if (inode->u.i_ops)
    {
      if (inode->u.i_ops->read)
        {
          buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR;
        }

      if (inode->u.i_ops->write)
        {
          buf->st_mode |= S_IWOTH|S_IWGRP|S_IWUSR;
        }

      if (INODE_IS_MOUNTPT(inode))
        {
          buf->st_mode |= S_IFDIR;
        }
      else if (INODE_IS_BLOCK(inode))
        {
          /* What is it also has child inodes? */

          buf->st_mode |= S_IFBLK;
        }
      else
        {
          /* What is it if it also has child inodes? */

          buf->st_mode |= S_IFCHR;
        }
    }
  else
    {
      /* If it has no operations, then it must just be a intermediate
       * node in the inode tree.  It is something like a directory.
       * We'll say that all pseudo-directories are read-able but not
       * write-able.
       */

      buf->st_mode |= S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR;
    }

  return OK;
}
int close_blockdriver(FAR struct inode *inode)
{
  int ret = 0; /* Assume success */

  /* Sanity checks */

#ifdef CONFIG_DEBUG
  if (!inode || !inode->u.i_bops)
    {
      ret = -EINVAL;
      goto errout;
    }
#endif

  /* Verify that the inode is a block driver. */

  if (!INODE_IS_BLOCK(inode))
    { 
      fdbg("inode is not a block driver\n");
      ret = -ENOTBLK;
      goto errout;
   }

  /* Close the block driver.  Not that no mutually exclusive access
   * to the driver is enforced here.  That must be done in the driver
   * if needed.
   */

  if (inode->u.i_bops->close)
    {
      ret = inode->u.i_bops->close(inode);
    }

  /* Then release the reference on the inode */

  inode_release(inode);

errout:
  return ret;
}
Beispiel #5
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;
            }

          /* Notify the driver that it has been unlinked.  If there are no
           * open references to the driver instance, then the driver should
           * release all resources because it is no longer accessible.
           */

          if (INODE_IS_DRIVER(inode) && inode->u.i_ops->unlink)
            {
              /* Notify the character driver that it has been unlinked */

              ret = inode->u.i_ops->unlink(inode);
              if (ret < 0)
                {
                  errcode = -ret;
                  goto errout_with_inode;
                }
            }
#ifndef CONFIG_DISABLE_MOUNTPOINT
          else if (INODE_IS_BLOCK(inode) && inode->u.i_bops->unlink)
            {
              /* Notify the block driver that it has been unlinked */

              ret = inode->u.i_bops->unlink(inode);
              if (ret < 0)
                {
                  errcode = -ret;
                  goto errout_with_inode;
                }
            }
#endif

          /* 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;
}
Beispiel #6
0
static inline int readpsuedodir(struct fs_dirent_s *idir)
{
  FAR struct inode *prev;

  /* Check if we are at the end of the list */

  if (!idir->u.psuedo.fd_next)
    {
      /* End of file and error conditions are not distinguishable
       * with readdir.  Here we return -ENOENT to signal the end
       * of the directory.
       */

      return -ENOENT;
    }

  /* Copy the inode name into the dirent structure */

  strncpy(idir->fd_dir.d_name, idir->u.psuedo.fd_next->i_name, NAME_MAX+1);

  /* If the node has file operations, we will say that it is
   * a file.
   */

  idir->fd_dir.d_type = 0;
  if (idir->u.psuedo.fd_next->u.i_ops)
    {
#ifndef CONFIG_DISABLE_MOUNTPOINT
      if (INODE_IS_BLOCK(idir->u.psuedo.fd_next)) 
        {
           idir->fd_dir.d_type |= DTYPE_BLK;
        }
      if (INODE_IS_MOUNTPT(idir->u.psuedo.fd_next)) 
        {
           idir->fd_dir.d_type |= DTYPE_DIRECTORY;
        }
      else
#endif
        {
           idir->fd_dir.d_type |= DTYPE_CHR;
        }
    }

  /* If the node has child node(s), then we will say that it
   * is a directory.  NOTE: that the node can be both!
   */

  if (idir->u.psuedo.fd_next->i_child || !idir->u.psuedo.fd_next->u.i_ops)
    {
      idir->fd_dir.d_type |= DTYPE_DIRECTORY;
    }

  /* Now get the inode to vist next time that readdir() is called */

  inode_semtake();

  prev                   = idir->u.psuedo.fd_next;
  idir->u.psuedo.fd_next = prev->i_peer; /* The next node to visit */

  if (idir->u.psuedo.fd_next)
    {
      /* Increment the reference count on this next node */

      idir->u.psuedo.fd_next->i_crefs++;
    }

  inode_semgive();

  if (prev)
    {
      inode_release(prev);
    }

  return OK;
}
Beispiel #7
0
int open(const char *path, int oflags, ...)
{
  FAR struct file *filep;
  FAR struct inode *inode;
  FAR const char *relpath = NULL;
#if defined(CONFIG_FILE_MODE) || !defined(CONFIG_DISABLE_MOUNTPOINT)
  mode_t mode = 0666;
#endif
  int ret;
  int fd;

#ifdef CONFIG_FILE_MODE
#  ifdef CONFIG_CPP_HAVE_WARNING
#    warning "File creation not implemented"
#  endif

  /* If the file is opened for creation, then get the mode bits */

  if ((oflags & (O_WRONLY | O_CREAT)) != 0)
    {
      va_list ap;
      va_start(ap, oflags);
      mode = va_arg(ap, mode_t);
      va_end(ap);
    }
#endif

  /* Get an inode for this file */

  inode = inode_find(path, &relpath);
  if (!inode)
    {
      /* "O_CREAT is not set and the named file does not exist.  Or, a
       * directory component in pathname does not exist or is a dangling
       * symbolic link."
       */

      ret = ENOENT;
      goto errout;
    }

#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && \
    !defined(CONFIG_DISABLE_MOUNTPOINT)
   /* If the inode is block driver, then we may return a character driver
    * proxy for the block driver.  block_proxy() will instantiate a BCH
    * character driver wrapper around the block driver, open(), then
    * unlink() the character driver.  On success, block_proxy() will
    * return the file descriptor of the opened character driver.
    *
    * NOTE: This will recurse to open the character driver proxy.
    */

   if (INODE_IS_BLOCK(inode))
     {
       /* Release the inode reference */

       inode_release(inode);

       /* Get the file descriptor of the opened character driver proxy */

       fd = block_proxy(path, oflags);
       if (fd < 0)
         {
           ret = fd;
           goto errout;
         }

       /* Return the file descriptor */

       return fd;
     }
   else
#endif

  /* Verify that the inode is either a "normal" character driver or a
   * mountpoint.  We specifically "special" inodes (semaphores, message
   * queues, shared memory).
   */

#ifndef CONFIG_DISABLE_MOUNTPOINT
  if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops)
#else
  if (!INODE_IS_DRIVER(inode) || !inode->u.i_ops)
#endif
    {
      ret = ENXIO;
      goto errout_with_inode;
    }

  /* Make sure that the inode supports the requested access */

  ret = inode_checkflags(inode, oflags);
  if (ret < 0)
    {
      ret = -ret;
      goto errout_with_inode;
    }

  /* Associate the inode with a file structure */

  fd = files_allocate(inode, oflags, 0, 0);
  if (fd < 0)
    {
      ret = EMFILE;
      goto errout_with_inode;
    }

  /* Get the file structure corresponding to the file descriptor. */

  filep = fs_getfilep(fd);
  if (!filep)
    {
      /* The errno value has already been set */

      return ERROR;
    }

  /* Perform the driver open operation.  NOTE that the open method may be
   * called many times.  The driver/mountpoint logic should handled this
   * because it may also be closed that many times.
   */

  ret = OK;
  if (inode->u.i_ops->open)
    {
#ifndef CONFIG_DISABLE_MOUNTPOINT
      if (INODE_IS_MOUNTPT(inode))
        {
          ret = inode->u.i_mops->open(filep, relpath, oflags, mode);
        }
      else
#endif
        {
          ret = inode->u.i_ops->open(filep);
        }
    }

  if (ret < 0)
    {
      ret = -ret;
      goto errout_with_fd;
    }

  return fd;

errout_with_fd:
  files_release(fd);
errout_with_inode:
  inode_release(inode);
errout:
  set_errno(ret);
  return ERROR;
}