From 8ec7abb551a23bdf47509189145885a364810006 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Thu, 4 Mar 2010 06:36:51 +0000 Subject: 010-03-04 Chris Johns * libcsupport/include/rtems/libio.h, libcsupport/src/_rename_r.c: Add a rename file op and have rename use it. * libfs/Makefile.am, libfs/src/dosfs/msdos_rename.c, libfs/src/imfs/imfs_rename.c: New files to support the rename file op. * libfs/src/imfs/imfs.h: Add rename interface. * libfs/src/imfs/imfs_init.c: Add rename handler. * libfs/src/imfs/miniimfs_init.c: Fix up ops struct. * libfs/src/dosfs/msdos.h: Add msdos_rename and remove msdos_file_link. * libfs/src/dosfs/msdos_create.c: Remove the link call. * libfs/src/dosfs/msdos_eval.c: Fix a path parsing bug. * libfs/src/dosfs/msdos_init.c: Add rename handler and clean up the struct naming. * libfs/src/rfs/rtems-rfs-link.c, libfs/src/rfs/rtems-rfs-link.h: Change the link call to allow linking of directories if told to and change the unlink to handle unlink directories that are not empty so rename can be supported. * libfs/src/rfs/rtems-rfs-rtems-dir.c: Fix the link/unlink calls. * libfs/src/rfs/rtems-rfs-rtems.c: Add a rename handler. Fix the link/unlink calls. * libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_format.c, libfs/src/dosfs/msdos_misc.c, httpd/asp.c, libfs/src/nfsclient/src/nfs.c: Work around a newlib warning when using the is*() family of calls. --- cpukit/libcsupport/include/rtems/libio.h | 8 +++ cpukit/libcsupport/src/_rename_r.c | 104 ++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 2 deletions(-) (limited to 'cpukit/libcsupport') diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h index 0ee6ee8458..5cd6dc5a24 100644 --- a/cpukit/libcsupport/include/rtems/libio.h +++ b/cpukit/libcsupport/include/rtems/libio.h @@ -251,6 +251,13 @@ typedef int (*rtems_filesystem_readlink_t)( size_t bufsize ); +typedef int (*rtems_filesystem_rename_t)( + rtems_filesystem_location_info_t *old_parent_loc, /* IN */ + rtems_filesystem_location_info_t *old_loc, /* IN */ + rtems_filesystem_location_info_t *new_parent_loc, /* IN */ + const char *name /* IN */ +); + typedef int (*rtems_filesystem_statvfs_t)( rtems_filesystem_location_info_t *loc, /* IN */ struct statvfs *buf /* OUT */ @@ -280,6 +287,7 @@ struct _rtems_filesystem_operations_table { rtems_filesystem_evaluate_link_t eval_link_h; rtems_filesystem_symlink_t symlink_h; rtems_filesystem_readlink_t readlink_h; + rtems_filesystem_rename_t rename_h; rtems_filesystem_statvfs_t statvfs_h; }; diff --git a/cpukit/libcsupport/src/_rename_r.c b/cpukit/libcsupport/src/_rename_r.c index 12eeb59e53..d12355c8d0 100644 --- a/cpukit/libcsupport/src/_rename_r.c +++ b/cpukit/libcsupport/src/_rename_r.c @@ -20,7 +20,8 @@ #include #include -#include +#include +#include int _rename_r( struct _reent *ptr __attribute__((unused)), @@ -28,6 +29,104 @@ int _rename_r( const char *new ) { + int old_parent_pathlen; + rtems_filesystem_location_info_t old_loc; + rtems_filesystem_location_info_t old_parent_loc; + rtems_filesystem_location_info_t new_parent_loc; + int i; + int result; + const char *name; + bool free_old_parentloc = false; + + /* + * Get the parent node of the old path to be renamed. Find the parent path. + */ + + old_parent_pathlen = rtems_filesystem_dirname ( old ); + + if ( old_parent_pathlen == 0 ) + rtems_filesystem_get_start_loc( old, &i, &old_parent_loc ); + else { + result = rtems_filesystem_evaluate_path( old, old_parent_pathlen, + RTEMS_LIBIO_PERMS_WRITE, + &old_parent_loc, + false ); + if ( result != 0 ) + return -1; + + free_old_parentloc = true; + } + + /* + * Start from the parent to find the node that should be under it. + */ + + old_loc = old_parent_loc; + name = old + old_parent_pathlen; + name += rtems_filesystem_prefix_separators( name, strlen( name ) ); + + result = rtems_filesystem_evaluate_relative_path( name , strlen( name ), + 0, &old_loc, false ); + if ( result != 0 ) { + if ( free_old_parentloc ) + rtems_filesystem_freenode( &old_parent_loc ); + rtems_set_errno_and_return_minus_one( result ); + } + + /* + * Get the parent of the new node we are renaming to. + */ + + rtems_filesystem_get_start_loc( new, &i, &new_parent_loc ); + + if ( !new_parent_loc.ops->evalformake_h ) { + if ( free_old_parentloc ) + rtems_filesystem_freenode( &old_parent_loc ); + rtems_filesystem_freenode( &old_loc ); + rtems_set_errno_and_return_minus_one( ENOTSUP ); + } + + result = (*new_parent_loc.ops->evalformake_h)( &new[i], &new_parent_loc, &name ); + if ( result != 0 ) { + rtems_filesystem_freenode( &new_parent_loc ); + if ( free_old_parentloc ) + rtems_filesystem_freenode( &old_parent_loc ); + rtems_filesystem_freenode( &old_loc ); + rtems_set_errno_and_return_minus_one( result ); + } + + /* + * Check to see if the caller is trying to rename across file system + * boundaries. + */ + + if ( old_parent_loc.mt_entry != new_parent_loc.mt_entry ) { + rtems_filesystem_freenode( &new_parent_loc ); + if ( free_old_parentloc ) + rtems_filesystem_freenode( &old_parent_loc ); + rtems_filesystem_freenode( &old_loc ); + rtems_set_errno_and_return_minus_one( EXDEV ); + } + + if ( !new_parent_loc.ops->rename_h ) { + rtems_filesystem_freenode( &new_parent_loc ); + if ( free_old_parentloc ) + rtems_filesystem_freenode( &old_parent_loc ); + rtems_filesystem_freenode( &old_loc ); + rtems_set_errno_and_return_minus_one( ENOTSUP ); + } + + result = (*new_parent_loc.ops->rename_h)( &old_parent_loc, &old_loc, &new_parent_loc, name ); + + rtems_filesystem_freenode( &new_parent_loc ); + if ( free_old_parentloc ) + rtems_filesystem_freenode( &old_parent_loc ); + rtems_filesystem_freenode( &old_loc ); + + return result; +} + +#if 0 struct stat sb; int s; @@ -38,5 +137,6 @@ int _rename_r( if ( s < 0 ) return s; return S_ISDIR(sb.st_mode) ? rmdir( old ) : unlink( old ); -} +#endif + #endif -- cgit v1.2.3