Add group{add,del,mod}
This commit is contained in:
parent
dc3be29614
commit
519bb60aef
|
@ -14,7 +14,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures
|
|||
echo eject env error expand expr
|
||||
factor false fdinfo ffm filepanel find finddir FirstBootPrompt fmt fold
|
||||
fortune frcode ftp ftpd funzip fwcontrol
|
||||
gawk gdb@x86 getlimits groups gzip gzexe
|
||||
gawk gdb@x86 getlimits groupadd groupdel groupmod groups gzip gzexe
|
||||
hd head hey hostname
|
||||
id ident ifconfig <bin>install installsound iroster isvolume
|
||||
ideinfo@ide idestatus@ide
|
||||
|
|
|
@ -14,7 +14,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures
|
|||
echo eject env error expand expr
|
||||
factor false fdinfo ffm filepanel find finddir fmt fold
|
||||
fortune frcode ftp ftpd funzip
|
||||
gawk gdb@x86 getlimits groups gzip gzexe
|
||||
gawk gdb@x86 getlimits groupadd groupdel groupmod groups gzip gzexe
|
||||
hd head hey hostname
|
||||
id ident ifconfig <bin>install isvolume
|
||||
ideinfo@ide idestatus@ide
|
||||
|
|
|
@ -17,5 +17,11 @@ BinCommand useradd : useradd.cpp ;
|
|||
|
||||
BinCommand userdel : userdel.cpp ;
|
||||
|
||||
BinCommand groupadd : groupadd.cpp ;
|
||||
|
||||
BinCommand groupdel : groupdel.cpp ;
|
||||
|
||||
BinCommand groupmod : groupmod.cpp : $(TARGET_LIBSTDC++) ;
|
||||
|
||||
# set set-uid bit on passwd
|
||||
MODE on passwd = 04755 ;
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <grp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <RegistrarDefs.h>
|
||||
#include <user_group.h>
|
||||
#include <util/KMessage.h>
|
||||
|
||||
#include "multiuser_utils.h"
|
||||
|
||||
|
||||
extern const char *__progname;
|
||||
|
||||
|
||||
static const char* kUsage =
|
||||
"Usage: %s [ <options> ] <group name>\n"
|
||||
"Creates a new group <group name>.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help\n"
|
||||
" Print usage info.\n"
|
||||
;
|
||||
|
||||
static void
|
||||
print_usage_and_exit(bool error)
|
||||
{
|
||||
fprintf(error ? stderr : stdout, kUsage, __progname);
|
||||
exit(error ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char* const* argv)
|
||||
{
|
||||
while (true) {
|
||||
static struct option sLongOptions[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
opterr = 0; // don't print errors
|
||||
int c = getopt_long(argc, (char**)argv, "h", sLongOptions, NULL);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_usage_and_exit(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage_and_exit(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc - 1)
|
||||
print_usage_and_exit(true);
|
||||
|
||||
const char* group = argv[optind];
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "Error: Only root may add groups.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// check, if group already exists
|
||||
if (getgrnam(group) != NULL) {
|
||||
fprintf(stderr, "Error: Group \"%s\" already exists.\n", group);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// find an unused GID
|
||||
gid_t gid = 100;
|
||||
while (getgrgid(gid) != NULL)
|
||||
gid++;
|
||||
|
||||
// prepare request for the registrar
|
||||
KMessage message(BPrivate::B_REG_UPDATE_GROUP);
|
||||
if (message.AddInt32("gid", gid) != B_OK
|
||||
|| message.AddString("name", group) != B_OK
|
||||
|| message.AddString("password", "x") != B_OK
|
||||
|| message.AddBool("add group", true) != B_OK) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// send the request
|
||||
KMessage reply;
|
||||
status_t error = send_authentication_request_to_registrar(message, reply);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to create group: %s\n", strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <grp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <RegistrarDefs.h>
|
||||
#include <user_group.h>
|
||||
#include <util/KMessage.h>
|
||||
|
||||
#include "multiuser_utils.h"
|
||||
|
||||
|
||||
extern const char *__progname;
|
||||
|
||||
|
||||
static const char* kUsage =
|
||||
"Usage: %s [ <options> ] <group name>\n"
|
||||
"Deletes the specified group.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help\n"
|
||||
" Print usage info.\n"
|
||||
;
|
||||
|
||||
static void
|
||||
print_usage_and_exit(bool error)
|
||||
{
|
||||
fprintf(error ? stderr : stdout, kUsage, __progname);
|
||||
exit(error ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char* const* argv)
|
||||
{
|
||||
while (true) {
|
||||
static struct option sLongOptions[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
opterr = 0; // don't print errors
|
||||
int c = getopt_long(argc, (char**)argv, "h", sLongOptions, NULL);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_usage_and_exit(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage_and_exit(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc - 1)
|
||||
print_usage_and_exit(true);
|
||||
|
||||
const char* group = argv[optind];
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "Error: Only root may delete groups.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (getgrnam(group) == NULL) {
|
||||
fprintf(stderr, "Error: Group \"%s\" doesn't exists.\n", group);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// prepare request for the registrar
|
||||
KMessage message(BPrivate::B_REG_DELETE_GROUP);
|
||||
if (message.AddString("name", group) != B_OK) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// send the request
|
||||
KMessage reply;
|
||||
status_t error = send_authentication_request_to_registrar(message, reply);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to delete group: %s\n", strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <grp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <RegistrarDefs.h>
|
||||
#include <user_group.h>
|
||||
#include <util/KMessage.h>
|
||||
|
||||
#include "multiuser_utils.h"
|
||||
|
||||
|
||||
extern const char *__progname;
|
||||
|
||||
|
||||
static const char* kUsage =
|
||||
"Usage: %s [ <options> ] <group name>\n"
|
||||
"Creates a new group <group name>.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -A, --add-user <user>\n"
|
||||
" Add the user <user> to the group.\n"
|
||||
" -h, --help\n"
|
||||
" Print usage info.\n"
|
||||
" -R, --remove-user <user>\n"
|
||||
" Remove the user <user> from the group.\n"
|
||||
;
|
||||
|
||||
static void
|
||||
print_usage_and_exit(bool error)
|
||||
{
|
||||
fprintf(error ? stderr : stdout, kUsage, __progname);
|
||||
exit(error ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char* const* argv)
|
||||
{
|
||||
typedef std::set<std::string> StringSet;
|
||||
|
||||
StringSet usersToAdd;
|
||||
StringSet usersToRemove;
|
||||
|
||||
while (true) {
|
||||
static struct option sLongOptions[] = {
|
||||
{ "add-user", required_argument, 0, 'A' },
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "remove-user", required_argument, 0, 'A' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
opterr = 0; // don't print errors
|
||||
int c = getopt_long(argc, (char**)argv, "A:hR:", sLongOptions, NULL);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
|
||||
switch (c) {
|
||||
case 'A':
|
||||
usersToAdd.insert(optarg);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
print_usage_and_exit(false);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
usersToRemove.insert(optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage_and_exit(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc - 1)
|
||||
print_usage_and_exit(true);
|
||||
|
||||
const char* group = argv[optind];
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "Error: Only root may modify groups.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// get the group
|
||||
struct group* groupInfo = getgrnam(group);
|
||||
if (groupInfo == NULL) {
|
||||
fprintf(stderr, "Error: Group \"%s\" doesn't exist.\n", group);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// check, if anything needs to be done
|
||||
if (usersToAdd.empty() && usersToRemove.empty()) {
|
||||
fprintf(stderr, "Error: No modification specified.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// prepare request for the registrar
|
||||
KMessage message(BPrivate::B_REG_UPDATE_GROUP);
|
||||
if (message.AddInt32("gid", groupInfo->gr_gid) != B_OK
|
||||
|| message.AddString("name", group) != B_OK
|
||||
|| message.AddString("password", groupInfo->gr_passwd) != B_OK
|
||||
|| message.AddBool("add group", false) != B_OK) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int32 i = 0; const char* user = groupInfo->gr_mem[i]; i++) {
|
||||
if (usersToRemove.erase(user) > 0)
|
||||
continue;
|
||||
|
||||
usersToAdd.insert(user);
|
||||
}
|
||||
|
||||
if (!usersToRemove.empty()) {
|
||||
fprintf(stderr, "Error: \"%s\" is not a member of group \"%s\"\n",
|
||||
usersToRemove.begin()->c_str(), group);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// If the group doesn't have any more members, insert an empty string as an
|
||||
// indicator for the registrar to remove all members.
|
||||
if (usersToAdd.empty())
|
||||
usersToAdd.insert("");
|
||||
|
||||
for (StringSet::const_iterator it = usersToAdd.begin();
|
||||
it != usersToAdd.end(); ++it) {
|
||||
if (message.AddString("members", it->c_str()) != B_OK) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// send the request
|
||||
KMessage reply;
|
||||
status_t error = send_authentication_request_to_registrar(message, reply);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to create group: %s\n", strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -12,9 +12,11 @@
|
|||
|
||||
#include <map>
|
||||
#include <new>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <DataIO.h>
|
||||
#include <StringList.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <RegistrarDefs.h>
|
||||
|
@ -30,6 +32,9 @@ using std::string;
|
|||
using namespace BPrivate;
|
||||
|
||||
|
||||
typedef std::set<std::string> StringSet;
|
||||
|
||||
|
||||
class AuthenticationManager::FlatStore {
|
||||
public:
|
||||
FlatStore()
|
||||
|
@ -337,22 +342,29 @@ private:
|
|||
|
||||
class AuthenticationManager::Group {
|
||||
public:
|
||||
Group()
|
||||
:
|
||||
fGID(0),
|
||||
fName(),
|
||||
fPassword(),
|
||||
fMembers()
|
||||
{
|
||||
}
|
||||
|
||||
Group(const char* name, const char* password, gid_t gid,
|
||||
const char* const* members, int memberCount)
|
||||
:
|
||||
fGID(gid),
|
||||
fName(name),
|
||||
fPassword(password),
|
||||
fMembers(new string[memberCount]),
|
||||
fMemberCount(memberCount)
|
||||
fMembers()
|
||||
{
|
||||
for (int i = 0; i < memberCount; i++)
|
||||
fMembers[i] = members[i];
|
||||
fMembers.insert(members[i]);
|
||||
}
|
||||
|
||||
~Group()
|
||||
{
|
||||
delete[] fMembers;
|
||||
}
|
||||
|
||||
const string& Name() const { return fName; }
|
||||
|
@ -360,12 +372,40 @@ public:
|
|||
|
||||
bool HasMember(const char* name)
|
||||
{
|
||||
for (int i = 0; i < fMemberCount; i++) {
|
||||
if (fMembers[i] == name)
|
||||
return true;
|
||||
try {
|
||||
return fMembers.find(name) != fMembers.end();
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
bool MemberRemoved(const std::string& name)
|
||||
{
|
||||
return fMembers.erase(name) > 0;
|
||||
}
|
||||
|
||||
void UpdateFromMessage(const KMessage& message)
|
||||
{
|
||||
int32 intValue;
|
||||
if (message.FindInt32("gid", &intValue) == B_OK)
|
||||
fGID = intValue;
|
||||
|
||||
const char* stringValue;
|
||||
if (message.FindString("name", &stringValue) == B_OK)
|
||||
fName = stringValue;
|
||||
|
||||
if (message.FindString("password", &stringValue) == B_OK)
|
||||
fPassword = stringValue;
|
||||
|
||||
if (message.FindString("members", &stringValue) == B_OK) {
|
||||
fMembers.clear();
|
||||
for (int32 i = 0;
|
||||
(stringValue = message.GetString("members", i, NULL)) != NULL;
|
||||
i++) {
|
||||
if (stringValue != NULL && *stringValue != '\0')
|
||||
fMembers.insert(stringValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group* WriteFlatGroup(FlatStore& store) const
|
||||
|
@ -373,15 +413,18 @@ public:
|
|||
struct group group;
|
||||
|
||||
char* members[MAX_GROUP_MEMBER_COUNT + 1];
|
||||
for (int i = 0; i < fMemberCount; i++)
|
||||
members[i] = store.AppendString(fMembers[i].c_str());
|
||||
members[fMemberCount] = (char*)-1;
|
||||
int32 count = 0;
|
||||
for (StringSet::const_iterator it = fMembers.begin();
|
||||
it != fMembers.end(); ++it) {
|
||||
members[count++] = store.AppendString(it->c_str());
|
||||
}
|
||||
members[count] = (char*)-1;
|
||||
|
||||
group.gr_gid = fGID;
|
||||
group.gr_name = store.AppendString(fName);
|
||||
group.gr_passwd = store.AppendString(fPassword);
|
||||
group.gr_mem = (char**)store.AppendData(members,
|
||||
sizeof(char*) * (fMemberCount + 1), true);
|
||||
sizeof(char*) * (count + 1), true);
|
||||
|
||||
return store.AppendData(group);
|
||||
}
|
||||
|
@ -396,22 +439,34 @@ public:
|
|||
return error;
|
||||
}
|
||||
|
||||
for (int i = 0; i < fMemberCount; i++) {
|
||||
if ((error = message.AddString("members", fMembers[i].c_str()))
|
||||
!= B_OK) {
|
||||
for (StringSet::const_iterator it = fMembers.begin();
|
||||
it != fMembers.end(); ++it) {
|
||||
if ((error = message.AddString("members", it->c_str())) != B_OK)
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void WriteGroupLine(FILE* file)
|
||||
{
|
||||
fprintf(file, "%s:%s:%d:",
|
||||
fName.c_str(), fPassword.c_str(), (int)fGID);
|
||||
for (StringSet::const_iterator it = fMembers.begin();
|
||||
it != fMembers.end(); ++it) {
|
||||
if (it == fMembers.begin())
|
||||
fprintf(file, "%s", it->c_str());
|
||||
else
|
||||
fprintf(file, ",%s", it->c_str());
|
||||
}
|
||||
fputs("\n", file);
|
||||
}
|
||||
|
||||
private:
|
||||
gid_t fGID;
|
||||
string fName;
|
||||
string fPassword;
|
||||
string* fMembers;
|
||||
int fMemberCount;
|
||||
gid_t fGID;
|
||||
string fName;
|
||||
string fPassword;
|
||||
StringSet fMembers;
|
||||
};
|
||||
|
||||
|
||||
|
@ -555,6 +610,23 @@ public:
|
|||
return B_OK;
|
||||
}
|
||||
|
||||
void RemoveGroup(Group* group)
|
||||
{
|
||||
fGroupsByID.erase(fGroupsByID.find(group->GID()));
|
||||
fGroupsByName.erase(fGroupsByName.find(group->Name()));
|
||||
}
|
||||
|
||||
bool UserRemoved(const std::string& user)
|
||||
{
|
||||
bool changed = false;
|
||||
for (map<gid_t, Group*>::const_iterator it = fGroupsByID.begin();
|
||||
it != fGroupsByID.end(); ++it) {
|
||||
Group* group = it->second;
|
||||
changed |= group->MemberRemoved(user);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
Group* GroupByID(gid_t gid) const
|
||||
{
|
||||
map<gid_t, Group*>::const_iterator it = fGroupsByID.find(gid);
|
||||
|
@ -605,6 +677,31 @@ public:
|
|||
return count;
|
||||
}
|
||||
|
||||
void WriteToDisk()
|
||||
{
|
||||
// rename the old files
|
||||
string groupBackup(kGroupFile);
|
||||
groupBackup += ".old";
|
||||
|
||||
rename(kGroupFile, groupBackup.c_str());
|
||||
// Don't check errors. We can't do anything anyway.
|
||||
|
||||
// open file
|
||||
FILE* groupFile = fopen(kGroupFile, "w");
|
||||
if (groupFile == NULL) {
|
||||
debug_printf("REG: Failed to open group file \"%s\" for "
|
||||
"writing: %s\n", kGroupFile, strerror(errno));
|
||||
}
|
||||
CObjectDeleter<FILE, int> _1(groupFile, fclose);
|
||||
|
||||
// write groups
|
||||
for (map<gid_t, Group*>::const_iterator it = fGroupsByID.begin();
|
||||
it != fGroupsByID.end(); ++it) {
|
||||
Group* group = it->second;
|
||||
group->WriteGroupLine(groupFile);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
map<uid_t, Group*> fGroupsByID;
|
||||
map<string, Group*> fGroupsByName;
|
||||
|
@ -1002,10 +1099,17 @@ AuthenticationManager::_RequestThread()
|
|||
|
||||
// apply the change
|
||||
if (error == B_OK) {
|
||||
std::string userName = user->Name();
|
||||
|
||||
fUserDB->RemoveUser(user);
|
||||
fUserDB->WriteToDisk();
|
||||
_InvalidatePasswdDBReply();
|
||||
_InvalidateShadowPwdDBReply();
|
||||
|
||||
if (fGroupDB->UserRemoved(userName)) {
|
||||
fGroupDB->WriteToDisk();
|
||||
_InvalidateGroupDBReply();
|
||||
}
|
||||
}
|
||||
|
||||
// send reply
|
||||
|
@ -1017,13 +1121,110 @@ AuthenticationManager::_RequestThread()
|
|||
}
|
||||
|
||||
case B_REG_UPDATE_GROUP:
|
||||
debug_printf("B_REG_UPDATE_GROUP done: currently unsupported!\n");
|
||||
{
|
||||
// find group
|
||||
Group* group = NULL;
|
||||
int32 gid;
|
||||
const char* name;
|
||||
|
||||
if (message.FindInt32("gid", &gid) == B_OK) {
|
||||
group = fGroupDB->GroupByID(gid);
|
||||
} else if (message.FindString("name", &name) == B_OK) {
|
||||
group = fGroupDB->GroupByName(name);
|
||||
} else {
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// only root can change anything
|
||||
if (error == B_OK && !isRoot)
|
||||
error = EPERM;
|
||||
|
||||
// check addGroup vs. existing group
|
||||
bool addGroup = message.GetBool("add group", false);
|
||||
if (error == B_OK) {
|
||||
if (addGroup) {
|
||||
if (group != NULL)
|
||||
error = EEXIST;
|
||||
} else if (group == NULL)
|
||||
error = ENOENT;
|
||||
}
|
||||
|
||||
// apply all changes
|
||||
if (error == B_OK) {
|
||||
// clone the group object and update it from the message
|
||||
Group* oldGroup = group;
|
||||
group = NULL;
|
||||
try {
|
||||
group = (oldGroup != NULL ? new Group(*oldGroup)
|
||||
: new Group);
|
||||
group->UpdateFromMessage(message);
|
||||
|
||||
// gid and name should remain the same
|
||||
if (oldGroup != NULL) {
|
||||
if (oldGroup->GID() != group->GID()
|
||||
|| oldGroup->Name() != group->Name()) {
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// replace the old group and write DBs to disk
|
||||
if (error == B_OK) {
|
||||
fGroupDB->AddGroup(group);
|
||||
fGroupDB->WriteToDisk();
|
||||
_InvalidateGroupDBReply();
|
||||
}
|
||||
} catch (...) {
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (error == B_OK)
|
||||
delete oldGroup;
|
||||
else
|
||||
delete group;
|
||||
}
|
||||
|
||||
// send reply
|
||||
KMessage reply;
|
||||
reply.SetWhat(error);
|
||||
message.SendReply(&reply, -1, -1, 0, registrarTeam);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case B_REG_DELETE_GROUP:
|
||||
{
|
||||
debug_printf(
|
||||
"B_REG_DELETE_GROUP done: currently unsupported!\n");
|
||||
// find group
|
||||
Group* group = NULL;
|
||||
int32 gid;
|
||||
const char* name;
|
||||
|
||||
if (message.FindInt32("gid", &gid) == B_OK) {
|
||||
group = fGroupDB->GroupByID(gid);
|
||||
} else if (message.FindString("name", &name) == B_OK) {
|
||||
group = fGroupDB->GroupByName(name);
|
||||
} else {
|
||||
error = B_BAD_VALUE;
|
||||
}
|
||||
|
||||
if (error == B_OK && group == NULL)
|
||||
error = ENOENT;
|
||||
|
||||
// only root can change anything
|
||||
if (error == B_OK && !isRoot)
|
||||
error = EPERM;
|
||||
|
||||
// apply the change
|
||||
if (error == B_OK) {
|
||||
fGroupDB->RemoveGroup(group);
|
||||
fGroupDB->WriteToDisk();
|
||||
_InvalidateGroupDBReply();
|
||||
}
|
||||
|
||||
// send reply
|
||||
KMessage reply;
|
||||
reply.SetWhat(error);
|
||||
message.SendReply(&reply, -1, -1, 0, registrarTeam);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue