diff --git a/ChangeLog b/ChangeLog index 03942b0f73..c6d46b359a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -140,5 +140,6 @@ 0.2.6 2007-xx-xx Gregory Nutt + * Added unlink(), mkdir(), rmdir(), and rename() * Started m68322 diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index 965b575e75..726a5a5c5f 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -519,6 +519,7 @@ Other memory: 0.2.6 2007-xx-xx Gregory Nutt + * Added unlink(), mkdir(), rmdir(), and rename() * Started m68322 diff --git a/TODO b/TODO index f5cf5bff58..4a3c815f23 100644 --- a/TODO +++ b/TODO @@ -38,9 +38,8 @@ o Libraries - sscanf() and lib_vsprintf() do not support floating point values. o File system -- Add disk usage stats, stat(), unlink(), mkdir(), chmod(), rename(), -etc. -- FAT32: long file names +- Add disk usage stats, stat(), chmod(), truncate(). +- FAT32: long file names, unlink(), mkdir(), rmdir(), rename() o Console Output diff --git a/fs/Makefile b/fs/Makefile index 4f2b1e5ba5..69ffce62dd 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -46,7 +46,8 @@ CSRCS = fs_open.c fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_dup.c \ fs_inode.c fs_inodefind.c fs_inodefinddir.c fs_inodereserve.c \ fs_inoderemove.c fs_registerdriver.c fs_unregisterdriver.c \ fs_registerblockdriver.c fs_unregisterblockdriver.c \ - fs_mount.c fs_umount.c fs_inodeaddref.c fs_inoderelease.c + fs_mount.c fs_umount.c fs_unlink.c fs_mkdir.c fs_rmdir.c \ + fs_rename.c fs_inodeaddref.c fs_inoderelease.c ifeq ($(CONFIG_FS_FAT),y) CSRCS += fs_fat32.c fs_fat32util.c endif diff --git a/fs/fs_fat32.c b/fs/fs_fat32.c index f6c0ec421b..81992e72d0 100644 --- a/fs/fs_fat32.c +++ b/fs/fs_fat32.c @@ -82,9 +82,16 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer, static off_t fat_seek(FAR struct file *filp, off_t offset, int whence); static int fat_ioctl(FAR struct file *filp, int cmd, unsigned long arg); static int fat_sync(FAR struct file *filp); + static int fat_bind(FAR struct inode *blkdriver, const void *data, void **handle); static int fat_unbind(void *handle); +static int fat_unlink(struct inode *mountpt, const char *rel_path); +static int fat_mkdir(struct inode *mountpt, const char *rel_path, + mode_t mode); +static int fat_rmdir(struct inode *mountpt, const char *rel_path); +static int fat_rename(struct inode *mountpt, const char *old_relpath, + const char *new_relpath); /**************************************************************************** * Private Variables @@ -108,8 +115,12 @@ const struct mountpt_operations fat_operations = fat_seek, fat_ioctl, fat_sync, + fat_bind, - fat_unbind + fat_unbind, + fat_unlink, + fat_mkdir, + fat_rename }; /**************************************************************************** @@ -1302,6 +1313,155 @@ static int fat_unbind(void *handle) return ret; } +/**************************************************************************** + * Name: fat_unlink + * + * Description: Remove a file + * + ****************************************************************************/ + +static int fat_unlink(struct inode *mountpt, const char *rel_path) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + +#warning "fat_unlink is not implemented" + ret = -ENOSYS; + + errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_mkdir + * + * Description: Create a directory + * + ****************************************************************************/ + +static int fat_mkdir(struct inode *mountpt, const char *rel_path, mode_t mode) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + +#warning "fat_mkdir is not implemented" + ret = -ENOSYS; + + errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_rmdir + * + * Description: Remove a directory + * + ****************************************************************************/ + +int fat_rmdir(struct inode *mountpt, const char *rel_path) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + +#warning "fat_rmdir is not implemented" + ret = -ENOSYS; + + errout_with_semaphore: + fat_semgive(fs); + return ret; +} + +/**************************************************************************** + * Name: fat_rename + * + * Description: Rename a file or directory + * + ****************************************************************************/ + +int fat_rename(struct inode *mountpt, const char *old_relpath, + const char *new_relpath) +{ + struct fat_mountpt_s *fs; + int ret; + + /* Sanity checks */ + + DEBUGASSERT(mountpt && mountpt->i_private); + + /* Get the mountpoint private data from the inode structure */ + + fs = mountpt->i_private; + + /* Check if the mount is still healthy */ + + fat_semtake(fs); + ret = fat_checkmount(fs); + if (ret != OK) + { + goto errout_with_semaphore; + } + +#warning "fat_rename is not implemented" + ret = -ENOSYS; + + errout_with_semaphore: + fat_semgive(fs); + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/fs/fs_mkdir.c b/fs/fs_mkdir.c new file mode 100644 index 0000000000..3536744dde --- /dev/null +++ b/fs/fs_mkdir.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * fs_mkdir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "fs_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mkdir + * + * Description: Create a directory + * + ****************************************************************************/ + +int mkdir(const char *pathname, mode_t mode) +{ + FAR struct inode *inode; + const char *relpath = NULL; + int ret; + + /* Get an inode for this file */ + + inode = inode_find(pathname, &relpath); + if (!inode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the inode is a valid mountpoint. */ + + if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops) + { + ret = ENXIO; + goto errout_with_inode; + } + + /* Perform the mkdir operation using the relative path + * at the mountpoint. + */ + + if (inode->u.i_mops->mkdir) + { + ret = inode->u.i_mops->mkdir(inode, relpath, mode); + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + } + else + { + ret = ENOSYS; + goto errout_with_inode; + } + + /* Directory successfully created */ + + inode_release(inode); + return OK; + + errout_with_inode: + inode_release(inode); + errout: + *get_errno_ptr() = ret; + return ERROR; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/fs/fs_open.c b/fs/fs_open.c index fd4462c993..55427c0d3b 100644 --- a/fs/fs_open.c +++ b/fs/fs_open.c @@ -63,8 +63,7 @@ int inode_checkflags(FAR struct inode *inode, int oflags) if (((oflags & O_RDOK) != 0 && !inode->u.i_ops->read) || ((oflags & O_WROK) != 0 && !inode->u.i_ops->write)) { - *get_errno_ptr() = EACCES; - return ERROR; + return -EACCES; } else { @@ -74,19 +73,20 @@ int inode_checkflags(FAR struct inode *inode, int oflags) int open(const char *path, int oflags, ...) { - struct filelist *list; + struct filelist *list; FAR struct inode *inode; - mode_t mode = 0666; - int status; - int fd; + const char *relpath = NULL; + mode_t mode = 0666; + int ret; + int fd; /* Get the thread-specific file list */ list = sched_getfiles(); if (!list) { - *get_errno_ptr() = EMFILE; - return ERROR; + ret = EMFILE; + goto errout; } #ifdef CONFIG_FILE_MODE @@ -105,7 +105,6 @@ int open(const char *path, int oflags, ...) /* Get an inode for this file */ - const char *relpath = NULL; inode = inode_find(path, &relpath); if (!inode) { @@ -114,26 +113,27 @@ int open(const char *path, int oflags, ...) * dangling symbolic link." */ - *get_errno_ptr() = ENOENT; - return ERROR; + ret = ENOENT; + goto errout; } - /* Verify that the inode is either a "normal" or a mountpoint. We + /* Verify that the inode is valid and either a "normal" or a mountpoint. We * specifically exclude block drivers. */ - if (!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) + if ((!INODE_IS_DRIVER(inode) && !INODE_IS_MOUNTPT(inode)) || !inode->u.i_ops) { - *get_errno_ptr() = ENXIO; - return ERROR; + ret = ENXIO; + goto errout_with_inode; } /* Make sure that the inode supports the requested access */ - if (inode_checkflags(inode, oflags) != OK) + ret = inode_checkflags(inode, oflags); + if (ret < 0) { - inode_release(inode); - return ERROR; + ret = -ret; + goto errout_with_inode; } /* Associate the inode with a file structure */ @@ -141,9 +141,8 @@ int open(const char *path, int oflags, ...) fd = files_allocate(inode, oflags, 0); if (fd < 0) { - inode_release(inode); - *get_errno_ptr() = EMFILE; - return ERROR; + ret = EMFILE; + goto errout_with_inode; } /* Perform the driver open operation. NOTE that the open method may @@ -151,29 +150,35 @@ int open(const char *path, int oflags, ...) * becuase it may also be closed that many times. */ - status = OK; - if (inode->u.i_ops && inode->u.i_ops->open) + ret = OK; + if (inode->u.i_ops->open) { if (INODE_IS_MOUNTPT(inode)) { - status = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd], - relpath, oflags, mode); + ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd], + relpath, oflags, mode); } else { - status = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]); + ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]); } } - if (status != OK || !inode->u.i_ops) + if (ret < 0) { - files_release(fd); - inode_release(inode); - *get_errno_ptr() = ENODEV; - return ERROR; + ret = -ret; + goto errout_with_fd; } return fd; + + errout_with_fd: + files_release(fd); + errout_with_inode: + inode_release(inode); + errout: + *get_errno_ptr() = ret; + return ERROR; } #endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/fs/fs_rename.c b/fs/fs_rename.c new file mode 100644 index 0000000000..cf5208eea5 --- /dev/null +++ b/fs/fs_rename.c @@ -0,0 +1,157 @@ +/**************************************************************************** + * fs_rename.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "fs_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rename + * + * Description: Remove a file managed a mountpoint + * + ****************************************************************************/ + +int rename(const char *oldpath, const char *newpath) +{ + FAR struct inode *oldinode; + FAR struct inode *newinode; + const char *oldrelpath = NULL; + const char *newrelpath = NULL; + int ret; + + /* Get an inode for the old relpath */ + + oldinode = inode_find(oldpath, &oldrelpath); + if (!oldinode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the old inode is a valid mountpoint. */ + + if (!INODE_IS_MOUNTPT(oldinode) || !oldinode->u.i_mops) + { + ret = ENXIO; + goto errout_with_oldinode; + } + + /* Get an inode for the new relpath -- it should like on the same mountpoint */ + + newinode = inode_find(newpath, &newrelpath); + if (!newinode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout_with_oldinode; + } + + /* Verify that the two pathes lie on the same mountpt inode */ + + if (oldinode != newinode) + { + ret = EXDEV; + goto errout_with_newinode; + } + + /* Perform the rename operation using the relative pathes + * at the common mountpoint. + */ + + if (oldinode->u.i_mops->rename) + { + ret = oldinode->u.i_mops->rename(oldinode, oldrelpath, newrelpath); + if (ret < 0) + { + ret = -ret; + goto errout_with_newinode; + } + } + else + { + ret = ENOSYS; + goto errout_with_newinode; + } + + /* Successfully renamed */ + + inode_release(oldinode); + inode_release(newinode); + return OK; + + errout_with_newinode: + inode_release(newinode); + errout_with_oldinode: + inode_release(oldinode); + errout: + *get_errno_ptr() = ret; + return ERROR; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/fs/fs_rmdir.c b/fs/fs_rmdir.c new file mode 100644 index 0000000000..c999206fb6 --- /dev/null +++ b/fs/fs_rmdir.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * fs_rmdir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "fs_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rmdir + * + * Description: Remove a file managed a mountpoint + * + ****************************************************************************/ + +int rmdir(const char *pathname) +{ + FAR struct inode *inode; + const char *relpath = NULL; + int ret; + + /* Get an inode for this file */ + + inode = inode_find(pathname, &relpath); + if (!inode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the inode is a valid mountpoint. */ + + if (!INODE_IS_MOUNTPT(inode) || !inode->u.i_mops) + { + ret = ENXIO; + goto errout_with_inode; + } + + /* Perform the rmdir operation using the relative path + * at the mountpoint. + */ + + if (inode->u.i_mops->rmdir) + { + ret = inode->u.i_mops->rmdir(inode, relpath); + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + } + else + { + ret = ENOSYS; + goto errout_with_inode; + } + + /* Successfully removed the directory */ + + inode_release(inode); + return OK; + + errout_with_inode: + inode_release(inode); + errout: + *get_errno_ptr() = ret; + return ERROR; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/fs/fs_unlink.c b/fs/fs_unlink.c new file mode 100644 index 0000000000..46c7f0cd0a --- /dev/null +++ b/fs/fs_unlink.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * fs_unlink.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "fs_internal.h" + +#if CONFIG_NFILE_DESCRIPTORS > 0 + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: unlink + * + * Description: Remove a file managed a mountpoint + * + ****************************************************************************/ + +int unlink(const char *pathname) +{ + FAR struct inode *inode; + const char *relpath = NULL; + int ret; + + /* Get an inode for this file */ + + inode = inode_find(pathname, &relpath); + if (!inode) + { + /* There is no mountpoint that includes in this path */ + + ret = ENOENT; + goto errout; + } + + /* Verify that the inode is a valid mountpoint. */ + + 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. + */ + + if (inode->u.i_mops->unlink) + { + ret = inode->u.i_mops->unlink(inode, relpath); + if (ret < 0) + { + ret = -ret; + goto errout_with_inode; + } + } + else + { + ret = ENOSYS; + goto errout_with_inode; + } + + /* Successfully unlinked */ + + inode_release(inode); + return OK; + + errout_with_inode: + inode_release(inode); + errout: + *get_errno_ptr() = ret; + return ERROR; +} + +#endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/include/nuttx/fs.h b/include/nuttx/fs.h index 043514034c..639f688567 100644 --- a/include/nuttx/fs.h +++ b/include/nuttx/fs.h @@ -139,20 +139,24 @@ struct mountpt_operations /* The two structures need not be common after this point. The following * are extended methods needed to deal with the unique needs of mounted * file systems. + * + * Additional open-file-specific mountpoint operations: */ int (*sync)(FAR struct file *filp); - /* The two structures need not be common after this point. For the - * case of struct mountpt_operations, additional operations are included - * that used only for mounting and unmounting the volume. - */ + /* General volume-related mountpoint operations: */ int (*bind)(FAR struct inode *blkdriver, const void *data, void **handle); int (*unbind)(void *handle); + int (*unlink)(struct inode *mountpt, const char *rel_path); + int (*mkdir)(struct inode *mountpt, const char *rel_path, mode_t mode); + int (*rmdir)(struct inode *mountpt, const char *rel_path); + int (*rename)(struct inode *mountpt, const char *old_relpath, const char *new_relpath); + /* NOTE: More operations will be needed here to support: disk usage stats - * stat(), unlink(), mkdir(), chmod(), rename(), etc. + * file stat(), file attributes, file truncation, etc. */ }; diff --git a/include/stdio.h b/include/stdio.h index b2937ed91b..bdad75eb68 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -155,7 +155,7 @@ EXTERN char *gets(char *s); EXTERN int printf(const char *format, ...); EXTERN int puts(const char *s); -EXTERN int rename(const char *source, const char *target); +EXTERN int rename(const char *oldpath, const char *newpath); EXTERN int sprintf(char *dest, const char *format, ...); EXTERN int ungetc(int c, FILE *stream); EXTERN int vprintf(const char *s, va_list ap); @@ -168,8 +168,6 @@ EXTERN int chdir(const char *path); EXTERN FILE *fdopen(int fd, const char *type); EXTERN int fstat(int fd, FAR struct stat *buf); EXTERN char *getcwd(FAR char *buf, size_t size); -EXTERN int mkdir(const char *path, mode_t mode); -EXTERN int rmdir(const char *path); EXTERN int stat(const char *path, FAR struct stat *buf); EXTERN int statfs(const char *path, FAR struct statfs *buf); diff --git a/include/sys/stat.h b/include/sys/stat.h index 12e78313cd..0d686e10f2 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -46,4 +46,23 @@ * Type Definitions ************************************************************/ +/************************************************************ + * Global Function Prototypes + ************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN int mkdir(const char *pathname, mode_t mode); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + #endif /* __SYS_STAT_H */ diff --git a/include/unistd.h b/include/unistd.h index 16414fc773..4e843c5ebb 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -108,7 +108,7 @@ extern "C" { #define EXTERN extern #endif -/* Task Control Interfaces (based on ANSII APIs) */ +/* Task Control Interfaces */ EXTERN pid_t getpid(void); EXTERN void _exit(int status) noreturn_function; @@ -126,6 +126,11 @@ EXTERN int read(int fd, void *buf, unsigned int nbytes); EXTERN int unlink(const char *path); EXTERN int write(int fd, const void *buf, unsigned int nbytes); +/* File path operations */ + +EXTERN int unlink(const char *pathname); +EXTERN int rmdir(const char *pathname); + #undef EXTERN #if defined(__cplusplus) }