rmdir now may be used to remove empty nodes from the pseudo-filesystem

This commit is contained in:
Gregory Nutt 2014-02-19 10:01:26 -06:00
parent 66a0cfe88f
commit 5bae65fa6c
4 changed files with 95 additions and 49 deletions

View File

@ -6609,5 +6609,8 @@
the kconfig-frontends tools (unverified) (2014-2-18).
* fs/fs_opendir.c, fs_readdir.c, et al: Modified so that errors
will not be reported if you attempt to list a empty pseudo-directory
(2014-2-18).
(2014-2-19).
* fs/fs_rmdir.c: rmdir can be used to removed empty directories in
the pseudo-filesystem such as might be left after umounting a
file system (2014-2-19).

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttShell (NSH)</i></font></big></h1>
<p>Last Updated: February 3, 2014</p>
<p>Last Updated: February 19, 2014</p>
</td>
</tr>
</table>
@ -2727,7 +2727,7 @@ nsh>
</tr>
<tr>
<td><b><code>rmdir</code></b></td>
<td>!<code>CONFIG_DISABLE_MOUNTPOINT</code> &amp;&amp; <code>CONFIG_NFILE_DESCRIPTORS</code> &gt; 0 &amp;&amp; <code>CONFIG_FS_WRITABLE</code><sup>4</sup></td>
<td><code>CONFIG_NFILE_DESCRIPTORS</code> &gt; 0</td>
<td><code>CONFIG_NSH_DISABLE_RMDIR</code></td>
</tr>
<tr>

View File

@ -1,7 +1,7 @@
############################################################################
# fs/Makefile
#
# Copyright (C) 2007, 2008, 2011-2013 Gregory Nutt. All rights reserved.
# Copyright (C) 2007, 2008, 2011-2014 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@ -35,10 +35,10 @@
-include $(TOPDIR)/Make.defs
ASRCS =
AOBJS = $(ASRCS:.S=$(OBJEXT))
ASRCS =
AOBJS = $(ASRCS:.S=$(OBJEXT))
CSRCS =
CSRCS =
# If there are no file descriptors configured, then a small part of the
# logic in this directory may still apply to socket descriptors
@ -48,29 +48,30 @@ ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)
# Socket descriptor support
CSRCS += fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_poll.c fs_select.c
CSRCS += fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_poll.c fs_select.c
endif
# Support for network access using streams
ifneq ($(CONFIG_NFILE_STREAMS),0)
CSRCS += fs_fdopen.c
CSRCS += fs_fdopen.c
endif
else
# Common file/socket descriptor support
CSRCS += fs_close.c fs_closedir.c fs_dup.c fs_dup2.c fs_fcntl.c \
fs_filedup.c fs_filedup2.c fs_ioctl.c fs_lseek.c fs_open.c \
fs_opendir.c fs_poll.c fs_read.c fs_readdir.c fs_rewinddir.c \
fs_seekdir.c fs_stat.c fs_statfs.c fs_select.c fs_write.c
CSRCS += fs_files.c fs_foreachinode.c fs_inode.c fs_inodeaddref.c \
fs_inodefind.c fs_inoderelease.c fs_inoderemove.c \
fs_inodereserve.c
CSRCS += fs_registerdriver.c fs_unregisterdriver.c
CSRCS += fs_registerblockdriver.c fs_unregisterblockdriver.c \
fs_findblockdriver.c fs_openblockdriver.c fs_closeblockdriver.c
CSRCS += fs_close.c fs_closedir.c fs_dup.c fs_dup2.c fs_fcntl.c
CSRCS += fs_filedup.c fs_filedup2.c fs_ioctl.c fs_lseek.c fs_open.c
CSRCS += fs_opendir.c fs_poll.c fs_read.c fs_readdir.c fs_rewinddir.c
CSRCS += fs_rmdir.c fs_seekdir.c fs_stat.c fs_statfs.c fs_select.c
CSRCS += fs_write.c
CSRCS += fs_files.c fs_foreachinode.c fs_inode.c fs_inodeaddref.c
CSRCS += fs_inodefind.c fs_inoderelease.c fs_inoderemove.c
CSRCS += fs_inodereserve.c
CSRCS += fs_registerdriver.c fs_unregisterdriver.c
CSRCS += fs_registerblockdriver.c fs_unregisterblockdriver.c
CSRCS += fs_findblockdriver.c fs_openblockdriver.c fs_closeblockdriver.c
DEPPATH =
VPATH = .
@ -80,7 +81,7 @@ include mmap/Make.defs
# Stream support
ifneq ($(CONFIG_NFILE_STREAMS),0)
CSRCS += fs_fdopen.c
CSRCS += fs_fdopen.c
endif
# Support for sendfile()
@ -93,7 +94,7 @@ endif
ifeq ($(CONFIG_SYSLOG),y)
ifeq ($(CONFIG_SYSLOG_CHAR),y)
CSRCS += fs_syslog.c
CSRCS += fs_syslog.c
endif
endif
@ -101,9 +102,9 @@ endif
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
CSRCS += fs_fsync.c fs_mkdir.c fs_mount.c fs_rename.c fs_rmdir.c \
fs_umount.c fs_unlink.c
CSRCS += fs_foreachmountpoint.c
CSRCS += fs_fsync.c fs_mkdir.c fs_mount.c fs_rename.c fs_umount.c
CSRCS += fs_unlink.c
CSRCS += fs_foreachmountpoint.c
include fat/Make.defs
include romfs/Make.defs
@ -116,16 +117,16 @@ include procfs/Make.defs
endif
endif
COBJS = $(CSRCS:.c=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
OBJS = $(AOBJS) $(COBJS)
SRCS = $(ASRCS) $(CSRCS)
OBJS = $(AOBJS) $(COBJS)
BIN = libfs$(LIBEXT)
BIN = libfs$(LIBEXT)
SUBDIRS = mmap fat romfs nxffs nfs binfs procfs
SUBDIRS = mmap fat romfs nxffs nfs binfs procfs
all: $(BIN)
all: $(BIN)
$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)

View File

@ -76,43 +76,85 @@ int rmdir(FAR const char *pathname)
{
FAR struct inode *inode;
const char *relpath = NULL;
int ret;
int errcode;
/* Get an inode for this file */
/* Get an inode for this file. inode_find() automatically increments the
* reference count on the inode if one is found.
*/
inode = inode_find(pathname, &relpath);
if (!inode)
{
/* There is no mountpoint that includes in this path */
/* There is no inode that includes in this path */
ret = ENOENT;
errcode = ENOENT;
goto errout;
}
/* Verify that the inode is a valid mountpoint. */
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Check if the inode is a valid mountpoint. */
if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops)
if (INODE_IS_MOUNTPT(inode) && inode->u.i_mops)
{
ret = ENXIO;
goto errout_with_inode;
}
/* Perform the rmdir operation using the relative path
* from the mountpoint.
*/
/* Perform the rmdir operation using the relative path
* at the mountpoint.
if (inode->u.i_mops->rmdir)
{
int ret = inode->u.i_mops->rmdir(inode, relpath);
if (ret < 0)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
errcode = ENOSYS;
goto errout_with_inode;
}
}
else
#endif
/* If this is a "dangling" pseudo-file node (i.e., it has no operations)
* then rmdir should remove the node.
*/
if (inode->u.i_mops->rmdir)
if (!inode->u.i_ops)
{
ret = inode->u.i_mops->rmdir(inode, relpath);
if (ret < 0)
int ret;
/* If the directory inode has children, however, then it cannot be
* removed.
*/
if (inode->i_child)
{
ret = -ret;
errcode = ENOTEMPTY;
goto errout_with_inode;
}
/* Remove the inode. NOTE: Because we hold a reference count on the
* inode, it will not be deleted now. But probably when inode_release()
* is called below. inode_remove should return -EBUSY to indicate that
* the inode was not deleted now.
*/
inode_semtake();
ret = inode_remove(pathname);
inode_semgive();
if (ret < 0 && ret != -EBUSY)
{
errcode = -ret;
goto errout_with_inode;
}
}
else
{
ret = ENOSYS;
errcode = ENXIO;
goto errout_with_inode;
}
@ -121,10 +163,10 @@ int rmdir(FAR const char *pathname)
inode_release(inode);
return OK;
errout_with_inode:
errout_with_inode:
inode_release(inode);
errout:
set_errno(ret);
errout:
set_errno(errcode);
return ERROR;
}