You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/09 15:30:11 UTC

[incubator-nuttx] 05/05: fs/dir: support fchdir and dirfd

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 4dbf4555ebb743a908e3016d43b5b456d7a2cf16
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Aug 5 12:04:37 2022 +0800

    fs/dir: support fchdir and dirfd
    
    Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
 fs/vfs/fs_dir.c               | 31 +++++++++++++++--
 include/dirent.h              |  2 ++
 include/nuttx/fs/fs.h         |  4 +++
 include/unistd.h              |  1 +
 libs/libc/dirent/Make.defs    |  2 +-
 libs/libc/dirent/lib_dirfd.c  | 65 +++++++++++++++++++++++++++++++++++
 libs/libc/unistd/Make.defs    |  2 +-
 libs/libc/unistd/lib_fchdir.c | 79 +++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 182 insertions(+), 4 deletions(-)

diff --git a/fs/vfs/fs_dir.c b/fs/vfs/fs_dir.c
index 21371f32bd..1397884206 100644
--- a/fs/vfs/fs_dir.c
+++ b/fs/vfs/fs_dir.c
@@ -29,6 +29,7 @@
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
+#include <nuttx/fs/ioctl.h>
 
 #include "inode/inode.h"
 
@@ -51,10 +52,12 @@ struct fs_pseudodir_s
  * Private Functions Prototypes
  ****************************************************************************/
 
+static int     dir_open(FAR struct file *filep);
 static int     dir_close(FAR struct file *filep);
 static ssize_t dir_read(FAR struct file *filep, FAR char *buffer,
                         size_t buflen);
 static off_t   dir_seek(FAR struct file *filep, off_t offset, int whence);
+static int     dir_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
 
 /****************************************************************************
  * Private Data
@@ -62,12 +65,12 @@ static off_t   dir_seek(FAR struct file *filep, off_t offset, int whence);
 
 static const struct file_operations g_dir_fileops =
 {
-  NULL,       /* open */
+  dir_open,   /* open */
   dir_close,  /* close */
   dir_read,   /* read */
   NULL,       /* write */
   dir_seek,   /* seek */
-  NULL,       /* ioctl */
+  dir_ioctl,  /* ioctl */
   NULL,       /* poll */
 #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
   NULL,       /* unlink */
@@ -391,10 +394,18 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir,
   return 0;
 }
 
+static int dir_open(FAR struct file *filep)
+{
+  FAR struct fs_dirent_s *dir = filep->f_priv;
+
+  return dir_allocate(filep, dir->fd_path);
+}
+
 static int dir_close(FAR struct file *filep)
 {
   FAR struct fs_dirent_s *dir = filep->f_priv;
   FAR struct inode *inode = dir->fd_root;
+  FAR char *relpath = dir->fd_path;
   int ret = 0;
 
   /* This is the 'root' inode of the directory. This means different
@@ -440,6 +451,7 @@ static int dir_close(FAR struct file *filep)
   /* Release our references on the contained 'root' inode */
 
   inode_release(inode);
+  kmm_free(relpath);
   return ret;
 }
 
@@ -533,6 +545,20 @@ static off_t dir_seek(FAR struct file *filep, off_t offset, int whence)
   return pos;
 }
 
+static int dir_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+  FAR struct fs_dirent_s *dir = filep->f_priv;
+  int ret = -ENOTTY;
+
+  if (cmd == FIOC_FILEPATH)
+    {
+      strcpy((FAR char *)(uintptr_t)arg, dir->fd_path);
+      ret = OK;
+    }
+
+  return ret;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -574,6 +600,7 @@ int dir_allocate(FAR struct file *filep, FAR const char *relpath)
         }
     }
 
+  dir->fd_path = strdup(relpath);
   filep->f_inode  = &g_dir_inode;
   filep->f_priv   = dir;
   inode_addref(&g_dir_inode);
diff --git a/include/dirent.h b/include/dirent.h
index 8865059f63..54ea3aeb7c 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -154,6 +154,8 @@ int        scandir(FAR const char *path, FAR struct dirent ***namelist,
 int        alphasort(FAR const struct dirent **a,
                      FAR const struct dirent **b);
 
+int        dirfd(FAR DIR *dirp);
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h
index 032706e1be..152e65ae0f 100644
--- a/include/nuttx/fs/fs.h
+++ b/include/nuttx/fs/fs.h
@@ -191,6 +191,10 @@ struct fs_dirent_s
    */
 
   FAR struct inode *fd_root;
+
+  /* The path name of current directory for FIOC_FILEPATH */
+
+  FAR char *fd_path;
 };
 
 /* This structure is provided by devices when they are registered with the
diff --git a/include/unistd.h b/include/unistd.h
index e754e0a804..9a43b23f05 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -362,6 +362,7 @@ unsigned int alarm(unsigned int seconds);
 /* Working directory operations */
 
 int     chdir(FAR const char *path);
+int     fchdir(int fd);
 FAR char *getcwd(FAR char *buf, size_t size);
 
 /* File path operations */
diff --git a/libs/libc/dirent/Make.defs b/libs/libc/dirent/Make.defs
index f8690bea4a..440a3d0477 100644
--- a/libs/libc/dirent/Make.defs
+++ b/libs/libc/dirent/Make.defs
@@ -22,7 +22,7 @@
 
 CSRCS += lib_readdirr.c lib_telldir.c lib_alphasort.c lib_scandir.c
 CSRCS += lib_ftw.c lib_nftw.c lib_opendir.c lib_closedir.c lib_readdir.c
-CSRCS += lib_rewinddir.c lib_seekdir.c
+CSRCS += lib_rewinddir.c lib_seekdir.c lib_dirfd.c
 
 # Add the dirent directory to the build
 
diff --git a/libs/libc/dirent/lib_dirfd.c b/libs/libc/dirent/lib_dirfd.c
new file mode 100644
index 0000000000..f98d9ce040
--- /dev/null
+++ b/libs/libc/dirent/lib_dirfd.c
@@ -0,0 +1,65 @@
+/****************************************************************************
+ * libs/libc/dirent/lib_dirfd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <dirent.h>
+#include <errno.h>
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: dirfd
+ *
+ * Description:
+ *   The dirfd() function returns the file descriptor associated
+ *   with the directory stream dirp.
+ *
+ * Input Parameters:
+ *   dirp -- An instance of type DIR created by a previous
+ *           call to opendir();
+ *
+ * Returned Value:
+ *   On success, a nonnegative file descriptor is returned.
+ *   On error, -1 is returned, and errno is set to indicate
+ *   the cause of the error.
+ *
+ *   EINVAL - dirp does not refer to a valid directory stream.
+ *
+ ****************************************************************************/
+
+int dirfd(FAR DIR *dirp)
+{
+  if (dirp != NULL)
+    {
+      return dirp->fd;
+    }
+
+  set_errno(EINVAL);
+  return -1;
+}
diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs
index 926f1c7b9c..f182d8346e 100644
--- a/libs/libc/unistd/Make.defs
+++ b/libs/libc/unistd/Make.defs
@@ -35,7 +35,7 @@ CSRCS += lib_setuid.c lib_setgid.c lib_getuid.c lib_getgid.c
 endif
 
 ifneq ($(CONFIG_DISABLE_ENVIRON),y)
-CSRCS += lib_chdir.c lib_getcwd.c lib_restoredir.c
+CSRCS += lib_chdir.c lib_fchdir.c lib_getcwd.c lib_restoredir.c
 endif
 
 ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
diff --git a/libs/libc/unistd/lib_fchdir.c b/libs/libc/unistd/lib_fchdir.c
new file mode 100644
index 0000000000..b59cc66963
--- /dev/null
+++ b/libs/libc/unistd/lib_fchdir.c
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * libs/libc/unistd/lib_fchdir.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+
+#ifndef CONFIG_DISABLE_ENVIRON
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: fchdir
+ *
+ * Description:
+ *   The fchdir() function changes the current workint directory of the
+ *   calling process to the directory specified in fd.
+ *
+ *   The fchdir() function is identical to chdir(); the only difference is
+ *   that the directory is given as an open file diescriptor.
+ *
+ * Input Parameters:
+ *   fd - The file descriptor is the one used internally by the directory
+ *        stream.
+ *
+ * Returned Value:
+ *   0(OK) on success; -1(ERROR) on failure with errno set appropriately:
+ *
+ *   EACCES
+ *     Search permission was denied on the directory open on fd.
+ *   EBADF
+ *     fd is not a valid file descriptor.
+ *
+ ****************************************************************************/
+
+int fchdir(int fd)
+{
+  char path[PATH_MAX];
+  int ret;
+
+  ret = fcntl(fd, F_GETPATH, path);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  return chdir(path);
+}
+
+#endif /* !CONFIG_DISABLE_ENVIRON */