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 <[email protected]> AuthorDate: Fri Aug 5 12:04:37 2022 +0800 fs/dir: support fchdir and dirfd Signed-off-by: Jiuzhu Dong <[email protected]> --- 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 */
