diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c index e0325305620..1057d71c98f 100644 --- a/fs/mount/fs_mount.c +++ b/fs/mount/fs_mount.c @@ -356,7 +356,7 @@ int nx_mount(FAR const char *source, FAR const char *target, * node)? */ - if (INODE_IS_SPECIAL(mountpt_inode)) + if (!INODE_IS_PSEUDODIR(mountpt_inode)) { ferr("ERROR: target %s exists and is a special node\n", target); ret = -ENOTDIR; diff --git a/fs/vfs/fs_stat.c b/fs/vfs/fs_stat.c index c1a6b54831d..ad31c586474 100644 --- a/fs/vfs/fs_stat.c +++ b/fs/vfs/fs_stat.c @@ -259,115 +259,110 @@ int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve) /* Handle "special" nodes */ - if (INODE_IS_SPECIAL(inode)) - { #if defined(CONFIG_FS_NAMED_SEMAPHORES) - /* Check for a named semaphore */ + /* Check for a named semaphore */ - if (INODE_IS_NAMEDSEM(inode)) - { - buf->st_mode = S_IFSEM; - } - else + if (INODE_IS_NAMEDSEM(inode)) + { + buf->st_mode = S_IFSEM; + } + else #endif #if !defined(CONFIG_DISABLE_MQUEUE) - /* Check for a message queue */ + /* Check for a message queue */ - if (INODE_IS_MQUEUE(inode)) - { - buf->st_mode = S_IFMQ; - } - else + if (INODE_IS_MQUEUE(inode)) + { + buf->st_mode = S_IFMQ; + } + else #endif #if defined(CONFIG_FS_SHM) - /* Check for shared memory */ + /* Check for shared memory */ - if (INODE_IS_SHM(inode)) - { - buf->st_mode = S_IFSHM; - } - else + if (INODE_IS_SHM(inode)) + { + buf->st_mode = S_IFSHM; + } + else #endif #if defined(CONFIG_MTD) - /* Check for an MTD driver */ + /* Check for an MTD driver */ - if (INODE_IS_MTD(inode)) - { - struct mtd_geometry_s mtdgeo; - - buf->st_mode = S_IFMTD; - buf->st_mode |= S_IROTH | S_IRGRP | S_IRUSR; - buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR; - - if (inode->u.i_mtd != NULL && - MTD_IOCTL(inode->u.i_mtd, MTDIOC_GEOMETRY, - (unsigned long)((uintptr_t)&mtdgeo)) >= 0) - { - buf->st_size = mtdgeo.neraseblocks * mtdgeo.erasesize; - } - } - else -#endif -#ifdef CONFIG_PSEUDOFS_SOFTLINKS - /* Handle softlinks differently. Just call stat() recursively on the - * target of the softlink. - * - * REVISIT: This has the possibility of an infinite loop! - */ - - if (INODE_IS_SOFTLINK(inode)) - { - if (resolve) - { - int ret; - - /* Increment the link counter. This is necessary to avoid - * infinite recursion if loops are encountered in the - * traversal. If we encounter more SYMLOOP_MAX symbolic links - * at any time during the traversal, error out. - * - * NOTE: That inode_search() will automatically skip over - * consecutive, intermediate symbolic links. Those numbers - * will not be included in the total. - */ - - if (++buf->st_count > SYMLOOP_MAX) - { - return -ELOOP; - } - - DEBUGASSERT(buf->st_count > 0); /* Check for unsigned integer overflow */ - - /* stat() the target of the soft link. */ - - ret = stat_recursive(inode->u.i_link, buf, 1); - - /* If stat() fails, then there is a problem with the target of - * the symbolic link, but not with the symbolic link itself. - * We should still report success, just with less information. - */ - - if (ret < 0) - { - RESET_BUF(buf); - } - } - else - { - /* Make sure the caller knows that this is a symbolic link. */ - - buf->st_mode = S_IRWXO | S_IRWXG | S_IRWXU | S_IFLNK; - } - } - else -#endif + if (INODE_IS_MTD(inode)) + { + struct mtd_geometry_s mtdgeo; + + buf->st_mode = S_IFMTD; + buf->st_mode |= S_IROTH | S_IRGRP | S_IRUSR; + buf->st_mode |= S_IWOTH | S_IWGRP | S_IWUSR; + + if (inode->u.i_mtd != NULL && + MTD_IOCTL(inode->u.i_mtd, MTDIOC_GEOMETRY, + (unsigned long)((uintptr_t)&mtdgeo)) >= 0) { + buf->st_size = mtdgeo.neraseblocks * mtdgeo.erasesize; } } + else +#endif +#ifdef CONFIG_PSEUDOFS_SOFTLINKS + /* Handle softlinks differently. Just call stat() recursively on the + * target of the softlink. + * + * REVISIT: This has the possibility of an infinite loop! + */ + + if (INODE_IS_SOFTLINK(inode)) + { + if (resolve) + { + int ret; + + /* Increment the link counter. This is necessary to avoid + * infinite recursion if loops are encountered in the + * traversal. If we encounter more SYMLOOP_MAX symbolic links + * at any time during the traversal, error out. + * + * NOTE: That inode_search() will automatically skip over + * consecutive, intermediate symbolic links. Those numbers + * will not be included in the total. + */ + + if (++buf->st_count > SYMLOOP_MAX) + { + return -ELOOP; + } + + DEBUGASSERT(buf->st_count > 0); /* Check for unsigned integer overflow */ + + /* stat() the target of the soft link. */ + + ret = stat_recursive(inode->u.i_link, buf, 1); + + /* If stat() fails, then there is a problem with the target of + * the symbolic link, but not with the symbolic link itself. + * We should still report success, just with less information. + */ + + if (ret < 0) + { + RESET_BUF(buf); + } + } + else + { + /* Make sure the caller knows that this is a symbolic link. */ + + buf->st_mode = S_IRWXO | S_IRWXG | S_IRWXU | S_IFLNK; + } + } + else +#endif /* Handle "normal inodes */ - else if (inode->u.i_ops != NULL) + if (inode->u.i_ops != NULL) { /* Determine read/write privileges based on the existence of read * and write methods. diff --git a/fs/vfs/fs_unlink.c b/fs/vfs/fs_unlink.c index dde986b617a..82c5b9b13e5 100644 --- a/fs/vfs/fs_unlink.c +++ b/fs/vfs/fs_unlink.c @@ -106,96 +106,83 @@ int nx_unlink(FAR const char *pathname) else #endif -#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS - /* If this is a "dangling" pseudo-file node (i.e., it has no operations) - * or a soft link, then rm should remove the node. - */ - -#ifdef CONFIG_PSEUDOFS_SOFTLINKS - /* A soft link is the only "specal" file that we can remove via unlink(). */ - - if (!INODE_IS_SPECIAL(inode) || INODE_IS_SOFTLINK(inode)) -#else - if (!INODE_IS_SPECIAL(inode)) -#endif { - /* If this is a pseudo-file node (i.e., it has no operations) - * then unlink should remove the node. +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + ret = inode_semtake(); + if (ret < 0) + { + 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. */ - if (inode->u.i_ops != NULL) + if (inode->i_child != NULL) { - ret = inode_semtake(); + ret = -ENOTEMPTY; + goto errout_with_sem; + } + + /* 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) { - 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. - */ - - if (inode->i_child != NULL) - { - ret = -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) - { - goto errout_with_inode; - } + goto errout_with_sem; } + } #ifndef CONFIG_DISABLE_MOUNTPOINT - else if (INODE_IS_BLOCK(inode) && inode->u.i_bops->unlink) - { - /* Notify the block driver that it has been unlinked */ + 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) - { - goto errout_with_inode; - } + ret = inode->u.i_bops->unlink(inode); + if (ret < 0) + { + goto errout_with_sem; } + } #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 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) - { - goto errout_with_inode; - } +#ifdef CONFIG_PSEUDOFS_SOFTLINKS + else if (INODE_IS_PSEUDODIR(inode) || INODE_IS_SOFTLINK(inode)) +#else + else if (INODE_IS_PSEUDODIR(inode)) +#endif + { + /* If this is a "dangling" pseudo-file node + * (i.e., it has no operations) or a soft link, + * then rm should remove the node. + */ } else { - ret = -EISDIR; + ret = -ENXIO; + goto errout_with_sem; + } + + /* 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 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) + { goto errout_with_inode; } - } - else #endif - { - ret = -ENXIO; - goto errout_with_inode; } /* Successfully unlinked */ @@ -204,6 +191,9 @@ int nx_unlink(FAR const char *pathname) RELEASE_SEARCH(&desc); return OK; +errout_with_sem: + inode_semgive(); + errout_with_inode: inode_release(inode); diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index bb9ad8ff14f..70e6f9e6c6c 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -108,23 +108,22 @@ * Bit 4: Set if inode has been unlinked and is pending removal. */ -#define FSNODEFLAG_TYPE_MASK 0x0000000f /* Isolates type field */ -#define FSNODEFLAG_TYPE_DRIVER 0x00000000 /* Character driver */ -#define FSNODEFLAG_TYPE_BLOCK 0x00000001 /* Block driver */ -#define FSNODEFLAG_TYPE_MOUNTPT 0x00000002 /* Mount point */ -#define FSNODEFLAG_TYPE_SPECIAL 0x00000008 /* Special OS type */ -#define FSNODEFLAG_TYPE_NAMEDSEM 0x00000008 /* Named semaphore */ -#define FSNODEFLAG_TYPE_MQUEUE 0x00000009 /* Message Queue */ -#define FSNODEFLAG_TYPE_SHM 0x0000000a /* Shared memory region */ -#define FSNODEFLAG_TYPE_MTD 0x0000000b /* Named MTD driver */ -#define FSNODEFLAG_TYPE_SOFTLINK 0x0000000c /* Soft link */ -#define FSNODEFLAG_DELETED 0x00000010 /* Unlinked */ +#define FSNODEFLAG_TYPE_MASK 0x0000000f /* Isolates type field */ +#define FSNODEFLAG_TYPE_PSEUDODIR 0x00000000 /* Pseudo dir (default) */ +#define FSNODEFLAG_TYPE_DRIVER 0x00000001 /* Character driver */ +#define FSNODEFLAG_TYPE_BLOCK 0x00000002 /* Block driver */ +#define FSNODEFLAG_TYPE_MOUNTPT 0x00000003 /* Mount point */ +#define FSNODEFLAG_TYPE_NAMEDSEM 0x00000004 /* Named semaphore */ +#define FSNODEFLAG_TYPE_MQUEUE 0x00000005 /* Message Queue */ +#define FSNODEFLAG_TYPE_SHM 0x00000006 /* Shared memory region */ +#define FSNODEFLAG_TYPE_MTD 0x00000007 /* Named MTD driver */ +#define FSNODEFLAG_TYPE_SOFTLINK 0x00000008 /* Soft link */ +#define FSNODEFLAG_DELETED 0x00000010 /* Unlinked */ #define INODE_IS_TYPE(i,t) \ (((i)->i_flags & FSNODEFLAG_TYPE_MASK) == (t)) -#define INODE_IS_SPECIAL(i) \ - (((i)->i_flags & FSNODEFLAG_TYPE_SPECIAL) != 0) +#define INODE_IS_PSEUDODIR(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_PSEUDODIR) #define INODE_IS_DRIVER(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_DRIVER) #define INODE_IS_BLOCK(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_BLOCK) #define INODE_IS_MOUNTPT(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_MOUNTPT)