From 4e0e80ed6cbc449889d81464a9c67e11d8b76ff3 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 5 Mar 2007 05:16:08 +0000 Subject: [PATCH] We analyze a client FS's capabilities -- i.e. which hooks it provides or can be emulated -- and pass this info to the kernel add-on. Thus we can avoid passing requests to the userland that can't be serviced anyway. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20331 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../userlandfs/private/FSCapabilities.h | 191 +++++++++++++++ headers/private/userlandfs/private/Requests.h | 6 +- .../userlandfs/kernel_add_on/FileSystem.cpp | 15 +- .../userlandfs/kernel_add_on/FileSystem.h | 16 +- .../kernel_add_on/FileSystemInitializer.cpp | 2 +- .../userlandfs/kernel_add_on/Volume.cpp | 223 ++++++++++++++++++ .../server/BeOSKernelFileSystem.cpp | 113 +++++++++ .../userlandfs/server/BeOSKernelFileSystem.h | 3 + .../userlandfs/server/BeOSKernelVolume.cpp | 2 +- .../file_systems/userlandfs/server/FSInfo.h | 46 +++- .../userlandfs/server/FileSystem.h | 9 + .../server/UserlandFSDispatcher.cpp | 11 +- .../userlandfs/server/UserlandFSServer.cpp | 11 +- 13 files changed, 629 insertions(+), 19 deletions(-) create mode 100644 headers/private/userlandfs/private/FSCapabilities.h diff --git a/headers/private/userlandfs/private/FSCapabilities.h b/headers/private/userlandfs/private/FSCapabilities.h new file mode 100644 index 0000000000..5cdd02ba74 --- /dev/null +++ b/headers/private/userlandfs/private/FSCapabilities.h @@ -0,0 +1,191 @@ +// FSCapabilities.h + +#ifndef USERLAND_FS_FS_CAPABILITIES_H +#define USERLAND_FS_FS_CAPABILITIES_H + +#include +#include + +#include "Debug.h" + +enum client_fs_type { + CLIENT_FS_BEOS_KERNEL = 0, + CLIENT_FS_HAIKU_KERNEL, +}; + +enum { + // FS operations + FS_CAPABILITY_MOUNT = 0, + FS_CAPABILITY_UNMOUNT, + + FS_CAPABILITY_READ_FS_INFO, + FS_CAPABILITY_WRITE_FS_INFO, + FS_CAPABILITY_SYNC, + + // vnode operations + FS_CAPABILITY_LOOKUP, + FS_CAPABILITY_GET_VNODE_NAME, + + FS_CAPABILITY_GET_VNODE, + FS_CAPABILITY_PUT_VNODE, + FS_CAPABILITY_REMOVE_VNODE, + + // VM file access + FS_CAPABILITY_CAN_PAGE, + FS_CAPABILITY_READ_PAGES, + FS_CAPABILITY_WRITE_PAGES, + + // cache file access + FS_CAPABILITY_GET_FILE_MAP, + + // common operations + FS_CAPABILITY_IOCTL, + FS_CAPABILITY_SET_FLAGS, + FS_CAPABILITY_SELECT, + FS_CAPABILITY_DESELECT, + FS_CAPABILITY_FSYNC, + + FS_CAPABILITY_READ_SYMLINK, + FS_CAPABILITY_CREATE_SYMLINK, + + FS_CAPABILITY_LINK, + FS_CAPABILITY_UNLINK, + FS_CAPABILITY_RENAME, + + FS_CAPABILITY_ACCESS, + FS_CAPABILITY_READ_STAT, + FS_CAPABILITY_WRITE_STAT, + + // file operations + FS_CAPABILITY_CREATE, + FS_CAPABILITY_OPEN, + FS_CAPABILITY_CLOSE, + FS_CAPABILITY_FREE_COOKIE, + FS_CAPABILITY_READ, + FS_CAPABILITY_WRITE, + + // directory operations + FS_CAPABILITY_CREATE_DIR, + FS_CAPABILITY_REMOVE_DIR, + FS_CAPABILITY_OPEN_DIR, + FS_CAPABILITY_CLOSE_DIR, + FS_CAPABILITY_FREE_DIR_COOKIE, + FS_CAPABILITY_READ_DIR, + FS_CAPABILITY_REWIND_DIR, + + // attribute directory operations + FS_CAPABILITY_OPEN_ATTR_DIR, + FS_CAPABILITY_CLOSE_ATTR_DIR, + FS_CAPABILITY_FREE_ATTR_DIR_COOKIE, + FS_CAPABILITY_READ_ATTR_DIR, + FS_CAPABILITY_REWIND_ATTR_DIR, + + // attribute operations + FS_CAPABILITY_CREATE_ATTR, + FS_CAPABILITY_OPEN_ATTR, + FS_CAPABILITY_CLOSE_ATTR, + FS_CAPABILITY_FREE_ATTR_COOKIE, + FS_CAPABILITY_READ_ATTR, + FS_CAPABILITY_WRITE_ATTR, + + FS_CAPABILITY_READ_ATTR_STAT, + FS_CAPABILITY_WRITE_ATTR_STAT, + FS_CAPABILITY_RENAME_ATTR, + FS_CAPABILITY_REMOVE_ATTR, + + // index directory & index operations + FS_CAPABILITY_OPEN_INDEX_DIR, + FS_CAPABILITY_CLOSE_INDEX_DIR, + FS_CAPABILITY_FREE_INDEX_DIR_COOKIE, + FS_CAPABILITY_READ_INDEX_DIR, + FS_CAPABILITY_REWIND_INDEX_DIR, + + FS_CAPABILITY_CREATE_INDEX, + FS_CAPABILITY_REMOVE_INDEX, + FS_CAPABILITY_READ_INDEX_STAT, + + // query operations + FS_CAPABILITY_OPEN_QUERY, + FS_CAPABILITY_CLOSE_QUERY, + FS_CAPABILITY_FREE_QUERY_COOKIE, + FS_CAPABILITY_READ_QUERY, + FS_CAPABILITY_REWIND_QUERY, + + FS_CAPABILITY_COUNT, +}; + + +namespace UserlandFSUtil { + +struct FSCapabilities { + client_fs_type clientFSType; + uint8 capabilities[(FS_CAPABILITY_COUNT + 7) / 8]; + + inline void ClearAll(); + + inline void Set(uint32 capability, bool set = true); + inline void Clear(uint32 capability); + inline bool Get(uint32 capability) const; + + inline void Dump() const; +}; + +// ClearAll +inline void +FSCapabilities::ClearAll() +{ + memset(capabilities, 0, sizeof(capabilities)); +} + +// Set +inline void +FSCapabilities::Set(uint32 capability, bool set) +{ + if (capability >= FS_CAPABILITY_COUNT) + return; + + uint8 flag = uint8(1 << (capability % 8)); + if (set) + capabilities[capability / 8] |= flag; + else + capabilities[capability / 8] &= ~flag; +} + +// Clear +inline void +FSCapabilities::Clear(uint32 capability) +{ + Set(capability, false); +} + +// Get +inline bool +FSCapabilities::Get(uint32 capability) const +{ + if (capability >= FS_CAPABILITY_COUNT) + return false; + + uint8 flag = uint8(1 << (capability % 8)); + return (capabilities[capability / 8] & flag); +} + +// Dump +inline void +FSCapabilities::Dump() const +{ + D( + char buffer[128]; + int byteCount = sizeof(capabilities); + for (int i = 0; i < byteCount; i++) + sprintf(buffer + 2 * i, "%02x", (int)capabilities[i]); + + PRINT(("FSCapabilities[%d, %s]\n", clientFSType, buffer)); + ) +} + + +} // namespace UserlandFSUtil + +using UserlandFSUtil::FSCapabilities; + +#endif // USERLAND_FS_FS_CAPABILITIES_H diff --git a/headers/private/userlandfs/private/Requests.h b/headers/private/userlandfs/private/Requests.h index d5f4178c90..ed3fb8c95f 100644 --- a/headers/private/userlandfs/private/Requests.h +++ b/headers/private/userlandfs/private/Requests.h @@ -9,6 +9,7 @@ #include #include "Compatibility.h" +#include "FSCapabilities.h" #include "Request.h" @@ -304,8 +305,9 @@ public: FSConnectReply() : ReplyRequest(FS_CONNECT_REPLY) {} status_t GetAddressInfos(AddressInfo* infos, int32* count); - Address portInfos; - int32 portInfoCount; + Address portInfos; + int32 portInfoCount; + FSCapabilities capabilities; }; diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.cpp index 21d2a22645..989922213b 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.cpp @@ -64,9 +64,11 @@ FileSystem::~FileSystem() // Init status_t -FileSystem::Init(const char* name, Port::Info* infos, int32 count) +FileSystem::Init(const char* name, Port::Info* infos, int32 count, + const FSCapabilities& capabilities) { - PRINT(("FileSystem::Init(\"%s\", %p, %ld)\n", name, infos, infoCount)); + PRINT(("FileSystem::Init(\"%s\", %p, %ld)\n", name, infos, count)); + capabilities.Dump(); // check parameters if (!name || !infos || count < 2) @@ -76,6 +78,8 @@ FileSystem::Init(const char* name, Port::Info* infos, int32 count) if (!fName.SetTo(name)) return B_NO_MEMORY; + fCapabilities = capabilities; + // create the select sync entry map fSelectSyncs = new(nothrow) SelectSyncMap; if (!fSelectSyncs) @@ -159,6 +163,13 @@ FileSystem::GetName() const return fName.GetString(); } +// GetCapabilities +const FSCapabilities& +FileSystem::GetCapabilities() const +{ + return fCapabilities; +} + // GetPortPool RequestPortPool* FileSystem::GetPortPool() diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.h b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.h index 697bda55c4..f530e6194b 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.h +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.h @@ -5,6 +5,7 @@ #include +#include "FSCapabilities.h" #include "LazyInitializable.h" #include "Locker.h" #include "Referencable.h" @@ -24,10 +25,14 @@ public: ~FileSystem(); status_t Init(const char* name, Port::Info* infos, - int32 infoCount); + int32 infoCount, + const FSCapabilities& capabilities); const char* GetName() const; + const FSCapabilities& GetCapabilities() const; + inline bool HasCapability(uint32 capability) const; + RequestPortPool* GetPortPool(); status_t Mount(mount_id id, const char* device, @@ -59,6 +64,7 @@ private: Vector fVolumes; Locker fVolumeLock; String fName; + FSCapabilities fCapabilities; RequestPort* fNotificationPort; thread_id fNotificationThread; RequestPortPool fPortPool; @@ -69,4 +75,12 @@ private: volatile bool fTerminating; }; + +// HasCapability +inline bool +FileSystem::HasCapability(uint32 capability) const +{ + return fCapabilities.Get(capability); +} + #endif // USERLAND_FS_FILE_SYSTEM_H diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystemInitializer.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystemInitializer.cpp index adf78984f2..387010ce72 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystemInitializer.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystemInitializer.cpp @@ -68,7 +68,7 @@ FileSystemInitializer::FirstTimeInit() if (!fFileSystem) return B_NO_MEMORY; - error = fFileSystem->Init(fName, infos, count); + error = fFileSystem->Init(fName, infos, count, reply->capabilities); if (error != B_OK) return B_ERROR; diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp index 11049e4c56..62f0ae7e64 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp @@ -280,6 +280,10 @@ Volume::Unmount() status_t Volume::Sync() { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_SYNC)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -337,6 +341,10 @@ Volume::ReadFSInfo(fs_info* info) status_t Volume::WriteFSInfo(const struct fs_info *info, uint32 mask) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_FS_INFO)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -574,6 +582,10 @@ Volume::IOCtl(fs_vnode node, fs_cookie cookie, uint32 command, void *buffer, } } + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_IOCTL)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -630,6 +642,10 @@ Volume::IOCtl(fs_vnode node, fs_cookie cookie, uint32 command, void *buffer, status_t Volume::SetFlags(fs_vnode node, fs_cookie cookie, int flags) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_SET_FLAGS)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -667,6 +683,12 @@ status_t Volume::Select(fs_vnode node, fs_cookie cookie, uint8 event, uint32 ref, selectsync* sync) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_SELECT)) { + notify_select_event(sync, ref, event); + return B_OK; + } + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -714,6 +736,10 @@ Volume::Select(fs_vnode node, fs_cookie cookie, uint8 event, uint32 ref, status_t Volume::Deselect(fs_vnode node, fs_cookie cookie, uint8 event, selectsync* sync) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_DESELECT)) + return B_OK; + struct SyncRemover { SyncRemover(FileSystem* fs, selectsync* sync) : fs(fs), sync(sync) {} @@ -760,6 +786,10 @@ Volume::Deselect(fs_vnode node, fs_cookie cookie, uint8 event, selectsync* sync) status_t Volume::FSync(fs_vnode node) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_FSYNC)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -796,6 +826,11 @@ Volume::ReadSymlink(fs_vnode node, char* buffer, size_t bufferSize, size_t* bytesRead) { *bytesRead = 0; + + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_SYMLINK)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -841,6 +876,10 @@ status_t Volume::CreateSymlink(fs_vnode dir, const char* name, const char* target, int mode) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_SYMLINK)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -881,6 +920,10 @@ Volume::CreateSymlink(fs_vnode dir, const char* name, const char* target, status_t Volume::Link(fs_vnode dir, const char* name, fs_vnode node) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_LINK)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -919,6 +962,10 @@ Volume::Link(fs_vnode dir, const char* name, fs_vnode node) status_t Volume::Unlink(fs_vnode dir, const char* name) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_UNLINK)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -957,6 +1004,10 @@ status_t Volume::Rename(fs_vnode oldDir, const char* oldName, fs_vnode newDir, const char* newName) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_RENAME)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -997,6 +1048,10 @@ Volume::Rename(fs_vnode oldDir, const char* oldName, fs_vnode newDir, status_t Volume::Access(fs_vnode node, int mode) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_ACCESS)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1062,6 +1117,10 @@ Volume::ReadStat(fs_vnode node, struct stat* st) status_t Volume::WriteStat(fs_vnode node, const struct stat* st, uint32 mask) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_STAT)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1102,6 +1161,10 @@ status_t Volume::Create(fs_vnode dir, const char* name, int openMode, int mode, void** cookie, vnode_id* vnid) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1148,6 +1211,10 @@ Volume::Create(fs_vnode dir, const char* name, int openMode, int mode, status_t Volume::Open(fs_vnode node, int openMode, fs_cookie* cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1223,6 +1290,10 @@ Volume::Read(fs_vnode node, fs_cookie cookie, off_t pos, void* buffer, { *bytesRead = 0; + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1272,6 +1343,10 @@ Volume::Write(fs_vnode node, fs_cookie cookie, off_t pos, const void* buffer, { *bytesWritten = 0; + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1315,6 +1390,10 @@ Volume::Write(fs_vnode node, fs_cookie cookie, off_t pos, const void* buffer, status_t Volume::CreateDir(fs_vnode dir, const char* name, int mode, vnode_id *newDir) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1354,6 +1433,10 @@ Volume::CreateDir(fs_vnode dir, const char* name, int mode, vnode_id *newDir) status_t Volume::RemoveDir(fs_vnode dir, const char* name) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_REMOVE_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1391,6 +1474,10 @@ Volume::RemoveDir(fs_vnode dir, const char* name) status_t Volume::OpenDir(fs_vnode node, fs_cookie* cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1466,6 +1553,10 @@ Volume::ReadDir(fs_vnode node, fs_vnode cookie, void* buffer, size_t bufferSize, { *countRead = 0; + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1521,6 +1612,10 @@ reply->buffer.GetSize())); status_t Volume::RewindDir(fs_vnode node, fs_vnode cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1560,6 +1655,10 @@ Volume::RewindDir(fs_vnode node, fs_vnode cookie) status_t Volume::OpenAttrDir(fs_vnode node, fs_cookie *cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_ATTR_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1635,6 +1734,10 @@ status_t Volume::ReadAttrDir(fs_vnode node, fs_cookie cookie, void* buffer, size_t bufferSize, uint32 count, uint32* countRead) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_ATTR_DIR)) + return B_BAD_VALUE; + *countRead = 0; // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); @@ -1689,6 +1792,10 @@ Volume::ReadAttrDir(fs_vnode node, fs_cookie cookie, void* buffer, status_t Volume::RewindAttrDir(fs_vnode node, fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_ATTR_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1728,6 +1835,10 @@ status_t Volume::CreateAttr(fs_vnode node, const char* name, uint32 type, int openMode, fs_cookie* cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_ATTR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1771,6 +1882,10 @@ status_t Volume::OpenAttr(fs_vnode node, const char* name, int openMode, fs_cookie* cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_ATTR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1851,6 +1966,10 @@ Volume::ReadAttr(fs_vnode node, fs_cookie cookie, off_t pos, { *bytesRead = 0; + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_ATTR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1900,6 +2019,10 @@ Volume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos, { *bytesWritten = 0; + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_ATTR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1940,6 +2063,10 @@ Volume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos, status_t Volume::ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_ATTR_STAT)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -1977,6 +2104,10 @@ status_t Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode, const char* newName) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_RENAME_ATTR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2017,6 +2148,10 @@ Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode, status_t Volume::RemoveAttr(fs_vnode node, const char* name) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_REMOVE_ATTR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2058,6 +2193,10 @@ Volume::RemoveAttr(fs_vnode node, const char* name) status_t Volume::OpenIndexDir(fs_cookie *cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_INDEX_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2134,6 +2273,10 @@ Volume::ReadIndexDir(fs_cookie cookie, void* buffer, size_t bufferSize, { *countRead = 0; + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_INDEX_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2186,6 +2329,10 @@ Volume::ReadIndexDir(fs_cookie cookie, void* buffer, size_t bufferSize, status_t Volume::RewindIndexDir(fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_INDEX_DIR)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2220,6 +2367,10 @@ Volume::RewindIndexDir(fs_cookie cookie) status_t Volume::CreateIndex(const char* name, uint32 type, uint32 flags) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_INDEX)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2258,6 +2409,10 @@ Volume::CreateIndex(const char* name, uint32 type, uint32 flags) status_t Volume::RemoveIndex(const char* name) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_REMOVE_INDEX)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2294,6 +2449,10 @@ Volume::RemoveIndex(const char* name) status_t Volume::ReadIndexStat(const char* name, struct stat *st) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_INDEX_STAT)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2336,6 +2495,10 @@ status_t Volume::OpenQuery(const char* queryString, uint32 flags, port_id targetPort, uint32 token, fs_cookie *cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_QUERY)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2417,6 +2580,10 @@ Volume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize, { *countRead = 0; + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_QUERY)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2560,6 +2727,10 @@ Volume::_Unmount() status_t Volume::_ReadFSInfo(fs_info* info) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_FS_INFO)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2669,6 +2840,10 @@ Volume::_WriteVNode(fs_vnode node, bool reenter) status_t Volume::_ReadStat(fs_vnode node, struct stat* st) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_STAT)) + return B_BAD_VALUE; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2704,6 +2879,10 @@ Volume::_ReadStat(fs_vnode node, struct stat* st) status_t Volume::_Close(fs_vnode node, fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2739,6 +2918,10 @@ Volume::_Close(fs_vnode node, fs_cookie cookie) status_t Volume::_FreeCookie(fs_vnode node, fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_COOKIE)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2774,6 +2957,10 @@ Volume::_FreeCookie(fs_vnode node, fs_cookie cookie) status_t Volume::_CloseDir(fs_vnode node, fs_vnode cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_DIR)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2809,6 +2996,10 @@ Volume::_CloseDir(fs_vnode node, fs_vnode cookie) status_t Volume::_FreeDirCookie(fs_vnode node, fs_vnode cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_DIR_COOKIE)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2844,6 +3035,10 @@ Volume::_FreeDirCookie(fs_vnode node, fs_vnode cookie) status_t Volume::_CloseAttrDir(fs_vnode node, fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_ATTR_DIR)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2879,6 +3074,10 @@ Volume::_CloseAttrDir(fs_vnode node, fs_cookie cookie) status_t Volume::_FreeAttrDirCookie(fs_vnode node, fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_ATTR_DIR_COOKIE)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2914,6 +3113,10 @@ Volume::_FreeAttrDirCookie(fs_vnode node, fs_cookie cookie) status_t Volume::_CloseAttr(fs_vnode node, fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_ATTR)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2949,6 +3152,10 @@ Volume::_CloseAttr(fs_vnode node, fs_cookie cookie) status_t Volume::_FreeAttrCookie(fs_vnode node, fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_ATTR_COOKIE)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -2984,6 +3191,10 @@ Volume::_FreeAttrCookie(fs_vnode node, fs_cookie cookie) status_t Volume::_CloseIndexDir(fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_INDEX_DIR)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -3018,6 +3229,10 @@ Volume::_CloseIndexDir(fs_cookie cookie) status_t Volume::_FreeIndexDirCookie(fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_INDEX_DIR_COOKIE)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -3052,6 +3267,10 @@ Volume::_FreeIndexDirCookie(fs_cookie cookie) status_t Volume::_CloseQuery(fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_QUERY)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) @@ -3086,6 +3305,10 @@ Volume::_CloseQuery(fs_cookie cookie) status_t Volume::_FreeQueryCookie(fs_cookie cookie) { + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_QUERY_COOKIE)) + return B_OK; + // get a free port RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); if (!port) diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelFileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelFileSystem.cpp index a8c9c1279e..c1268cff69 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelFileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelFileSystem.cpp @@ -4,6 +4,7 @@ #include +#include "beos_fs_interface.h" #include "BeOSKernelVolume.h" using std::nothrow; @@ -13,6 +14,7 @@ BeOSKernelFileSystem::BeOSKernelFileSystem(beos_vnode_ops* fsOps) : FileSystem(), fFSOps(fsOps) { + _InitCapabilities(fsOps); } // destructor @@ -45,3 +47,114 @@ BeOSKernelFileSystem::DeleteVolume(Volume* volume) return B_OK; } +// _InitCapabilities +void +BeOSKernelFileSystem::_InitCapabilities(beos_vnode_ops* fsOps) +{ + fCapabilities.ClearAll(); + + // FS interface type + fCapabilities.clientFSType = CLIENT_FS_BEOS_KERNEL; + + // FS operations + fCapabilities.Set(FS_CAPABILITY_MOUNT, fsOps->mount); + fCapabilities.Set(FS_CAPABILITY_UNMOUNT, fsOps->unmount); + + fCapabilities.Set(FS_CAPABILITY_READ_FS_INFO, fsOps->rfsstat); + fCapabilities.Set(FS_CAPABILITY_WRITE_FS_INFO, fsOps->wfsstat); + fCapabilities.Set(FS_CAPABILITY_SYNC, fsOps->sync); + + // vnode operations + fCapabilities.Set(FS_CAPABILITY_LOOKUP, fsOps->walk); + // missing: FS_CAPABILITY_GET_VNODE_NAME, + + fCapabilities.Set(FS_CAPABILITY_GET_VNODE, fsOps->read_vnode); + fCapabilities.Set(FS_CAPABILITY_PUT_VNODE, fsOps->write_vnode); + fCapabilities.Set(FS_CAPABILITY_REMOVE_VNODE, fsOps->remove_vnode); + + // VM file access + // missing: FS_CAPABILITY_CAN_PAGE, + // missing: FS_CAPABILITY_READ_PAGES, + // missing: FS_CAPABILITY_WRITE_PAGES, + + // cache file access + // missing: FS_CAPABILITY_GET_FILE_MAP, + + // common operations + fCapabilities.Set(FS_CAPABILITY_IOCTL, fsOps->ioctl); + fCapabilities.Set(FS_CAPABILITY_SET_FLAGS, fsOps->setflags); + fCapabilities.Set(FS_CAPABILITY_SELECT, fsOps->select); + fCapabilities.Set(FS_CAPABILITY_DESELECT, fsOps->deselect); + fCapabilities.Set(FS_CAPABILITY_FSYNC, fsOps->fsync); + + fCapabilities.Set(FS_CAPABILITY_READ_SYMLINK, fsOps->readlink); + fCapabilities.Set(FS_CAPABILITY_CREATE_SYMLINK, fsOps->symlink); + + fCapabilities.Set(FS_CAPABILITY_LINK, fsOps->link); + fCapabilities.Set(FS_CAPABILITY_UNLINK, fsOps->unlink); + fCapabilities.Set(FS_CAPABILITY_RENAME, fsOps->rename); + + fCapabilities.Set(FS_CAPABILITY_ACCESS, fsOps->access); + fCapabilities.Set(FS_CAPABILITY_READ_STAT, fsOps->rstat); + fCapabilities.Set(FS_CAPABILITY_WRITE_STAT, fsOps->wstat); + + // file operations + fCapabilities.Set(FS_CAPABILITY_CREATE, fsOps->create); + fCapabilities.Set(FS_CAPABILITY_OPEN, fsOps->open); + fCapabilities.Set(FS_CAPABILITY_CLOSE, fsOps->close); + fCapabilities.Set(FS_CAPABILITY_FREE_COOKIE, fsOps->free_cookie); + fCapabilities.Set(FS_CAPABILITY_READ, fsOps->read); + fCapabilities.Set(FS_CAPABILITY_WRITE, fsOps->write); + + // directory operations + fCapabilities.Set(FS_CAPABILITY_CREATE_DIR, fsOps->mkdir); + fCapabilities.Set(FS_CAPABILITY_REMOVE_DIR, fsOps->rmdir); + fCapabilities.Set(FS_CAPABILITY_OPEN_DIR, fsOps->opendir); + fCapabilities.Set(FS_CAPABILITY_CLOSE_DIR, fsOps->closedir); + fCapabilities.Set(FS_CAPABILITY_FREE_DIR_COOKIE, fsOps->free_dircookie); + fCapabilities.Set(FS_CAPABILITY_READ_DIR, fsOps->readdir); + fCapabilities.Set(FS_CAPABILITY_REWIND_DIR, fsOps->rewinddir); + + // attribute directory operations + fCapabilities.Set(FS_CAPABILITY_OPEN_ATTR_DIR, fsOps->open_attrdir); + fCapabilities.Set(FS_CAPABILITY_CLOSE_ATTR_DIR, fsOps->close_attrdir); + fCapabilities.Set(FS_CAPABILITY_FREE_ATTR_DIR_COOKIE, + fsOps->free_attrdircookie); + fCapabilities.Set(FS_CAPABILITY_READ_ATTR_DIR, fsOps->read_attrdir); + fCapabilities.Set(FS_CAPABILITY_REWIND_ATTR_DIR, fsOps->rewind_attrdir); + + // attribute operations + // we emulate open_attr() and free_attr_dir_cookie() if either read_attr() + // or write_attr() is present + bool hasAttributes = (fsOps->read_attr || fsOps->write_attr); + fCapabilities.Set(FS_CAPABILITY_CREATE_ATTR, hasAttributes); + fCapabilities.Set(FS_CAPABILITY_OPEN_ATTR, hasAttributes); + fCapabilities.Set(FS_CAPABILITY_CLOSE_ATTR, false); + fCapabilities.Set(FS_CAPABILITY_FREE_ATTR_COOKIE, hasAttributes); + fCapabilities.Set(FS_CAPABILITY_READ_ATTR, fsOps->read_attr); + fCapabilities.Set(FS_CAPABILITY_WRITE_ATTR, fsOps->write_attr); + + fCapabilities.Set(FS_CAPABILITY_READ_ATTR_STAT, fsOps->stat_attr); + // missing: FS_CAPABILITY_WRITE_ATTR_STAT + fCapabilities.Set(FS_CAPABILITY_RENAME_ATTR, fsOps->rename_attr); + fCapabilities.Set(FS_CAPABILITY_REMOVE_ATTR, fsOps->remove_attr); + + // index directory & index operations + fCapabilities.Set(FS_CAPABILITY_OPEN_INDEX_DIR, fsOps->open_indexdir); + fCapabilities.Set(FS_CAPABILITY_CLOSE_INDEX_DIR, fsOps->close_indexdir); + fCapabilities.Set(FS_CAPABILITY_FREE_INDEX_DIR_COOKIE, + fsOps->free_indexdircookie); + fCapabilities.Set(FS_CAPABILITY_READ_INDEX_DIR, fsOps->read_indexdir); + fCapabilities.Set(FS_CAPABILITY_REWIND_INDEX_DIR, fsOps->rewind_indexdir); + + fCapabilities.Set(FS_CAPABILITY_CREATE_INDEX, fsOps->create_index); + fCapabilities.Set(FS_CAPABILITY_REMOVE_INDEX, fsOps->remove_index); + fCapabilities.Set(FS_CAPABILITY_READ_INDEX_STAT, fsOps->stat_index); + + // query operations + fCapabilities.Set(FS_CAPABILITY_OPEN_QUERY, fsOps->open_query); + fCapabilities.Set(FS_CAPABILITY_CLOSE_QUERY, fsOps->close_query); + fCapabilities.Set(FS_CAPABILITY_FREE_QUERY_COOKIE, fsOps->free_querycookie); + fCapabilities.Set(FS_CAPABILITY_READ_QUERY, fsOps->read_query); + // missing: FS_CAPABILITY_REWIND_QUERY, +} diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelFileSystem.h b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelFileSystem.h index e1fd4886c3..9094c12e3e 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelFileSystem.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelFileSystem.h @@ -17,6 +17,9 @@ public: virtual status_t CreateVolume(Volume** volume, mount_id id); virtual status_t DeleteVolume(Volume* volume); +private: + void _InitCapabilities(beos_vnode_ops* fsOps); + private: beos_vnode_ops* fFSOps; }; diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.cpp index bf7794ce92..0f32f7c2de 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.cpp @@ -294,7 +294,7 @@ status_t BeOSKernelVolume::Access(fs_vnode node, int mode) { if (!fFSOps->access) - return B_BAD_VALUE; + return B_OK; return fFSOps->access(fVolumeCookie, node, mode); } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/FSInfo.h b/src/add-ons/kernel/file_systems/userlandfs/server/FSInfo.h index 710b516bae..8ef0e8ff41 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/FSInfo.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/FSInfo.h @@ -9,6 +9,7 @@ #include +#include "FSCapabilities.h" #include "Port.h" #include "String.h" @@ -25,12 +26,13 @@ public: { } - FSInfo(const char* fsName, const Port::Info* infos, int32 count) + FSInfo(const char* fsName, const Port::Info* infos, int32 count, + const FSCapabilities& capabilities) : fName(), fInfos(NULL), fCount(0) { - SetTo(fsName, infos, count); + SetTo(fsName, infos, count, capabilities); } FSInfo(const BMessage* message) @@ -46,7 +48,7 @@ public: fInfos(NULL), fCount(0) { - SetTo(other.GetName(), other.fInfos, other.fCount); + SetTo(other.GetName(), other.fInfos, other.fCount, other.fCapabilities); } ~FSInfo() @@ -54,17 +56,24 @@ public: Unset(); } - status_t SetTo(const char* fsName, const Port::Info* infos, int32 count) + status_t SetTo(const char* fsName, const Port::Info* infos, int32 count, + const FSCapabilities& capabilities) { Unset(); + if (!fsName || !infos || count <= 0) return B_BAD_VALUE; + if (!fName.SetTo(fsName)) return B_NO_MEMORY; + fInfos = new(nothrow) Port::Info[count]; if (!fInfos) return B_NO_MEMORY; memcpy(fInfos, infos, sizeof(Port::Info) * count); + + fCapabilities = capabilities; + fCount = count; return B_OK; } @@ -72,17 +81,25 @@ public: status_t SetTo(const BMessage* message) { Unset(); + if (!message) return B_BAD_VALUE; + const void* infos; ssize_t size; const char* fsName; + const void* capabilities; + ssize_t capabilitiesSize; + if (message->FindData("infos", B_RAW_TYPE, &infos, &size) != B_OK - || size < 0 || message->FindString("fsName", &fsName) != B_OK) { + || size < 0 || message->FindString("fsName", &fsName) != B_OK + || message->FindData("capabilities", B_RAW_TYPE, &capabilities, + &capabilitiesSize) != B_OK + || capabilitiesSize != sizeof(FSCapabilities)) { return B_BAD_VALUE; } return SetTo(fsName, (const Port::Info*)infos, - size / sizeof(Port::Info)); + size / sizeof(Port::Info), *(const FSCapabilities*)capabilities); } void Unset() @@ -108,26 +125,39 @@ public: return fCount; } - int32 GetSize() const + int32 GetInfosSize() const { return fCount * sizeof(Port::Info); } + const FSCapabilities& GetCapabilities() const + { + return fCapabilities; + } + status_t Archive(BMessage* archive) { if (!fName.GetString() || !fInfos) return B_NO_INIT; + status_t error = archive->AddString("fsName", fName.GetString()); if (error != B_OK) return error; - return archive->AddData("infos", B_RAW_TYPE, fInfos, + + error = archive->AddData("infos", B_RAW_TYPE, fInfos, fCount * sizeof(Port::Info)); + if (error != B_OK) + return error; + + return archive->AddData("capabilities", B_RAW_TYPE, &fCapabilities, + sizeof(FSCapabilities)); } private: String fName; Port::Info* fInfos; int32 fCount; + FSCapabilities fCapabilities; }; } // namespace UserlandFS diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.h b/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.h index ea8110ef8a..262cb8c855 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/FileSystem.h @@ -6,6 +6,8 @@ #include #include +#include "FSCapabilities.h" + namespace UserlandFS { class Volume; @@ -17,6 +19,13 @@ public: virtual status_t CreateVolume(Volume** volume, mount_id id) = 0; virtual status_t DeleteVolume(Volume* volume) = 0; + + void GetCapabilities( + FSCapabilities& capabilities) const + { capabilities = fCapabilities; } + +protected: + FSCapabilities fCapabilities; }; } // namespace UserlandFS diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandFSDispatcher.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandFSDispatcher.cpp index 81584ecb29..8705f356d5 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandFSDispatcher.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandFSDispatcher.cpp @@ -319,6 +319,7 @@ UserlandFSDispatcher::_ProcessRequests() if (error != B_OK) RETURN_ERROR(error); RequestReleaser _(fRequestPort, request); + // check the request type if (request->GetType() == UFS_DISCONNECT_REQUEST) return B_OK; @@ -326,6 +327,7 @@ UserlandFSDispatcher::_ProcessRequests() RETURN_ERROR(B_BAD_VALUE); PRINT(("UserlandFSDispatcher::_ProcessRequests(): received FS connect " "request\n")); + // it's an FS connect request FSConnectRequest* connectRequest = (FSConnectRequest*)request; // get the FS name @@ -338,24 +340,27 @@ UserlandFSDispatcher::_ProcessRequests() fsName.SetTo((const char*)connectRequest->fsName.GetData(), len); if (result == B_OK && fsName.GetLength() == 0) result = B_BAD_DATA; + // prepare the reply RequestAllocator allocator(fRequestPort->GetPort()); FSConnectReply* reply; error = AllocateRequest(allocator, &reply); if (error != B_OK) RETURN_ERROR(error); + FileSystem* fileSystem = NULL; if (result == B_OK) result = _GetFileSystem(fsName.GetString(), &fileSystem); if (result == B_OK) { const FSInfo* info = fileSystem->GetInfo(); result = allocator.AllocateData(reply->portInfos, - info->GetInfos(), info->GetSize(), sizeof(Port::Info)); - if (result == B_OK) - reply->portInfoCount = info->CountInfos(); + info->GetInfos(), info->GetInfosSize(), sizeof(Port::Info)); + reply->portInfoCount = info->CountInfos(); + reply->capabilities = info->GetCapabilities(); _PutFileSystem(fileSystem); } reply->error = result; + // send it error = fRequestPort->SendRequest(&allocator); if (error != B_OK) diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandFSServer.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandFSServer.cpp index c28ff96bd2..2ebb0bbf54 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandFSServer.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandFSServer.cpp @@ -183,20 +183,29 @@ UserlandFSServer::_RegisterWithDispatcher(const char* fsName) ERROR(("Failed to lock the clipboard.\n")); return B_ERROR; } + // get the port infos Port::Info infos[kRequestThreadCount + 1]; infos[0] = *fNotificationRequestPort->GetPortInfo(); for (int32 i = 0; i < kRequestThreadCount; i++) infos[i + 1] = *fRequestThreads[i].GetPortInfo(); + + // FS capabilities + FSCapabilities capabilities; + fFileSystem->GetCapabilities(capabilities); + // init an FS info FSInfo info; - status_t error = info.SetTo(fsName, infos, kRequestThreadCount + 1); + status_t error = info.SetTo(fsName, infos, kRequestThreadCount + 1, + capabilities); + // prepare the message BMessage message(UFS_REGISTER_FS); if (error == B_OK) error = message.AddInt32("team", Team()); if (error == B_OK) error = info.Archive(&message); + // send the message BMessage reply; error = messenger.SendMessage(&message, &reply);