From bebb5d8c4d66f68cb286d56805119c8efe6c268f Mon Sep 17 00:00:00 2001
From: Gregory Nutt
Date: Thu, 20 Feb 2014 18:14:02 -0600
Subject: [PATCH] unlink/rm can now be used on nodes in the pseudo-filesystem.
There is new configuration option to suppress these costly and mostly useless
operations on the pseudo-filesystem
---
ChangeLog | 9 ++-
Documentation/NfsHowto.html | 6 +-
Documentation/NuttShell.html | 58 +++++++++---------
arch/arm/src/samd/sam_spi.c | 2 +-
fs/Kconfig | 10 ++++
fs/Makefile | 5 +-
fs/fs_mkdir.c | 34 ++++++++++-
fs/fs_rename.c | 31 +++++++++-
fs/fs_rmdir.c | 28 ++++++++-
fs/fs_unlink.c | 113 +++++++++++++++++++++++++++++------
10 files changed, 233 insertions(+), 63 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1227cad0d9..ab2b470c7a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6089,7 +6089,7 @@
* arch/arm/src/lpc31xx/lpc31_ehci.c: Add USB host trace support
(2013-11-19).
* configs/olimex-lpc-h3131/include/board.h, src/lpc31_boot.c,
- lpc31_leds.c, lpc31_usbhost.c, and lpc_h3131.h: Add GPIO
+ lpc31_leds.c, lpc31_usbhost.c, and lpc_h3131.h: Add GPIO
support for LED1/2 and for USB power enable and overcurrent
detection (2013-11-19).
* configs/olimex-lpc-h3131/nsh/defconfig: Drop loops-per-msec
@@ -6267,7 +6267,7 @@
README.txt, and src/stm32_highpri.c: This is the initial framework
for a test of the high priority, nested interrupt logic. Still
incomplete and does not yet run (2013-12-22).
- * arch/arm/src/armv7-m/ram_vectors.h and up_ramvec_initialize.c:
+ * arch/arm/src/armv7-m/ram_vectors.h and up_ramvec_initialize.c:
Correct alignment of the RAM vector table (2013-12-22).
* Kconfig: Support configuration of interrupt controller debug output
(2013-12-22).
@@ -6630,4 +6630,9 @@
but untested (2014-2-20).
* configs/olimex-lpc1766stck/ftpc: Configuration convert to use
the kconfig-frontends tools by Alan Carvalho de Assis (2014-2-20).
+ * fs/fs_mkdir.c: 'unlink' can now be used to remove things from the
+ pseudo-filesystem. A new configuration option as been added:
+ CONFIG_DISABLE_PSEUDOFS_OPERATIONS that effectively can be set
+ back out these recent changes in rmdir, mkdir, unlink, and rename
+ for operations on the pseudo-filesystem (2014-2-20).
diff --git a/Documentation/NfsHowto.html b/Documentation/NfsHowto.html
index 3eb986bb6a..ed5e6793b8 100644
--- a/Documentation/NfsHowto.html
+++ b/Documentation/NfsHowto.html
@@ -302,7 +302,7 @@ This is a test
# sudo mkdir /export
- It is important that /export
directory allow access to everyone (777 permissions) as we will be accessing the NFS share from the client with no authentication.
+ It is important that /export
directory allow access to everyone (777 permissions) as we will be accessing the NFS share from the client with no authentication.
# sudo chmod 777 /export
@@ -327,7 +327,7 @@ directory machine1(option11,option12)
In our case we are using all the default options except for the ro
that we replaced with rw
so that our client will have read and write access to the directory that we are exporting.
- After we do all the require configurations, we are ready to start the server with the next command:
+ After we do all the require configurations, we are ready to start the server with the next command:
# sudo /etc/init.d/nfs-kernel-server start
@@ -337,7 +337,7 @@ directory machine1(option11,option12)
or run command exportfs.
-# sudo /etc/init.d/nfs-kernel-server start
+# sudo /etc/init.d/nfs-kernel-server start
Or
diff --git a/Documentation/NuttShell.html b/Documentation/NuttShell.html
index 4130294cc4..0f90e76109 100644
--- a/Documentation/NuttShell.html
+++ b/Documentation/NuttShell.html
@@ -8,7 +8,7 @@
NuttShell (NSH)
- Last Updated: February 19, 2014
+ Last Updated: February 20, 2014
|
@@ -1301,7 +1301,7 @@ nsh> df
Size Blocks Used Available Mounted on
64 6 6 0 /etc
512 985 2 983 /tmp
-nsh>
+nsh>
If CONFIG_NSH_CMDOPT_DF_H
is defined in the NuttX configuration, then the df
will also support an option -h
which may be used to show the volume information in human readable format.
@@ -1653,7 +1653,7 @@ losetup [-o ] [-r] <dev-path> <file-path>
Synopsis.
Setup the loop device at <dev-path> to access the file at <file-path> as a block device.
In the following example a 256K file is created (dd
) and losetup
is
- used to make the file accessible as a block device.
+ used to make the file accessible as a block device.
A FAT file system is created (mkfatfs
) and mounted (mount
).
Files can then be managed on the loop-mounted file.
@@ -2488,7 +2488,7 @@ nsh>
The availability of the above commands depends upon features that
- may or may not be enabled in the NuttX configuration file. The
+ may or may not be enabled in the NuttX configuration file. The
following table indicates the dependency of each command on NuttX
configuration settings. General configuration settings are discussed
in the NuttX Porting Guide.
@@ -2664,7 +2664,7 @@ nsh>
mkdir |
- !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE 4 |
+ (((!CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_WRITABLE ) || !CONFIG_DISABLE_PSEUDOFS_OPERATIONS ) && CONFIG_NFILE_DESCRIPTORS > 0)4 |
CONFIG_NSH_DISABLE_MKDIR |
@@ -2689,7 +2689,7 @@ nsh>
mv |
- !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE 3 |
+ (((!CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_WRITABLE ) || !CONFIG_DISABLE_PSEUDOFS_OPERATIONS ) && CONFIG_NFILE_DESCRIPTORS > 0)4 |
CONFIG_NSH_DISABLE_MV |
@@ -2722,12 +2722,12 @@ nsh>
rm |
- !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_WRITABLE 4 |
+ (((!CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_WRITABLE ) || !CONFIG_DISABLE_PSEUDOFS_OPERATIONS ) && CONFIG_NFILE_DESCRIPTORS > 0)4 |
CONFIG_NSH_DISABLE_RM |
rmdir |
- CONFIG_NFILE_DESCRIPTORS > 0 |
+ (((!CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_WRITABLE ) || !CONFIG_DISABLE_PSEUDOFS_OPERATIONS ) && CONFIG_NFILE_DESCRIPTORS > 0)4 |
CONFIG_NSH_DISABLE_RMDIR |
@@ -3007,7 +3007,7 @@ set FOOBAR ABC_${FOO}_${BAR}
CONFIG_NSH_USBCONSOLE
.
If defined, then the an arbitrary USB device may be used to as the NSH console.
- In this case, CONFIG_NSH_CONDEV
must be defined to indicate which USB device to use as the console.
+ In this case, CONFIG_NSH_CONDEV
must be defined to indicate which USB device to use as the console.
The advantage of using a device other that /dev/console is that normal debug output can not use /dev/console while NSH uses CONFIG_NSH_USBCONDEV
.
CONFIG_NSH_USBCONDEV
.
@@ -3365,7 +3365,7 @@ set FOOBAR ABC_${FOO}_${BAR}
4.1.1 NSH Initialization sequence
- The NSH start-up sequence is very simple.
+ The NSH start-up sequence is very simple.
As an example, the code at apps/examples/nsh/nsh_main.c
illustrates how to start NSH.
It simple does the following:
@@ -3469,7 +3469,7 @@ mount -t vfat /dev/ram1 /tmp
- Mount the FAT filesystem at a configured mountpoint, /tmp
.
+ Mount the FAT filesystem at a configured mountpoint, /tmp
.
@@ -3502,7 +3502,7 @@ mount -t vfat /dev/ram1 /tmp
Overview.
NSH supports a variety of commands as part of the NSH program.
All of the NSH commands are listed in the NSH documentation above.
- Not all of these commands may be available at any time, however.
+ Not all of these commands may be available at any time, however.
Many commands depend upon certain NuttX configuration options.
You can enter the help command at the NSH prompt to see the commands actual available:
@@ -3619,7 +3619,7 @@ struct cmdmap_s
Overview.
In addition to these commands that are a part of NSH, external programs can also be executed as NSH commands.
- These external programs are called "Built-In" Applications for historic reasons.
+ These external programs are called "Built-In" Applications for historic reasons.
That terminology is somewhat confusing because the actual NSH commands as described above are truly "built-into" NSH whereas these applications are really external to NuttX.
@@ -3716,7 +3716,7 @@ Builtin Apps:
The NuttX build occurs in several phases as different build targets are executed:
(1) context when the configuration is established,
(2) depend when target dependencies are generated, and
- (3) default (all
) when the normal compilation and link operations are performed.
+ (3) default (all
) when the normal compilation and link operations are performed.
Built-in application information is collected during the make context build phase.
@@ -3912,7 +3912,7 @@ CONFIGURED_APPS += examples/hello
You replace the sample code at apps/examples/nsh/nsh_main.c
with whatever start-up logic that you want.
- NSH is a library at apps/nshlib
.
+ NSH is a library at apps/nshlib
.
apps.examplex/nsh
is just a tiny, example start-up function (CONFIG_USER_ENTRYPOINT
()) that that runs immediately and illustrates how to start NSH
If you want something else to run immediately then you can write your write your own custom CONFIG_USER_ENTRYPOINT
() function and then start other tasks from your custom CONFIG_USER_ENTRYPOINT
().
@@ -3938,7 +3938,7 @@ CONFIGURED_APPS += examples/hello
NSH supports options to provide a start up script for NSH.
The start-up script contains any command support by NSH (i.e., that you see when you enter 'nsh> help').
In general this capability is enabled with CONFIG_NSH_ROMFSETC=y
, but has several other related configuration options as described with the NSH-specific configuration settings paragraph.
- This capability also depends on:
+ This capability also depends on:
@@ -3962,26 +3962,26 @@ CONFIGURED_APPS += examples/hello
Default Start-Up Behavior.
The implementation that is provided is intended to provide great flexibility for the use of Start-Up files.
- This paragraph will discuss the general behavior when all of the configuration options are set to the default values.
+ This paragraph will discuss the general behavior when all of the configuration options are set to the default values.
- In this default case, enabling CONFIG_NSH_ROMFSETC
will cause NSH to behave as follows at NSH start-up time:
+ In this default case, enabling CONFIG_NSH_ROMFSETC
will cause NSH to behave as follows at NSH start-up time:
-
- NSH will create a read-only RAM disk (a ROM disk), containing a tiny ROMFS filesystem containing the following:
+ NSH will create a read-only RAM disk (a ROM disk), containing a tiny ROMFS filesystem containing the following:
`--init.d/
`-- rcS
- Where rcS
is the NSH start-up script.
+ Where rcS
is the NSH start-up script.
-
- NSH will then mount the ROMFS filesystem at /etc
, resulting in:
+ NSH will then mount the ROMFS filesystem at /etc
, resulting in:
|--dev/
@@ -3992,7 +3992,7 @@ CONFIGURED_APPS += examples/hello
- By default, the contents of rcS
script are:
+ By default, the contents of rcS
script are:
# Create a RAMDISK and mount it at /tmp
@@ -4004,7 +4004,7 @@ mount -t vfat /dev/ram1 /tmp
NSH will execute the script at /etc/init.d/rcS
at start-up (before the first NSH prompt).
- After execution of the script, the root FS will look like:
+ After execution of the script, the root FS will look like:
|--dev/
@@ -4048,7 +4048,7 @@ mount -t vfat /dev/ram1 /tmp
Modifying the ROMFS Image.
The contents of the /etc
directory are retained in the file apps/nshlib/nsh_romfsimg.h
OR, if CONFIG_NSH_ARCHROMFS
is defined, include/arch/board/rcs.template
.
- In order to modify the start-up behavior, there are three things to study:
+ In order to modify the start-up behavior, there are three things to study:
@@ -4062,15 +4062,15 @@ mount -t vfat /dev/ram1 /tmp
tools/mkromfsimg.sh
Script.
The script tools/mkromfsimg.sh
creates nsh_romfsimg.h
.
It is not automatically executed.
- If you want to change the configuration settings associated with creating and mounting the /tmp
directory, then it will be necessary to re-generate this header file using the tools/mkromfsimg.sh
script.
+ If you want to change the configuration settings associated with creating and mounting the /tmp
directory, then it will be necessary to re-generate this header file using the tools/mkromfsimg.sh
script.
- The behavior of this script depends upon several things:
+ The behavior of this script depends upon several things:
-
- The configuration settings then installed configuration.
+ The configuration settings then installed configuration.
-
@@ -4089,7 +4089,7 @@ mount -t vfat /dev/ram1 /tmp
-
rcS.template
.
- The file apps/nshlib/rcS.template
contains the general form of the rcS
file; configured values are plugged into this template file to produce the final rcS
file.
+ The file apps/nshlib/rcS.template
contains the general form of the rcS
file; configured values are plugged into this template file to produce the final rcS
file.
@@ -4273,7 +4273,7 @@ mount -t vfat /dev/ram1 /tmp
- NSH library (
nshlib
)
- NSH library (
nshlib
)
nsh_archinitialize()
- nsh_consolemain()
+ nsh_consolemain()
nsh_initialize()
nsh_main()
nsh_main.c
diff --git a/arch/arm/src/samd/sam_spi.c b/arch/arm/src/samd/sam_spi.c
index 46ea0f4672..9c9bf522a8 100644
--- a/arch/arm/src/samd/sam_spi.c
+++ b/arch/arm/src/samd/sam_spi.c
@@ -1550,7 +1550,7 @@ struct spi_dev_s *up_spiinitialize(int port)
(void)spi_setfrequency((struct spi_dev_s *)priv, 400000);
- /* Set MSB first data order and the configured pad mux setting,
+ /* Set MSB first data order and the configured pad mux setting,
* Note that SPI mode 0 is assumed initially (CPOL=0 and CPHA=0).
*/
diff --git a/fs/Kconfig b/fs/Kconfig
index b7f3f059df..defeba0111 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -9,6 +9,16 @@ config DISABLE_MOUNTPOINT
bool "Disable support for mount points"
default n
+config DISABLE_PSEUDOFS_OPERATIONS
+ bool "Disable pseudo-filesytem operations"
+ default n
+ ---help---
+ Disable certain operations on pseudo-file systems include mkdir,
+ rmdir, unlink, and rename. These are necessary for the logical
+ completeness of the illusion created by the pseudo-filesystem.
+ However, in practical embedded system, they are seldom needed and
+ you can save a little FLASH space by disabling the capability.
+
config FS_READABLE
bool
default n
diff --git a/fs/Makefile b/fs/Makefile
index 05a27d7ebe..3acfe606d3 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -65,7 +65,7 @@ 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_mkdir.c
CSRCS += fs_open.c fs_opendir.c fs_poll.c fs_read.c fs_readdir.c
CSRCS += fs_rename.c fs_rewinddir.c fs_rmdir.c fs_seekdir.c fs_stat.c
-CSRCS += fs_statfs.c fs_select.c fs_write.c
+CSRCS += fs_statfs.c fs_select.c fs_unlink.c fs_write.c
CSRCS += fs_files.c fs_foreachinode.c fs_inode.c fs_inodeaddref.c
CSRCS += fs_inodebasename.c fs_inodefind.c fs_inoderelease.c
@@ -104,8 +104,7 @@ endif
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
-CSRCS += fs_fsync.c fs_mount.c fs_umount.c fs_unlink.c
-CSRCS += fs_foreachmountpoint.c
+CSRCS += fs_fsync.c fs_mount.c fs_umount.c fs_foreachmountpoint.c
include fat/Make.defs
include romfs/Make.defs
diff --git a/fs/fs_mkdir.c b/fs/fs_mkdir.c
index 2cf20afe25..74d5e04f62 100644
--- a/fs/fs_mkdir.c
+++ b/fs/fs_mkdir.c
@@ -46,9 +46,27 @@
#include "fs_internal.h"
/****************************************************************************
- * Definitions
+ * Pre-processor Definitions
****************************************************************************/
+#undef FS_HAVE_WRITABLE_MOUNTPOINT
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
+ CONFIG_NFILE_STREAMS > 0
+# define FS_HAVE_WRITABLE_MOUNTPOINT 1
+#endif
+
+#undef FS_HAVE_PSEUDOFS_OPERATIONS
+#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
+# define FS_HAVE_PSEUDOFS_OPERATIONS 1
+#endif
+
+#undef FS_HAVE_MKDIR
+#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
+# define FS_HAVE_MKDIR 1
+#endif
+
+#ifdef FS_HAVE_MKDIR
+
/****************************************************************************
* Private Variables
****************************************************************************/
@@ -113,7 +131,7 @@ int mkdir(const char *pathname, mode_t mode)
}
}
else
- {
+ {
errcode = ENOSYS;
goto errout_with_inode;
}
@@ -125,10 +143,11 @@ int mkdir(const char *pathname, mode_t mode)
/* But mountpoints are not supported in this configuration */
errcode = EEXIST;
- goto errout_with_inode;
+ 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.
*/
@@ -147,6 +166,13 @@ int mkdir(const char *pathname, mode_t mode)
goto errout;
}
}
+#else
+ else
+ {
+ errcode = ENXIO;
+ goto errout;
+ }
+#endif
/* Directory successfully created */
@@ -158,3 +184,5 @@ int mkdir(const char *pathname, mode_t mode)
set_errno(errcode);
return ERROR;
}
+
+#endif /* FS_HAVE_MKDIR */
diff --git a/fs/fs_rename.c b/fs/fs_rename.c
index 405d25cc2e..38da25b970 100644
--- a/fs/fs_rename.c
+++ b/fs/fs_rename.c
@@ -49,6 +49,24 @@
* Pre-processor Definitions
****************************************************************************/
+#undef FS_HAVE_WRITABLE_MOUNTPOINT
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
+ CONFIG_NFILE_STREAMS > 0
+# define FS_HAVE_WRITABLE_MOUNTPOINT 1
+#endif
+
+#undef FS_HAVE_PSEUDOFS_OPERATIONS
+#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
+# define FS_HAVE_PSEUDOFS_OPERATIONS 1
+#endif
+
+#undef FS_HAVE_RENAME
+#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
+# define FS_HAVE_RENAME 1
+#endif
+
+#ifdef FS_HAVE_RENAME
+
/****************************************************************************
* Private Variables
****************************************************************************/
@@ -75,9 +93,9 @@
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
- FAR struct inode *newinode;
const char *newrelpath = NULL;
#endif
int errcode;
@@ -144,7 +162,7 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
}
}
else
- {
+ {
errcode = ENOSYS;
goto errout_with_newinode;
}
@@ -155,6 +173,7 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
}
else
#endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
{
/* Create a new, empty inode at the destination location */
@@ -210,6 +229,12 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
oldinode->i_child = NULL;
inode_semgive();
}
+#else
+ {
+ errcode = ENXIO;
+ goto errout;
+ }
+#endif
/* Successfully renamed */
@@ -226,3 +251,5 @@ int rename(FAR const char *oldpath, FAR const char *newpath)
set_errno(errcode);
return ERROR;
}
+
+#endif /* FS_HAVE_RENAME */
diff --git a/fs/fs_rmdir.c b/fs/fs_rmdir.c
index 9c863d8c4f..14f3250097 100644
--- a/fs/fs_rmdir.c
+++ b/fs/fs_rmdir.c
@@ -49,6 +49,24 @@
* Pre-processor Definitions
****************************************************************************/
+#undef FS_HAVE_WRITABLE_MOUNTPOINT
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
+ CONFIG_NFILE_STREAMS > 0
+# define FS_HAVE_WRITABLE_MOUNTPOINT 1
+#endif
+
+#undef FS_HAVE_PSEUDOFS_OPERATIONS
+#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
+# define FS_HAVE_PSEUDOFS_OPERATIONS 1
+#endif
+
+#undef FS_HAVE_RMDIR
+#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
+# define FS_HAVE_RMDIR 1
+#endif
+
+#ifdef FS_HAVE_RMDIR
+
/****************************************************************************
* Private Variables
****************************************************************************/
@@ -118,7 +136,8 @@ int rmdir(FAR const char *pathname)
else
#endif
- /* If this is a "dangling" pseudo-file node (i.e., it has no operations)
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ /* If this is a "dangling" pseudo-directory node (i.e., it has no operations)
* then rmdir should remove the node.
*/
@@ -153,10 +172,16 @@ int rmdir(FAR const char *pathname)
}
}
else
+ {
+ errcode = ENOTDIR;
+ goto errout_with_inode;
+ }
+#else
{
errcode = ENXIO;
goto errout_with_inode;
}
+#endif
/* Successfully removed the directory */
@@ -170,3 +195,4 @@ errout:
return ERROR;
}
+#endif /* FS_HAVE_RMDIR */
diff --git a/fs/fs_unlink.c b/fs/fs_unlink.c
index f57bd33b57..c17bed7136 100644
--- a/fs/fs_unlink.c
+++ b/fs/fs_unlink.c
@@ -49,6 +49,24 @@
* Pre-processor Definitions
****************************************************************************/
+#undef FS_HAVE_WRITABLE_MOUNTPOINT
+#if !defined(CONFIG_DISABLE_MOUNTPOINT) && defined(CONFIG_FS_WRITABLE) && \
+ CONFIG_NFILE_STREAMS > 0
+# define FS_HAVE_WRITABLE_MOUNTPOINT 1
+#endif
+
+#undef FS_HAVE_PSEUDOFS_OPERATIONS
+#if !defined(CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_STREAMS > 0
+# define FS_HAVE_PSEUDOFS_OPERATIONS 1
+#endif
+
+#undef FS_HAVE_UNLINK
+#if defined(FS_HAVE_WRITABLE_MOUNTPOINT) || defined(FS_HAVE_PSEUDOFS_OPERATIONS)
+# define FS_HAVE_UNLINK 1
+#endif
+
+#ifdef FS_HAVE_UNLINK
+
/****************************************************************************
* Private Variables
****************************************************************************/
@@ -76,6 +94,7 @@ int unlink(FAR const char *pathname)
{
FAR struct inode *inode;
const char *relpath = NULL;
+ int errcode;
int ret;
/* Get an inode for this file */
@@ -83,38 +102,93 @@ int unlink(FAR const char *pathname)
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 unlink operation using the relative path at the
+ * mountpoint.
+ */
- /* Perform the unlink operation using the relative path
- * at the mountpoint.
- */
-
- if (inode->u.i_mops->unlink)
- {
- ret = inode->u.i_mops->unlink(inode, relpath);
- if (ret < 0)
+ if (inode->u.i_mops->unlink)
{
- ret = -ret;
+ ret = inode->u.i_mops->unlink(inode, relpath);
+ if (ret < 0)
+ {
+ errcode = -ret;
+ goto errout_with_inode;
+ }
+ }
+ else
+ {
+ errcode = ENOSYS;
goto errout_with_inode;
}
}
else
- {
- ret = ENOSYS;
+#endif
+
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+ /* If this is a "dangling" pseudo-file node (i.e., it has operations) then rm
+ * should remove the node.
+ */
+
+ if (inode->u.i_ops)
+ {
+ /* If this is a pseudo-file node (i.e., it has no operations)
+ * then rmdir should remove the node.
+ */
+
+ if (inode->u.i_ops)
+ {
+ inode_semtake();
+
+ /* 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)
+ {
+ errcode = ENOTEMPTY;
+ inode_semgive();
+ goto errout_with_inode;
+ }
+
+ /* 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() will
+ * return -EBUSY to indicate that the inode was not deleted now.
+ */
+
+ ret = inode_remove(pathname);
+ inode_semgive();
+
+ if (ret < 0 && ret != -EBUSY)
+ {
+ errcode = -ret;
+ goto errout_with_inode;
+ }
+ }
+ else
+ {
+ errcode = EISDIR;
+ goto errout_with_inode;
+ }
+ }
+#else
+ {
+ errcode = ENXIO;
goto errout_with_inode;
}
+#endif
/* Successfully unlinked */
@@ -124,7 +198,8 @@ int unlink(FAR const char *pathname)
errout_with_inode:
inode_release(inode);
errout:
- set_errno(ret);
+ set_errno(errcode);
return ERROR;
}
+#endif /* FS_HAVE_UNLINK */