diff --git a/rtemsbsd/rtems/rtems-bsd-syscall-api.c b/rtemsbsd/rtems/rtems-bsd-syscall-api.c index 434cacbd..3ff73dc1 100644 --- a/rtemsbsd/rtems/rtems-bsd-syscall-api.c +++ b/rtemsbsd/rtems/rtems-bsd-syscall-api.c @@ -61,6 +61,8 @@ static int rtems_bsd_sysgen_open_error( rtems_libio_t *iop, const char *path, int oflag, mode_t mode); +static int rtems_bsd_sysgen_opendir( + rtems_libio_t *iop, const char *path, int oflag, mode_t mode); static int rtems_bsd_sysgen_open( rtems_libio_t *iop, const char *path, int oflag, mode_t mode); static int rtems_bsd_sysgen_close(rtems_libio_t *iop); @@ -90,7 +92,7 @@ static int rtems_bsd_sysgen_poll(rtems_libio_t *iop, int events); static int rtems_bsd_sysgen_kqfilter(rtems_libio_t *iop, struct knote *kn); const rtems_filesystem_file_handlers_r rtems_bsd_sysgen_dirops = { - .open_h = rtems_bsd_sysgen_open, + .open_h = rtems_bsd_sysgen_opendir, .close_h = rtems_bsd_sysgen_close, .read_h = rtems_bsd_sysgen_read, .write_h = rtems_filesystem_default_write, @@ -928,9 +930,9 @@ rtems_bsd_sysgen_open_error( return rtems_bsd_error_to_status_and_errno(ENXIO); } -int -rtems_bsd_sysgen_open( - rtems_libio_t *iop, const char *path, int oflag, mode_t mode) +static int +rtems_bsd_sysgen_open_node( + rtems_libio_t *iop, const char *path, int oflag, mode_t mode, bool isdir) { struct thread *td = rtems_bsd_get_curthread_or_null(); struct filedesc *fdp; @@ -954,13 +956,13 @@ rtems_bsd_sysgen_open( /* * There is no easy or clean means to open a vnode and follow the - * POSIX open semantics. You can open a vnode but the extra - * functionality such as create and truncate are not part of the - * basic vnode open. All the calls that provide that functionality - * take a path as the argument. As a result find the last token in - * the path and use the parent directory vnode to position ourselves - * in the parent directory. The pathloc vnode points to the '.' or - * '..' directory. + * POSIX open semantics. See `kern_openat`. You can open a vnode but + * the extra functionality such as the file pointer, descriptor, + * create and truncate are not part of the basic vnode open. All the + * calls that provide that functionality take a path as the + * argument. As a result find the last token in the path and use the + * parent directory vnode to position ourselves in the parent + * directory. The pathloc vnode points to the '.' or '..' directory. */ opath = path + strlen(path); opathlen = 0; @@ -982,10 +984,20 @@ rtems_bsd_sysgen_open( rtems_filesystem_location_info_t *rootloc = &iop->pathinfo.mt_entry->mt_fs_root->location; cdir = rtems_bsd_libio_loc_to_vnode_dir(&iop->pathinfo); - if (fdp->fd_cdir == NULL || - rtems_bsd_libio_loc_to_vnode(&iop->pathinfo) == - rtems_bsd_libio_loc_to_vnode(rootloc)) { + if (fdp->fd_cdir == NULL) { cdir = rtems_bsd_libio_loc_to_vnode(rootloc); + } else if (rtems_bsd_libio_loc_to_vnode(&iop->pathinfo) == + rtems_bsd_libio_loc_to_vnode(rootloc)) { + /* + * If this is a directory and this is the root node of + * the mounted file system we need to move up the + * hidden pseudo file system node. + */ + if (isdir) { + cdir = rootvnode; + } else { + cdir = rtems_bsd_libio_loc_to_vnode(rootloc); + } } } @@ -999,10 +1011,10 @@ rtems_bsd_sysgen_open( if (RTEMS_BSD_SYSCALL_TRACE) { printf("bsd: sys: open: path=%s opath=%s vn=%p cwd=%p" - " flags=%08x mode=%08x\n", + " flags=%08x mode=%08x isdir=%s\n", path, opath, creat ? NULL : rtems_bsd_libio_loc_to_vnode(&iop->pathinfo), - fdp->fd_cdir, oflag, mode); + fdp->fd_cdir, oflag, mode, isdir ? "yes" : "no"); } VREF(fdp->fd_cdir); @@ -1047,6 +1059,20 @@ rtems_bsd_sysgen_open( return 0; } +int +rtems_bsd_sysgen_opendir( + rtems_libio_t *iop, const char *path, int oflag, mode_t mode) +{ + return rtems_bsd_sysgen_open_node(iop, path, oflag, mode, true); +} + +int +rtems_bsd_sysgen_open( + rtems_libio_t *iop, const char *path, int oflag, mode_t mode) +{ + return rtems_bsd_sysgen_open_node(iop, path, oflag, mode, false); +} + int rtems_bsd_sysgen_close(rtems_libio_t *iop) { @@ -1084,8 +1110,8 @@ rtems_bsd_sysgen_read(rtems_libio_t *iop, void *buffer, size_t count) ssize_t size = 0; if (RTEMS_BSD_SYSCALL_TRACE) { - printf("bsd: sys: read: %d -> %d: vn=%p len=%d\n", - rtems_libio_iop_to_descriptor(iop), fd, vp, count); + printf("bsd: sys: read: %d -> %d: vn=%p vn-type=%d len=%d\n", + rtems_libio_iop_to_descriptor(iop), fd, vp, vp->v_type, count); } if (td == NULL) { diff --git a/rtemsbsd/rtems/rtems-kernel-vfs.c b/rtemsbsd/rtems/rtems-kernel-vfs.c index c387271b..2f4d009b 100644 --- a/rtemsbsd/rtems/rtems-kernel-vfs.c +++ b/rtemsbsd/rtems/rtems-kernel-vfs.c @@ -335,6 +335,9 @@ rtems_bsd_vfs_eval_token(rtems_filesystem_eval_path_context_t *ctx, void *arg, if (*vpp != NULL) { rtems_filesystem_eval_path_clear_token(ctx); + if ((*vpp)->v_type != VDIR) { + currentloc->handlers = &rtems_bsd_sysgen_fileops; + } } return no_more_path ? RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE : diff --git a/testsuite/nfs01/test_main.c b/testsuite/nfs01/test_main.c index a6cb91f3..d0642630 100644 --- a/testsuite/nfs01/test_main.c +++ b/testsuite/nfs01/test_main.c @@ -37,6 +37,7 @@ */ #include +#include #include #include @@ -279,7 +280,11 @@ test_walk_tree_unlink(walk_tree_dir state, static void test_setup(const char *base) { + struct DIR *ddir; printf("test: nfs: setup\n"); + printf("test: nfs: opendir: %s\n", base); + rtems_test_errno_assert((ddir = opendir(base)) != NULL); + rtems_test_errno_assert(closedir(ddir) == 0); printf("test: nfs: chdir: %s\n", base); rtems_test_errno_assert(chdir(base) == 0); printf("test: nfs: mkdir: %s\n", test_top);