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
This commit is contained in:
Ingo Weinhold
2007-03-05 05:16:08 +00:00
parent cf4ccd6575
commit 4e0e80ed6c
13 changed files with 629 additions and 19 deletions
@@ -0,0 +1,191 @@
// FSCapabilities.h
#ifndef USERLAND_FS_FS_CAPABILITIES_H
#define USERLAND_FS_FS_CAPABILITIES_H
#include <string.h>
#include <stdio.h>
#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
@@ -9,6 +9,7 @@
#include <fs_interface.h> #include <fs_interface.h>
#include "Compatibility.h" #include "Compatibility.h"
#include "FSCapabilities.h"
#include "Request.h" #include "Request.h"
@@ -306,6 +307,7 @@ public:
Address portInfos; Address portInfos;
int32 portInfoCount; int32 portInfoCount;
FSCapabilities capabilities;
}; };
@@ -64,9 +64,11 @@ FileSystem::~FileSystem()
// Init // Init
status_t 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 // check parameters
if (!name || !infos || count < 2) if (!name || !infos || count < 2)
@@ -76,6 +78,8 @@ FileSystem::Init(const char* name, Port::Info* infos, int32 count)
if (!fName.SetTo(name)) if (!fName.SetTo(name))
return B_NO_MEMORY; return B_NO_MEMORY;
fCapabilities = capabilities;
// create the select sync entry map // create the select sync entry map
fSelectSyncs = new(nothrow) SelectSyncMap; fSelectSyncs = new(nothrow) SelectSyncMap;
if (!fSelectSyncs) if (!fSelectSyncs)
@@ -159,6 +163,13 @@ FileSystem::GetName() const
return fName.GetString(); return fName.GetString();
} }
// GetCapabilities
const FSCapabilities&
FileSystem::GetCapabilities() const
{
return fCapabilities;
}
// GetPortPool // GetPortPool
RequestPortPool* RequestPortPool*
FileSystem::GetPortPool() FileSystem::GetPortPool()
@@ -5,6 +5,7 @@
#include <fs_interface.h> #include <fs_interface.h>
#include "FSCapabilities.h"
#include "LazyInitializable.h" #include "LazyInitializable.h"
#include "Locker.h" #include "Locker.h"
#include "Referencable.h" #include "Referencable.h"
@@ -24,10 +25,14 @@ public:
~FileSystem(); ~FileSystem();
status_t Init(const char* name, Port::Info* infos, status_t Init(const char* name, Port::Info* infos,
int32 infoCount); int32 infoCount,
const FSCapabilities& capabilities);
const char* GetName() const; const char* GetName() const;
const FSCapabilities& GetCapabilities() const;
inline bool HasCapability(uint32 capability) const;
RequestPortPool* GetPortPool(); RequestPortPool* GetPortPool();
status_t Mount(mount_id id, const char* device, status_t Mount(mount_id id, const char* device,
@@ -59,6 +64,7 @@ private:
Vector<Volume*> fVolumes; Vector<Volume*> fVolumes;
Locker fVolumeLock; Locker fVolumeLock;
String fName; String fName;
FSCapabilities fCapabilities;
RequestPort* fNotificationPort; RequestPort* fNotificationPort;
thread_id fNotificationThread; thread_id fNotificationThread;
RequestPortPool fPortPool; RequestPortPool fPortPool;
@@ -69,4 +75,12 @@ private:
volatile bool fTerminating; volatile bool fTerminating;
}; };
// HasCapability
inline bool
FileSystem::HasCapability(uint32 capability) const
{
return fCapabilities.Get(capability);
}
#endif // USERLAND_FS_FILE_SYSTEM_H #endif // USERLAND_FS_FILE_SYSTEM_H
@@ -68,7 +68,7 @@ FileSystemInitializer::FirstTimeInit()
if (!fFileSystem) if (!fFileSystem)
return B_NO_MEMORY; return B_NO_MEMORY;
error = fFileSystem->Init(fName, infos, count); error = fFileSystem->Init(fName, infos, count, reply->capabilities);
if (error != B_OK) if (error != B_OK)
return B_ERROR; return B_ERROR;
@@ -280,6 +280,10 @@ Volume::Unmount()
status_t status_t
Volume::Sync() Volume::Sync()
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_SYNC))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -337,6 +341,10 @@ Volume::ReadFSInfo(fs_info* info)
status_t status_t
Volume::WriteFSInfo(const struct fs_info *info, uint32 mask) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -630,6 +642,10 @@ Volume::IOCtl(fs_vnode node, fs_cookie cookie, uint32 command, void *buffer,
status_t status_t
Volume::SetFlags(fs_vnode node, fs_cookie cookie, int flags) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -667,6 +683,12 @@ status_t
Volume::Select(fs_vnode node, fs_cookie cookie, uint8 event, uint32 ref, Volume::Select(fs_vnode node, fs_cookie cookie, uint8 event, uint32 ref,
selectsync* sync) selectsync* sync)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_SELECT)) {
notify_select_event(sync, ref, event);
return B_OK;
}
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -714,6 +736,10 @@ Volume::Select(fs_vnode node, fs_cookie cookie, uint8 event, uint32 ref,
status_t status_t
Volume::Deselect(fs_vnode node, fs_cookie cookie, uint8 event, selectsync* sync) 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 { struct SyncRemover {
SyncRemover(FileSystem* fs, selectsync* sync) SyncRemover(FileSystem* fs, selectsync* sync)
: fs(fs), sync(sync) {} : fs(fs), sync(sync) {}
@@ -760,6 +786,10 @@ Volume::Deselect(fs_vnode node, fs_cookie cookie, uint8 event, selectsync* sync)
status_t status_t
Volume::FSync(fs_vnode node) Volume::FSync(fs_vnode node)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FSYNC))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -796,6 +826,11 @@ Volume::ReadSymlink(fs_vnode node, char* buffer, size_t bufferSize,
size_t* bytesRead) size_t* bytesRead)
{ {
*bytesRead = 0; *bytesRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_SYMLINK))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -841,6 +876,10 @@ status_t
Volume::CreateSymlink(fs_vnode dir, const char* name, const char* target, Volume::CreateSymlink(fs_vnode dir, const char* name, const char* target,
int mode) int mode)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_SYMLINK))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -881,6 +920,10 @@ Volume::CreateSymlink(fs_vnode dir, const char* name, const char* target,
status_t status_t
Volume::Link(fs_vnode dir, const char* name, fs_vnode node) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -919,6 +962,10 @@ Volume::Link(fs_vnode dir, const char* name, fs_vnode node)
status_t status_t
Volume::Unlink(fs_vnode dir, const char* name) Volume::Unlink(fs_vnode dir, const char* name)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_UNLINK))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -957,6 +1004,10 @@ status_t
Volume::Rename(fs_vnode oldDir, const char* oldName, fs_vnode newDir, Volume::Rename(fs_vnode oldDir, const char* oldName, fs_vnode newDir,
const char* newName) const char* newName)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_RENAME))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -997,6 +1048,10 @@ Volume::Rename(fs_vnode oldDir, const char* oldName, fs_vnode newDir,
status_t status_t
Volume::Access(fs_vnode node, int mode) Volume::Access(fs_vnode node, int mode)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_ACCESS))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1062,6 +1117,10 @@ Volume::ReadStat(fs_vnode node, struct stat* st)
status_t status_t
Volume::WriteStat(fs_vnode node, const struct stat* st, uint32 mask) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1102,6 +1161,10 @@ status_t
Volume::Create(fs_vnode dir, const char* name, int openMode, int mode, Volume::Create(fs_vnode dir, const char* name, int openMode, int mode,
void** cookie, vnode_id* vnid) void** cookie, vnode_id* vnid)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1148,6 +1211,10 @@ Volume::Create(fs_vnode dir, const char* name, int openMode, int mode,
status_t status_t
Volume::Open(fs_vnode node, int openMode, fs_cookie* cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1223,6 +1290,10 @@ Volume::Read(fs_vnode node, fs_cookie cookie, off_t pos, void* buffer,
{ {
*bytesRead = 0; *bytesRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1272,6 +1343,10 @@ Volume::Write(fs_vnode node, fs_cookie cookie, off_t pos, const void* buffer,
{ {
*bytesWritten = 0; *bytesWritten = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1315,6 +1390,10 @@ Volume::Write(fs_vnode node, fs_cookie cookie, off_t pos, const void* buffer,
status_t status_t
Volume::CreateDir(fs_vnode dir, const char* name, int mode, vnode_id *newDir) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1354,6 +1433,10 @@ Volume::CreateDir(fs_vnode dir, const char* name, int mode, vnode_id *newDir)
status_t status_t
Volume::RemoveDir(fs_vnode dir, const char* name) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1391,6 +1474,10 @@ Volume::RemoveDir(fs_vnode dir, const char* name)
status_t status_t
Volume::OpenDir(fs_vnode node, fs_cookie* cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1466,6 +1553,10 @@ Volume::ReadDir(fs_vnode node, fs_vnode cookie, void* buffer, size_t bufferSize,
{ {
*countRead = 0; *countRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_DIR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1521,6 +1612,10 @@ reply->buffer.GetSize()));
status_t status_t
Volume::RewindDir(fs_vnode node, fs_vnode cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1560,6 +1655,10 @@ Volume::RewindDir(fs_vnode node, fs_vnode cookie)
status_t status_t
Volume::OpenAttrDir(fs_vnode node, fs_cookie *cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1635,6 +1734,10 @@ status_t
Volume::ReadAttrDir(fs_vnode node, fs_cookie cookie, void* buffer, Volume::ReadAttrDir(fs_vnode node, fs_cookie cookie, void* buffer,
size_t bufferSize, uint32 count, uint32* countRead) size_t bufferSize, uint32 count, uint32* countRead)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_ATTR_DIR))
return B_BAD_VALUE;
*countRead = 0; *countRead = 0;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
@@ -1689,6 +1792,10 @@ Volume::ReadAttrDir(fs_vnode node, fs_cookie cookie, void* buffer,
status_t status_t
Volume::RewindAttrDir(fs_vnode node, fs_cookie cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1728,6 +1835,10 @@ status_t
Volume::CreateAttr(fs_vnode node, const char* name, uint32 type, int openMode, Volume::CreateAttr(fs_vnode node, const char* name, uint32 type, int openMode,
fs_cookie* cookie) fs_cookie* cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CREATE_ATTR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1771,6 +1882,10 @@ status_t
Volume::OpenAttr(fs_vnode node, const char* name, int openMode, Volume::OpenAttr(fs_vnode node, const char* name, int openMode,
fs_cookie* cookie) fs_cookie* cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_ATTR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1851,6 +1966,10 @@ Volume::ReadAttr(fs_vnode node, fs_cookie cookie, off_t pos,
{ {
*bytesRead = 0; *bytesRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_ATTR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1900,6 +2019,10 @@ Volume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos,
{ {
*bytesWritten = 0; *bytesWritten = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_ATTR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1940,6 +2063,10 @@ Volume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos,
status_t status_t
Volume::ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -1977,6 +2104,10 @@ status_t
Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode, Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode,
const char* newName) const char* newName)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_RENAME_ATTR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2017,6 +2148,10 @@ Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode,
status_t status_t
Volume::RemoveAttr(fs_vnode node, const char* name) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2058,6 +2193,10 @@ Volume::RemoveAttr(fs_vnode node, const char* name)
status_t status_t
Volume::OpenIndexDir(fs_cookie *cookie) Volume::OpenIndexDir(fs_cookie *cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_INDEX_DIR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2134,6 +2273,10 @@ Volume::ReadIndexDir(fs_cookie cookie, void* buffer, size_t bufferSize,
{ {
*countRead = 0; *countRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_INDEX_DIR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2186,6 +2329,10 @@ Volume::ReadIndexDir(fs_cookie cookie, void* buffer, size_t bufferSize,
status_t status_t
Volume::RewindIndexDir(fs_cookie cookie) Volume::RewindIndexDir(fs_cookie cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_INDEX_DIR))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2220,6 +2367,10 @@ Volume::RewindIndexDir(fs_cookie cookie)
status_t status_t
Volume::CreateIndex(const char* name, uint32 type, uint32 flags) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2258,6 +2409,10 @@ Volume::CreateIndex(const char* name, uint32 type, uint32 flags)
status_t status_t
Volume::RemoveIndex(const char* name) Volume::RemoveIndex(const char* name)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_REMOVE_INDEX))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2294,6 +2449,10 @@ Volume::RemoveIndex(const char* name)
status_t status_t
Volume::ReadIndexStat(const char* name, struct stat *st) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2336,6 +2495,10 @@ status_t
Volume::OpenQuery(const char* queryString, uint32 flags, port_id targetPort, Volume::OpenQuery(const char* queryString, uint32 flags, port_id targetPort,
uint32 token, fs_cookie *cookie) uint32 token, fs_cookie *cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_OPEN_QUERY))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2417,6 +2580,10 @@ Volume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize,
{ {
*countRead = 0; *countRead = 0;
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_QUERY))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2560,6 +2727,10 @@ Volume::_Unmount()
status_t status_t
Volume::_ReadFSInfo(fs_info* info) Volume::_ReadFSInfo(fs_info* info)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_READ_FS_INFO))
return B_BAD_VALUE;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2669,6 +2840,10 @@ Volume::_WriteVNode(fs_vnode node, bool reenter)
status_t status_t
Volume::_ReadStat(fs_vnode node, struct stat* st) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2704,6 +2879,10 @@ Volume::_ReadStat(fs_vnode node, struct stat* st)
status_t status_t
Volume::_Close(fs_vnode node, fs_cookie cookie) Volume::_Close(fs_vnode node, fs_cookie cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2739,6 +2918,10 @@ Volume::_Close(fs_vnode node, fs_cookie cookie)
status_t status_t
Volume::_FreeCookie(fs_vnode node, fs_cookie cookie) Volume::_FreeCookie(fs_vnode node, fs_cookie cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_COOKIE))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2774,6 +2957,10 @@ Volume::_FreeCookie(fs_vnode node, fs_cookie cookie)
status_t status_t
Volume::_CloseDir(fs_vnode node, fs_vnode cookie) Volume::_CloseDir(fs_vnode node, fs_vnode cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_DIR))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2809,6 +2996,10 @@ Volume::_CloseDir(fs_vnode node, fs_vnode cookie)
status_t status_t
Volume::_FreeDirCookie(fs_vnode node, fs_vnode cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2844,6 +3035,10 @@ Volume::_FreeDirCookie(fs_vnode node, fs_vnode cookie)
status_t status_t
Volume::_CloseAttrDir(fs_vnode node, fs_cookie cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2879,6 +3074,10 @@ Volume::_CloseAttrDir(fs_vnode node, fs_cookie cookie)
status_t status_t
Volume::_FreeAttrDirCookie(fs_vnode node, fs_cookie cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2914,6 +3113,10 @@ Volume::_FreeAttrDirCookie(fs_vnode node, fs_cookie cookie)
status_t status_t
Volume::_CloseAttr(fs_vnode node, fs_cookie cookie) Volume::_CloseAttr(fs_vnode node, fs_cookie cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_ATTR))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2949,6 +3152,10 @@ Volume::_CloseAttr(fs_vnode node, fs_cookie cookie)
status_t status_t
Volume::_FreeAttrCookie(fs_vnode node, fs_cookie cookie) 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 // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -2984,6 +3191,10 @@ Volume::_FreeAttrCookie(fs_vnode node, fs_cookie cookie)
status_t status_t
Volume::_CloseIndexDir(fs_cookie cookie) Volume::_CloseIndexDir(fs_cookie cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_INDEX_DIR))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -3018,6 +3229,10 @@ Volume::_CloseIndexDir(fs_cookie cookie)
status_t status_t
Volume::_FreeIndexDirCookie(fs_cookie cookie) Volume::_FreeIndexDirCookie(fs_cookie cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_INDEX_DIR_COOKIE))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -3052,6 +3267,10 @@ Volume::_FreeIndexDirCookie(fs_cookie cookie)
status_t status_t
Volume::_CloseQuery(fs_cookie cookie) Volume::_CloseQuery(fs_cookie cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_CLOSE_QUERY))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -3086,6 +3305,10 @@ Volume::_CloseQuery(fs_cookie cookie)
status_t status_t
Volume::_FreeQueryCookie(fs_cookie cookie) Volume::_FreeQueryCookie(fs_cookie cookie)
{ {
// check capability
if (!fFileSystem->HasCapability(FS_CAPABILITY_FREE_QUERY_COOKIE))
return B_OK;
// get a free port // get a free port
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
if (!port) if (!port)
@@ -4,6 +4,7 @@
#include <new> #include <new>
#include "beos_fs_interface.h"
#include "BeOSKernelVolume.h" #include "BeOSKernelVolume.h"
using std::nothrow; using std::nothrow;
@@ -13,6 +14,7 @@ BeOSKernelFileSystem::BeOSKernelFileSystem(beos_vnode_ops* fsOps)
: FileSystem(), : FileSystem(),
fFSOps(fsOps) fFSOps(fsOps)
{ {
_InitCapabilities(fsOps);
} }
// destructor // destructor
@@ -45,3 +47,114 @@ BeOSKernelFileSystem::DeleteVolume(Volume* volume)
return B_OK; 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,
}
@@ -17,6 +17,9 @@ public:
virtual status_t CreateVolume(Volume** volume, mount_id id); virtual status_t CreateVolume(Volume** volume, mount_id id);
virtual status_t DeleteVolume(Volume* volume); virtual status_t DeleteVolume(Volume* volume);
private:
void _InitCapabilities(beos_vnode_ops* fsOps);
private: private:
beos_vnode_ops* fFSOps; beos_vnode_ops* fFSOps;
}; };
@@ -294,7 +294,7 @@ status_t
BeOSKernelVolume::Access(fs_vnode node, int mode) BeOSKernelVolume::Access(fs_vnode node, int mode)
{ {
if (!fFSOps->access) if (!fFSOps->access)
return B_BAD_VALUE; return B_OK;
return fFSOps->access(fVolumeCookie, node, mode); return fFSOps->access(fVolumeCookie, node, mode);
} }
@@ -9,6 +9,7 @@
#include <Message.h> #include <Message.h>
#include "FSCapabilities.h"
#include "Port.h" #include "Port.h"
#include "String.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(), : fName(),
fInfos(NULL), fInfos(NULL),
fCount(0) fCount(0)
{ {
SetTo(fsName, infos, count); SetTo(fsName, infos, count, capabilities);
} }
FSInfo(const BMessage* message) FSInfo(const BMessage* message)
@@ -46,7 +48,7 @@ public:
fInfos(NULL), fInfos(NULL),
fCount(0) fCount(0)
{ {
SetTo(other.GetName(), other.fInfos, other.fCount); SetTo(other.GetName(), other.fInfos, other.fCount, other.fCapabilities);
} }
~FSInfo() ~FSInfo()
@@ -54,17 +56,24 @@ public:
Unset(); 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(); Unset();
if (!fsName || !infos || count <= 0) if (!fsName || !infos || count <= 0)
return B_BAD_VALUE; return B_BAD_VALUE;
if (!fName.SetTo(fsName)) if (!fName.SetTo(fsName))
return B_NO_MEMORY; return B_NO_MEMORY;
fInfos = new(nothrow) Port::Info[count]; fInfos = new(nothrow) Port::Info[count];
if (!fInfos) if (!fInfos)
return B_NO_MEMORY; return B_NO_MEMORY;
memcpy(fInfos, infos, sizeof(Port::Info) * count); memcpy(fInfos, infos, sizeof(Port::Info) * count);
fCapabilities = capabilities;
fCount = count; fCount = count;
return B_OK; return B_OK;
} }
@@ -72,17 +81,25 @@ public:
status_t SetTo(const BMessage* message) status_t SetTo(const BMessage* message)
{ {
Unset(); Unset();
if (!message) if (!message)
return B_BAD_VALUE; return B_BAD_VALUE;
const void* infos; const void* infos;
ssize_t size; ssize_t size;
const char* fsName; const char* fsName;
const void* capabilities;
ssize_t capabilitiesSize;
if (message->FindData("infos", B_RAW_TYPE, &infos, &size) != B_OK 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 B_BAD_VALUE;
} }
return SetTo(fsName, (const Port::Info*)infos, return SetTo(fsName, (const Port::Info*)infos,
size / sizeof(Port::Info)); size / sizeof(Port::Info), *(const FSCapabilities*)capabilities);
} }
void Unset() void Unset()
@@ -108,26 +125,39 @@ public:
return fCount; return fCount;
} }
int32 GetSize() const int32 GetInfosSize() const
{ {
return fCount * sizeof(Port::Info); return fCount * sizeof(Port::Info);
} }
const FSCapabilities& GetCapabilities() const
{
return fCapabilities;
}
status_t Archive(BMessage* archive) status_t Archive(BMessage* archive)
{ {
if (!fName.GetString() || !fInfos) if (!fName.GetString() || !fInfos)
return B_NO_INIT; return B_NO_INIT;
status_t error = archive->AddString("fsName", fName.GetString()); status_t error = archive->AddString("fsName", fName.GetString());
if (error != B_OK) if (error != B_OK)
return error; return error;
return archive->AddData("infos", B_RAW_TYPE, fInfos,
error = archive->AddData("infos", B_RAW_TYPE, fInfos,
fCount * sizeof(Port::Info)); fCount * sizeof(Port::Info));
if (error != B_OK)
return error;
return archive->AddData("capabilities", B_RAW_TYPE, &fCapabilities,
sizeof(FSCapabilities));
} }
private: private:
String fName; String fName;
Port::Info* fInfos; Port::Info* fInfos;
int32 fCount; int32 fCount;
FSCapabilities fCapabilities;
}; };
} // namespace UserlandFS } // namespace UserlandFS
@@ -6,6 +6,8 @@
#include <fs_interface.h> #include <fs_interface.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include "FSCapabilities.h"
namespace UserlandFS { namespace UserlandFS {
class Volume; class Volume;
@@ -17,6 +19,13 @@ public:
virtual status_t CreateVolume(Volume** volume, mount_id id) = 0; virtual status_t CreateVolume(Volume** volume, mount_id id) = 0;
virtual status_t DeleteVolume(Volume* volume) = 0; virtual status_t DeleteVolume(Volume* volume) = 0;
void GetCapabilities(
FSCapabilities& capabilities) const
{ capabilities = fCapabilities; }
protected:
FSCapabilities fCapabilities;
}; };
} // namespace UserlandFS } // namespace UserlandFS
@@ -319,6 +319,7 @@ UserlandFSDispatcher::_ProcessRequests()
if (error != B_OK) if (error != B_OK)
RETURN_ERROR(error); RETURN_ERROR(error);
RequestReleaser _(fRequestPort, request); RequestReleaser _(fRequestPort, request);
// check the request type // check the request type
if (request->GetType() == UFS_DISCONNECT_REQUEST) if (request->GetType() == UFS_DISCONNECT_REQUEST)
return B_OK; return B_OK;
@@ -326,6 +327,7 @@ UserlandFSDispatcher::_ProcessRequests()
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
PRINT(("UserlandFSDispatcher::_ProcessRequests(): received FS connect " PRINT(("UserlandFSDispatcher::_ProcessRequests(): received FS connect "
"request\n")); "request\n"));
// it's an FS connect request // it's an FS connect request
FSConnectRequest* connectRequest = (FSConnectRequest*)request; FSConnectRequest* connectRequest = (FSConnectRequest*)request;
// get the FS name // get the FS name
@@ -338,24 +340,27 @@ UserlandFSDispatcher::_ProcessRequests()
fsName.SetTo((const char*)connectRequest->fsName.GetData(), len); fsName.SetTo((const char*)connectRequest->fsName.GetData(), len);
if (result == B_OK && fsName.GetLength() == 0) if (result == B_OK && fsName.GetLength() == 0)
result = B_BAD_DATA; result = B_BAD_DATA;
// prepare the reply // prepare the reply
RequestAllocator allocator(fRequestPort->GetPort()); RequestAllocator allocator(fRequestPort->GetPort());
FSConnectReply* reply; FSConnectReply* reply;
error = AllocateRequest(allocator, &reply); error = AllocateRequest(allocator, &reply);
if (error != B_OK) if (error != B_OK)
RETURN_ERROR(error); RETURN_ERROR(error);
FileSystem* fileSystem = NULL; FileSystem* fileSystem = NULL;
if (result == B_OK) if (result == B_OK)
result = _GetFileSystem(fsName.GetString(), &fileSystem); result = _GetFileSystem(fsName.GetString(), &fileSystem);
if (result == B_OK) { if (result == B_OK) {
const FSInfo* info = fileSystem->GetInfo(); const FSInfo* info = fileSystem->GetInfo();
result = allocator.AllocateData(reply->portInfos, result = allocator.AllocateData(reply->portInfos,
info->GetInfos(), info->GetSize(), sizeof(Port::Info)); info->GetInfos(), info->GetInfosSize(), sizeof(Port::Info));
if (result == B_OK)
reply->portInfoCount = info->CountInfos(); reply->portInfoCount = info->CountInfos();
reply->capabilities = info->GetCapabilities();
_PutFileSystem(fileSystem); _PutFileSystem(fileSystem);
} }
reply->error = result; reply->error = result;
// send it // send it
error = fRequestPort->SendRequest(&allocator); error = fRequestPort->SendRequest(&allocator);
if (error != B_OK) if (error != B_OK)
@@ -183,20 +183,29 @@ UserlandFSServer::_RegisterWithDispatcher(const char* fsName)
ERROR(("Failed to lock the clipboard.\n")); ERROR(("Failed to lock the clipboard.\n"));
return B_ERROR; return B_ERROR;
} }
// get the port infos // get the port infos
Port::Info infos[kRequestThreadCount + 1]; Port::Info infos[kRequestThreadCount + 1];
infos[0] = *fNotificationRequestPort->GetPortInfo(); infos[0] = *fNotificationRequestPort->GetPortInfo();
for (int32 i = 0; i < kRequestThreadCount; i++) for (int32 i = 0; i < kRequestThreadCount; i++)
infos[i + 1] = *fRequestThreads[i].GetPortInfo(); infos[i + 1] = *fRequestThreads[i].GetPortInfo();
// FS capabilities
FSCapabilities capabilities;
fFileSystem->GetCapabilities(capabilities);
// init an FS info // init an FS info
FSInfo 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 // prepare the message
BMessage message(UFS_REGISTER_FS); BMessage message(UFS_REGISTER_FS);
if (error == B_OK) if (error == B_OK)
error = message.AddInt32("team", Team()); error = message.AddInt32("team", Team());
if (error == B_OK) if (error == B_OK)
error = info.Archive(&message); error = info.Archive(&message);
// send the message // send the message
BMessage reply; BMessage reply;
error = messenger.SendMessage(&message, &reply); error = messenger.SendMessage(&message, &reply);