diff options
Diffstat (limited to 'cpukit/libcsupport/src/fchdir.c')
-rw-r--r-- | cpukit/libcsupport/src/fchdir.c | 76 |
1 files changed, 32 insertions, 44 deletions
diff --git a/cpukit/libcsupport/src/fchdir.c b/cpukit/libcsupport/src/fchdir.c index c95e2b7fb3..7b64ea8f21 100644 --- a/cpukit/libcsupport/src/fchdir.c +++ b/cpukit/libcsupport/src/fchdir.c @@ -4,6 +4,9 @@ * COPYRIGHT (c) 1989-2011. * On-Line Applications Research Corporation (OAR). * + * Modifications to support reference counting in the file system are + * Copyright (c) 2012 embedded brains GmbH. + * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. @@ -12,65 +15,50 @@ */ #if HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include <unistd.h> -#include <sys/stat.h> -#include <errno.h> -#include <rtems.h> -#include <rtems/libio.h> #include <rtems/libio_.h> -#include <rtems/seterr.h> -int fchdir( - int fd -) +int fchdir( int fd ) { + int rv = 0; rtems_libio_t *iop; - rtems_filesystem_location_info_t loc, saved; + struct stat st; + rtems_filesystem_location_info_t loc; + + st.st_mode = 0; + st.st_uid = 0; + st.st_gid = 0; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); - rtems_libio_check_is_open(iop); + rtems_libio_check_is_open( iop ); - /* - * Verify you can change directory into this node. - */ + rtems_filesystem_instance_lock( &iop->pathinfo ); + rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, &st ); + if ( rv == 0 ) { + bool access_ok = rtems_filesystem_check_access( + RTEMS_LIBIO_PERMS_EXEC, + st.st_mode, + st.st_uid, + st.st_gid + ); - if ( (*iop->pathinfo.ops->node_type_h)( &iop->pathinfo ) != - RTEMS_FILESYSTEM_DIRECTORY ) { - rtems_set_errno_and_return_minus_one( ENOTDIR ); + if ( access_ok ) { + rtems_filesystem_location_clone( &loc, &iop->pathinfo ); + } else { + errno = EACCES; + rv = -1; + } } + rtems_filesystem_instance_unlock( &iop->pathinfo ); - - /* - * FIXME : I feel there should be another call to - * actually take into account the extra reference to - * this node which we are making here. I can - * see the freenode interface but do not see - * allocnode node interface. It maybe node_type. - * - * FIXED: T.Straumann: it is evaluate_path() - * but note the race condition. Threads who - * share their rtems_filesystem_current better - * be synchronized! - */ - - saved = rtems_filesystem_current; - rtems_filesystem_current = iop->pathinfo; - - /* clone the current node */ - if (rtems_filesystem_evaluate_path(".", 1, 0, &loc, 0)) { - /* cloning failed; restore original and bail out */ - rtems_filesystem_current = saved; - return -1; + if ( rv == 0 ) { + rv = rtems_filesystem_chdir( &loc ); } - /* release the old one */ - rtems_filesystem_freenode( &saved ); - - rtems_filesystem_current = loc; - return 0; + return rv; } |