From ed07b9c7e338367449b81e28a8d2114f07666c1c Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 3 Apr 2007 04:40:54 +0000 Subject: [PATCH] The last missing hooks -- get_vnode_name(), write_attr_stat() and rewind_query() -- are passed to the userland. get_vnode_name() has an emulation in userland, in case the client FS doesn't implement it. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20522 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/userlandfs/private/Requests.h | 68 +++++++++ .../userlandfs/kernel_add_on/Volume.cpp | 133 +++++++++++++++++- .../userlandfs/kernel_add_on/Volume.h | 10 +- .../kernel_add_on/kernel_interface.cpp | 50 +++++-- .../userlandfs/private/Requests.cpp | 21 ++- .../private/SingleReplyRequestHandler.cpp | 3 +- .../userlandfs/server/BeOSKernelVolume.cpp | 10 ++ .../userlandfs/server/BeOSKernelVolume.h | 3 + .../userlandfs/server/HaikuKernelVolume.cpp | 32 +++++ .../userlandfs/server/HaikuKernelVolume.h | 5 + .../server/UserlandRequestHandler.cpp | 102 ++++++++++++++ .../server/UserlandRequestHandler.h | 6 + .../file_systems/userlandfs/server/Volume.cpp | 99 ++++++++++++- .../file_systems/userlandfs/server/Volume.h | 10 +- 14 files changed, 537 insertions(+), 15 deletions(-) diff --git a/headers/private/userlandfs/private/Requests.h b/headers/private/userlandfs/private/Requests.h index ed3fb8c95f..7a35e312a0 100644 --- a/headers/private/userlandfs/private/Requests.h +++ b/headers/private/userlandfs/private/Requests.h @@ -43,6 +43,8 @@ enum { // vnodes LOOKUP_REQUEST, LOOKUP_REPLY, + GET_VNODE_NAME_REQUEST, + GET_VNODE_NAME_REPLY, READ_VNODE_REQUEST, READ_VNODE_REPLY, WRITE_VNODE_REQUEST, @@ -137,6 +139,8 @@ enum { WRITE_ATTR_REPLY, READ_ATTR_STAT_REQUEST, READ_ATTR_STAT_REPLY, + WRITE_ATTR_STAT_REQUEST, + WRITE_ATTR_STAT_REPLY, RENAME_ATTR_REQUEST, RENAME_ATTR_REPLY, REMOVE_ATTR_REQUEST, @@ -169,6 +173,8 @@ enum { FREE_QUERY_COOKIE_REPLY, READ_QUERY_REQUEST, READ_QUERY_REPLY, + REWIND_QUERY_REQUEST, + REWIND_QUERY_REPLY, // userland -> kernel requests // notifications @@ -428,6 +434,23 @@ public: int type; }; +// GetVNodeNameRequest +class GetVNodeNameRequest : public NodeRequest { +public: + GetVNodeNameRequest() : NodeRequest(GET_VNODE_NAME_REQUEST) {} + + size_t size; +}; + +// GetVNodeNameReply +class GetVNodeNameReply : public ReplyRequest { +public: + GetVNodeNameReply() : ReplyRequest(GET_VNODE_NAME_REPLY) {} + status_t GetAddressInfos(AddressInfo* infos, int32* count); + + Address buffer; +}; + // ReadVNodeRequest class ReadVNodeRequest : public VolumeRequest { public: @@ -1085,6 +1108,21 @@ public: struct stat st; }; +// WriteAttrStatRequest +class WriteAttrStatRequest : public AttributeRequest { +public: + WriteAttrStatRequest() : AttributeRequest(WRITE_ATTR_STAT_REQUEST) {} + + struct stat st; + uint32 mask; +}; + +// WriteAttrStatReply +class WriteAttrStatReply : public ReplyRequest { +public: + WriteAttrStatReply() : ReplyRequest(WRITE_ATTR_STAT_REPLY) {} +}; + // RenameAttrRequest class RenameAttrRequest : public VolumeRequest { public: @@ -1308,6 +1346,18 @@ public: Address buffer; }; +// RewindQueryRequest +class RewindQueryRequest : public QueryRequest { +public: + RewindQueryRequest() : QueryRequest(REWIND_QUERY_REQUEST) {} +}; + +// RewindQueryReply +class RewindQueryReply : public ReplyRequest { +public: + RewindQueryReply() : ReplyRequest(REWIND_QUERY_REPLY) {} +}; + // #pragma mark - // #pragma mark ----- userland requests ----- @@ -1552,6 +1602,10 @@ do_for_request(Request* request, Task& task) return task((LookupRequest*)request); case LOOKUP_REPLY: return task((LookupReply*)request); + case GET_VNODE_NAME_REQUEST: + return task((GetVNodeNameRequest*)request); + case GET_VNODE_NAME_REPLY: + return task((GetVNodeNameReply*)request); case READ_VNODE_REQUEST: return task((ReadVNodeRequest*)request); case READ_VNODE_REPLY: @@ -1721,6 +1775,10 @@ do_for_request(Request* request, Task& task) return task((ReadAttrStatRequest*)request); case READ_ATTR_STAT_REPLY: return task((ReadAttrStatReply*)request); + case WRITE_ATTR_STAT_REQUEST: + return task((WriteAttrStatRequest*)request); + case WRITE_ATTR_STAT_REPLY: + return task((WriteAttrStatReply*)request); case RENAME_ATTR_REQUEST: return task((RenameAttrRequest*)request); case RENAME_ATTR_REPLY: @@ -1779,6 +1837,10 @@ do_for_request(Request* request, Task& task) return task((ReadQueryRequest*)request); case READ_QUERY_REPLY: return task((ReadQueryReply*)request); + case REWIND_QUERY_REQUEST: + return task((RewindQueryRequest*)request); + case REWIND_QUERY_REPLY: + return task((RewindQueryReply*)request); // userland -> kernel requests // notifications @@ -1869,6 +1931,8 @@ using UserlandFSUtil::WriteFSInfoReply; // vnodes using UserlandFSUtil::LookupRequest; using UserlandFSUtil::LookupReply; +using UserlandFSUtil::GetVNodeNameRequest; +using UserlandFSUtil::GetVNodeNameReply; using UserlandFSUtil::ReadVNodeRequest; using UserlandFSUtil::ReadVNodeReply; using UserlandFSUtil::WriteVNodeRequest; @@ -1956,6 +2020,8 @@ using UserlandFSUtil::WriteAttrRequest; using UserlandFSUtil::WriteAttrReply; using UserlandFSUtil::ReadAttrStatRequest; using UserlandFSUtil::ReadAttrStatReply; +using UserlandFSUtil::WriteAttrStatRequest; +using UserlandFSUtil::WriteAttrStatReply; using UserlandFSUtil::RenameAttrRequest; using UserlandFSUtil::RenameAttrReply; using UserlandFSUtil::RemoveAttrRequest; @@ -1986,6 +2052,8 @@ using UserlandFSUtil::FreeQueryCookieRequest; using UserlandFSUtil::FreeQueryCookieReply; using UserlandFSUtil::ReadQueryRequest; using UserlandFSUtil::ReadQueryReply; +using UserlandFSUtil::RewindQueryRequest; +using UserlandFSUtil::RewindQueryReply; // userland -> kernel requests // notifications 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 62f0ae7e64..a87be29cf4 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 @@ -1,6 +1,9 @@ // Volume.cpp +#include "Volume.h" + #include +#include #include #include @@ -16,7 +19,6 @@ #include "RequestPort.h" #include "Requests.h" #include "userlandfs_ioctl.h" -#include "Volume.h" // missing ioctl()s // TODO: Place somewhere else. @@ -402,6 +404,55 @@ Volume::Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type) return error; } +// GetVNodeName +status_t +Volume::GetVNodeName(fs_vnode node, char* buffer, size_t bufferSize) +{ + // We don't check the capability -- if not implemented by the client FS, + // the functionality is emulated in userland. + + // get a free port + RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); + if (!port) + return B_ERROR; + PortReleaser _(fFileSystem->GetPortPool(), port); + + // prepare the request + RequestAllocator allocator(port->GetPort()); + GetVNodeNameRequest* request; + status_t error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->volume = fUserlandVolume; + request->node = node; + request->size = bufferSize; + + // send the request + KernelRequestHandler handler(this, GET_VNODE_NAME_REPLY); + GetVNodeNameReply* reply; + error = _SendRequest(port, &allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + if (reply->error != B_OK) + return reply->error; + + char* readBuffer = (char*)reply->buffer.GetData(); + size_t nameLen = reply->buffer.GetSize(); + nameLen = strnlen(readBuffer, nameLen); + if (nameLen <= 1 || nameLen >= bufferSize) + RETURN_ERROR(B_BAD_DATA); + + memcpy(buffer, readBuffer, nameLen); + buffer[nameLen] = '\0'; + + _SendReceiptAck(port); + return error; +} + // ReadVNode status_t Volume::ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node) @@ -2099,6 +2150,48 @@ Volume::ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st) return error; } +// WriteAttrStat +status_t +Volume::WriteAttrStat(fs_vnode node, fs_cookie cookie, const struct stat *st, + int statMask) +{ + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_WRITE_ATTR_STAT)) + return B_BAD_VALUE; + + // get a free port + RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); + if (!port) + return B_ERROR; + PortReleaser _(fFileSystem->GetPortPool(), port); + + // prepare the request + RequestAllocator allocator(port->GetPort()); + WriteAttrStatRequest* request; + status_t error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->volume = fUserlandVolume; + request->node = node; + request->attrCookie = cookie; + request->st = *st; + request->mask = statMask; + + // send the request + KernelRequestHandler handler(this, WRITE_ATTR_STAT_REPLY); + WriteAttrStatReply* reply; + error = _SendRequest(port, &allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + if (reply->error != B_OK) + return reply->error; + return error; +} + // RenameAttr status_t Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode, @@ -2632,6 +2725,44 @@ Volume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize, return error; } +// RewindQuery +status_t +Volume::RewindQuery(fs_cookie cookie) +{ + // check capability + if (!fFileSystem->HasCapability(FS_CAPABILITY_REWIND_QUERY)) + return B_BAD_VALUE; + + // get a free port + RequestPort* port = fFileSystem->GetPortPool()->AcquirePort(); + if (!port) + return B_ERROR; + PortReleaser _(fFileSystem->GetPortPool(), port); + + // prepare the request + RequestAllocator allocator(port->GetPort()); + RewindQueryRequest* request; + status_t error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->volume = fUserlandVolume; + request->queryCookie = cookie; + + // send the request + KernelRequestHandler handler(this, REWIND_QUERY_REPLY); + RewindQueryReply* reply; + error = _SendRequest(port, &allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + if (reply->error != B_OK) + return reply->error; + return error; +} + // #pragma mark - // #pragma mark ----- private implementations ----- diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h index 27bc3d75c2..e1c3a74986 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.h @@ -12,15 +12,18 @@ namespace UserlandFSUtil { class Request; class RequestAllocator; class RequestHandler; +class RequestPort; +struct userlandfs_ioctl; } using UserlandFSUtil::Request; using UserlandFSUtil::RequestAllocator; using UserlandFSUtil::RequestHandler; +using UserlandFSUtil::RequestPort; +using UserlandFSUtil::userlandfs_ioctl; class FileSystem; -struct userlandfs_ioctl; class Volume : public Referencable { public: @@ -55,6 +58,8 @@ public: // vnodes status_t Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type); + status_t GetVNodeName(fs_vnode node, char* buffer, + size_t bufferSize); status_t ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node); status_t WriteVNode(fs_vnode node, bool reenter); @@ -141,6 +146,8 @@ public: size_t bufferSize, size_t* bytesWritten); status_t ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st); + status_t WriteAttrStat(fs_vnode node, fs_cookie cookie, + const struct stat *st, int statMask); status_t RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode, const char* newName); @@ -169,6 +176,7 @@ public: status_t ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize, uint32 count, uint32* countRead); + status_t RewindQuery(fs_cookie cookie); private: status_t _Mount(const char* device, uint32 flags, diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/kernel_interface.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/kernel_interface.cpp index 864cb49020..64f33849ab 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/kernel_interface.cpp @@ -176,7 +176,19 @@ userlandfs_lookup(fs_volume fs, fs_vnode dir, const char *entryName, return error; } -// TODO: userlandfs_get_vnode_name() +// userlandfs_get_vnode_name +static status_t +userlandfs_get_vnode_name(fs_volume fs, fs_vnode node, char *buffer, + size_t bufferSize) +{ + Volume* volume = (Volume*)fs; + PRINT(("userlandfs_get_vnode_name(%p, %p, %p, %lu)\n", fs, node, + buffer, bufferSize)); + status_t error = volume->GetVNodeName(node, buffer, bufferSize); + PRINT(("userlandfs_get_vnode_name() done: (%lx, \"%.*s\")\n", error, + (int)bufferSize, (error == B_OK ? buffer : NULL))); + return error; +} // userlandfs_get_vnode static status_t @@ -546,7 +558,7 @@ userlandfs_read_dir(fs_volume fs, fs_vnode node, fs_cookie cookie, PRINT(("userlandfs_read_dir() done: (%lx, %lu)\n", error, *count)); #if DEBUG dirent* entry = buffer; - for (uint32 i = 0; i < *count; i++) { + for (uint32 i = 0; error == B_OK && i < *count; i++) { // R5's kernel vsprintf() doesn't seem to know `%.s', so // we need to work around. char name[B_FILE_NAME_LENGTH]; @@ -722,14 +734,25 @@ userlandfs_read_attr_stat(fs_volume fs, fs_vnode node, fs_cookie cookie, struct stat *st) { Volume* volume = (Volume*)fs; - PRINT(("userlandfs_read_attr_stat(%p, %p, %p', %p)\n", fs, node, cookie, + PRINT(("userlandfs_read_attr_stat(%p, %p, %p, %p)\n", fs, node, cookie, st)); status_t error = volume->ReadAttrStat(node, cookie, st); PRINT(("userlandfs_read_attr_stat() done: (%lx)\n", error)); return error; } -// TODO: userlandfs_write_attr_stat +// userlandfs_write_attr_stat +static status_t +userlandfs_write_attr_stat(fs_volume fs, fs_vnode node, fs_cookie cookie, + const struct stat *st, int statMask) +{ + Volume* volume = (Volume*)fs; + PRINT(("userlandfs_write_attr_stat(%p, %p, %p, %p, 0x%x)\n", fs, node, + cookie, st, statMask)); + status_t error = volume->WriteAttrStat(node, cookie, st, statMask); + PRINT(("userlandfs_write_attr_stat() done: (%lx)\n", error)); + return error; +} // userlandfs_rename_attr static status_t @@ -903,7 +926,7 @@ userlandfs_read_query(fs_volume fs, fs_cookie cookie, count); PRINT(("userlandfs_read_query() done: (%lx, %ld)\n", error, *count)); #if DEBUG - if (*count > 0) { + if (error == B_OK && *count > 0) { // R5's kernel vsprintf() doesn't seem to know `%.s', so // we need to work around. char name[B_FILE_NAME_LENGTH]; @@ -919,7 +942,16 @@ userlandfs_read_query(fs_volume fs, fs_cookie cookie, return error; } -// TODO: userlandfs_rewind_query() +// userlandfs_rewind_query +static status_t +userlandfs_rewind_query(fs_volume fs, fs_cookie cookie) +{ + Volume* volume = (Volume*)fs; + PRINT(("userlandfs_rewind_query(%p, %p)\n", fs, cookie)); + status_t error = volume->RewindQuery(cookie); + PRINT(("userlandfs_rewind_query() done: (%lx)\n", error)); + return error; +} // userlandfs_initialize @@ -1017,7 +1049,7 @@ static file_system_module_info sUserlandFSModuleInfo = { /* vnode operations */ &userlandfs_lookup, - NULL, // &userlandfs_get_vnode_name, + &userlandfs_get_vnode_name, &userlandfs_get_vnode, &userlandfs_put_vnode, &userlandfs_remove_vnode, @@ -1079,7 +1111,7 @@ static file_system_module_info sUserlandFSModuleInfo = { &userlandfs_write_attr, &userlandfs_read_attr_stat, - NULL, // &userlandfs_write_attr_stat, + &userlandfs_write_attr_stat, &userlandfs_rename_attr, &userlandfs_remove_attr, @@ -1099,7 +1131,7 @@ static file_system_module_info sUserlandFSModuleInfo = { &userlandfs_close_query, &userlandfs_free_query_cookie, &userlandfs_read_query, - NULL, // &userlandfs_rewind_query, + &userlandfs_rewind_query }; module_info *modules[] = { diff --git a/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp b/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp index 31afd22299..29a1b77f09 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp @@ -53,6 +53,14 @@ MountVolumeRequest::GetAddressInfos(AddressInfo* infos, int32* count) // return B_OK; //} +// GetVNodeNameReply +status_t +GetVNodeNameReply::GetAddressInfos(AddressInfo* infos, int32* count) +{ + ADD_STRING(buffer); + return B_OK; +} + // CreateRequest status_t CreateRequest::GetAddressInfos(AddressInfo* infos, int32* count) @@ -496,11 +504,13 @@ UserlandFSUtil::is_kernel_request(uint32 type) return false; // vnodes case LOOKUP_REQUEST: + case GET_VNODE_NAME_REQUEST: case READ_VNODE_REQUEST: case WRITE_VNODE_REQUEST: case FS_REMOVE_VNODE_REQUEST: return true; case LOOKUP_REPLY: + case GET_VNODE_NAME_REPLY: case READ_VNODE_REPLY: case WRITE_VNODE_REPLY: case FS_REMOVE_VNODE_REPLY: @@ -587,6 +597,7 @@ UserlandFSUtil::is_kernel_request(uint32 type) case READ_ATTR_REQUEST: case WRITE_ATTR_REQUEST: case READ_ATTR_STAT_REQUEST: + case WRITE_ATTR_STAT_REQUEST: case RENAME_ATTR_REQUEST: case REMOVE_ATTR_REQUEST: return true; @@ -594,10 +605,10 @@ UserlandFSUtil::is_kernel_request(uint32 type) case OPEN_ATTR_REPLY: case CLOSE_ATTR_REPLY: case FREE_ATTR_COOKIE_REPLY: - case READ_ATTR_REPLY: case WRITE_ATTR_REPLY: case READ_ATTR_STAT_REPLY: + case WRITE_ATTR_STAT_REPLY: case RENAME_ATTR_REPLY: case REMOVE_ATTR_REPLY: return false; @@ -625,11 +636,13 @@ UserlandFSUtil::is_kernel_request(uint32 type) case CLOSE_QUERY_REQUEST: case FREE_QUERY_COOKIE_REQUEST: case READ_QUERY_REQUEST: + case REWIND_QUERY_REQUEST: return true; case OPEN_QUERY_REPLY: case CLOSE_QUERY_REPLY: case FREE_QUERY_COOKIE_REPLY: case READ_QUERY_REPLY: + case REWIND_QUERY_REPLY: return false; // userland -> kernel requests @@ -697,11 +710,13 @@ UserlandFSUtil::is_userland_request(uint32 type) return true; // vnodes case LOOKUP_REQUEST: + case GET_VNODE_NAME_REQUEST: case READ_VNODE_REQUEST: case WRITE_VNODE_REQUEST: case FS_REMOVE_VNODE_REQUEST: return false; case LOOKUP_REPLY: + case GET_VNODE_NAME_REPLY: case READ_VNODE_REPLY: case WRITE_VNODE_REPLY: case FS_REMOVE_VNODE_REPLY: @@ -789,6 +804,7 @@ UserlandFSUtil::is_userland_request(uint32 type) case WRITE_ATTR_REQUEST: case RENAME_ATTR_REQUEST: case READ_ATTR_STAT_REQUEST: + case WRITE_ATTR_STAT_REQUEST: case REMOVE_ATTR_REQUEST: return false; case CREATE_ATTR_REPLY: @@ -798,6 +814,7 @@ UserlandFSUtil::is_userland_request(uint32 type) case READ_ATTR_REPLY: case WRITE_ATTR_REPLY: case READ_ATTR_STAT_REPLY: + case WRITE_ATTR_STAT_REPLY: case RENAME_ATTR_REPLY: case REMOVE_ATTR_REPLY: return true; @@ -825,11 +842,13 @@ UserlandFSUtil::is_userland_request(uint32 type) case CLOSE_QUERY_REQUEST: case FREE_QUERY_COOKIE_REQUEST: case READ_QUERY_REQUEST: + case REWIND_QUERY_REQUEST: return false; case OPEN_QUERY_REPLY: case CLOSE_QUERY_REPLY: case FREE_QUERY_COOKIE_REPLY: case READ_QUERY_REPLY: + case REWIND_QUERY_REPLY: return true; // userland -> kernel requests diff --git a/src/add-ons/kernel/file_systems/userlandfs/private/SingleReplyRequestHandler.cpp b/src/add-ons/kernel/file_systems/userlandfs/private/SingleReplyRequestHandler.cpp index aedaeff94d..b3f73df0eb 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/private/SingleReplyRequestHandler.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/private/SingleReplyRequestHandler.cpp @@ -1,9 +1,10 @@ // SingleReplyRequestHandler.cpp +#include "SingleReplyRequestHandler.h" + #include "Compatibility.h" #include "Debug.h" #include "Request.h" -#include "SingleReplyRequestHandler.h" // constructor SingleReplyRequestHandler::SingleReplyRequestHandler() 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 0f32f7c2de..d5f09011be 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.cpp @@ -157,6 +157,16 @@ BeOSKernelVolume::Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, return error; } +// LookupNoType +status_t +BeOSKernelVolume::LookupNoType(fs_vnode dir, const char* entryName, + vnode_id* vnid) +{ + if (!fFSOps->walk) + return B_BAD_VALUE; + return fFSOps->walk(fVolumeCookie, dir, entryName, NULL, vnid); +} + // ReadVNode status_t BeOSKernelVolume::ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node) diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.h b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.h index e09bd4fc95..c71b5468dd 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/BeOSKernelVolume.h @@ -27,6 +27,9 @@ public: // vnodes virtual status_t Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type); + virtual status_t LookupNoType(fs_vnode dir, + const char* entryName, vnode_id* vnid); + // not required virtual status_t ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node); virtual status_t WriteVNode(fs_vnode node, bool reenter); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/HaikuKernelVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/HaikuKernelVolume.cpp index f32047d5d2..a77869b95f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/HaikuKernelVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/HaikuKernelVolume.cpp @@ -126,6 +126,17 @@ HaikuKernelVolume::Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, return fFSModule->lookup(fVolumeCookie, dir, entryName, vnid, type); } +// GetVNodeName +status_t +HaikuKernelVolume::GetVNodeName(fs_vnode node, char* buffer, size_t bufferSize) +{ + // If not implemented by the client file system, we invoke our super class + // version, which emulates the functionality. + if (!fFSModule->get_vnode_name) + return Volume::GetVNodeName(node, buffer, bufferSize); + return fFSModule->get_vnode_name(fVolumeCookie, node, buffer, bufferSize); +} + // ReadVNode status_t HaikuKernelVolume::ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node) @@ -563,6 +574,17 @@ HaikuKernelVolume::ReadAttrStat(fs_vnode node, fs_cookie cookie, return fFSModule->read_attr_stat(fVolumeCookie, node, cookie, st); } +// WriteAttrStat +status_t +HaikuKernelVolume::WriteAttrStat(fs_vnode node, fs_cookie cookie, + const struct stat* st, int statMask) +{ + if (!fFSModule->write_attr_stat) + return B_BAD_VALUE; + return fFSModule->write_attr_stat(fVolumeCookie, node, cookie, st, + statMask); +} + // RenameAttr status_t HaikuKernelVolume::RenameAttr(fs_vnode oldNode, const char* oldName, @@ -710,3 +732,13 @@ HaikuKernelVolume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize, return fFSModule->read_query(fVolumeCookie, cookie, (struct dirent*)buffer, bufferSize, countRead); } + +// RewindQuery +status_t +HaikuKernelVolume::RewindQuery(fs_cookie cookie) +{ + if (!fFSModule->rewind_query) + return B_BAD_VALUE; + return fFSModule->rewind_query(fVolumeCookie, cookie); +} + diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/HaikuKernelVolume.h b/src/add-ons/kernel/file_systems/userlandfs/server/HaikuKernelVolume.h index 457ac90988..2692b4ed78 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/HaikuKernelVolume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/HaikuKernelVolume.h @@ -33,6 +33,8 @@ public: // vnodes virtual status_t Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type); + virtual status_t GetVNodeName(fs_vnode node, char* buffer, + size_t bufferSize); virtual status_t ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node); virtual status_t WriteVNode(fs_vnode node, bool reenter); @@ -119,6 +121,8 @@ public: size_t bufferSize, size_t* bytesWritten); virtual status_t ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st); + virtual status_t WriteAttrStat(fs_vnode node, fs_cookie cookie, + const struct stat* st, int statMask); virtual status_t RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode, const char* newName); @@ -147,6 +151,7 @@ public: virtual status_t ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize, uint32 count, uint32* countRead); + virtual status_t RewindQuery(fs_cookie cookie); private: file_system_module_info* fFSModule; diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp index e7460971c8..957464bafc 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp @@ -60,6 +60,8 @@ UserlandRequestHandler::HandleRequest(Request* request) // vnodes case LOOKUP_REQUEST: return _HandleRequest((LookupRequest*)request); + case GET_VNODE_NAME_REQUEST: + return _HandleRequest((GetVNodeNameRequest*)request); case READ_VNODE_REQUEST: return _HandleRequest((ReadVNodeRequest*)request); case WRITE_VNODE_REQUEST: @@ -152,6 +154,8 @@ UserlandRequestHandler::HandleRequest(Request* request) return _HandleRequest((WriteAttrRequest*)request); case READ_ATTR_STAT_REQUEST: return _HandleRequest((ReadAttrStatRequest*)request); + case WRITE_ATTR_STAT_REQUEST: + return _HandleRequest((WriteAttrStatRequest*)request); case RENAME_ATTR_REQUEST: return _HandleRequest((RenameAttrRequest*)request); case REMOVE_ATTR_REQUEST: @@ -184,6 +188,8 @@ UserlandRequestHandler::HandleRequest(Request* request) return _HandleRequest((FreeQueryCookieRequest*)request); case READ_QUERY_REQUEST: return _HandleRequest((ReadQueryRequest*)request); + case REWIND_QUERY_REQUEST: + return _HandleRequest((RewindQueryRequest*)request); } PRINT(("UserlandRequestHandler::HandleRequest(): unexpected request: %lu\n", request->GetType())); @@ -394,6 +400,45 @@ UserlandRequestHandler::_HandleRequest(LookupRequest* request) return _SendReply(allocator, false); } +// _HandleRequest +status_t +UserlandRequestHandler::_HandleRequest(GetVNodeNameRequest* request) +{ + // check and execute the request + status_t result = B_OK; + Volume* volume = (Volume*)request->volume; + if (!volume) + result = B_BAD_VALUE; + + void* node = request->node; + size_t bufferSize = request->size; + + // allocate the reply + RequestAllocator allocator(fPort->GetPort()); + GetVNodeNameReply* reply; + status_t error = AllocateRequest(allocator, &reply); + if (error != B_OK) + RETURN_ERROR(error); + char* buffer; + if (result == B_OK) { + result = allocator.AllocateAddress(reply->buffer, bufferSize, 1, + (void**)&buffer, true); + } + + // execute the request + if (result == B_OK) { + RequestThreadContext context(volume); + result = volume->GetVNodeName(node, buffer, bufferSize); + } + + // reconstruct the reply, in case it has been overwritten + reply = new(reply) GetVNodeNameReply; + + // send the reply + reply->error = result; + return _SendReply(allocator, (result == B_OK)); +} + // _HandleRequest status_t UserlandRequestHandler::_HandleRequest(ReadVNodeRequest* request) @@ -1729,6 +1774,35 @@ UserlandRequestHandler::_HandleRequest(ReadAttrStatRequest* request) return _SendReply(allocator, false); } +// _HandleRequest +status_t +UserlandRequestHandler::_HandleRequest(WriteAttrStatRequest* request) +{ + // check and execute the request + status_t result = B_OK; + Volume* volume = (Volume*)request->volume; + if (!volume) + result = B_BAD_VALUE; + + if (result == B_OK) { + RequestThreadContext context(volume); + result = volume->WriteAttrStat(request->node, request->attrCookie, + &request->st, request->mask); + } + + // prepare the reply + RequestAllocator allocator(fPort->GetPort()); + WriteAttrStatReply* reply; + status_t error = AllocateRequest(allocator, &reply); + if (error != B_OK) + RETURN_ERROR(error); + + reply->error = result; + + // send the reply + return _SendReply(allocator, false); +} + // _HandleRequest status_t UserlandRequestHandler::_HandleRequest(RenameAttrRequest* request) @@ -2173,6 +2247,34 @@ UserlandRequestHandler::_HandleRequest(ReadQueryRequest* request) return _SendReply(allocator, (result == B_OK)); } +// _HandleRequest +status_t +UserlandRequestHandler::_HandleRequest(RewindQueryRequest* request) +{ + // check and execute the request + status_t result = B_OK; + Volume* volume = (Volume*)request->volume; + if (!volume) + result = B_BAD_VALUE; + + if (result == B_OK) { + RequestThreadContext context(volume); + result = volume->RewindQuery(request->queryCookie); + } + + // prepare the reply + RequestAllocator allocator(fPort->GetPort()); + RewindQueryReply* reply; + status_t error = AllocateRequest(allocator, &reply); + if (error != B_OK) + RETURN_ERROR(error); + + reply->error = result; + + // send the reply + return _SendReply(allocator, false); +} + // #pragma mark - other diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h index 94342df573..bc0675f16f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h @@ -15,6 +15,7 @@ class ReadFSInfoRequest; class WriteFSInfoRequest; // vnodes class LookupRequest; +class GetVNodeNameRequest; class ReadVNodeRequest; class WriteVNodeRequest; class FSRemoveVNodeRequest; @@ -61,6 +62,7 @@ class FreeAttrCookieRequest; class ReadAttrRequest; class WriteAttrRequest; class ReadAttrStatRequest; +class WriteAttrStatRequest; class RenameAttrRequest; class RemoveAttrRequest; // indices @@ -77,6 +79,7 @@ class OpenQueryRequest; class CloseQueryRequest; class FreeQueryCookieRequest; class ReadQueryRequest; +class RewindQueryRequest; class RequestAllocator; @@ -107,6 +110,7 @@ private: // vnodes status_t _HandleRequest(LookupRequest* request); + status_t _HandleRequest(GetVNodeNameRequest* request); status_t _HandleRequest(ReadVNodeRequest* request); status_t _HandleRequest(WriteVNodeRequest* request); status_t _HandleRequest(FSRemoveVNodeRequest* request); @@ -159,6 +163,7 @@ private: status_t _HandleRequest(ReadAttrRequest* request); status_t _HandleRequest(WriteAttrRequest* request); status_t _HandleRequest(ReadAttrStatRequest* request); + status_t _HandleRequest(WriteAttrStatRequest* request); status_t _HandleRequest(RenameAttrRequest* request); status_t _HandleRequest(RemoveAttrRequest* request); @@ -178,6 +183,7 @@ private: status_t _HandleRequest(CloseQueryRequest* request); status_t _HandleRequest(FreeQueryCookieRequest* request); status_t _HandleRequest(ReadQueryRequest* request); + status_t _HandleRequest(RewindQueryRequest* request); status_t _SendReply(RequestAllocator& allocator, bool expectsReceipt); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp index f56683fbf7..7f624c7547 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp @@ -2,6 +2,12 @@ #include "Volume.h" +#include +#include +#include + +#include "kernel_emu.h" + // constructor Volume::Volume(FileSystem* fileSystem, mount_id id) : fFileSystem(fileSystem), @@ -79,6 +85,82 @@ Volume::Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type) return B_BAD_VALUE; } +// LookupNoType +status_t +Volume::LookupNoType(fs_vnode dir, const char* entryName, vnode_id* vnid) +{ + int type; + return Lookup(dir, entryName, vnid, &type); +} + +// GetVNodeName +status_t +Volume::GetVNodeName(fs_vnode node, char* buffer, size_t bufferSize) +{ + // stat the node to get its ID + struct stat st; + status_t error = ReadStat(node, &st); + if (error != B_OK) + return error; + + // look up the parent directory + vnode_id parentID; + error = LookupNoType(node, "..", &parentID); + if (error != B_OK) + return error; + + // get the parent node handle + fs_vnode parentNode; + error = UserlandFS::KernelEmu::get_vnode(GetID(), parentID, &parentNode); + // Lookup() has already called get_vnode() for us, so we need to put it once + UserlandFS::KernelEmu::put_vnode(GetID(), parentID); + if (error != B_OK) + return error; + + // open the parent dir + fs_cookie cookie; + error = OpenDir(parentNode, &cookie); + if (error == B_OK) { + + while (true) { + // read an entry + char _entry[sizeof(struct dirent) + B_FILE_NAME_LENGTH]; + struct dirent* entry = (struct dirent*)_entry; + uint32 num; + + error = ReadDir(parentNode, cookie, entry, sizeof(_entry), 1, &num); + + if (error != B_OK) + break; + if (num == 0) { + error = B_ENTRY_NOT_FOUND; + break; + } + + // found an entry for our node? + if (st.st_ino == entry->d_ino) { + // yep, copy the entry name + size_t nameLen = strnlen(entry->d_name, B_FILE_NAME_LENGTH); + if (nameLen < bufferSize) { + memcpy(buffer, entry->d_name, nameLen); + buffer[nameLen] = '\0'; + } else + error = B_BUFFER_OVERFLOW; + break; + } + } + + // close the parent dir + CloseDir(parentNode, cookie); + FreeDirCookie(parentNode, cookie); + } + + // put the parent node + UserlandFS::KernelEmu::put_vnode(GetID(), parentID); + + return error; +} + // ReadVNode status_t Volume::ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node) @@ -393,13 +475,21 @@ Volume::WriteAttr(fs_vnode node, fs_cookie cookie, off_t pos, return B_BAD_VALUE; } -// StatAttr +// ReadAttrStat status_t Volume::ReadAttrStat(fs_vnode node, fs_cookie cookie, struct stat *st) { return B_BAD_VALUE; } +// WriteAttrStat +status_t +Volume::WriteAttrStat(fs_vnode node, fs_cookie cookie, const struct stat* st, + int statMask) +{ + return B_BAD_VALUE; +} + // RenameAttr status_t Volume::RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode, @@ -510,3 +600,10 @@ Volume::ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize, return B_BAD_VALUE; } +// RewindQuery +status_t +Volume::RewindQuery(fs_cookie cookie) +{ + return B_BAD_VALUE; +} + diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h index 76bd6055c2..af86a39b33 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h @@ -30,6 +30,11 @@ public: // vnodes virtual status_t Lookup(fs_vnode dir, const char* entryName, vnode_id* vnid, int* type); + virtual status_t LookupNoType(fs_vnode dir, + const char* entryName, vnode_id* vnid); + // not required + virtual status_t GetVNodeName(fs_vnode node, char* buffer, + size_t bufferSize); virtual status_t ReadVNode(vnode_id vnid, bool reenter, fs_vnode* node); virtual status_t WriteVNode(fs_vnode node, bool reenter); @@ -115,7 +120,9 @@ public: off_t pos, const void* buffer, size_t bufferSize, size_t* bytesWritten); virtual status_t ReadAttrStat(fs_vnode node, fs_cookie cookie, - struct stat *st); + struct stat* st); + virtual status_t WriteAttrStat(fs_vnode node, fs_cookie cookie, + const struct stat* st, int statMask); virtual status_t RenameAttr(fs_vnode oldNode, const char* oldName, fs_vnode newNode, const char* newName); @@ -144,6 +151,7 @@ public: virtual status_t ReadQuery(fs_cookie cookie, void* buffer, size_t bufferSize, uint32 count, uint32* countRead); + virtual status_t RewindQuery(fs_cookie cookie); protected: FileSystem* fFileSystem;