Soft links: Initial, incompete implementation

This commit is contained in:
Gregory Nutt 2017-02-02 10:39:41 -06:00
parent 74189d84e2
commit 92305e400a
7 changed files with 239 additions and 13 deletions

View file

@ -40,6 +40,19 @@ config DISABLE_PSEUDOFS_OPERATIONS
However, in practical embedded system, they are seldom needed and
you can save a little FLASH space by disabling the capability.
config PSEUDOFS_SOFTLINKS
bool "Pseudo-filesystem soft links"
default y if DEFAULT_SMALL
default n if !DEFAULT_SMALL
depends on !DISABLE_PSEUDOFS_OPERATIONS
---help---
Enable support for soft links in the pseudeo file system. Soft
links are not supported within mounted volumes by any NuttX file
system. However, if this option is selected, then soft links
may be add in the pseudo file system. This might be useful, for
to link a directory in the pseudo-file system, such as /bin, to
to a directory in a mounted volume, say /mnt/sdcard/bin.
config FS_READABLE
bool
default n

View file

@ -1,7 +1,7 @@
/****************************************************************************
* fs/inode/fs_inode.c
*
* Copyright (C) 2007-2009, 2011-2012, 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2012, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -41,6 +41,7 @@
#include <assert.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
@ -345,6 +346,7 @@ FAR struct inode *inode_search(FAR const char **path,
{
*relpath = name;
}
break;
}
else
@ -401,8 +403,29 @@ void inode_free(FAR struct inode *node)
if (node != NULL)
{
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
/* Symbol links should never have peers or children */
DEBUGASSERT(!INODE_IS_SOFTLINK(node)) ||
(node->i_peer == NULL && node->i_child == NULL)
#endif
/* Free all peers and children of this i_node */
inode_free(node->i_peer);
inode_free(node->i_child);
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
/* If the inode is a symbolic link, the free the path to the linked
* entity.
*/
if (INODE_IS_SOFTLINK(node) && inode->u.i_link != NULL)
{
kmm_free(node->u.i_link);
}
#endif
kmm_free(node);
}
}

View file

@ -1,7 +1,7 @@
############################################################################
# fs/vfs/Make.defs
#
# Copyright (C) 2014-2015 Gregory Nutt. All rights reserved.
# Copyright (C) 2014-2015, 2017 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@ -43,7 +43,11 @@ ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)
CSRCS += fs_close.c fs_read.c fs_write.c fs_ioctl.c
# Support for network access using streams
ifneq ($(CONFIG_PSEUDOFS_SOFTLINKS),0)
CSRCS += fs_softlink.c
endif
# Stream support
ifneq ($(CONFIG_NFILE_STREAMS),0)
CSRCS += fs_fdopen.c
@ -86,6 +90,10 @@ endif
CSRCS += fs_pread.c fs_pwrite.c
ifneq ($(CONFIG_PSEUDOFS_SOFTLINKS),0)
CSRCS += fs_softlink.c
endif
# Stream support
ifneq ($(CONFIG_NFILE_STREAMS),0)

View file

@ -84,8 +84,9 @@ int rmdir(FAR const char *pathname)
const char *relpath = NULL;
int errcode;
/* Get an inode for this file. inode_find() automatically increments the
* reference count on the inode if one is found.
/* Get an inode for the directory (or for the mountpoint containing the
* directory). inode_find() automatically increments the reference count
* on the inode if one is found.
*/
inode = inode_find(pathname, &relpath);

169
fs/vfs/fs_softlink.c Normal file
View file

@ -0,0 +1,169 @@
/****************************************************************************
* fs/vfs/fs_softlink.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 NuttX 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 <nuttx/config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include "inode/inode.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: link
*
* Description:
* The link() function will create a new link (directory entry) for the
* existing file, path1. This implementation is simplied for use with
* NuttX in these ways:
*
* - Links may be created only within the NuttX top-level, pseudo file
* system. No file system currently supported by NuttX provides
* symbolic links.
* - For the same reason, only soft links are implemented.
* - File privileges are ignored.
* - c_time is not updated.
*
* Input Parameters:
* path1 - Points to a pathname naming an existing file.
* path2 - Points to a pathname naming the new directory entry to be created.
*
* Returned Value:
* On success, zero (OK) is returned. Otherwise, -1 (ERROR) is returned
* the the errno variable is set appropriately.
*
****************************************************************************/
int link(FAR const char *path1, FAR const char *path2)
{
FAR struct inode *inode;
int errcode;
int ret;
DEBUGASSERT(path1 != NULL && path2 != NULL && *path2 != '\0');
/* Check that no inode exists at the 'path2' and that the path up to 'path2'
* does not lie on a mounted volume.
*/
inode = inode_find(pathname, NULL);
if (inode != NULL)
{
#ifndef CONFIG_DISABLE_MOUNTPOINT
/* Check if the inode is a mountpoint. */
if (INODE_IS_MOUNTPT(inode))
{
/* Symbol links within the mounted volume are not supported */
errcode = ENOSYS;
}
else
#endif
{
/* A node already exists in the pseudofs at 'path2' */
errorcode = EEXIST;
}
goto errout_with_inode;
}
/* No inode exists that contains this path. Create a new inode in the
* pseudo-filesystem at this location.
*/
else
{
/* Copy path2 */
FAR char newpath2 = strdup(path2);
if (newpath2 == NULL)
{
errcode = ENOMEM;
goto errout;
}
/* Create an inode in the pseudo-filesystem at this path.
* NOTE that the new inode will be created with a reference
* count of zero.
*/
inode_semtake();
ret = inode_reserve(pathname, &inode);
inode_semgive();
if (ret < 0)
{
kmm_free(newpath2)
errcode = -ret;
goto errout;
}
/* Initialize the inode */
INODE_SET_SOFTLINK(inode);
inode->u.i_link = newpath2;
inode->i_crefs = 1;
}
/* Symbolic link successfully created */
return OK;
errout_with_inode:
inode_release(inode);
errout:
set_errno(errcode);
return ERROR;
}
#endif /* CONFIG_PSEUDOFS_SOFTLINKS */

View file

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/fs/fs.h
*
* Copyright (C) 2007-2009, 2011-2013, 2015-2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2013, 2015-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -66,12 +66,17 @@
#define __FS_FLAG_EOF (1 << 0) /* EOF detected by a read operation */
#define __FS_FLAG_ERROR (1 << 1) /* Error detected by any operation */
/* Inode i_flag values */
/* Inode i_flag values:
*
* Bit 0-3: Inode type (Bit 4 indicates internal OS types)
* Bit 4: Set if inode has been unlinked and is pending removal.
*/
#define FSNODEFLAG_TYPE_MASK 0x00000007 /* 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_SOFTLINK 0x00000003 /* Soft link */
#define FSNODEFLAG_TYPE_SPECIAL 0x00000004 /* Special OS type */
#define FSNODEFLAG_TYPE_NAMEDSEM 0x00000004 /* Named semaphore */
#define FSNODEFLAG_TYPE_MQUEUE 0x00000005 /* Message Queue */
@ -86,6 +91,7 @@
#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)
#define INODE_IS_SOFTLINK(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_SOFTLINK)
#define INODE_IS_NAMEDSEM(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_NAMEDSEM)
#define INODE_IS_MQUEUE(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_MQUEUE)
#define INODE_IS_SHM(i) INODE_IS_TYPE(i,FSNODEFLAG_TYPE_SHM)
@ -101,6 +107,7 @@
#define INODE_SET_DRIVER(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_DRIVER)
#define INODE_SET_BLOCK(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_BLOCK)
#define INODE_SET_MOUNTPT(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_MOUNTPT)
#define (i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_SOFTLINK)
#define INODE_SET_NAMEDSEM(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_NAMEDSEM)
#define INODE_SET_MQUEUE(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_MQUEUE)
#define INODE_SET_SHM(i) INODE_SET_TYPE(i,FSNODEFLAG_TYPE_SHM)
@ -309,16 +316,19 @@ struct mountpt_operations
union inode_ops_u
{
FAR const struct file_operations *i_ops; /* Driver operations for inode */
FAR const struct file_operations *i_ops; /* Driver operations for inode */
#ifndef CONFIG_DISABLE_MOUNTPOINT
FAR const struct block_operations *i_bops; /* Block driver operations */
FAR const struct mountpt_operations *i_mops; /* Operations on a mountpoint */
FAR const struct block_operations *i_bops; /* Block driver operations */
FAR const struct mountpt_operations *i_mops; /* Operations on a mountpoint */
#endif
#ifdef CONFIG_FS_NAMED_SEMAPHORES
FAR struct nsem_inode_s *i_nsem; /* Named semaphore */
FAR struct nsem_inode_s *i_nsem; /* Named semaphore */
#endif
#ifndef CONFIG_DISABLE_MQUEUE
FAR struct mqueue_inode_s *i_mqueue; /* POSIX message queue */
FAR struct mqueue_inode_s *i_mqueue; /* POSIX message queue */
#endif
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
FAR char *i_link; /* Full path to link */
#endif
};
@ -337,6 +347,7 @@ struct inode
FAR void *i_private; /* Per inode driver private data */
char i_name[1]; /* Name of inode (variable) */
};
#define FSNODE_SIZE(n) (sizeof(struct inode) + (n))
/* This is the underlying representation of an open file. A file

View file

@ -1,7 +1,7 @@
/****************************************************************************
* include/unistd.h
*
* Copyright (C) 2007-2009, 2013-2014, 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2013-2014, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -190,6 +190,7 @@ FAR char *getcwd(FAR char *buf, size_t size);
int access(FAR const char *path, int amode);
int rmdir(FAR const char *pathname);
int unlink(FAR const char *pathname);
int link(FAR const char *path1, FAR const char *path2);
/* Execution of programs from files */