nfs4: Add id mapper
This commit is contained in:
@@ -106,7 +106,7 @@ PRIVATE_SYSTEM_LIBS =
|
|||||||
SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon
|
SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon
|
||||||
media_addon_server media_server midi_server mount_server net_server
|
media_addon_server media_server midi_server mount_server net_server
|
||||||
notification_server power_daemon print_server print_addon_server registrar syslog_daemon
|
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 ;
|
SYSTEM_NETWORK_DEVICES = ethernet loopback ;
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, [email protected]
|
||||||
|
*/
|
||||||
|
#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
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
|
|
||||||
|
#include "IdMap.h"
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
#include "RootInode.h"
|
#include "RootInode.h"
|
||||||
|
|
||||||
@@ -345,11 +346,24 @@ Inode::CreateLink(const char* name, const char* path, int mode)
|
|||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
|
|
||||||
AttrValue attr;
|
uint32 i = 0;
|
||||||
attr.fAttribute = FATTR4_MODE;
|
AttrValue cattr[3];
|
||||||
attr.fFreePointer = false;
|
cattr[i].fAttribute = FATTR4_MODE;
|
||||||
attr.fData.fValue32 = mode;
|
cattr[i].fFreePointer = false;
|
||||||
req.Create(NF4LNK, name, &attr, 1, path);
|
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();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
@@ -460,6 +474,7 @@ Inode::Stat(struct stat* st)
|
|||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
|
|
||||||
Attribute attr[] = { FATTR4_SIZE, FATTR4_MODE, FATTR4_NUMLINKS,
|
Attribute attr[] = { FATTR4_SIZE, FATTR4_MODE, FATTR4_NUMLINKS,
|
||||||
|
FATTR4_OWNER, FATTR4_OWNER_GROUP,
|
||||||
FATTR4_TIME_ACCESS, FATTR4_TIME_CREATE,
|
FATTR4_TIME_ACCESS, FATTR4_TIME_CREATE,
|
||||||
FATTR4_TIME_METADATA, FATTR4_TIME_MODIFY };
|
FATTR4_TIME_METADATA, FATTR4_TIME_MODIFY };
|
||||||
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
|
||||||
@@ -526,6 +541,20 @@ Inode::Stat(struct stat* st)
|
|||||||
} else
|
} else
|
||||||
st->st_nlink = 1;
|
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) {
|
if (count >= next && values[next].fAttribute == FATTR4_TIME_ACCESS) {
|
||||||
memcpy(&st->st_atim, values[next].fData.fPointer, sizeof(timespec));
|
memcpy(&st->st_atim, values[next].fData.fPointer, sizeof(timespec));
|
||||||
next++;
|
next++;
|
||||||
@@ -551,9 +580,6 @@ Inode::Stat(struct stat* st)
|
|||||||
} else
|
} else
|
||||||
memset(&st->st_mtim, 0, sizeof(timespec));
|
memset(&st->st_mtim, 0, sizeof(timespec));
|
||||||
|
|
||||||
st->st_uid = 0;
|
|
||||||
st->st_gid = 0;
|
|
||||||
|
|
||||||
delete[] values;
|
delete[] values;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "IdMap.h"
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
#include "RootInode.h"
|
#include "RootInode.h"
|
||||||
|
|
||||||
@@ -26,11 +27,24 @@ Inode::CreateDir(const char* name, int mode)
|
|||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
|
|
||||||
AttrValue attr;
|
uint32 i = 0;
|
||||||
attr.fAttribute = FATTR4_MODE;
|
AttrValue cattr[3];
|
||||||
attr.fFreePointer = false;
|
cattr[i].fAttribute = FATTR4_MODE;
|
||||||
attr.fData.fValue32 = mode;
|
cattr[i].fFreePointer = false;
|
||||||
req.Create(NF4DIR, name, &attr, 1);
|
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();
|
status_t result = request.Send();
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
|
|
||||||
|
#include "IdMap.h"
|
||||||
#include "Request.h"
|
#include "Request.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
|
|||||||
|
|
||||||
req.PutFH(fInfo.fHandle);
|
req.PutFH(fInfo.fHandle);
|
||||||
|
|
||||||
AttrValue cattr[2];
|
AttrValue cattr[4];
|
||||||
uint32 i = 0;
|
uint32 i = 0;
|
||||||
if ((mode & O_TRUNC) == O_TRUNC) {
|
if ((mode & O_TRUNC) == O_TRUNC) {
|
||||||
cattr[i].fAttribute = FATTR4_SIZE;
|
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].fAttribute = FATTR4_MODE;
|
||||||
cattr[i].fFreePointer = false;
|
cattr[i].fFreePointer = false;
|
||||||
cattr[i].fData.fValue32 = perms;
|
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),
|
req.Open(CLAIM_NULL, cookie->fSequence++, sModeToAccess(mode),
|
||||||
cookie->fClientId, OPEN4_CREATE, cookie->fOwnerId, name, cattr,
|
cookie->fClientId, OPEN4_CREATE, cookie->fOwnerId, name, cattr,
|
||||||
i + 1, (mode & O_EXCL) == O_EXCL);
|
i, (mode & O_EXCL) == O_EXCL);
|
||||||
|
|
||||||
req.GetFH();
|
req.GetFH();
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ KernelAddon nfs4 :
|
|||||||
Connection.cpp
|
Connection.cpp
|
||||||
FileInfo.cpp
|
FileInfo.cpp
|
||||||
Filesystem.cpp
|
Filesystem.cpp
|
||||||
|
IdMap.cpp
|
||||||
Inode.cpp
|
Inode.cpp
|
||||||
InodeDir.cpp
|
InodeDir.cpp
|
||||||
InodeRegular.cpp
|
InodeRegular.cpp
|
||||||
@@ -23,3 +24,6 @@ KernelAddon nfs4 :
|
|||||||
RPCServer.cpp
|
RPCServer.cpp
|
||||||
XDR.cpp
|
XDR.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel file_systems nfs4 idmapper ;
|
||||||
|
|
||||||
|
|||||||
@@ -614,6 +614,20 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
|||||||
current++;
|
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)) {
|
if (sIsAttrSet(FATTR4_SPACE_FREE, bitmap, bcount)) {
|
||||||
values[current].fAttribute = FATTR4_SPACE_FREE;
|
values[current].fAttribute = FATTR4_SPACE_FREE;
|
||||||
values[current].fData.fValue64 = stream.GetUHyper();
|
values[current].fData.fValue64 = stream.GetUHyper();
|
||||||
|
|||||||
@@ -776,6 +776,16 @@ RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr,
|
|||||||
i++;
|
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) {
|
if (i < count && attr[i].fAttribute == FATTR4_TIME_ACCESS_SET) {
|
||||||
str.AddInt(1); // SET_TO_CLIENT_TIME4
|
str.AddInt(1); // SET_TO_CLIENT_TIME4
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ ReadStream::GetUHyper()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
char*
|
||||||
ReadStream::GetString()
|
ReadStream::GetString()
|
||||||
{
|
{
|
||||||
if (_PositionToSize() >= fSize) {
|
if (_PositionToSize() >= fSize) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public:
|
|||||||
|
|
||||||
inline bool GetBoolean();
|
inline bool GetBoolean();
|
||||||
|
|
||||||
const char* GetString();
|
char* GetString();
|
||||||
|
|
||||||
const void* GetOpaque(uint32* size);
|
const void* GetOpaque(uint32* size);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, pdziepak@quarnos.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Haiku, Inc. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Paweł Dziepak, pdziepak@quarnos.org
|
||||||
|
*/
|
||||||
|
#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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
;
|
||||||
@@ -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"
|
||||||
|
};
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
#include "Filesystem.h"
|
#include "Filesystem.h"
|
||||||
|
#include "IdMap.h"
|
||||||
#include "Inode.h"
|
#include "Inode.h"
|
||||||
#include "NFS4Defs.h"
|
#include "NFS4Defs.h"
|
||||||
#include "RequestBuilder.h"
|
#include "RequestBuilder.h"
|
||||||
@@ -546,6 +547,13 @@ nfs4_init()
|
|||||||
gRPCServerManager = new(std::nothrow) RPC::ServerManager;
|
gRPCServerManager = new(std::nothrow) RPC::ServerManager;
|
||||||
if (gRPCServerManager == NULL)
|
if (gRPCServerManager == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
gIdMapper = new(std::nothrow) IdMap;
|
||||||
|
if (gIdMapper == NULL) {
|
||||||
|
delete gRPCServerManager;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,6 +563,7 @@ nfs4_uninit()
|
|||||||
{
|
{
|
||||||
dprintf("NFS4 Uninit\n");
|
dprintf("NFS4 Uninit\n");
|
||||||
|
|
||||||
|
delete gIdMapper;
|
||||||
delete gRPCServerManager;
|
delete gRPCServerManager;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user