summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/fchmod.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-09-11 10:34:02 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-09-12 15:31:12 +0200
commitb6657c395747eedba02409388780ad5f05581322 (patch)
tree103bebd674a55b80248959552b3d40272cc14346 /cpukit/libcsupport/src/fchmod.c
parentdosfs: Correct handling of iconv() return value (diff)
downloadrtems-b6657c395747eedba02409388780ad5f05581322.tar.bz2
Filesystem: Add and use rtems_filesystem_chmod()
Implement POSIX requirements in the high-level file system layer.
Diffstat (limited to 'cpukit/libcsupport/src/fchmod.c')
-rw-r--r--cpukit/libcsupport/src/fchmod.c49
1 files changed, 41 insertions, 8 deletions
diff --git a/cpukit/libcsupport/src/fchmod.c b/cpukit/libcsupport/src/fchmod.c
index 94e82647fc..b8f4d333fb 100644
--- a/cpukit/libcsupport/src/fchmod.c
+++ b/cpukit/libcsupport/src/fchmod.c
@@ -22,6 +22,42 @@
#include <rtems/libio_.h>
+int rtems_filesystem_chmod(
+ const rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
+ int rv;
+
+ if ( mt_entry->writeable || rtems_filesystem_location_is_null( loc ) ) {
+ struct stat st;
+
+ memset( &st, 0, sizeof(st) );
+
+ rv = (*loc->handlers->fstat_h)( loc, &st );
+ if ( rv == 0 ) {
+ uid_t uid = geteuid();
+
+ if ( uid == 0 || st.st_uid == uid ) {
+ mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX;
+
+ mode = (st.st_mode & ~mask) | (mode & mask);
+
+ rv = (*mt_entry->ops->fchmod_h)( loc, mode );
+ } else {
+ errno = EPERM;
+ rv = -1;
+ }
+ }
+ } else {
+ errno = EROFS;
+ rv = -1;
+ }
+
+ return rv;
+}
+
/**
* POSIX 1003.1b 5.6.4 - Change File Modes
*/
@@ -34,14 +70,11 @@ int fchmod( int fd, mode_t mode )
iop = rtems_libio_iop( fd );
rtems_libio_check_is_open(iop);
- if (iop->pathinfo.mt_entry->writeable) {
- rtems_filesystem_instance_lock( &iop->pathinfo );
- rv = (*iop->pathinfo.mt_entry->ops->fchmod_h)( &iop->pathinfo, mode );
- rtems_filesystem_instance_unlock( &iop->pathinfo );
- } else {
- errno = EROFS;
- rv = -1;
- }
+ rtems_filesystem_instance_lock( &iop->pathinfo );
+
+ rv = rtems_filesystem_chmod( &iop->pathinfo, mode );
+
+ rtems_filesystem_instance_unlock( &iop->pathinfo );
return rv;
}