diff --git a/Documentation/NuttxUserGuide.html b/Documentation/NuttxUserGuide.html
index 5f1b35ca946..35032cc8201 100644
--- a/Documentation/NuttxUserGuide.html
+++ b/Documentation/NuttxUserGuide.html
@@ -479,14 +479,14 @@ int task_delete(pid_t pid);
Description:
This function causes a specified task to cease to exist.
- Its stack and TCB will be deallocated.
+ Its stack and TCB will be deallocated.
This function is the companion to task_create().
This is the version of the function exposed to the user;
it is simply a wrapper around the internal, task_terminate() function.
The logic in this function only deletes non-running tasks.
- If the pid parameter refers to to the currently runing task, then processing is redirected to exit().
+ If the pid parameter refers to to the currently runing task, then processing is redirected to exit().
This can only happen if a task calls task_delete() in order to delete itself.
@@ -6223,7 +6223,7 @@ interface of the same name.
Description:
The pthread_cancel() function will request that thread be canceled.
-The target thread's cancelability state, enabled, or disabled, determines when the cancellation takes effect: When the cancellation is acted on, thread will be terminated.
+The target thread's cancelability state, enabled, or disabled, determines when the cancellation takes effect: When the cancellation is acted on, thread will be terminated.
When cancelability is disabled, all cancellations are held pending in the target thread until the thread re-enables cancelability.
The target thread's cancelability state determines how the cancellation is acted on:
@@ -6592,16 +6592,16 @@ interface of the same name.
sched_ss_low_priority
- Low scheduling priority for sporadic server.
+ Low scheduling priority for sporadic server.
sched_ss_repl_period
- Replenishment period for sporadic server.
+ Replenishment period for sporadic server.
sched_ss_init_budget
- Initial budget for sporadic server.
+ Initial budget for sporadic server.
sched_ss_max_repl
- Maximum pending replenishments for sporadic server.
+ Maximum pending replenishments for sporadic server.
@@ -8584,6 +8584,8 @@ int telldir(FAR DIR *dirp);
#include <unistd.h>
+/* Task Control Interfaces */
+
pid_t vfork(void);
pid_t getpid(void);
void _exit(int status) noreturn_function;
@@ -8591,6 +8593,8 @@ unsigned int sleep(unsigned int seconds);
void usleep(unsigned long usec);
int pause(void);
+/* File descriptor operations */
+
int close(int fd);
int dup(int fd);
int dup2(int fd1, int fd2);
@@ -8598,21 +8602,58 @@ int fsync(int fd);
off_t lseek(int fd, off_t offset, int whence);
ssize_t read(int fd, FAR void *buf, size_t nbytes);
ssize_t write(int fd, FAR const void *buf, size_t nbytes);
+ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset);
+ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset);
+
+/* Check if a file descriptor corresponds to a terminal I/O file */
+
+int isatty(int fd);
+
+/* Memory management */
+
+#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_PGALLOC) && \
+ defined(CONFIG_ARCH_USE_MMU)
+FAR void *sbrk(intptr_t incr);
+#endif
+
+/* Special devices */
int pipe(int fd[2]);
+/* Working directory operations */
+
int chdir(FAR const char *path);
FAR char *getcwd(FAR char *buf, size_t size);
-int unlink(FAR const char *pathname);
+/* File path operations */
+
+int access(FAR const char *path, int amode);
int rmdir(FAR const char *pathname);
+int unlink(FAR const char *pathname);
+
+#ifdef CONFIG_PSEUDOFS_SOFTLINKS
+int link(FAR const char *path1, FAR const char *path2);
+ssize_t readlink(FAR const char *path, FAR char *buf, size_t bufsize);
+#endif
+
+/* Execution of programs from files */
#ifdef CONFIG_LIBC_EXECFUNCS
int execl(FAR const char *path, ...);
int execv(FAR const char *path, FAR char *const argv[]);
#endif
+/* Networking */
+
+#ifdef CONFIG_NET
+int gethostname(FAR char *name, size_t size);
+int sethostname(FAR const char *name, size_t size);
+#endif
+
+/* Other */
+
int getopt(int argc, FAR char *const argv[], FAR const char *optstring);
+
diff --git a/fs/Kconfig b/fs/Kconfig
index 1bd8d5f945f..05ab5daea93 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -43,7 +43,7 @@ config DISABLE_PSEUDOFS_OPERATIONS
config PSEUDOFS_SOFTLINKS
bool "Pseudo-filesystem soft links"
default n
- depends on !DISABLE_PSEUDOFS_OPERATIONSi && EXPERIMENTAL
+ depends on !DISABLE_PSEUDOFS_OPERATIONS
---help---
Enable support for soft links in the pseudeo file system. Soft
links are not supported within mounted volumes by any NuttX file
diff --git a/fs/dirent/fs_opendir.c b/fs/dirent/fs_opendir.c
index 91a49ba9375..62b39d44102 100644
--- a/fs/dirent/fs_opendir.c
+++ b/fs/dirent/fs_opendir.c
@@ -235,6 +235,8 @@ FAR DIR *opendir(FAR const char *path)
* request for the root inode.
*/
+ SETUP_SEARCH(&desc, path, false);
+
inode_semtake();
if (path == NULL || *path == '\0' || strcmp(path, "/") == 0)
{
@@ -253,9 +255,6 @@ FAR DIR *opendir(FAR const char *path)
/* Find the node matching the path. */
- RESET_SEARCH(&desc);
- desc.path = path;
-
ret = inode_search(&desc);
if (ret >= 0)
{
@@ -357,6 +356,7 @@ FAR DIR *opendir(FAR const char *path)
}
}
+ RELEASE_SEARCH(&desc);
inode_semgive();
return ((FAR DIR *)dir);
@@ -366,6 +366,7 @@ errout_with_direntry:
kumm_free(dir);
errout_with_semaphore:
+ RELEASE_SEARCH(&desc);
inode_semgive();
set_errno(ret);
return NULL;
diff --git a/fs/driver/fs_findblockdriver.c b/fs/driver/fs_findblockdriver.c
index 5376c7b5a1a..0615a474b23 100644
--- a/fs/driver/fs_findblockdriver.c
+++ b/fs/driver/fs_findblockdriver.c
@@ -89,22 +89,20 @@ int find_blockdriver(FAR const char *pathname, int mountflags, FAR struct inode
#ifdef CONFIG_DEBUG_FEATURES
if (!pathname || !ppinode)
{
- ret = -EINVAL;
- goto errout;
+ return -EINVAL;
}
#endif
/* Find the inode registered with this pathname */
- RESET_SEARCH(&desc);
- desc.path = pathname;
+ SETUP_SEARCH(&desc, pathname, false);
ret = inode_find(&desc);
if (ret < 0)
{
ferr("ERROR: Failed to find %s\n", pathname);
ret = -ENOENT;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -132,10 +130,12 @@ int find_blockdriver(FAR const char *pathname, int mountflags, FAR struct inode
}
*ppinode = inode;
+ RELEASE_SEARCH(&desc);
return OK;
errout_with_inode:
inode_release(inode);
-errout:
+errout_with_search:
+ RELEASE_SEARCH(&desc);
return ret;
}
diff --git a/fs/fat/fs_fat32attrib.c b/fs/fat/fs_fat32attrib.c
index 3dc4712d0e7..0dd9b60a2ed 100644
--- a/fs/fat/fs_fat32attrib.c
+++ b/fs/fat/fs_fat32attrib.c
@@ -61,25 +61,25 @@ static int fat_attrib(const char *path, fat_attrib_t *retattrib,
fat_attrib_t setbits, fat_attrib_t clearbits)
{
struct fat_mountpt_s *fs;
- struct fat_dirinfo_s dirinfo;
+ struct fat_dirinfo_s dirinfo;
struct inode_search_s desc;
- FAR struct inode *inode;
- uint8_t *direntry;
- uint8_t oldattributes;
- uint8_t newattributes;
- int ret;
+ FAR struct inode *inode;
+ uint8_t *direntry;
+ uint8_t oldattributes;
+ uint8_t newattributes;
+ int status;
+ int ret;
/* Find the inode for this file */
- RESET_SEARCH(&desc);
- desc.path = path;
+ SETUP_SEARCH(&desc, path, false);
- ret = inode_find(&desc);
- if (ret < 0)
+ status = inode_find(&desc);
+ if (status < 0)
{
/* There is no mountpoint that includes in this path */
- ret = ENOENT;
+ ret = -status;
goto errout;
}
@@ -165,14 +165,18 @@ static int fat_attrib(const char *path, fat_attrib_t *retattrib,
fat_semgive(fs);
inode_release(inode);
+ RELEASE_SEARCH(&desc);
return OK;
errout_with_semaphore:
fat_semgive(fs);
+
errout_with_inode:
inode_release(inode);
+
errout:
- *get_errno_ptr() = ret;
+ RELEASE_SEARCH(&desc);
+ set_errno(ret);
return ERROR;
}
diff --git a/fs/inode/fs_inoderemove.c b/fs/inode/fs_inoderemove.c
index 49d7f84750b..7da8235964e 100644
--- a/fs/inode/fs_inoderemove.c
+++ b/fs/inode/fs_inoderemove.c
@@ -83,11 +83,7 @@ FAR struct inode *inode_unlink(FAR const char *path)
/* Find the node to unlink */
- RESET_SEARCH(&desc);
- desc.path = path;
-#ifdef CONFIG_PSEUDOFS_SOFTLINKS
- desc.nofollow = true;
-#endif
+ SETUP_SEARCH(&desc, path, true);
ret = inode_search(&desc);
if (ret >= 0)
@@ -123,6 +119,7 @@ FAR struct inode *inode_unlink(FAR const char *path)
node->i_peer = NULL;
}
+ RELEASE_SEARCH(&desc);
return node;
}
diff --git a/fs/inode/fs_inodereserve.c b/fs/inode/fs_inodereserve.c
index ecd3a564154..1c08b055676 100644
--- a/fs/inode/fs_inodereserve.c
+++ b/fs/inode/fs_inodereserve.c
@@ -183,8 +183,7 @@ int inode_reserve(FAR const char *path, FAR struct inode **inode)
/* Find the location to insert the new subtree */
- RESET_SEARCH(&desc);
- desc.path = path;
+ SETUP_SEARCH(&desc, path, false);
ret = inode_search(&desc);
if (ret >= 0)
@@ -193,7 +192,8 @@ int inode_reserve(FAR const char *path, FAR struct inode **inode)
* lies within a mountpoint, we don't distinguish here).
*/
- return -EEXIST;
+ ret = -EEXIST;
+ goto errout_with_search;
}
/* Now we now where to insert the subtree */
@@ -236,12 +236,18 @@ int inode_reserve(FAR const char *path, FAR struct inode **inode)
{
inode_insert(node, left, parent);
*inode = node;
- return OK;
+ ret = OK;
+ break;
}
}
/* We get here on failures to allocate node memory */
- return -ENOMEM;
+ ret = -ENOMEM;
+ break;
}
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
+ return ret;
}
diff --git a/fs/inode/fs_inodesearch.c b/fs/inode/fs_inodesearch.c
index b92d30963e6..82ebafd8b48 100644
--- a/fs/inode/fs_inodesearch.c
+++ b/fs/inode/fs_inodesearch.c
@@ -180,9 +180,8 @@ static int _inode_linktarget(FAR struct inode *node,
{
/* Reset and reinitialize the search descriptor. */
- RESET_SEARCH(desc);
- desc->path = (FAR const char *)node->u.i_link;
- desc->nofollow = true;
+ RELEASE_SEARCH(desc);
+ SETUP_SEARCH(desc, (FAR const char *)node->u.i_link, true);
/* Look up inode associated with the target of the symbolic link */
@@ -516,6 +515,8 @@ int inode_search(FAR struct inode_search_s *desc)
if (desc->linktgt != NULL && INODE_IS_MOUNTPT(node))
{
+ FAR char *buffer;
+
/* There would be no problem in this case if the link was to
* either to the root directory of the MOUNTPOINT or to a
* regular file within the the mounted volume. However,
@@ -531,20 +532,28 @@ int inode_search(FAR struct inode_search_s *desc)
if (desc->relpath != NULL && *desc->relpath != '\0')
{
- snprintf(desc->fullpath, PATH_MAX, "%s/%s",
- desc->linktgt, desc->relpath);
+ (void)asprintf(&buffer, "%s/%s",
+ desc->linktgt, desc->relpath);
}
else
{
- strncpy(desc->fullpath, desc->linktgt, PATH_MAX);
+ buffer = strdup(desc->linktgt);
}
- /* Reset the search description and perform the search again. */
+ if (buffer == NULL)
+ {
+ ret = -ENOMEM;
+ }
+ else
+ {
+ /* Reset the search description and perform the search again. */
- RESET_SEARCH(desc);
- desc->path = desc->fullpath;
+ RELEASE_SEARCH(desc);
+ SETUP_SEARCH(desc, buffer, false);
+ desc->buffer = buffer;
- ret = _inode_search(desc);
+ ret = _inode_search(desc);
+ }
}
}
#endif
diff --git a/fs/inode/inode.h b/fs/inode/inode.h
index 9d4e966e212..4e2f6aa1508 100644
--- a/fs/inode/inode.h
+++ b/fs/inode/inode.h
@@ -48,6 +48,7 @@
#include
#include
+#include
#include
/****************************************************************************
@@ -55,29 +56,43 @@
****************************************************************************/
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
-# define RESET_SEARCH(d) \
+
+# define SETUP_SEARCH(d,p,n) \
do \
{ \
- (d)->path = NULL; \
+ (d)->path = (p); \
(d)->node = NULL; \
(d)->peer = NULL; \
(d)->parent = NULL; \
(d)->relpath = NULL; \
(d)->linktgt = NULL; \
- (d)->nofollow = false; \
+ (d)->buffer = NULL; \
+ (d)->nofollow = (n); \
} \
while (0)
+
+# define RELEASE_SEARCH(d) \
+ if ((d)->buffer != NULL) \
+ { \
+ kmm_free((d)->buffer); \
+ (d)->buffer = NULL; \
+ }
+
#else
-# define RESET_SEARCH(d) \
+
+# define SETUP_SEARCH(d,p,n) \
do \
{ \
- (d)->path = NULL; \
+ (d)->path = (p); \
(d)->node = NULL; \
(d)->peer = NULL; \
(d)->parent = NULL; \
(d)->relpath = NULL; \
} \
while (0)
+
+# define RELEASE_SEARCH(d)
+
#endif
/****************************************************************************
@@ -107,9 +122,10 @@
* terminal is a soft link, then return the inode of
* the link target.
* - OUTPUT: (not used)
- * fullpath - INPUT: Not used
- * - OUTPUT: May hold an intermediate path which is probably of
- * no interest to the caller.
+ * buffer - INPUT: Not used
+ * - OUTPUT: May hold an allocated intermediate path which is
+ * probably of no interest to the caller unless it holds
+ * the relpath.
*/
struct inode_search_s
@@ -121,8 +137,8 @@ struct inode_search_s
FAR const char *relpath; /* Relative path into the mountpoint */
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
FAR const char *linktgt; /* Target of symbolic link if linked to a directory */
+ FAR char *buffer; /* Path expansion buffer */
bool nofollow; /* true: Don't follow terminal soft link */
- char fullpath[PATH_MAX]; /* Path expansion buffer */
#endif
};
diff --git a/fs/mount/fs_automount.c b/fs/mount/fs_automount.c
index 55484dc6ed6..e73ce50e244 100644
--- a/fs/mount/fs_automount.c
+++ b/fs/mount/fs_automount.c
@@ -137,8 +137,7 @@ static int automount_findinode(FAR const char *path)
/* Find the inode */
- RESET_SEARCH(&desc);
- desc.path = path;
+ SETUP_SEARCH(&desc, path, false);
ret = inode_search(&desc);
@@ -169,6 +168,7 @@ static int automount_findinode(FAR const char *path)
/* Relinquish our exclusive access to the inode try and return the result */
inode_semgive();
+ RELEASE_SEARCH(&desc);
return ret;
}
diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c
index b00cce8dd2a..2fc9d7376fd 100644
--- a/fs/mount/fs_mount.c
+++ b/fs/mount/fs_mount.c
@@ -284,8 +284,7 @@ int mount(FAR const char *source, FAR const char *target,
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
/* Check if the inode already exists */
- RESET_SEARCH(&desc);
- desc.path = target;
+ SETUP_SEARCH(&desc, target, false);
ret = inode_find(&desc);
if (ret >= 0)
@@ -414,6 +413,9 @@ int mount(FAR const char *source, FAR const char *target,
}
#endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ RELEASE_SEARCH(&desc);
+#endif
return OK;
/* A lot of goto's! But they make the error handling much simpler */
@@ -432,10 +434,14 @@ errout_with_mountpt:
#endif
inode_release(mountpt_inode);
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ RELEASE_SEARCH(&desc);
+#endif
goto errout;
errout_with_semaphore:
inode_semgive();
+
#ifdef BDFS_SUPPORT
#ifdef NONBDFS_SUPPORT
if (blkdrvr_inode)
@@ -445,6 +451,10 @@ errout_with_semaphore:
}
#endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ RELEASE_SEARCH(&desc);
+#endif
+
errout:
set_errno(errcode);
return ERROR;
diff --git a/fs/mount/fs_umount2.c b/fs/mount/fs_umount2.c
index 138bb8e6423..e342ae2e16d 100644
--- a/fs/mount/fs_umount2.c
+++ b/fs/mount/fs_umount2.c
@@ -88,14 +88,13 @@ int umount2(FAR const char *target, unsigned int flags)
/* Find the mountpt */
- RESET_SEARCH(&desc);
- desc.path = target;
+ SETUP_SEARCH(&desc, target, false);
ret = inode_find(&desc);
if (ret < 0)
{
errcode = ENOENT;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -199,18 +198,24 @@ int umount2(FAR const char *target, unsigned int flags)
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;
diff --git a/fs/mqueue/mq_open.c b/fs/mqueue/mq_open.c
index e80f64d9523..85474e0f3fe 100644
--- a/fs/mqueue/mq_open.c
+++ b/fs/mqueue/mq_open.c
@@ -133,8 +133,7 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
* have incremented the reference count on the inode.
*/
- RESET_SEARCH(&desc);
- desc.path = fullpath;
+ SETUP_SEARCH(&desc, fullpath, false);
ret = inode_find(&desc);
if (ret >= 0)
@@ -236,16 +235,21 @@ mqd_t mq_open(FAR const char *mq_name, int oflags, ...)
inode->i_crefs = 1;
}
+ RELEASE_SEARCH(&desc);
sched_unlock();
return mqdes;
errout_with_msgq:
mq_msgqfree(msgq);
inode->u.i_mqueue = NULL;
+
errout_with_inode:
inode_release(inode);
+
errout_with_lock:
+ RELEASE_SEARCH(&desc);
sched_unlock();
+
errout:
set_errno(errcode);
return (mqd_t)ERROR;
diff --git a/fs/mqueue/mq_unlink.c b/fs/mqueue/mq_unlink.c
index 09ab08d7ada..9705a0ef8ba 100644
--- a/fs/mqueue/mq_unlink.c
+++ b/fs/mqueue/mq_unlink.c
@@ -87,8 +87,7 @@ int mq_unlink(FAR const char *mq_name)
/* Get the inode for this message queue. */
- RESET_SEARCH(&desc);
- desc.path = fullpath;
+ SETUP_SEARCH(&desc, fullpath, false);
sched_lock();
ret = inode_find(&desc);
@@ -97,7 +96,7 @@ int mq_unlink(FAR const char *mq_name)
/* There is no inode that includes in this path */
errcode = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -149,14 +148,18 @@ int mq_unlink(FAR const char *mq_name)
inode_semgive();
mq_inode_release(inode);
+ RELEASE_SEARCH(&desc);
sched_unlock();
return OK;
errout_with_semaphore:
inode_semgive();
+
errout_with_inode:
inode_release(inode);
-errout:
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
set_errno(errcode);
sched_unlock();
return ERROR;
diff --git a/fs/semaphore/sem_open.c b/fs/semaphore/sem_open.c
index 3f8934b43ed..847d7285942 100644
--- a/fs/semaphore/sem_open.c
+++ b/fs/semaphore/sem_open.c
@@ -114,149 +114,148 @@ FAR sem_t *sem_open (FAR const char *name, int oflags, ...)
/* Make sure that a non-NULL name is supplied */
- if (name)
+ DEBUGASSERT(name != NULL);
+
+ /* The POSIX specification requires that the "check for the existence
+ * of a semaphore and the creation of the semaphore if it does not
+ * exist shall be atomic with respect to other processes executing
+ * sem_open()..." A simple sched_lock() should be sufficient to meet
+ * this requirement.
+ */
+
+ sched_lock();
+
+ /* Get the full path to the semaphore */
+
+ snprintf(fullpath, MAX_SEMPATH, CONFIG_FS_NAMED_SEMPATH "/%s", name);
+
+ /* Get the inode for this semaphore. This should succeed if the
+ * semaphore has already been created. In this case, inode_find()
+ * will have incremented the reference count on the inode.
+ */
+
+ SETUP_SEARCH(&desc, fullpath, false);
+
+ ret = inode_find(&desc);
+ if (ret >= 0)
{
- /* The POSIX specification requires that the "check for the existence
- * of a semaphore and the creation of the semaphore if it does not
- * exist shall be atomic with respect to other processes executing
- * sem_open()..." A simple sched_lock() should be sufficient to meet
- * this requirement.
- */
+ /* Something exists at this path. Get the search results */
- sched_lock();
+ inode = desc.node;
+ relpath = desc.relpath;
+ DEBUGASSERT(inode != NULL);
- /* Get the full path to the semaphore */
+ /* Verify that the inode is a semaphore */
- snprintf(fullpath, MAX_SEMPATH, CONFIG_FS_NAMED_SEMPATH "/%s", name);
-
- /* Get the inode for this semaphore. This should succeed if the
- * semaphore has already been created. In this case, inode_find()
- * will have incremented the reference count on the inode.
- */
-
- RESET_SEARCH(&desc);
- desc.path = fullpath;
-
- ret = inode_find(&desc);
- if (ret >= 0)
+ if (!INODE_IS_NAMEDSEM(inode))
{
- /* Something exists at this path. Get the search results */
-
- inode = desc.node;
- relpath = desc.relpath;
- DEBUGASSERT(inode != NULL);
-
- /* Verify that the inode is a semaphore */
-
- if (!INODE_IS_NAMEDSEM(inode))
- {
- errcode = ENXIO;
- goto errout_with_inode;
- }
-
- /* It exists and is a semaphore. Check if the caller wanted to
- * create a new semaphore with this name.
- */
-
- if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
- {
- errcode = EEXIST;
- goto errout_with_inode;
- }
-
- /* Return a reference to the semaphore, retaining the reference
- * count on the inode.
- */
-
- sem = &inode->u.i_nsem->ns_sem;
-
- }
- else
- {
- va_list ap;
-
- /* The semaphore does not exists. Were we asked to create it? */
-
- if ((oflags & O_CREAT) == 0)
- {
- /* The semaphore does not exist and O_CREAT is not set */
-
- errcode = ENOENT;
- goto errout_with_lock;
- }
-
- /* Create the semaphore. First we have to extract the additional
- * parameters from the variable argument list.
- * REVISIT: Mode parameter is not currently used.
- */
-
- va_start(ap, oflags);
- mode = va_arg(ap, mode_t);
- value = va_arg(ap, unsigned);
- va_end(ap);
-
- UNUSED(mode);
-
- /* Check the semaphore value */
-
- if (value > SEM_VALUE_MAX)
- {
- errcode = EINVAL;
- goto errout_with_lock;
- }
-
- /* Create an inode in the pseudo-filesystem at this path. The new
- * inode will be created with a reference count of zero.
- */
-
- inode_semtake();
- ret = inode_reserve(fullpath, &inode);
- inode_semgive();
-
- if (ret < 0)
- {
- errcode = -ret;
- goto errout_with_lock;
- }
-
- /* Allocate the semaphore structure (using the appropriate allocator
- * for the group)
- */
-
- nsem = group_malloc(NULL, sizeof(struct nsem_inode_s));
- if (!nsem)
- {
- errcode = ENOMEM;
- goto errout_with_inode;
- }
-
- /* Link to the inode */
-
- inode->u.i_nsem = nsem;
- nsem->ns_inode = inode;
-
- /* Initialize the inode */
-
- INODE_SET_NAMEDSEM(inode);
- inode->i_crefs = 1;
-
- /* Initialize the semaphore */
-
- sem_init(&nsem->ns_sem, 0, value);
-
- /* Return a reference to the semaphore */
-
- sem = &nsem->ns_sem;
+ errcode = ENXIO;
+ goto errout_with_inode;
}
- sched_unlock();
+ /* It exists and is a semaphore. Check if the caller wanted to
+ * create a new semaphore with this name.
+ */
+
+ if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ {
+ errcode = EEXIST;
+ goto errout_with_inode;
+ }
+
+ /* Return a reference to the semaphore, retaining the reference
+ * count on the inode.
+ */
+
+ sem = &inode->u.i_nsem->ns_sem;
+ }
+ else
+ {
+ va_list ap;
+
+ /* The semaphore does not exists. Were we asked to create it? */
+
+ if ((oflags & O_CREAT) == 0)
+ {
+ /* The semaphore does not exist and O_CREAT is not set */
+
+ errcode = ENOENT;
+ goto errout_with_lock;
+ }
+
+ /* Create the semaphore. First we have to extract the additional
+ * parameters from the variable argument list.
+ * REVISIT: Mode parameter is not currently used.
+ */
+
+ va_start(ap, oflags);
+ mode = va_arg(ap, mode_t);
+ value = va_arg(ap, unsigned);
+ va_end(ap);
+
+ UNUSED(mode);
+
+ /* Check the semaphore value */
+
+ if (value > SEM_VALUE_MAX)
+ {
+ errcode = EINVAL;
+ goto errout_with_lock;
+ }
+
+ /* Create an inode in the pseudo-filesystem at this path. The new
+ * inode will be created with a reference count of zero.
+ */
+
+ inode_semtake();
+ ret = inode_reserve(fullpath, &inode);
+ inode_semgive();
+
+ if (ret < 0)
+ {
+ errcode = -ret;
+ goto errout_with_lock;
+ }
+
+ /* Allocate the semaphore structure (using the appropriate allocator
+ * for the group)
+ */
+
+ nsem = group_malloc(NULL, sizeof(struct nsem_inode_s));
+ if (!nsem)
+ {
+ errcode = ENOMEM;
+ goto errout_with_inode;
+ }
+
+ /* Link to the inode */
+
+ inode->u.i_nsem = nsem;
+ nsem->ns_inode = inode;
+
+ /* Initialize the inode */
+
+ INODE_SET_NAMEDSEM(inode);
+ inode->i_crefs = 1;
+
+ /* Initialize the semaphore */
+
+ sem_init(&nsem->ns_sem, 0, value);
+
+ /* Return a reference to the semaphore */
+
+ sem = &nsem->ns_sem;
}
+ RELEASE_SEARCH(&desc);
+ sched_unlock();
return sem;
errout_with_inode:
inode_release(inode);
+
errout_with_lock:
+ RELEASE_SEARCH(&desc);
set_errno(errcode);
sched_unlock();
return (FAR sem_t *)ERROR;
diff --git a/fs/semaphore/sem_unlink.c b/fs/semaphore/sem_unlink.c
index 33675487b0b..ca73a800418 100644
--- a/fs/semaphore/sem_unlink.c
+++ b/fs/semaphore/sem_unlink.c
@@ -91,8 +91,7 @@ int sem_unlink(FAR const char *name)
/* Get the inode for this semaphore. */
- RESET_SEARCH(&desc);
- desc.path = fullpath;
+ SETUP_SEARCH(&desc, fullpath, false);
sched_lock();
ret = inode_find(&desc);
@@ -101,7 +100,7 @@ int sem_unlink(FAR const char *name)
/* There is no inode that includes in this path */
errcode = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -152,14 +151,18 @@ int sem_unlink(FAR const char *name)
inode_semgive();
ret = sem_close((FAR sem_t *)inode->u.i_nsem);
+ RELEASE_SEARCH(&desc);
sched_unlock();
return ret;
errout_with_semaphore:
inode_semgive();
+
errout_with_inode:
inode_release(inode);
-errout:
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
set_errno(errcode);
sched_unlock();
return ERROR;
diff --git a/fs/unionfs/fs_unionfs.c b/fs/unionfs/fs_unionfs.c
index fb037889771..7746efd47c7 100644
--- a/fs/unionfs/fs_unionfs.c
+++ b/fs/unionfs/fs_unionfs.c
@@ -2446,15 +2446,14 @@ static int unionfs_getmount(FAR const char *path, FAR struct inode **inode)
/* Find the mountpt */
- RESET_SEARCH(&desc);
- desc.path = path;
+ SETUP_SEARCH(&desc, path, false);
ret = inode_find(&desc);
if (ret < 0)
{
/* Mountpoint inode not found */
- return ret;
+ goto errout_with_search;
}
/* Get the search results */
@@ -2462,20 +2461,33 @@ static int unionfs_getmount(FAR const char *path, FAR struct inode **inode)
minode = desc.node;
DEBUGASSERT(minode != NULL);
- /* Verify that the inode is a mountpoint */
+ /* Verify that the inode is a mountpoint.
+ *
+ * REVISIT: If desc.relpath points to a non-empty string, then the path
+ * does not really refer to a mountpoint but, rather, to a some entity
+ * within the mounted volume.
+ */
if (!INODE_IS_MOUNTPT(minode))
{
- /* Inode was found, but is it is a mounpoint */
+ /* Inode was found, but is it is not a mounpoint */
- inode_release(minode);
- return -EINVAL;
+ ret = -EINVAL;
+ goto errout_with_inode;
}
/* Success! */
*inode = minode;
+ RELEASE_SEARCH(&desc);
return OK;
+
+errout_with_inode:
+ inode_release(minode);
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
+ return ret;
}
/****************************************************************************
diff --git a/fs/vfs/fs_link.c b/fs/vfs/fs_link.c
index 2bad20a224d..e9155cf84af 100644
--- a/fs/vfs/fs_link.c
+++ b/fs/vfs/fs_link.c
@@ -107,8 +107,7 @@ int link(FAR const char *path1, FAR const char *path2)
* does not lie on a mounted volume.
*/
- RESET_SEARCH(&desc);
- desc.path = path2;
+ SETUP_SEARCH(&desc, path2, false);
ret = inode_find(&desc);
if (ret >= 0)
@@ -149,7 +148,7 @@ int link(FAR const char *path1, FAR const char *path2)
if (newpath2 == NULL)
{
errcode = ENOMEM;
- goto errout;
+ goto errout_with_search;
}
/* Create an inode in the pseudo-filesystem at this path.
@@ -165,7 +164,7 @@ int link(FAR const char *path1, FAR const char *path2)
{
kmm_free(newpath2);
errcode = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Initialize the inode */
@@ -177,10 +176,15 @@ int link(FAR const char *path1, FAR const char *path2)
/* Symbolic link successfully created */
+ RELEASE_SEARCH(&desc);
return OK;
errout_with_inode:
inode_release(inode);
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
+
errout:
set_errno(errcode);
return ERROR;
diff --git a/fs/vfs/fs_mkdir.c b/fs/vfs/fs_mkdir.c
index 8b40384c47a..e310b358595 100644
--- a/fs/vfs/fs_mkdir.c
+++ b/fs/vfs/fs_mkdir.c
@@ -86,13 +86,12 @@ int mkdir(const char *pathname, mode_t mode)
{
struct inode_search_s desc;
FAR struct inode *inode;
- int errcode;
- int ret;
+ int errcode;
+ int ret;
/* Find the inode that includes this path */
- RESET_SEARCH(&desc);
- desc.path = pathname;
+ SETUP_SEARCH(&desc, pathname, false);
ret = inode_find(&desc);
if (ret >= 0)
@@ -164,24 +163,27 @@ int mkdir(const char *pathname, mode_t mode)
if (ret < 0)
{
errcode = -ret;
- goto errout;
+ goto errout_with_search;
}
}
#else
else
{
errcode = ENXIO;
- goto errout;
+ goto errout_with_search;
}
#endif
/* Directory successfully created */
+ RELEASE_SEARCH(&desc);
return OK;
errout_with_inode:
inode_release(inode);
-errout:
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
set_errno(errcode);
return ERROR;
}
diff --git a/fs/vfs/fs_open.c b/fs/vfs/fs_open.c
index 2c048b2beba..19bf437323b 100644
--- a/fs/vfs/fs_open.c
+++ b/fs/vfs/fs_open.c
@@ -121,8 +121,7 @@ int open(const char *path, int oflags, ...)
/* Get an inode for this file */
- RESET_SEARCH(&desc);
- desc.path = path;
+ SETUP_SEARCH(&desc, path, false);
ret = inode_find(&desc);
if (ret < 0)
@@ -133,7 +132,7 @@ int open(const char *path, int oflags, ...)
*/
ret = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -164,11 +163,12 @@ int open(const char *path, int oflags, ...)
if (fd < 0)
{
ret = fd;
- goto errout;
+ goto errout_with_search;
}
/* Return the file descriptor */
+ RELEASE_SEARCH(&desc);
leave_cancellation_point();
return fd;
}
@@ -215,8 +215,7 @@ int open(const char *path, int oflags, ...)
{
/* The errno value has already been set */
- leave_cancellation_point();
- return ERROR;
+ goto errout;
}
/* Perform the driver open operation. NOTE that the open method may be
@@ -276,15 +275,21 @@ int open(const char *path, int oflags, ...)
}
#endif
+ RELEASE_SEARCH(&desc);
leave_cancellation_point();
return fd;
errout_with_fd:
files_release(fd);
+
errout_with_inode:
inode_release(inode);
-errout:
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
set_errno(ret);
+
+errout:
leave_cancellation_point();
return ERROR;
}
diff --git a/fs/vfs/fs_readlink.c b/fs/vfs/fs_readlink.c
index d4c3a195c3b..77b4afa9a1a 100644
--- a/fs/vfs/fs_readlink.c
+++ b/fs/vfs/fs_readlink.c
@@ -93,17 +93,13 @@ ssize_t readlink(FAR const char *path, FAR char *buf, size_t bufsize)
* symbolic link node.
*/
- RESET_SEARCH(&desc);
- desc.path = path;
-#ifdef CONFIG_PSEUDOFS_SOFTLINKS
- desc.nofollow = true;
-#endif
+ SETUP_SEARCH(&desc, path, true);
ret = inode_find(&desc);
if (ret < 0)
{
errcode = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -131,11 +127,14 @@ ssize_t readlink(FAR const char *path, FAR char *buf, size_t bufsize)
/* Release our reference on the inode and return the length */
inode_release(node);
+ RELEASE_SEARCH(&desc);
return strlen(buf);
errout_with_inode:
inode_release(node);
-errout:
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
set_errno(errcode);
return ERROR;
}
diff --git a/fs/vfs/fs_rename.c b/fs/vfs/fs_rename.c
index 965b4a370a3..12f3c334cc3 100644
--- a/fs/vfs/fs_rename.c
+++ b/fs/vfs/fs_rename.c
@@ -83,7 +83,9 @@
int rename(FAR const char *oldpath, FAR const char *newpath)
{
struct inode_search_s olddesc;
+#ifndef CONFIG_DISABLE_MOUNTPOINT
struct inode_search_s newdesc;
+#endif
FAR struct inode *oldinode;
FAR struct inode *newinode;
int errcode;
@@ -101,11 +103,7 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
/* Get an inode that includes the oldpath */
- RESET_SEARCH(&olddesc);
- olddesc.path = oldpath;
-#ifdef CONFIG_PSEUDOFS_SOFTLINKS
- olddesc.nofollow = true;
-#endif
+ SETUP_SEARCH(&olddesc, oldpath, true);
ret = inode_find(&olddesc);
if (ret < 0)
@@ -113,7 +111,7 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
/* There is no inode that includes in this path */
errcode = -ret;
- goto errout;
+ goto errout_with_oldsearch;
}
/* Get the search results */
@@ -130,11 +128,7 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
* mountpoint
*/
- RESET_SEARCH(&newdesc);
- newdesc.path = newpath;
-#ifdef CONFIG_PSEUDOFS_SOFTLINKS
- newdesc.nofollow = true;
-#endif
+ SETUP_SEARCH(&newdesc, newpath, true);
ret = inode_find(&newdesc);
if (ret < 0)
@@ -142,7 +136,7 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
/* There is no mountpoint that includes in this path */
errcode = -ret;
- goto errout_with_oldinode;
+ goto errout_with_newsearch;
}
/* Get the search results */
@@ -181,9 +175,10 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
/* Successfully renamed */
inode_release(newinode);
+ RELEASE_SEARCH(&newdesc);
}
else
-#endif
+#endif /* CONFIG_DISABLE_MOUNTPOINT */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
{
/* Create a new, empty inode at the destination location.
@@ -246,22 +241,29 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
#else
{
errcode = ENXIO;
- goto errout;
+ goto errout_with_oldsearch;
}
#endif
/* Successfully renamed */
inode_release(oldinode);
+ RELEASE_SEARCH(&olddesc);
return OK;
#ifndef CONFIG_DISABLE_MOUNTPOINT
errout_with_newinode:
inode_release(newinode);
+
+errout_with_newsearch:
+ RELEASE_SEARCH(&newdesc);
#endif
+
errout_with_oldinode:
inode_release(oldinode);
-errout:
+
+errout_with_oldsearch:
+ RELEASE_SEARCH(&olddesc);
set_errno(errcode);
return ERROR;
}
diff --git a/fs/vfs/fs_rmdir.c b/fs/vfs/fs_rmdir.c
index 3cb3d7ba61a..d75c83a7e19 100644
--- a/fs/vfs/fs_rmdir.c
+++ b/fs/vfs/fs_rmdir.c
@@ -93,11 +93,7 @@ int rmdir(FAR const char *pathname)
* on the inode if one is found.
*/
- RESET_SEARCH(&desc);
- desc.path = pathname;
-#ifdef CONFIG_PSEUDOFS_SOFTLINKS
- desc.nofollow = true;
-#endif
+ SETUP_SEARCH(&desc, pathname, true);
ret = inode_find(&desc);
if (ret < 0)
@@ -105,7 +101,7 @@ int rmdir(FAR const char *pathname)
/* There is no inode that includes in this path */
errcode = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -188,11 +184,13 @@ int rmdir(FAR const char *pathname)
/* Successfully removed the directory */
inode_release(inode);
+ RELEASE_SEARCH(&desc);
return OK;
errout_with_inode:
inode_release(inode);
-errout:
+errout_with_search:
+ RELEASE_SEARCH(&desc);
set_errno(errcode);
return ERROR;
}
diff --git a/fs/vfs/fs_stat.c b/fs/vfs/fs_stat.c
index e988fac25ca..9e9679249b5 100644
--- a/fs/vfs/fs_stat.c
+++ b/fs/vfs/fs_stat.c
@@ -234,11 +234,7 @@ int stat(FAR const char *path, FAR struct stat *buf)
/* Get an inode for this file */
- RESET_SEARCH(&desc);
- desc.path = path;
-#ifdef CONFIG_PSEUDOFS_SOFTLINKS
- desc.nofollow = true;
-#endif
+ SETUP_SEARCH(&desc, path, true);
ret = inode_find(&desc);
if (ret < 0)
@@ -248,7 +244,7 @@ int stat(FAR const char *path, FAR struct stat *buf)
*/
ret = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -293,12 +289,17 @@ int stat(FAR const char *path, FAR struct stat *buf)
/* Successfully stat'ed the file */
inode_release(inode);
+ RELEASE_SEARCH(&desc);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
+
errout:
set_errno(ret);
return ERROR;
diff --git a/fs/vfs/fs_statfs.c b/fs/vfs/fs_statfs.c
index d51fdf0eea4..ff2380fedd6 100644
--- a/fs/vfs/fs_statfs.c
+++ b/fs/vfs/fs_statfs.c
@@ -105,8 +105,7 @@ int statfs(FAR const char *path, FAR struct statfs *buf)
/* Get an inode for this file */
- RESET_SEARCH(&desc);
- desc.path = path;
+ SETUP_SEARCH(&desc, path, false);
ret = inode_find(&desc);
if (ret < 0)
@@ -116,7 +115,7 @@ int statfs(FAR const char *path, FAR struct statfs *buf)
*/
ret = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -161,12 +160,17 @@ int statfs(FAR const char *path, FAR struct statfs *buf)
/* Successfully statfs'ed the file */
inode_release(inode);
+ RELEASE_SEARCH(&desc);
return OK;
/* Failure conditions always set the errno appropriately */
errout_with_inode:
inode_release(inode);
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
+
errout:
set_errno(ret);
return ERROR;
diff --git a/fs/vfs/fs_unlink.c b/fs/vfs/fs_unlink.c
index 84d5b7953ef..c5f958de57c 100644
--- a/fs/vfs/fs_unlink.c
+++ b/fs/vfs/fs_unlink.c
@@ -92,11 +92,7 @@ int unlink(FAR const char *pathname)
* which may be a symbolic link)
*/
- RESET_SEARCH(&desc);
- desc.path = pathname;
-#ifdef CONFIG_PSEUDOFS_SOFTLINKS
- desc.nofollow = true;
-#endif
+ SETUP_SEARCH(&desc, pathname, true);
ret = inode_find(&desc);
if (ret < 0)
@@ -104,7 +100,7 @@ int unlink(FAR const char *pathname)
/* There is no inode that includes in this path */
errcode = -ret;
- goto errout;
+ goto errout_with_search;
}
/* Get the search results */
@@ -233,11 +229,14 @@ int unlink(FAR const char *pathname)
/* Successfully unlinked */
inode_release(inode);
+ RELEASE_SEARCH(&desc);
return OK;
errout_with_inode:
inode_release(inode);
-errout:
+
+errout_with_search:
+ RELEASE_SEARCH(&desc);
set_errno(errcode);
return ERROR;
}