From 5bae65fa6cc65591ee048ac4bfc21f8816560300 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 19 Feb 2014 10:01:26 -0600 Subject: [PATCH] rmdir now may be used to remove empty nodes from the pseudo-filesystem --- ChangeLog | 5 ++- Documentation/NuttShell.html | 4 +- fs/Makefile | 55 +++++++++++++------------ fs/fs_rmdir.c | 80 +++++++++++++++++++++++++++--------- 4 files changed, 95 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index 69437b8873..b8f92e7870 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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). diff --git a/Documentation/NuttShell.html b/Documentation/NuttShell.html index e3078d732c..4130294cc4 100644 --- a/Documentation/NuttShell.html +++ b/Documentation/NuttShell.html @@ -8,7 +8,7 @@

NuttShell (NSH)

-

Last Updated: February 3, 2014

+

Last Updated: February 19, 2014

@@ -2727,7 +2727,7 @@ nsh> rmdir - !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE4 + CONFIG_NFILE_DESCRIPTORS > 0 CONFIG_NSH_DISABLE_RMDIR diff --git a/fs/Makefile b/fs/Makefile index 7e90c4f7e9..206d038a77 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -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 # # 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, $<, $@) diff --git a/fs/fs_rmdir.c b/fs/fs_rmdir.c index 317d7cc42e..9c863d8c4f 100644 --- a/fs/fs_rmdir.c +++ b/fs/fs_rmdir.c @@ -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; }