From b747212f50e5d0656ca37fc0481dc5c54a98102e Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 26 Mar 2009 01:12:11 +0000 Subject: [PATCH] Implemented WriteStat() (backend for chown(), chmod(), utime(), truncate()). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29722 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../userlandfs/server/fuse/FUSEFileSystem.cpp | 5 +- .../userlandfs/server/fuse/FUSEVolume.cpp | 79 ++++++++++++++++++- .../userlandfs/server/fuse/FUSEVolume.h | 2 +- 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp index 95381da14a..e072e977ad 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEFileSystem.cpp @@ -397,7 +397,10 @@ FUSEFileSystem::_InitCapabilities() fNodeCapabilities.Set(FS_VNODE_CAPABILITY_ACCESS, fFS->ops.access); fNodeCapabilities.Set(FS_VNODE_CAPABILITY_READ_STAT, fFS->ops.getattr); -// fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_STAT, fFS->ops.wstat); + fNodeCapabilities.Set(FS_VNODE_CAPABILITY_WRITE_STAT, + fFS->ops.chmod != NULL || fFS->ops.chown != NULL + || fFS->ops.truncate != NULL | fFS->ops.utimens != NULL + || fFS->ops.utime != NULL); // file operations fNodeCapabilities.Set(FS_VNODE_CAPABILITY_CREATE, fFS->ops.create); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp index ac759040ba..a954258a73 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.cpp @@ -10,6 +10,7 @@ #include #include +#include #include @@ -892,10 +893,82 @@ PRINT(("FUSEVolume::ReadStat(%p (%lld), %p)\n", node, node->id, st)); status_t -FUSEVolume::WriteStat(void* node, const struct stat *st, uint32 mask) +FUSEVolume::WriteStat(void* _node, const struct stat* st, uint32 mask) { - // TODO: Implement! - return B_UNSUPPORTED; + FUSENode* node = (FUSENode*)_node; +PRINT(("FUSEVolume::WriteStat(%p (%lld), %p, %#lx)\n", node, node->id, st, +mask)); + + // lock the directory + NodeReadLocker nodeLocker(this, node, true); + if (nodeLocker.Status() != B_OK) + RETURN_ERROR(nodeLocker.Status()); + + AutoLocker locker(fLock); + + // get a path for the node + char path[B_PATH_NAME_LENGTH]; + size_t pathLen; + status_t error = _BuildPath(node, path, pathLen); + if (error != B_OK) + RETURN_ERROR(error); + + locker.Unlock(); + + // permissions + if ((mask & B_STAT_MODE) != 0) { + int fuseError = fuse_fs_chmod(fFS, path, st->st_mode); + if (fuseError != 0) + RETURN_ERROR(fuseError); + } + + // owner + if ((mask & (B_STAT_UID | B_STAT_GID)) != 0) { + uid_t uid = (mask & B_STAT_UID) != 0 ? st->st_uid : (uid_t)-1; + gid_t gid = (mask & B_STAT_GID) != 0 ? st->st_gid : (gid_t)-1; + int fuseError = fuse_fs_chown(fFS, path, uid, gid); + if (fuseError != 0) + RETURN_ERROR(fuseError); + } + + // size + if ((mask & B_STAT_SIZE) != 0) { + // truncate + int fuseError = fuse_fs_truncate(fFS, path, st->st_size); + if (fuseError != 0) + RETURN_ERROR(fuseError); + } + + // access/modification time + if ((mask & (B_STAT_ACCESS_TIME | B_STAT_MODIFICATION_TIME)) != 0) { + timespec tv[2] = { + {st->st_atime, 0}, + {st->st_mtime, 0} + }; + + // If either time is not specified, we need to stat the file to get the + // current value. + if ((mask & (B_STAT_ACCESS_TIME | B_STAT_MODIFICATION_TIME)) + != (B_STAT_ACCESS_TIME | B_STAT_MODIFICATION_TIME)) { + struct stat currentStat; + int fuseError = fuse_fs_getattr(fFS, path, ¤tStat); + if (fuseError != 0) + RETURN_ERROR(fuseError); + + if ((mask & B_STAT_ACCESS_TIME) == 0) + tv[0].tv_sec = currentStat.st_atime; + else + tv[1].tv_sec = currentStat.st_mtime; + } + + int fuseError = fuse_fs_utimens(fFS, path, tv); + if (fuseError != 0) + RETURN_ERROR(fuseError); + } + +// TODO: Node monitoring! + + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.h b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.h index 83728c27d9..3dffc7c617 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/fuse/FUSEVolume.h @@ -83,7 +83,7 @@ public: virtual status_t Access(void* node, int mode); virtual status_t ReadStat(void* node, struct stat* st); - virtual status_t WriteStat(void* node, const struct stat *st, + virtual status_t WriteStat(void* node, const struct stat* st, uint32 mask); // files