added 6 changesets to branch 'refs/remotes/pdziepak-github/nfs4' old head: 491a326b7126c8a866eeb0de6cd50a552e1ad14f new head: 8f57d30ea4934abc215ae850fa3612474087d7a3 ---------------------------------------------------------------------------- 9b7f2d1: nfs4: Move file handle recovery code out of Inode class b2cea80: nfs4: Add id mapper ed097dd: nfs4: Do not attempt to set owner, owner_group when not supported 6197fa8: nfs4: Allow WriteStat() to set UID and GID 16ff38f: nfs4: Support legacy owner and owner_group values 8f57d30: nfs4: Abandon owner and owner_group when id mapping causes problems [ Pawel Dziepak <pdziepak@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- 23 files changed, 827 insertions(+), 100 deletions(-) build/jam/HaikuImage | 2 +- src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp | 90 ++++++ .../file_systems/nfs4/{Filehandle.h => FileInfo.h} | 10 +- src/add-ons/kernel/file_systems/nfs4/IdMap.cpp | 190 +++++++++++ src/add-ons/kernel/file_systems/nfs4/IdMap.h | 47 +++ src/add-ons/kernel/file_systems/nfs4/Inode.cpp | 155 +++++---- src/add-ons/kernel/file_systems/nfs4/Inode.h | 1 - src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp | 34 +- src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h | 2 +- .../kernel/file_systems/nfs4/InodeRegular.cpp | 26 +- src/add-ons/kernel/file_systems/nfs4/Jamfile | 5 + src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h | 1 - .../kernel/file_systems/nfs4/ReplyInterpreter.cpp | 14 + .../kernel/file_systems/nfs4/ReplyInterpreter.h | 1 + .../kernel/file_systems/nfs4/RequestBuilder.cpp | 10 + .../kernel/file_systems/nfs4/RequestBuilder.h | 1 + src/add-ons/kernel/file_systems/nfs4/XDR.cpp | 2 +- src/add-ons/kernel/file_systems/nfs4/XDR.h | 2 +- .../kernel/file_systems/nfs4/idmapper/IdMapper.cpp | 266 ++++++++++++++++ .../kernel/file_systems/nfs4/idmapper/IdMapper.h | 26 ++ .../kernel/file_systems/nfs4/idmapper/Jamfile | 13 + .../nfs4/idmapper/nfs4_idmapper_server.rdef | 20 ++ .../kernel/file_systems/nfs4/kernel_interface.cpp | 9 + ############################################################################ Commit: 9b7f2d1b24a8f67aacc5f80434f9480a10f88e25 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Jul 3 00:01:30 2012 UTC nfs4: Move file handle recovery code out of Inode class ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp new file mode 100644 index 0000000..1ec4daa --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.cpp @@ -0,0 +1,90 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ + + +#include "FileInfo.h" + +#include "Filesystem.h" +#include "Request.h" + + +static status_t +sParsePath(RequestBuilder& req, uint32* count, const char* _path) +{ + char* path = strdup(_path); + char* pathStart = path; + char* pathEnd; + while (pathStart != NULL) { + pathEnd = strpbrk(pathStart, "/"); + if (pathEnd != NULL) + *pathEnd = '\0'; + + req.LookUp(pathStart); + + if (pathEnd != NULL && pathEnd[1] != '\0') + pathStart = pathEnd + 1; + else + pathStart = NULL; + + (*count)++; + } + free(path); + + return B_OK; +} + + +status_t +FileInfo::UpdateFileHandles(Filesystem* fs) +{ + Request request(fs->Server()); + RequestBuilder& req = request.Builder(); + + req.PutRootFH(); + + uint32 lookupCount = 0; + + sParsePath(req, &lookupCount, fs->Path()); + sParsePath(req, &lookupCount, fPath); + + if (fs->IsAttrSupported(FATTR4_FILEID)) { + AttrValue attr; + attr.fAttribute = FATTR4_FILEID; + attr.fFreePointer = false; + attr.fData.fValue64 = fFileId; + req.Verify(&attr, 1); + } + + req.GetFH(); + req.LookUpUp(); + req.GetFH(); + + status_t result = request.Send(); + if (result != B_OK) + return result; + + ReplyInterpreter& reply = request.Reply(); + + reply.PutRootFH(); + for (uint32 i = 0; i < lookupCount; i++) + reply.LookUp(); + + if (fs->IsAttrSupported(FATTR4_FILEID)) { + result = reply.Verify(); + if (result != B_OK) + return result; + } + + reply.GetFH(&fHandle); + if (reply.LookUpUp() == B_ENTRY_NOT_FOUND) { + fParent = fHandle; + return B_OK; + } else + return reply.GetFH(&fParent); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/Filehandle.h b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h similarity index 94% rename from src/add-ons/kernel/file_systems/nfs4/Filehandle.h rename to src/add-ons/kernel/file_systems/nfs4/FileInfo.h index 423a721..a250262 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Filehandle.h +++ b/src/add-ons/kernel/file_systems/nfs4/FileInfo.h @@ -5,8 +5,8 @@ * Authors: * Paweł Dziepak, pdziepak@xxxxxxxxxxx */ -#ifndef FILEHANDLE_H -#define FILEHANDLE_H +#ifndef FILEINFO_H +#define FILEINFO_H #include <stdlib.h> @@ -27,6 +27,8 @@ struct Filehandle { }; +class Filesystem; + // Complete information needed to identify a file in any situation. // Unfortunately just a filehandle is not enough even when they are persistent // since OPEN requires both parent filehandle and file name (just like LOOKUP). @@ -42,6 +44,8 @@ struct FileInfo { inline ~FileInfo(); inline FileInfo(const FileInfo& fi); inline FileInfo& operator=(const FileInfo& fi); + + status_t UpdateFileHandles(Filesystem* fs); }; struct FilesystemId { @@ -140,5 +144,5 @@ FilesystemId::operator!=(const FilesystemId& fsid) const } -#endif // FILEHANDLE_H +#endif // FILEHINFO_H diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index ea5cc28..ccecb6f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -210,8 +210,8 @@ Inode::Link(Inode* dir, const char* name) // filehandle has expired if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) { - _LookUpFilehandle(); - dir->_LookUpFilehandle(); + fInfo.UpdateFileHandles(fFilesystem); + dir->fInfo.UpdateFileHandles(dir->fFilesystem); continue; } @@ -315,8 +315,8 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName) // filehandle has expired if (reply.NFS4Error() == NFS4ERR_FHEXPIRED) { - from->_LookUpFilehandle(); - to->_LookUpFilehandle(); + from->fInfo.UpdateFileHandles(from->fFilesystem); + to->fInfo.UpdateFileHandles(to->fFilesystem); continue; } @@ -956,7 +956,7 @@ Inode::_HandleErrors(uint32 nfs4Error, RPC::Server* serv, // filehandle has expired case NFS4ERR_FHEXPIRED: - if (_LookUpFilehandle() == B_OK) + if (fInfo.UpdateFileHandles(fFilesystem) == B_OK) return true; else return false; @@ -980,73 +980,3 @@ Inode::_HandleErrors(uint32 nfs4Error, RPC::Server* serv, } } - -static status_t -sParsePath(RequestBuilder& req, uint32* count, const char* _path) -{ - char* path = strdup(_path); - char* pathStart = path; - char* pathEnd; - while (pathStart != NULL) { - pathEnd = strpbrk(pathStart, "/"); - if (pathEnd != NULL) - *pathEnd = '\0'; - - req.LookUp(pathStart); - - if (pathEnd != NULL && pathEnd[1] != '\0') - pathStart = pathEnd + 1; - else - pathStart = NULL; - - (*count)++; - } - free(path); - - return B_OK; -} - - -status_t -Inode::_LookUpFilehandle() -{ - Request request(fFilesystem->Server()); - RequestBuilder& req = request.Builder(); - - req.PutRootFH(); - - uint32 lookupCount = 0; - - sParsePath(req, &lookupCount, fFilesystem->Path()); - sParsePath(req, &lookupCount, fInfo.fPath); - - req.GetFH(); - - if (fFilesystem->IsAttrSupported(FATTR4_FILEID)) { - AttrValue attr; - attr.fAttribute = FATTR4_FILEID; - attr.fFreePointer = false; - attr.fData.fValue64 = fInfo.fFileId; - req.Verify(&attr, 1); - } - - status_t result = request.Send(); - if (result != B_OK) - return result; - - ReplyInterpreter& reply = request.Reply(); - - reply.PutRootFH(); - for (uint32 i = 0; i < lookupCount; i++) - reply.LookUp(); - - result = reply.GetFH(&fInfo.fHandle); - if (result != B_OK) - return result; - - if (fFilesystem->IsAttrSupported(FATTR4_FILEID)) - return reply.Verify(); - else - return B_OK; -} - diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.h b/src/add-ons/kernel/file_systems/nfs4/Inode.h index 1551782..76445e7 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.h +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.h @@ -74,7 +74,6 @@ protected: bool _HandleErrors(uint32 nfs4Error, RPC::Server* serv, OpenFileCookie* cookie = NULL); - status_t _LookUpFilehandle(); status_t _ConfirmOpen(const Filehandle& fh, OpenFileCookie* cookie); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h index 6cde1f3..63ec1b0 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h +++ b/src/add-ons/kernel/file_systems/nfs4/InodeIdMap.h @@ -14,7 +14,7 @@ #include <util/AutoLock.h> #include <util/AVLTreeMap.h> -#include "Filehandle.h" +#include "FileInfo.h" class InodeIdMap { diff --git a/src/add-ons/kernel/file_systems/nfs4/Jamfile b/src/add-ons/kernel/file_systems/nfs4/Jamfile index 57060a1..eb8e5e8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Jamfile +++ b/src/add-ons/kernel/file_systems/nfs4/Jamfile @@ -6,6 +6,7 @@ UsePrivateHeaders shared ; KernelAddon nfs4 : Cookie.cpp Connection.cpp + FileInfo.cpp Filesystem.cpp Inode.cpp InodeDir.cpp diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h index 853c783..31e82c2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Defs.h @@ -14,7 +14,6 @@ #include <SupportDefs.h> -#include "Filehandle.h" enum Procedure { ProcNull = 0, diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h index 0595a8b..8e99e9e 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.h @@ -11,6 +11,7 @@ #include <SupportDefs.h> +#include "FileInfo.h" #include "NFS4Defs.h" #include "RPCReply.h" diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h index 0143a9a..f59aac7 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.h @@ -11,6 +11,7 @@ #include <SupportDefs.h> +#include "FileInfo.h" #include "NFS4Defs.h" #include "ReplyInterpreter.h" #include "RPCCall.h" ############################################################################ Commit: b2cea80ce5328c07e9f5c42c72213c186737aea5 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Jul 3 17:17:37 2012 UTC nfs4: Add id mapper ---------------------------------------------------------------------------- diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 0d2714b..3c7bb0e 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -106,7 +106,7 @@ PRIVATE_SYSTEM_LIBS = SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon media_addon_server media_server midi_server mount_server net_server notification_server power_daemon print_server print_addon_server registrar syslog_daemon - dns_resolver_server + dns_resolver_server nfs4_idmapper_server ; SYSTEM_NETWORK_DEVICES = ethernet loopback ; diff --git a/src/add-ons/kernel/file_systems/nfs4/IdMap.cpp b/src/add-ons/kernel/file_systems/nfs4/IdMap.cpp new file mode 100644 index 0000000..37d7559 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/IdMap.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ + + +#include "IdMap.h" + +#include <FindDirectory.h> +#include <team.h> +#include <util/AutoLock.h> + +#include "idmapper/IdMapper.h" + + +IdMap* gIdMapper = NULL; + + +IdMap::IdMap() +{ + mutex_init(&fLock, NULL); + _Repair(); +} + + +IdMap::~IdMap() +{ + delete_port(fRequestPort); + delete_port(fReplyPort); + mutex_destroy(&fLock); +} + + +uid_t +IdMap::GetUserId(const char* owner) +{ + return _GetValue<uid_t>(owner, MsgNameToUID); +} + + +gid_t +IdMap::GetGroupId(const char* ownerGroup) +{ + return _GetValue<gid_t>(ownerGroup, MsgNameToGID); +} + + +char* +IdMap::GetOwner(uid_t user) +{ + return reinterpret_cast<char*>(_GetBuffer(user, MsgUIDToName)); +} + + +char* +IdMap::GetOwnerGroup(gid_t group) +{ + return reinterpret_cast<char*>(_GetBuffer(group, MsgGIDToName)); +} + + +template<typename T> +T +IdMap::_GetValue(const char* buffer, int32 code) +{ + MutexLocker _(fLock); + do { + status_t result = write_port(fRequestPort, MsgNameToUID, buffer, + strlen(buffer) + 1); + if (result != B_OK) { + if (_Repair() != B_OK) + return 0; + else + continue; + } + + int32 code; + T value; + result = read_port(fReplyPort, &code, &value, sizeof(T)); + if (result < B_OK) { + if (_Repair() != B_OK) + return 0; + else + continue; + } + + if (code != MsgReply) + return 0; + else + return value; + } while (true); +} + + +template<typename T> +void* +IdMap::_GetBuffer(T value, int32 code) +{ + MutexLocker _(fLock); + do { + status_t result = write_port(fRequestPort, code, &value, sizeof(value)); + if (result != B_OK) { + if (_Repair() != B_OK) + return NULL; + else + continue; + } + + ssize_t size = port_buffer_size(fReplyPort); + if (size < B_OK) { + if (_Repair() != B_OK) + return NULL; + else + continue; + } + + int32 code; + void* buffer = malloc(size); + if (buffer == NULL) + return NULL; + + result = read_port(fReplyPort, &code, buffer, size); + if (result < B_OK) { + free(buffer); + + if (_Repair() != B_OK) + return 0; + else + continue; + } + + if (code != MsgReply) { + free(buffer); + return NULL; + } else + return buffer; + } while (true); +} + + +status_t +IdMap::_Repair() +{ + status_t result = B_OK; + + fRequestPort = create_port(1, kRequestPortName); + if (fRequestPort < B_OK) + return fRequestPort; + + fReplyPort = create_port(1, kReplyPortName); + if (fReplyPort < B_OK) { + delete_port(fRequestPort); + return fReplyPort; + } + + char path[256]; + if (find_directory(B_SYSTEM_SERVERS_DIRECTORY, static_cast<dev_t>(-1), + false, path, sizeof(path)) != B_OK) { + delete_port(fReplyPort); + delete_port(fRequestPort); + return B_NAME_NOT_FOUND; + } + strlcat(path, "/nfs4_idmapper_server", sizeof(path)); + + const char* args[] = { path, NULL }; + thread_id thread = load_image_etc(1, args, NULL, B_NORMAL_PRIORITY, + B_SYSTEM_TEAM, 0); + if (thread < B_OK) { + delete_port(fReplyPort); + delete_port(fRequestPort); + return thread; + } + + set_port_owner(fRequestPort, thread); + set_port_owner(fReplyPort, thread); + + result = resume_thread(thread); + if (result != B_OK) { + kill_thread(thread); + delete_port(fReplyPort); + delete_port(fRequestPort); + return result; + } + + return B_OK; +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/IdMap.h b/src/add-ons/kernel/file_systems/nfs4/IdMap.h new file mode 100644 index 0000000..266bef6 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/IdMap.h @@ -0,0 +1,47 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ +#ifndef IDMAP_H +#define IDMAP_H + + +#include <lock.h> +#include <port.h> +#include <SupportDefs.h> + + +class IdMap { +public: + IdMap(); + ~IdMap(); + + uid_t GetUserId(const char* owner); + gid_t GetGroupId(const char* ownerGroup); + + char* GetOwner(uid_t user); + char* GetOwnerGroup(gid_t group); + +private: + status_t _Repair(); + + template<typename T> + void* _GetBuffer(T value, int32 code); + + template<typename T> + T _GetValue(const char* buffer, int32 code); + + mutex fLock; + + port_id fRequestPort; + port_id fReplyPort; +}; + +extern IdMap* gIdMapper; + + +#endif // IDMAP_H + diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index ccecb6f..836962b 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -13,6 +13,7 @@ #include <NodeMonitor.h> +#include "IdMap.h" #include "Request.h" #include "RootInode.h" @@ -345,11 +346,24 @@ Inode::CreateLink(const char* name, const char* path, int mode) req.PutFH(fInfo.fHandle); - AttrValue attr; - attr.fAttribute = FATTR4_MODE; - attr.fFreePointer = false; - attr.fData.fValue32 = mode; - req.Create(NF4LNK, name, &attr, 1, path); + uint32 i = 0; + AttrValue cattr[3]; + cattr[i].fAttribute = FATTR4_MODE; + cattr[i].fFreePointer = false; + cattr[i].fData.fValue32 = mode; + i++; + + cattr[i].fAttribute = FATTR4_OWNER; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); + i++; + + cattr[i].fAttribute = FATTR4_OWNER_GROUP; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); + i++; + + req.Create(NF4LNK, name, cattr, i, path); status_t result = request.Send(); if (result != B_OK) @@ -460,6 +474,7 @@ Inode::Stat(struct stat* st) req.PutFH(fInfo.fHandle); Attribute attr[] = { FATTR4_SIZE, FATTR4_MODE, FATTR4_NUMLINKS, + FATTR4_OWNER, FATTR4_OWNER_GROUP, FATTR4_TIME_ACCESS, FATTR4_TIME_CREATE, FATTR4_TIME_METADATA, FATTR4_TIME_MODIFY }; req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); @@ -526,6 +541,20 @@ Inode::Stat(struct stat* st) } else st->st_nlink = 1; + if (count >= next && values[next].fAttribute == FATTR4_OWNER) { + char* owner = reinterpret_cast<char*>(values[next].fData.fPointer); + st->st_uid = gIdMapper->GetUserId(owner); + next++; + } else + st->st_uid = 0; + + if (count >= next && values[next].fAttribute == FATTR4_OWNER_GROUP) { + char* group = reinterpret_cast<char*>(values[next].fData.fPointer); + st->st_gid = gIdMapper->GetGroupId(group); + next++; + } else + st->st_gid = 0; + if (count >= next && values[next].fAttribute == FATTR4_TIME_ACCESS) { memcpy(&st->st_atim, values[next].fData.fPointer, sizeof(timespec)); next++; @@ -551,9 +580,6 @@ Inode::Stat(struct stat* st) } else memset(&st->st_mtim, 0, sizeof(timespec)); - st->st_uid = 0; - st->st_gid = 0; - delete[] values; return B_OK; } while (true); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index c1a3bb1..d41ddca 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -12,6 +12,7 @@ #include <dirent.h> #include <string.h> +#include "IdMap.h" #include "Request.h" #include "RootInode.h" @@ -26,11 +27,24 @@ Inode::CreateDir(const char* name, int mode) req.PutFH(fInfo.fHandle); - AttrValue attr; - attr.fAttribute = FATTR4_MODE; - attr.fFreePointer = false; - attr.fData.fValue32 = mode; - req.Create(NF4DIR, name, &attr, 1); + uint32 i = 0; + AttrValue cattr[3]; + cattr[i].fAttribute = FATTR4_MODE; + cattr[i].fFreePointer = false; + cattr[i].fData.fValue32 = mode; + i++; + + cattr[i].fAttribute = FATTR4_OWNER; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); + i++; + + cattr[i].fAttribute = FATTR4_OWNER_GROUP; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); + i++; + + req.Create(NF4DIR, name, cattr, i); status_t result = request.Send(); if (result != B_OK) diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 199dabe..b0e92cb 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -13,6 +13,7 @@ #include <NodeMonitor.h> +#include "IdMap.h" #include "Request.h" @@ -77,7 +78,7 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, req.PutFH(fInfo.fHandle); - AttrValue cattr[2]; + AttrValue cattr[4]; uint32 i = 0; if ((mode & O_TRUNC) == O_TRUNC) { cattr[i].fAttribute = FATTR4_SIZE; @@ -88,9 +89,21 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, cattr[i].fAttribute = FATTR4_MODE; cattr[i].fFreePointer = false; cattr[i].fData.fValue32 = perms; + i++; + + cattr[i].fAttribute = FATTR4_OWNER; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); + i++; + + cattr[i].fAttribute = FATTR4_OWNER_GROUP; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); + i++; + req.Open(CLAIM_NULL, cookie->fSequence++, sModeToAccess(mode), cookie->fClientId, OPEN4_CREATE, cookie->fOwnerId, name, cattr, - i + 1, (mode & O_EXCL) == O_EXCL); + i, (mode & O_EXCL) == O_EXCL); req.GetFH(); diff --git a/src/add-ons/kernel/file_systems/nfs4/Jamfile b/src/add-ons/kernel/file_systems/nfs4/Jamfile index eb8e5e8..822bf41 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Jamfile +++ b/src/add-ons/kernel/file_systems/nfs4/Jamfile @@ -8,6 +8,7 @@ KernelAddon nfs4 : Connection.cpp FileInfo.cpp Filesystem.cpp + IdMap.cpp Inode.cpp InodeDir.cpp InodeRegular.cpp @@ -23,3 +24,6 @@ KernelAddon nfs4 : RPCServer.cpp XDR.cpp ; + +SubInclude HAIKU_TOP src add-ons kernel file_systems nfs4 idmapper ; + diff --git a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp index c5c97c84..43755b2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/ReplyInterpreter.cpp @@ -614,6 +614,20 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs, current++; } + if (sIsAttrSet(FATTR4_OWNER, bitmap, bcount)) { + values[current].fAttribute = FATTR4_OWNER; + values[current].fFreePointer = true; + values[current].fData.fPointer = stream.GetString(); + current++; + } + + if (sIsAttrSet(FATTR4_OWNER_GROUP, bitmap, bcount)) { + values[current].fAttribute = FATTR4_OWNER_GROUP; + values[current].fFreePointer = true; + values[current].fData.fPointer = stream.GetString(); + current++; + } + if (sIsAttrSet(FATTR4_SPACE_FREE, bitmap, bcount)) { values[current].fAttribute = FATTR4_SPACE_FREE; values[current].fData.fValue64 = stream.GetUHyper(); diff --git a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp index 8f67dbc..81cade2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RequestBuilder.cpp @@ -776,6 +776,16 @@ RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr, i++; } + if (i < count && attr[i].fAttribute == FATTR4_OWNER) { + str.AddString(reinterpret_cast<char*>(attr[i].fData.fPointer)); + i++; + } + + if (i < count && attr[i].fAttribute == FATTR4_OWNER_GROUP) { + str.AddString(reinterpret_cast<char*>(attr[i].fData.fPointer)); + i++; + } + if (i < count && attr[i].fAttribute == FATTR4_TIME_ACCESS_SET) { str.AddInt(1); // SET_TO_CLIENT_TIME4 diff --git a/src/add-ons/kernel/file_systems/nfs4/XDR.cpp b/src/add-ons/kernel/file_systems/nfs4/XDR.cpp index 423d444..9cc116d 100644 --- a/src/add-ons/kernel/file_systems/nfs4/XDR.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/XDR.cpp @@ -115,7 +115,7 @@ ReadStream::GetUHyper() } -const char* +char* ReadStream::GetString() { if (_PositionToSize() >= fSize) { diff --git a/src/add-ons/kernel/file_systems/nfs4/XDR.h b/src/add-ons/kernel/file_systems/nfs4/XDR.h index 5d5300e..f52ae0f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/XDR.h +++ b/src/add-ons/kernel/file_systems/nfs4/XDR.h @@ -48,7 +48,7 @@ public: inline bool GetBoolean(); - const char* GetString(); + char* GetString(); const void* GetOpaque(uint32* size); diff --git a/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.cpp b/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.cpp new file mode 100644 index 0000000..a0d6c49 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.cpp @@ -0,0 +1,266 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ + + +#include "IdMapper.h" + +#include <grp.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include <File.h> +#include <FindDirectory.h> +#include <OS.h> +#include <Path.h> + + +port_id gRequestPort; +port_id gReplyPort; + +const char* kNobodyName = "nobody"; +uid_t gNobodyId; + +const char* kNogroupName = "nobody"; +uid_t gNogroupId; + +const char* gDomainName = "localdomain"; + + +status_t +SendError(status_t error) +{ + return write_port(gReplyPort, MsgError, &error, sizeof(error)); +} + + +status_t +MatchDomain(char* name) +{ + char* domain = strchr(name, '@'); + if (domain == NULL) + return B_MISMATCHED_VALUES; + + if (strcmp(domain + 1, gDomainName) != 0) + return B_BAD_VALUE; + + *domain = '\0'; + + return B_OK; +} + + +char* +AddDomain(const char* name) +{ + uint32 fullLength = strlen(name) + strlen(gDomainName) + 2; + char* fullName = reinterpret_cast<char*>(malloc(fullLength)); + + strcpy(fullName, name); + strcat(fullName, "@"); + strcat(fullName, gDomainName); + + return fullName; +} + + +status_t +NameToUID(void* buffer) +{ + char* userName = reinterpret_cast<char*>(buffer); + + struct passwd* userInfo = NULL; + + if (MatchDomain(userName) == B_OK) + userInfo = getpwnam(userName); + + if (userInfo == NULL) + return write_port(gReplyPort, MsgReply, &gNobodyId, sizeof(gNobodyId)); + + return write_port(gReplyPort, MsgReply, &userInfo->pw_uid, sizeof(uid_t)); +} + + +status_t +UIDToName(void* buffer) +{ + uid_t userId = *reinterpret_cast<uid_t*>(buffer); + + const char* fullName = kNobodyName; + + struct passwd* userInfo = getpwuid(userId); + if (userInfo != NULL) { + const char* name = userInfo->pw_name; + fullName = AddDomain(name); + } + + status_t result = write_port(gReplyPort, MsgReply, fullName, + strlen(fullName) + 1); + free(const_cast<char*>(fullName)); + + return result; +} + + +status_t +NameToGID(void* buffer) +{ + char* groupName = reinterpret_cast<char*>(buffer); + + struct group* groupInfo = NULL; + + if (MatchDomain(groupName) == B_OK) + groupInfo = getgrnam(groupName); + + if (groupInfo == NULL) { + return write_port(gReplyPort, MsgReply, &gNogroupId, + sizeof(gNogroupId)); + } + + return write_port(gReplyPort, MsgReply, &groupInfo->gr_gid, sizeof(gid_t)); +} + + +status_t +GIDToName(void* buffer) +{ + gid_t groupId = *reinterpret_cast<gid_t*>(buffer); + + const char* fullName = kNogroupName; + + struct group* groupInfo = getgrgid(groupId); + if (groupInfo != NULL) { + const char* name = groupInfo->gr_name; + fullName = AddDomain(name); + } + + status_t result = write_port(gReplyPort, MsgReply, fullName, + strlen(fullName) + 1); + free(const_cast<char*>(fullName)); + + return result; +} + + +status_t +ParseRequest(int32 code, void* buffer) +{ + switch (code) { + case MsgNameToUID: + return NameToUID(buffer); + + case MsgUIDToName: + return UIDToName(buffer); + + case MsgNameToGID: + return NameToGID(buffer); + + case MsgGIDToName: + return GIDToName(buffer); + + default: + return SendError(B_BAD_VALUE); + } +} + + +status_t +MainLoop() +{ + do { + ssize_t size = port_buffer_size(gRequestPort); + if (size < B_OK) + return 0; + + void* buffer = malloc(size); + if (buffer == NULL) + return B_NO_MEMORY; + + int32 code; + status_t result = read_port(gRequestPort, &code, buffer, size); + if (size < B_OK) { + free(buffer); + return 0; + } + + result = ParseRequest(code, buffer); + free(buffer); + + if (result == B_BAD_PORT_ID) + return 0; + + } while (true); +} + + +status_t +ReadSettings() +{ + BPath path; + status_t result = find_directory(B_COMMON_SETTINGS_DIRECTORY, &path); + if (result != B_OK) + return result; + result = path.Append("nfs4_idmapper.conf"); + if (result != B_OK) + return result; + + BFile file(path.Path(), B_READ_ONLY); + if (file.InitCheck() != B_OK) + return file.InitCheck(); + + off_t size; + result = file.GetSize(&size); + if (result != B_OK) + return result; + + void* buffer = malloc(size); + if (buffer == NULL) + return B_NO_MEMORY; + + file.Read(buffer, size); + + gDomainName = reinterpret_cast<char*>(buffer); + + return B_OK; +} + + +int +main(int argc, char** argv) +{ + gRequestPort = find_port(kRequestPortName); + if (gRequestPort == B_NAME_NOT_FOUND) { + fprintf(stderr, "%s\n", strerror(gRequestPort)); + return gRequestPort; + } + + gReplyPort = find_port(kReplyPortName); + if (gReplyPort == B_NAME_NOT_FOUND) { + fprintf(stderr, "%s\n", strerror(gReplyPort)); + return gReplyPort; + } + + ReadSettings(); + + struct passwd* userInfo = getpwnam(kNobodyName); + if (userInfo != NULL) + gNobodyId = userInfo->pw_uid; + else + gNobodyId = 0; + + struct group* groupInfo = getgrnam(kNogroupName); + if (groupInfo != NULL) + gNogroupId = groupInfo->gr_gid; + else + gNogroupId = 0; + + return MainLoop(); +} + diff --git a/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.h b/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.h new file mode 100644 index 0000000..bf0707e --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/idmapper/IdMapper.h @@ -0,0 +1,26 @@ +/* + * Copyright 2012 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@xxxxxxxxxxx + */ +#ifndef IDMAPPER_H +#define IDMAPPER_H + + +enum MsgCode { + MsgError, + MsgReply, + MsgNameToUID, + MsgUIDToName, + MsgNameToGID, + MsgGIDToName +}; + +static const char* kRequestPortName = "nfs4idmap_request"; +static const char* kReplyPortName = "nfs4idmap_reply"; + + +#endif // IDMAPPER_H + diff --git a/src/add-ons/kernel/file_systems/nfs4/idmapper/Jamfile b/src/add-ons/kernel/file_systems/nfs4/idmapper/Jamfile new file mode 100644 index 0000000..f9f4bb2 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/idmapper/Jamfile @@ -0,0 +1,13 @@ +SubDir HAIKU_TOP src add-ons kernel file_systems nfs4 idmapper ; + +Application nfs4_idmapper_server + : + IdMapper.cpp + + : + be + $(TARGET_LIBSUPC++) + + : + nfs4_idmapper_server.rdef +; diff --git a/src/add-ons/kernel/file_systems/nfs4/idmapper/nfs4_idmapper_server.rdef b/src/add-ons/kernel/file_systems/nfs4/idmapper/nfs4_idmapper_server.rdef new file mode 100644 index 0000000..9b60181 --- /dev/null +++ b/src/add-ons/kernel/file_systems/nfs4/idmapper/nfs4_idmapper_server.rdef @@ -0,0 +1,20 @@ +/* + * nfs4_idmapper_server.rdef + */ + +resource app_signature "application/x-vnd.Haiku-nfs4_idmapper-server"; + +resource app_flags B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + + variety = B_APPV_ALPHA, + internal = 0, + + short_info = "nfs4_idmapper_server", + long_info = "nfs4_idmapper_server ©2012 Haiku, Inc" +}; + diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index e2b40f9..1f3c216 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -15,6 +15,7 @@ #include "Connection.h" #include "Filesystem.h" +#include "IdMap.h" #include "Inode.h" #include "NFS4Defs.h" #include "RequestBuilder.h" @@ -546,6 +547,13 @@ nfs4_init() gRPCServerManager = new(std::nothrow) RPC::ServerManager; if (gRPCServerManager == NULL) return B_NO_MEMORY; + + gIdMapper = new(std::nothrow) IdMap; + if (gIdMapper == NULL) { + delete gRPCServerManager; + return B_NO_MEMORY; + } + return B_OK; } @@ -555,6 +563,7 @@ nfs4_uninit() { dprintf("NFS4 Uninit\n"); + delete gIdMapper; delete gRPCServerManager; return B_OK; ############################################################################ Commit: ed097dd0a27587d885a777401a519bf03991d62e Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Jul 3 19:57:08 2012 UTC nfs4: Do not attempt to set owner, owner_group when not supported ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 836962b..3a8a995 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -353,15 +353,19 @@ Inode::CreateLink(const char* name, const char* path, int mode) cattr[i].fData.fValue32 = mode; i++; - cattr[i].fAttribute = FATTR4_OWNER; - cattr[i].fFreePointer = true; - cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); - i++; + if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) { + cattr[i].fAttribute = FATTR4_OWNER; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); + i++; + } - cattr[i].fAttribute = FATTR4_OWNER_GROUP; - cattr[i].fFreePointer = true; - cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); - i++; + if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { + cattr[i].fAttribute = FATTR4_OWNER_GROUP; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); + i++; + } req.Create(NF4LNK, name, cattr, i, path); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index d41ddca..bde7506 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -34,15 +34,19 @@ Inode::CreateDir(const char* name, int mode) cattr[i].fData.fValue32 = mode; i++; - cattr[i].fAttribute = FATTR4_OWNER; - cattr[i].fFreePointer = true; - cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); - i++; + if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) { + cattr[i].fAttribute = FATTR4_OWNER; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); + i++; + } - cattr[i].fAttribute = FATTR4_OWNER_GROUP; - cattr[i].fFreePointer = true; - cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); - i++; + if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { + cattr[i].fAttribute = FATTR4_OWNER_GROUP; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); + i++; + } req.Create(NF4DIR, name, cattr, i); diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index b0e92cb..3f104fc 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -91,15 +91,19 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, cattr[i].fData.fValue32 = perms; i++; - cattr[i].fAttribute = FATTR4_OWNER; - cattr[i].fFreePointer = true; - cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); - i++; + if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) { + cattr[i].fAttribute = FATTR4_OWNER; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); + i++; + } - cattr[i].fAttribute = FATTR4_OWNER_GROUP; - cattr[i].fFreePointer = true; - cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); - i++; + if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { + cattr[i].fAttribute = FATTR4_OWNER_GROUP; + cattr[i].fFreePointer = true; + cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); + i++; + } req.Open(CLAIM_NULL, cookie->fSequence++, sModeToAccess(mode), cookie->fClientId, OPEN4_CREATE, cookie->fOwnerId, name, cattr, ############################################################################ Commit: 6197fa881fea5641fd7c1433c3c1adf27c5d3fdf Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Jul 3 20:00:55 2012 UTC nfs4: Allow WriteStat() to set UID and GID ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 3a8a995..3286dc6 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -595,7 +595,7 @@ Inode::WriteStat(const struct stat* st, uint32 mask) { status_t result; OpenFileCookie* cookie = NULL; - AttrValue attr[4]; + AttrValue attr[6]; uint32 i = 0; if ((mask & B_STAT_SIZE) != 0) { @@ -623,6 +623,20 @@ Inode::WriteStat(const struct stat* st, uint32 mask) i++; } + if ((mask & B_STAT_UID) != 0) { + attr[i].fAttribute = FATTR4_OWNER; + attr[i].fFreePointer = true; + attr[i].fData.fPointer = gIdMapper->GetOwner(st->st_uid); + i++; + } + + if ((mask & B_STAT_GID) != 0) { + attr[i].fAttribute = FATTR4_OWNER_GROUP; + attr[i].fFreePointer = true; + attr[i].fData.fPointer = gIdMapper->GetOwnerGroup(st->st_gid); + i++; + } + if ((mask & B_STAT_ACCESS_TIME) != 0) { attr[i].fAttribute = FATTR4_TIME_ACCESS_SET; attr[i].fFreePointer = true; ############################################################################ Commit: 16ff38f8289b93fe84a8e04aeddf33f9e78434fb Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Jul 3 20:08:35 2012 UTC nfs4: Support legacy owner and owner_group values ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 3286dc6..5199cb2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -9,6 +9,7 @@ #include "Inode.h" +#include <ctype.h> #include <string.h> #include <NodeMonitor.h> @@ -547,14 +548,20 @@ Inode::Stat(struct stat* st) if (count >= next && values[next].fAttribute == FATTR4_OWNER) { char* owner = reinterpret_cast<char*>(values[next].fData.fPointer); - st->st_uid = gIdMapper->GetUserId(owner); + if (owner != NULL && isdigit(owner[0])) + st->st_uid = atoi(owner); + else + st->st_uid = gIdMapper->GetUserId(owner); next++; } else st->st_uid = 0; if (count >= next && values[next].fAttribute == FATTR4_OWNER_GROUP) { char* group = reinterpret_cast<char*>(values[next].fData.fPointer); - st->st_gid = gIdMapper->GetGroupId(group); + if (group != NULL && isdigit(group[0])) + st->st_gid = atoi(group); + else + st->st_gid = gIdMapper->GetGroupId(group); next++; } else st->st_gid = 0; ############################################################################ Commit: 8f57d30ea4934abc215ae850fa3612474087d7a3 Author: Pawel Dziepak <pdziepak@xxxxxxxxxxx> Date: Tue Jul 3 20:16:08 2012 UTC nfs4: Abandon owner and owner_group when id mapping causes problems ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp index 5199cb2..055b6b2 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Inode.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Inode.cpp @@ -340,6 +340,8 @@ Inode::Rename(Inode* from, Inode* to, const char* fromName, const char* toName) status_t Inode::CreateLink(const char* name, const char* path, int mode) { + bool badOwner = false; + do { RPC::Server* serv = fFilesystem->Server(); Request request(serv); @@ -354,14 +356,14 @@ Inode::CreateLink(const char* name, const char* path, int mode) cattr[i].fData.fValue32 = mode; i++; - if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) { + if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER)) { cattr[i].fAttribute = FATTR4_OWNER; cattr[i].fFreePointer = true; cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); i++; } - if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { + if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { cattr[i].fAttribute = FATTR4_OWNER_GROUP; cattr[i].fFreePointer = true; cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); @@ -376,6 +378,10 @@ Inode::CreateLink(const char* name, const char* path, int mode) ReplyInterpreter& reply = request.Reply(); + if (reply.NFS4Error() == NFS4ERR_BADOWNER) { + badOwner = true; + continue; + } if (_HandleErrors(reply.NFS4Error(), serv)) continue; diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp index bde7506..19b2743 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp @@ -20,6 +20,8 @@ status_t Inode::CreateDir(const char* name, int mode) { + bool badOwner = false; + do { RPC::Server* serv = fFilesystem->Server(); Request request(serv); @@ -34,14 +36,14 @@ Inode::CreateDir(const char* name, int mode) cattr[i].fData.fValue32 = mode; i++; - if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) { + if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER)) { cattr[i].fAttribute = FATTR4_OWNER; cattr[i].fFreePointer = true; cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); i++; } - if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { + if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { cattr[i].fAttribute = FATTR4_OWNER_GROUP; cattr[i].fFreePointer = true; cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); @@ -56,6 +58,10 @@ Inode::CreateDir(const char* name, int mode) ReplyInterpreter& reply = request.Reply(); + if (reply.NFS4Error() == NFS4ERR_BADOWNER) { + badOwner = true; + continue; + } if (_HandleErrors(reply.NFS4Error(), serv)) continue; diff --git a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp index 3f104fc..742ba45 100644 --- a/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/InodeRegular.cpp @@ -66,6 +66,7 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, cookie->fSequence = 0; cookie->fLocks = NULL; + bool badOwner = false; Filehandle fh; do { cookie->fClientId = fFilesystem->NFSServer()->ClientId(); @@ -91,14 +92,14 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, cattr[i].fData.fValue32 = perms; i++; - if (fFilesystem->IsAttrSupported(FATTR4_OWNER)) { + if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER)) { cattr[i].fAttribute = FATTR4_OWNER; cattr[i].fFreePointer = true; cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid()); i++; } - if (fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { + if (!badOwner && fFilesystem->IsAttrSupported(FATTR4_OWNER_GROUP)) { cattr[i].fAttribute = FATTR4_OWNER_GROUP; cattr[i].fFreePointer = true; cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid()); @@ -122,6 +123,10 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, ReplyInterpreter& reply = request.Reply(); + if (reply.NFS4Error() == NFS4ERR_BADOWNER) { + badOwner = true; + continue; + } if (_HandleErrors(reply.NFS4Error(), serv)) continue;