2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
16 #include <errno_private.h>
17 #include <libroot_private.h>
18 #include <RegistrarDefs.h>
19 #include <user_group.h>
21 #include <util/KMessage.h>
24 using BPrivate::UserGroupLocker
;
25 using BPrivate::relocate_pointer
;
28 static KMessage sGroupDBReply
;
29 static group
** sGroupEntries
= NULL
;
30 static size_t sGroupEntryCount
= 0;
31 static size_t sIterationIndex
= 0;
33 static struct group sGroupBuffer
;
34 static char sGroupStringBuffer
[MAX_GROUP_BUFFER_SIZE
];
38 query_group_entry(const char* name
, gid_t _gid
, struct group
*group
,
39 char *buffer
, size_t bufferSize
, struct group
**_result
)
43 KMessage
message(BPrivate::B_REG_GET_GROUP
);
45 message
.AddString("name", name
);
47 message
.AddInt32("gid", _gid
);
50 status_t error
= BPrivate::send_authentication_request_to_registrar(message
,
53 return error
== ENOENT
? B_OK
: error
;
59 if ((error
= reply
.FindInt32("gid", &gid
)) != B_OK
60 || (error
= reply
.FindString("name", &name
)) != B_OK
61 || (error
= reply
.FindString("password", &password
)) != B_OK
) {
65 const char* members
[MAX_GROUP_MEMBER_COUNT
];
67 for (int32 index
= 0; memberCount
< MAX_GROUP_MEMBER_COUNT
; index
++) {
68 if (reply
.FindString("members", index
, members
+ memberCount
) != B_OK
)
73 error
= BPrivate::copy_group_to_buffer(name
, password
, gid
, members
,
74 memberCount
, group
, buffer
, bufferSize
);
85 if (sGroupEntries
!= NULL
)
89 KMessage
message(BPrivate::B_REG_GET_GROUP_DB
);
90 status_t error
= BPrivate::send_authentication_request_to_registrar(message
,
99 if ((error
= sGroupDBReply
.FindInt32("count", &count
)) != B_OK
100 || (error
= sGroupDBReply
.FindData("entries", B_RAW_TYPE
,
101 (const void**)&entries
, &numBytes
)) != B_OK
) {
105 // relocate the entries
106 addr_t baseAddress
= (addr_t
)entries
;
107 for (int32 i
= 0; i
< count
; i
++) {
108 group
* entry
= relocate_pointer(baseAddress
, entries
[i
]);
109 relocate_pointer(baseAddress
, entry
->gr_name
);
110 relocate_pointer(baseAddress
, entry
->gr_passwd
);
111 relocate_pointer(baseAddress
, entry
->gr_mem
);
113 for (; entry
->gr_mem
[k
] != (void*)-1; k
++)
114 relocate_pointer(baseAddress
, entry
->gr_mem
[k
]);
115 entry
->gr_mem
[k
] = NULL
;
118 sGroupEntries
= entries
;
119 sGroupEntryCount
= count
;
131 struct group
* result
= NULL
;
132 int status
= getgrent_r(&sGroupBuffer
, sGroupStringBuffer
,
133 sizeof(sGroupStringBuffer
), &result
);
141 getgrent_r(struct group
* group
, char* buffer
, size_t bufferSize
,
142 struct group
** _result
)
146 int status
= B_NO_MEMORY
;
150 if ((status
= init_group_db()) == B_OK
) {
151 if (sIterationIndex
>= sGroupEntryCount
)
154 status
= BPrivate::copy_group_to_buffer(
155 sGroupEntries
[sIterationIndex
], group
, buffer
, bufferSize
);
157 if (status
== B_OK
) {
179 UserGroupLocker locker
;
181 sGroupDBReply
.Unset();
182 sGroupEntries
= NULL
;
183 sGroupEntryCount
= 0;
189 getgrnam(const char *name
)
191 struct group
* result
= NULL
;
192 int status
= getgrnam_r(name
, &sGroupBuffer
, sGroupStringBuffer
,
193 sizeof(sGroupStringBuffer
), &result
);
201 getgrnam_r(const char *name
, struct group
*group
, char *buffer
,
202 size_t bufferSize
, struct group
**_result
)
204 return query_group_entry(name
, 0, group
, buffer
, bufferSize
, _result
);
211 struct group
* result
= NULL
;
212 int status
= getgrgid_r(gid
, &sGroupBuffer
, sGroupStringBuffer
,
213 sizeof(sGroupStringBuffer
), &result
);
221 getgrgid_r(gid_t gid
, struct group
*group
, char *buffer
,
222 size_t bufferSize
, struct group
**_result
)
224 return query_group_entry(NULL
, gid
, group
, buffer
, bufferSize
, _result
);
229 getgrouplist(const char* user
, gid_t baseGroup
, gid_t
* groupList
,
232 int maxGroupCount
= *groupCount
;
235 status_t error
= B_OK
;
238 KMessage
message(BPrivate::B_REG_GET_USER_GROUPS
);
239 if (message
.AddString("name", user
) != B_OK
240 || message
.AddInt32("max count", maxGroupCount
) != B_OK
) {
246 error
= BPrivate::send_authentication_request_to_registrar(message
, reply
);
254 if (reply
.FindInt32("count", &count
) != B_OK
255 || reply
.FindData("groups", B_INT32_TYPE
, (const void**)&groups
,
256 &groupsSize
) != B_OK
) {
260 memcpy(groupList
, groups
, groupsSize
);
263 // add the base group
264 if (*groupCount
< maxGroupCount
)
265 groupList
[*groupCount
] = baseGroup
;
268 return *groupCount
<= maxGroupCount
? *groupCount
: -1;
273 initgroups(const char* user
, gid_t baseGroup
)
275 gid_t groups
[NGROUPS_MAX
+ 1];
276 int groupCount
= NGROUPS_MAX
+ 1;
277 if (getgrouplist(user
, baseGroup
, groups
, &groupCount
) < 0)
280 return setgroups(groupCount
, groups
);