btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / src / add-ons / kernel / file_systems / nfs4 / IdMap.cpp
bloba779469eb7b42e706f9e3c3e001a72837b6f0286
1 /*
2 * Copyright 2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Paweł Dziepak, pdziepak@quarnos.org
7 */
10 #include "IdMap.h"
12 #include <AutoDeleter.h>
13 #include <FindDirectory.h>
14 #include <team.h>
15 #include <util/AutoLock.h>
17 #include "idmapper/IdMapper.h"
20 IdMap* gIdMapper = NULL;
21 mutex gIdMapperLock;
24 IdMap::IdMap()
26 mutex_init(&fLock, NULL);
27 fInitStatus = _Repair();
31 IdMap::~IdMap()
33 delete_port(fRequestPort);
34 delete_port(fReplyPort);
35 mutex_destroy(&fLock);
39 uid_t
40 IdMap::GetUserId(const char* owner)
42 ASSERT(owner != NULL);
43 return _GetValue<uid_t>(owner, MsgNameToUID);
47 gid_t
48 IdMap::GetGroupId(const char* ownerGroup)
50 ASSERT(ownerGroup != NULL);
51 return _GetValue<gid_t>(ownerGroup, MsgNameToGID);
55 char*
56 IdMap::GetOwner(uid_t user)
58 return reinterpret_cast<char*>(_GetBuffer(user, MsgUIDToName));
62 char*
63 IdMap::GetOwnerGroup(gid_t group)
65 return reinterpret_cast<char*>(_GetBuffer(group, MsgGIDToName));
69 template<typename T>
71 IdMap::_GetValue(const char* buffer, int32 code)
73 ASSERT(buffer != NULL);
75 MutexLocker _(fLock);
76 do {
77 status_t result = write_port(fRequestPort, MsgNameToUID, buffer,
78 strlen(buffer) + 1);
79 if (result != B_OK) {
80 if (_Repair() != B_OK)
81 return 0;
82 continue;
85 int32 code;
86 T value;
87 result = read_port(fReplyPort, &code, &value, sizeof(T));
88 if (result < B_OK) {
89 if (_Repair() != B_OK)
90 return 0;
91 continue;
94 if (code != MsgReply)
95 return 0;
97 return value;
98 } while (true);
102 template<typename T>
103 void*
104 IdMap::_GetBuffer(T value, int32 code)
106 MutexLocker _(fLock);
107 do {
108 status_t result = write_port(fRequestPort, code, &value, sizeof(value));
109 if (result != B_OK) {
110 if (_Repair() != B_OK)
111 return NULL;
112 continue;
115 ssize_t size = port_buffer_size(fReplyPort);
116 if (size < B_OK) {
117 if (_Repair() != B_OK)
118 return NULL;
119 continue;
122 int32 code;
123 void* buffer = malloc(size);
124 if (buffer == NULL)
125 return NULL;
126 MemoryDeleter bufferDeleter(buffer);
128 size = read_port(fReplyPort, &code, buffer, size);
129 if (size < B_OK) {
130 if (_Repair() != B_OK)
131 return 0;
132 continue;
135 if (code != MsgReply)
136 return NULL;
138 bufferDeleter.Detach();
139 return buffer;
140 } while (true);
144 status_t
145 IdMap::_Repair()
147 status_t result = B_OK;
149 fRequestPort = create_port(1, kRequestPortName);
150 if (fRequestPort < B_OK)
151 return fRequestPort;
153 fReplyPort = create_port(1, kReplyPortName);
154 if (fReplyPort < B_OK) {
155 delete_port(fRequestPort);
156 return fReplyPort;
159 char path[256];
160 if (find_directory(B_SYSTEM_SERVERS_DIRECTORY, static_cast<dev_t>(-1),
161 false, path, sizeof(path)) != B_OK) {
162 delete_port(fReplyPort);
163 delete_port(fRequestPort);
164 return B_NAME_NOT_FOUND;
166 strlcat(path, "/nfs4_idmapper_server", sizeof(path));
168 const char* args[] = { path, NULL };
169 thread_id thread = load_image_etc(1, args, NULL, B_NORMAL_PRIORITY,
170 B_SYSTEM_TEAM, 0);
171 if (thread < B_OK) {
172 delete_port(fReplyPort);
173 delete_port(fRequestPort);
174 return thread;
177 set_port_owner(fRequestPort, thread);
178 set_port_owner(fReplyPort, thread);
180 result = resume_thread(thread);
181 if (result != B_OK) {
182 kill_thread(thread);
183 delete_port(fReplyPort);
184 delete_port(fRequestPort);
185 return result;
188 return B_OK;