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 */