int register_driver(FAR const char *path, FAR const struct file_operations *fops, mode_t mode, FAR void *priv) { FAR struct inode *node; int ret; /* Insert a dummy node -- we need to hold the inode semaphore because we * will have a momentarily bad structure. */ inode_semtake(); ret = inode_reserve(path, &node); if (ret >= 0) { /* We have it, now populate it with driver specific information. */ INODE_SET_DRIVER(node); node->u.i_ops = fops; #ifdef CONFIG_FILE_MODE node->i_mode = mode; #endif node->i_private = priv; ret = OK; } inode_semgive(); return ret; }
int register_blockdriver(const char *path, const struct block_operations *bops, mode_t mode, void *priv) { struct inode *node; int ret = -ENOMEM; /* Insert an inode for the device driver -- we need to hold the inode semaphore * to prevent access to the tree while we this. This is because we will have a * momentarily bad true until we populate the inode with valid data. */ inode_semtake(); node = inode_reserve(path); if (node != NULL) { /* We have it, now populate it with block driver specific * information. */ INODE_SET_BLOCK(node); node->u.i_bops = bops; #ifdef CONFIG_FILE_MODE node->i_mode = mode; #endif node->i_private = priv; ret = OK; } inode_semgive(); return ret; }
int register_blockdriver(FAR const char *path, FAR const struct block_operations *bops, mode_t mode, FAR void *priv) { FAR struct inode *node; int ret; /* Insert an inode for the device driver -- we need to hold the inode * semaphore to prevent access to the tree while we this. This is because * we will have a momentarily bad true until we populate the inode with * valid data. */ inode_semtake(); ret = inode_reserve(path, &node); if (ret >= 0) { /* We have it, now populate it with block driver specific information. * NOTE that the initial reference count on the new inode is zero. */ INODE_SET_BLOCK(node); node->u.i_bops = bops; #ifdef CONFIG_FILE_MODE node->i_mode = mode; #endif node->i_private = priv; ret = OK; } inode_semgive(); return ret; }
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; }
int mkdir(const char *pathname, mode_t mode) { FAR struct inode *inode; const char *relpath = NULL; int errcode; int ret; /* Find the inode that includes this path */ inode = inode_find(pathname, &relpath); if (inode) { /* An inode was found that includes this path and possibly refers to a * mountpoint. */ #ifndef CONFIG_DISABLE_MOUNTPOINT /* Check if the inode is a valid mountpoint. */ if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops) { /* The inode is not a mountpoint */ errcode = ENXIO; goto errout_with_inode; } /* Perform the mkdir operation using the relative path * at the mountpoint. */ if (inode->u.i_mops->mkdir) { ret = inode->u.i_mops->mkdir(inode, relpath, mode); if (ret < 0) { errcode = -ret; goto errout_with_inode; } } else { errcode = ENOSYS; goto errout_with_inode; } /* Release our reference on the inode */ inode_release(inode); #else /* But mountpoints are not supported in this configuration */ errcode = EEXIST; goto errout_with_inode; #endif } #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS /* No inode exists that contains this path. Create a new inode in the * pseudo-filesystem at this location. */ else { /* Create an inode in the pseudo-filesystem at this path */ inode_semtake(); ret = inode_reserve(pathname, &inode); inode_semgive(); if (ret < 0) { errcode = -ret; goto errout; } } #else else {
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 */ }
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; }