Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
{
  FAR struct inode *inode;
  FAR const char *relpath = NULL;
  FAR struct mqueue_inode_s *msgq;
  char fullpath[MAX_MQUEUE_PATH];
  va_list ap;
  struct mq_attr *attr;
  mqd_t mqdes;
  mode_t mode;
  int errcode;
  int ret;

  /* Make sure that a non-NULL name is supplied */

  if (!mq_name)
    {
      errcode = EINVAL;
      goto errout;
    }

  /* Get the full path to the message queue */

  snprintf(fullpath, MAX_MQUEUE_PATH, CONFIG_FS_MQUEUE_MPATH "/%s", mq_name);

  /* Make sure that the check for the existence of the message queue
   * and the creation of the message queue are atomic with respect to
   * other processes executing mq_open().  A simple sched_lock() should
   * be sufficient.
   */

  sched_lock();

  /* Get the inode for this mqueue.  This should succeed if the message
   * queue has already been created.
   */

  inode = inode_find(fullpath, &relpath);
  if (inode)
    {
      /* It exists.  Verify that the inode is a message queue */

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

      /* It exists and is a message queue.  Check if the caller wanted to
       * create a new mqueue with this name.
       */

      if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
        {
          errcode = EEXIST;
          goto errout_with_inode;
        }

      /* Create a message queue descriptor for the current thread */

      msgq  = inode->u.i_mqueue;
      mqdes = mq_descreate(NULL, msgq, oflags);
      if (!mqdes)
        {
          errcode = ENOMEM;
          goto errout_with_inode;
        }
    }
  else
    {
      /* The mqueue does not exists.  Were we asked to create it? */

      if ((oflags & O_CREAT) == 0)
        {
          /* The mqueue does not exist and O_CREAT is not set */

          errcode = ENOENT;
          goto errout_with_lock;
        }

     /* Create the mqueue.  First we have to extract the additional
      * parameters from the variable argument list.
      */

      va_start(ap, oflags);
      mode = va_arg(ap, mode_t);
      attr = va_arg(ap, FAR struct mq_attr*);
      va_end(ap);

      /* Create an inode in the pseudo-filesystem at this path */

      inode_semtake();
      ret = inode_reserve(fullpath, &inode);
      inode_semgive();

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

      /* Allocate memory for the new message queue. */

      msgq = (FAR struct mqueue_inode_s*)mq_msgqalloc(mode, attr);
      if (!msgq)
        {
          errcode = ENOSPC;
          goto errout_with_inode;
        }

      /* Create a message queue descriptor for the TCB */

       mqdes = mq_descreate(NULL, msgq, oflags);
       if (!mqdes)
         {
           errcode = ENOMEM;
           goto errout_with_msgq;
         }

      /* Bind the message queue and the inode structure */

      INODE_SET_MQUEUE(inode);
      inode->u.i_mqueue = msgq;
      msgq->inode       = inode;

    }

  sched_unlock();
  return mqdes;

errout_with_msgq:
  mq_msgqfree(msgq);
  inode->u.i_mqueue = NULL;
errout_with_inode:
  inode_release(inode);
errout_with_lock:
  sched_unlock();
errout:
  set_errno(errcode);
  return (mqd_t)ERROR;
}
Ejemplo n.º 3
0
int mq_unlink(FAR const char *mq_name)
{
  FAR struct inode *inode;
  FAR const char *relpath = NULL;
  char fullpath[MAX_MQUEUE_PATH];
  int errcode;
  int ret;

  /* Get the full path to the message queue */

  snprintf(fullpath, MAX_MQUEUE_PATH, CONFIG_FS_MQUEUE_MPATH "/%s", mq_name);

  /* Get the inode for this message queue. */

  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 message queue */

  if (!INODE_IS_MQUEUE(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 mq_inode_release().  mq_inode_release
   * will decrement the reference count on the inode.  But it will also free
   * the message queue if that reference count decrements to zero.  Since we
   * hold one reference, that can only occur if the message queue is not
   * in-use.
   */

  inode_semgive();
  mq_inode_release(inode);
  sched_unlock();
  return OK;

errout_with_semaphore:
  inode_semgive();
errout_with_inode:
  inode_release(inode);
errout:
  set_errno(errcode);
  sched_unlock();
  return ERROR;
}