hpkg format: Add attributes for declaring users and groups
This commit is contained in:
parent
c82776b2fa
commit
0f4e11e75c
1
headers/build/os/package/User.h
Normal file
1
headers/build/os/package/User.h
Normal file
@ -0,0 +1 @@
|
||||
#include <../os/package/User.h>
|
@ -18,6 +18,7 @@
|
||||
#include <package/PackageResolvable.h>
|
||||
#include <package/PackageResolvableExpression.h>
|
||||
#include <package/PackageVersion.h>
|
||||
#include <package/User.h>
|
||||
#include <package/UserSettingsFileInfo.h>
|
||||
|
||||
|
||||
@ -86,6 +87,9 @@ public:
|
||||
const BObjectList<BUserSettingsFileInfo>&
|
||||
UserSettingsFileInfos() const;
|
||||
|
||||
const BObjectList<BUser>& Users() const;
|
||||
const BStringList& Groups() const;
|
||||
|
||||
const BObjectList<BPackageResolvable>& ProvidesList() const;
|
||||
const BObjectList<BPackageResolvableExpression>&
|
||||
RequiresList() const;
|
||||
@ -135,6 +139,12 @@ public:
|
||||
status_t AddUserSettingsFileInfo(
|
||||
const BUserSettingsFileInfo& info);
|
||||
|
||||
void ClearUsers();
|
||||
status_t AddUser(const BUser& user);
|
||||
|
||||
void ClearGroups();
|
||||
status_t AddGroup(const BString& group);
|
||||
|
||||
void ClearProvidesList();
|
||||
status_t AddProvides(const BPackageResolvable& provides);
|
||||
|
||||
@ -196,6 +206,8 @@ private:
|
||||
typedef BObjectList<BUserSettingsFileInfo>
|
||||
UserSettingsFileInfoList;
|
||||
|
||||
typedef BObjectList<BUser> UserList;
|
||||
|
||||
private:
|
||||
status_t _ReadFromPackageFile(
|
||||
const PackageFileLocation& fileLocation);
|
||||
@ -218,6 +230,8 @@ private:
|
||||
const char* field,
|
||||
const UserSettingsFileInfoList&
|
||||
infos);
|
||||
static status_t _AddUsers(BMessage* archive, const char* field,
|
||||
const UserList& users);
|
||||
|
||||
static status_t _ExtractVersion(BMessage* archive,
|
||||
const char* field, int32 index,
|
||||
@ -236,6 +250,8 @@ private:
|
||||
static status_t _ExtractUserSettingsFileInfos(
|
||||
BMessage* archive, const char* field,
|
||||
UserSettingsFileInfoList& _infos);
|
||||
static status_t _ExtractUsers(BMessage* archive,
|
||||
const char* field, UserList& _users);
|
||||
|
||||
private:
|
||||
BString fName;
|
||||
@ -259,6 +275,9 @@ private:
|
||||
BObjectList<BGlobalSettingsFileInfo> fGlobalSettingsFileInfos;
|
||||
BObjectList<BUserSettingsFileInfo> fUserSettingsFileInfos;
|
||||
|
||||
UserList fUsers;
|
||||
BStringList fGroups;
|
||||
|
||||
ResolvableList fProvidesList;
|
||||
|
||||
ResolvableExpressionList fRequiresList;
|
||||
|
@ -45,6 +45,10 @@ enum BPackageInfoAttributeID {
|
||||
// list of global settings file infos
|
||||
B_PACKAGE_INFO_USER_SETTINGS_FILES,
|
||||
// list of user settings file infos
|
||||
B_PACKAGE_INFO_USERS,
|
||||
// list of (Unix) users defined/needed
|
||||
B_PACKAGE_INFO_GROUPS,
|
||||
// list of (Unix) groups defined/needed
|
||||
//
|
||||
B_PACKAGE_INFO_ENUM_COUNT,
|
||||
};
|
||||
|
52
headers/os/package/User.h
Normal file
52
headers/os/package/User.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2013, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _PACKAGE__USER_H_
|
||||
#define _PACKAGE__USER_H_
|
||||
|
||||
|
||||
#include <String.h>
|
||||
#include <StringList.h>
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
|
||||
|
||||
class BUser {
|
||||
public:
|
||||
BUser();
|
||||
BUser(const BString& name,
|
||||
const BString& realName,
|
||||
const BString& home, const BString& shell,
|
||||
const BStringList& groups);
|
||||
~BUser();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
const BString& Name() const;
|
||||
const BString& RealName() const;
|
||||
const BString& Home() const;
|
||||
const BString& Shell() const;
|
||||
const BStringList& Groups() const;
|
||||
|
||||
status_t SetTo(const BString& name,
|
||||
const BString& realName,
|
||||
const BString& home, const BString& shell,
|
||||
const BStringList& groups);
|
||||
|
||||
static bool IsValidUserName(const char* name);
|
||||
|
||||
private:
|
||||
BString fName;
|
||||
BString fRealName;
|
||||
BString fHome;
|
||||
BString fShell;
|
||||
BStringList fGroups;
|
||||
};
|
||||
|
||||
|
||||
} // namespace BPackageKit
|
||||
|
||||
|
||||
#endif // _PACKAGE__USER_H_
|
@ -70,3 +70,10 @@ B_DEFINE_HPKG_ATTRIBUTE(44, UINT, "package:settings-file-update-type",
|
||||
PACKAGE_SETTINGS_FILE_UPDATE_TYPE)
|
||||
B_DEFINE_HPKG_ATTRIBUTE(45, STRING, "package:settings-file-template",
|
||||
PACKAGE_SETTINGS_FILE_TEMPLATE)
|
||||
B_DEFINE_HPKG_ATTRIBUTE(46, STRING, "package:user", PACKAGE_USER)
|
||||
B_DEFINE_HPKG_ATTRIBUTE(47, STRING, "package:user.real-name",
|
||||
PACKAGE_USER_REAL_NAME)
|
||||
B_DEFINE_HPKG_ATTRIBUTE(48, STRING, "package:user.home", PACKAGE_USER_HOME)
|
||||
B_DEFINE_HPKG_ATTRIBUTE(49, STRING, "package:user.shell", PACKAGE_USER_SHELL)
|
||||
B_DEFINE_HPKG_ATTRIBUTE(50, STRING, "package:user.group", PACKAGE_USER_GROUP)
|
||||
B_DEFINE_HPKG_ATTRIBUTE(51, STRING, "package:group", PACKAGE_GROUP)
|
||||
|
@ -59,6 +59,16 @@ struct BUserSettingsFileInfoData {
|
||||
};
|
||||
|
||||
|
||||
struct BUserData {
|
||||
const char* name;
|
||||
const char* realName;
|
||||
const char* home;
|
||||
const char* shell;
|
||||
const char* const* groups;
|
||||
size_t groupCount;
|
||||
};
|
||||
|
||||
|
||||
struct BPackageInfoAttributeValue {
|
||||
union {
|
||||
uint64 unsignedInt;
|
||||
@ -68,6 +78,7 @@ struct BPackageInfoAttributeValue {
|
||||
BPackageResolvableExpressionData resolvableExpression;
|
||||
BGlobalSettingsFileInfoData globalSettingsFileInfo;
|
||||
BUserSettingsFileInfoData userSettingsFileInfo;
|
||||
BUserData user;
|
||||
};
|
||||
BPackageInfoAttributeID attributeID;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <ByteOrder.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <Array.h>
|
||||
#include <util/SinglyLinkedList.h>
|
||||
|
||||
#include <package/hpkg/ErrorOutput.h>
|
||||
@ -103,6 +104,7 @@ protected:
|
||||
class PackageResolvableExpressionAttributeHandler;
|
||||
class GlobalSettingsFileInfoAttributeHandler;
|
||||
class UserSettingsFileInfoAttributeHandler;
|
||||
class UserAttributeHandler;
|
||||
class PackageAttributeHandler;
|
||||
class LowLevelAttributeHandler;
|
||||
|
||||
@ -344,6 +346,25 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ReaderImplBase::UserAttributeHandler
|
||||
: public PackageInfoAttributeHandlerBase {
|
||||
public:
|
||||
UserAttributeHandler(
|
||||
BPackageInfoAttributeValue&
|
||||
packageInfoValue);
|
||||
|
||||
virtual status_t HandleAttribute(
|
||||
AttributeHandlerContext* context, uint8 id,
|
||||
const AttributeValue& value,
|
||||
AttributeHandler** _handler);
|
||||
|
||||
virtual status_t Delete(AttributeHandlerContext* context);
|
||||
|
||||
private:
|
||||
Array<const char*> fGroups;
|
||||
};
|
||||
|
||||
|
||||
class ReaderImplBase::PackageAttributeHandler : public AttributeHandler {
|
||||
public:
|
||||
virtual status_t HandleAttribute(
|
||||
|
@ -163,6 +163,12 @@ private:
|
||||
= B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR;
|
||||
|
||||
private:
|
||||
PackageAttribute* _AddStringAttribute(BHPKGAttributeID id,
|
||||
const BString& value,
|
||||
DoublyLinkedList<PackageAttribute>& list);
|
||||
inline PackageAttribute* _AddStringAttributeIfNotEmpty(
|
||||
BHPKGAttributeID id, const BString& value,
|
||||
DoublyLinkedList<PackageAttribute>& list);
|
||||
void _WritePackageAttributes(
|
||||
const PackageAttributeList& attributes);
|
||||
|
||||
@ -252,6 +258,16 @@ WriterImplBase::SetFinished(bool finished)
|
||||
}
|
||||
|
||||
|
||||
inline WriterImplBase::PackageAttribute*
|
||||
WriterImplBase::_AddStringAttributeIfNotEmpty(BHPKGAttributeID id,
|
||||
const BString& value, DoublyLinkedList<PackageAttribute>& list)
|
||||
{
|
||||
if (value.IsEmpty())
|
||||
return NULL;
|
||||
return _AddStringAttribute(id, value, list);
|
||||
}
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
} // namespace BHPKG
|
||||
|
@ -310,6 +310,22 @@ struct PackageContentListHandler : VersionPolicy::PackageContentHandler {
|
||||
printf("\n");
|
||||
break;
|
||||
|
||||
case B_PACKAGE_INFO_USERS:
|
||||
printf("\tuser: %s\n", value.user.name);
|
||||
if (value.user.realName != NULL)
|
||||
printf("\t\treal name: %s\n", value.user.realName);
|
||||
if (value.user.home != NULL)
|
||||
printf("\t\thome: %s\n", value.user.home);
|
||||
if (value.user.shell != NULL)
|
||||
printf("\t\tshell: %s\n", value.user.shell);
|
||||
for (size_t i = 0; i < value.user.groupCount; i++)
|
||||
printf("\t\tgroup: %s\n", value.user.groups[i]);
|
||||
break;
|
||||
|
||||
case B_PACKAGE_INFO_GROUPS:
|
||||
printf("\tgroup: %s\n", value.string);
|
||||
break;
|
||||
|
||||
case B_PACKAGE_INFO_INSTALL_PATH:
|
||||
printf("\tinstall path: %s\n", value.string);
|
||||
break;
|
||||
|
@ -105,6 +105,7 @@ BuildPlatformSharedLibrary libpackage_build.so
|
||||
RepositoryInfo.cpp
|
||||
Request.cpp
|
||||
TempfileManager.cpp
|
||||
User.cpp
|
||||
ValidateChecksumJob.cpp
|
||||
|
||||
$(HPKG_SOURCES)
|
||||
|
@ -97,6 +97,7 @@ SharedLibrary libpackage.so
|
||||
RepositoryInfo.cpp
|
||||
Request.cpp
|
||||
TempfileManager.cpp
|
||||
User.cpp
|
||||
ValidateChecksumJob.cpp
|
||||
|
||||
$(HPKG_SOURCES)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -52,6 +53,8 @@ const char* const BPackageInfo::kElementNames[B_PACKAGE_INFO_ENUM_COUNT] = {
|
||||
"base-package",
|
||||
"global-settings-files",
|
||||
"user-settings-files",
|
||||
"users",
|
||||
"groups"
|
||||
};
|
||||
|
||||
|
||||
@ -160,18 +163,20 @@ BPackageInfo::BPackageInfo()
|
||||
BArchivable(),
|
||||
fFlags(0),
|
||||
fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT),
|
||||
fCopyrightList(5),
|
||||
fLicenseList(5),
|
||||
fURLList(5),
|
||||
fSourceURLList(5),
|
||||
fGlobalSettingsFileInfos(5, true),
|
||||
fUserSettingsFileInfos(5, true),
|
||||
fCopyrightList(4),
|
||||
fLicenseList(4),
|
||||
fURLList(4),
|
||||
fSourceURLList(4),
|
||||
fGlobalSettingsFileInfos(4, true),
|
||||
fUserSettingsFileInfos(4, true),
|
||||
fUsers(4, true),
|
||||
fGroups(4),
|
||||
fProvidesList(20, true),
|
||||
fRequiresList(20, true),
|
||||
fSupplementsList(20, true),
|
||||
fConflictsList(5, true),
|
||||
fFreshensList(5, true),
|
||||
fReplacesList(5)
|
||||
fConflictsList(4, true),
|
||||
fFreshensList(4, true),
|
||||
fReplacesList(4)
|
||||
{
|
||||
}
|
||||
|
||||
@ -181,18 +186,20 @@ BPackageInfo::BPackageInfo(BMessage* archive, status_t* _error)
|
||||
BArchivable(archive),
|
||||
fFlags(0),
|
||||
fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT),
|
||||
fCopyrightList(5),
|
||||
fLicenseList(5),
|
||||
fURLList(5),
|
||||
fSourceURLList(5),
|
||||
fGlobalSettingsFileInfos(5, true),
|
||||
fUserSettingsFileInfos(5, true),
|
||||
fCopyrightList(4),
|
||||
fLicenseList(4),
|
||||
fURLList(4),
|
||||
fSourceURLList(4),
|
||||
fGlobalSettingsFileInfos(4, true),
|
||||
fUserSettingsFileInfos(4, true),
|
||||
fUsers(4, true),
|
||||
fGroups(4),
|
||||
fProvidesList(20, true),
|
||||
fRequiresList(20, true),
|
||||
fSupplementsList(20, true),
|
||||
fConflictsList(5, true),
|
||||
fFreshensList(5, true),
|
||||
fReplacesList(5)
|
||||
fConflictsList(4, true),
|
||||
fFreshensList(4, true),
|
||||
fReplacesList(4)
|
||||
{
|
||||
status_t error;
|
||||
int32 architecture;
|
||||
@ -216,6 +223,8 @@ BPackageInfo::BPackageInfo(BMessage* archive, status_t* _error)
|
||||
"global-settings-files", fGlobalSettingsFileInfos)) == B_OK
|
||||
&& (error = _ExtractUserSettingsFileInfos(archive, "user-settings-files",
|
||||
fUserSettingsFileInfos)) == B_OK
|
||||
&& (error = _ExtractUsers(archive, "users", fUsers)) == B_OK
|
||||
&& (error = _ExtractStringList(archive, "groups", fGroups)) == B_OK
|
||||
&& (error = _ExtractResolvables(archive, "provides", fProvidesList))
|
||||
== B_OK
|
||||
&& (error = _ExtractResolvableExpressions(archive, "requires",
|
||||
@ -326,6 +335,50 @@ BPackageInfo::InitCheck() const
|
||||
|| fProvidesList.IsEmpty())
|
||||
return B_NO_INIT;
|
||||
|
||||
// check global settings files
|
||||
int32 globalSettingsFileCount = fGlobalSettingsFileInfos.CountItems();
|
||||
for (int32 i = 0; i < globalSettingsFileCount; i++) {
|
||||
const BGlobalSettingsFileInfo* info
|
||||
= fGlobalSettingsFileInfos.ItemAt(i);
|
||||
status_t error = info->InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
// check user settings files
|
||||
int32 userSettingsFileCount = fUserSettingsFileInfos.CountItems();
|
||||
for (int32 i = 0; i < userSettingsFileCount; i++) {
|
||||
const BUserSettingsFileInfo* info = fUserSettingsFileInfos.ItemAt(i);
|
||||
status_t error = info->InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
// check users
|
||||
int32 userCount = fUsers.CountItems();
|
||||
for (int32 i = 0; i < userCount; i++) {
|
||||
const BUser* user = fUsers.ItemAt(i);
|
||||
status_t error = user->InitCheck();
|
||||
if (error != B_OK)
|
||||
return B_NO_INIT;
|
||||
|
||||
// make sure the user's groups are specified as groups
|
||||
const BStringList& userGroups = user->Groups();
|
||||
int32 groupCount = userGroups.CountStrings();
|
||||
for (int32 k = 0; k < groupCount; k++) {
|
||||
const BString& group = userGroups.StringAt(k);
|
||||
if (!fGroups.HasString(group))
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// check groups
|
||||
int32 groupCount = fGroups.CountStrings();
|
||||
for (int32 i = 0; i< groupCount; i++) {
|
||||
if (!BUser::IsValidUserName(fGroups.StringAt(i)))
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -449,6 +502,20 @@ BPackageInfo::UserSettingsFileInfos() const
|
||||
}
|
||||
|
||||
|
||||
const BObjectList<BUser>&
|
||||
BPackageInfo::Users() const
|
||||
{
|
||||
return fUsers;
|
||||
}
|
||||
|
||||
|
||||
const BStringList&
|
||||
BPackageInfo::Groups() const
|
||||
{
|
||||
return fGroups;
|
||||
}
|
||||
|
||||
|
||||
const BObjectList<BPackageResolvable>&
|
||||
BPackageInfo::ProvidesList() const
|
||||
{
|
||||
@ -629,6 +696,13 @@ BPackageInfo::ClearSourceURLList()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BPackageInfo::AddSourceURL(const BString& url)
|
||||
{
|
||||
return fSourceURLList.Add(url) ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BPackageInfo::ClearGlobalSettingsFileInfos()
|
||||
{
|
||||
@ -671,10 +745,37 @@ BPackageInfo::AddUserSettingsFileInfo(const BUserSettingsFileInfo& info)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BPackageInfo::AddSourceURL(const BString& url)
|
||||
void
|
||||
BPackageInfo::ClearUsers()
|
||||
{
|
||||
return fSourceURLList.Add(url) ? B_OK : B_NO_MEMORY;
|
||||
fUsers.MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BPackageInfo::AddUser(const BUser& user)
|
||||
{
|
||||
BUser* newUser = new (std::nothrow) BUser(user);
|
||||
if (newUser == NULL || !fUsers.AddItem(newUser)) {
|
||||
delete newUser;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BPackageInfo::ClearGroups()
|
||||
{
|
||||
fGroups.MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BPackageInfo::AddGroup(const BString& group)
|
||||
{
|
||||
return fGroups.Add(group) ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
@ -807,6 +908,8 @@ BPackageInfo::Clear()
|
||||
fSourceURLList.MakeEmpty();
|
||||
fGlobalSettingsFileInfos.MakeEmpty();
|
||||
fUserSettingsFileInfos.MakeEmpty();
|
||||
fUsers.MakeEmpty();
|
||||
fGroups.MakeEmpty();
|
||||
fRequiresList.MakeEmpty();
|
||||
fProvidesList.MakeEmpty();
|
||||
fSupplementsList.MakeEmpty();
|
||||
@ -842,6 +945,8 @@ BPackageInfo::Archive(BMessage* archive, bool deep) const
|
||||
"global-settings-files", fGlobalSettingsFileInfos)) != B_OK
|
||||
|| (error = _AddUserSettingsFileInfos(archive,
|
||||
"user-settings-files", fUserSettingsFileInfos)) != B_OK
|
||||
|| (error = _AddUsers(archive, "users", fUsers)) != B_OK
|
||||
|| (error = archive->AddStrings("groups", fGroups)) != B_OK
|
||||
|| (error = _AddResolvables(archive, "provides", fProvidesList)) != B_OK
|
||||
|| (error = _AddResolvableExpressions(archive, "requires",
|
||||
fRequiresList)) != B_OK
|
||||
@ -887,6 +992,8 @@ BPackageInfo::GetConfigString(BString& _string) const
|
||||
.Write("source-urls", fSourceURLList)
|
||||
.Write("global-settings-files", fGlobalSettingsFileInfos)
|
||||
.Write("user-settings-files", fUserSettingsFileInfos)
|
||||
.Write("users", fUsers)
|
||||
.Write("groups", fGroups)
|
||||
.Write("provides", fProvidesList)
|
||||
.BeginRequires(fBasePackage)
|
||||
.Write("requires", fRequiresList)
|
||||
@ -1135,6 +1242,44 @@ BPackageInfo::_AddUserSettingsFileInfos(BMessage* archive, const char* field,
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
BPackageInfo::_AddUsers(BMessage* archive, const char* field,
|
||||
const UserList& users)
|
||||
{
|
||||
// construct the field names we need
|
||||
FieldName nameField(field, ":name");
|
||||
FieldName realNameField(field, ":realName");
|
||||
FieldName homeField(field, ":home");
|
||||
FieldName shellField(field, ":shell");
|
||||
FieldName groupsField(field, ":groups");
|
||||
|
||||
if (!nameField.IsValid() || !realNameField.IsValid() || !homeField.IsValid()
|
||||
|| !shellField.IsValid() || !groupsField.IsValid())
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// add fields
|
||||
int32 count = users.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
const BUser* user = users.ItemAt(i);
|
||||
BString groups = user->Groups().Join(" ");
|
||||
if (groups.IsEmpty() && !user->Groups().IsEmpty())
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error;
|
||||
if ((error = archive->AddString(nameField, user->Name())) != B_OK
|
||||
|| (error = archive->AddString(realNameField, user->RealName()))
|
||||
!= B_OK
|
||||
|| (error = archive->AddString(homeField, user->Home())) != B_OK
|
||||
|| (error = archive->AddString(shellField, user->Shell())) != B_OK
|
||||
|| (error = archive->AddString(groupsField, groups)) != B_OK) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
BPackageInfo::_ExtractVersion(BMessage* archive, const char* field, int32 index,
|
||||
BPackageVersion& _version)
|
||||
@ -1401,4 +1546,70 @@ BPackageInfo::_ExtractUserSettingsFileInfos(BMessage* archive,
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
BPackageInfo::_ExtractUsers(BMessage* archive, const char* field,
|
||||
UserList& _users)
|
||||
{
|
||||
// construct the field names we need
|
||||
FieldName nameField(field, ":name");
|
||||
FieldName realNameField(field, ":realName");
|
||||
FieldName homeField(field, ":home");
|
||||
FieldName shellField(field, ":shell");
|
||||
FieldName groupsField(field, ":groups");
|
||||
|
||||
if (!nameField.IsValid() || !realNameField.IsValid() || !homeField.IsValid()
|
||||
|| !shellField.IsValid() || !groupsField.IsValid())
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// get the number of items
|
||||
type_code type;
|
||||
int32 count;
|
||||
if (archive->GetInfo(nameField, &type, &count) != B_OK) {
|
||||
// the field is missing
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// extract fields
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BString name;
|
||||
status_t error = archive->FindString(nameField, i, &name);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
BString realName;
|
||||
error = archive->FindString(realNameField, i, &realName);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
BString home;
|
||||
error = archive->FindString(homeField, i, &home);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
BString shell;
|
||||
error = archive->FindString(shellField, i, &shell);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
BString groupsString;
|
||||
error = archive->FindString(groupsField, i, &groupsString);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
BStringList groups;
|
||||
if (!groupsString.Split(" ", false, groups))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
BUser* user = new(std::nothrow) BUser(name, realName, home, shell,
|
||||
groups);
|
||||
if (user == NULL || !_users.AddItem(user)) {
|
||||
delete user;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
} // namespace BPackageKit
|
||||
|
@ -703,6 +703,118 @@ BPackageInfo::Parser::_ParseUserSettingsFileInfos(
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BPackageInfo::Parser::_ParseUsers(UserList* users)
|
||||
{
|
||||
struct UserParser : public ListElementParser {
|
||||
Parser& parser;
|
||||
UserList* users;
|
||||
|
||||
UserParser(Parser& parser, UserList* users)
|
||||
:
|
||||
parser(parser),
|
||||
users(users)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(const Token& token)
|
||||
{
|
||||
if (token.type != TOKEN_WORD) {
|
||||
throw ParseError("expected a user name",
|
||||
token.pos);
|
||||
}
|
||||
|
||||
BString realName;
|
||||
BString home;
|
||||
BString shell;
|
||||
BStringList groups;
|
||||
|
||||
for (;;) {
|
||||
Token nextToken = parser._NextToken();
|
||||
if (nextToken.type != TOKEN_WORD) {
|
||||
parser._RewindTo(nextToken);
|
||||
break;
|
||||
}
|
||||
|
||||
if (nextToken.text == "real-name") {
|
||||
nextToken = parser._NextToken();
|
||||
if (nextToken.type != TOKEN_WORD
|
||||
&& nextToken.type != TOKEN_QUOTED_STRING) {
|
||||
throw ParseError("expected string (a user real name)",
|
||||
nextToken.pos);
|
||||
}
|
||||
realName = nextToken.text;
|
||||
} else if (nextToken.text == "home") {
|
||||
nextToken = parser._NextToken();
|
||||
if (nextToken.type != TOKEN_WORD
|
||||
&& nextToken.type != TOKEN_QUOTED_STRING) {
|
||||
throw ParseError("expected string (a home path)",
|
||||
nextToken.pos);
|
||||
}
|
||||
home = nextToken.text;
|
||||
} else if (nextToken.text == "shell") {
|
||||
nextToken = parser._NextToken();
|
||||
if (nextToken.type != TOKEN_WORD
|
||||
&& nextToken.type != TOKEN_QUOTED_STRING) {
|
||||
throw ParseError("expected string (a shell path)",
|
||||
nextToken.pos);
|
||||
}
|
||||
shell = nextToken.text;
|
||||
} else if (nextToken.text == "groups") {
|
||||
for (;;) {
|
||||
nextToken = parser._NextToken();
|
||||
if (nextToken.type == TOKEN_WORD) {
|
||||
if (!groups.Add(nextToken.text))
|
||||
throw std::bad_alloc();
|
||||
} else if (nextToken.type == TOKEN_ITEM_SEPARATOR
|
||||
|| nextToken.type == TOKEN_CLOSE_BRACE) {
|
||||
parser._RewindTo(nextToken);
|
||||
break;
|
||||
} else {
|
||||
throw ParseError("expected a group name",
|
||||
nextToken.pos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
throw ParseError(
|
||||
"expected 'real-name', 'home', 'shell', or 'groups'",
|
||||
nextToken.pos);
|
||||
}
|
||||
}
|
||||
|
||||
BString templatePath;
|
||||
|
||||
Token nextToken = parser._NextToken();
|
||||
if (nextToken.type == TOKEN_WORD && nextToken.text == "template") {
|
||||
nextToken = parser._NextToken();
|
||||
if (nextToken.type != TOKEN_WORD
|
||||
&& nextToken.type != TOKEN_QUOTED_STRING) {
|
||||
throw ParseError(
|
||||
"expected string (a settings template file path)",
|
||||
nextToken.pos);
|
||||
}
|
||||
templatePath = nextToken.text;
|
||||
} else if (nextToken.type == TOKEN_ITEM_SEPARATOR
|
||||
|| nextToken.type == TOKEN_CLOSE_BRACE) {
|
||||
parser._RewindTo(nextToken);
|
||||
} else {
|
||||
throw ParseError(
|
||||
"expected 'template', semicolon, new line or '}'",
|
||||
nextToken.pos);
|
||||
}
|
||||
|
||||
if (!users->AddItem(new BUser(token.text, realName, home, shell,
|
||||
groups))) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
} resolvableExpressionParser(*this, users);
|
||||
|
||||
_ParseList(resolvableExpressionParser, false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
|
||||
{
|
||||
@ -814,6 +926,14 @@ BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
|
||||
&packageInfo->fUserSettingsFileInfos);
|
||||
break;
|
||||
|
||||
case B_PACKAGE_INFO_USERS:
|
||||
_ParseUsers(&packageInfo->fUsers);
|
||||
break;
|
||||
|
||||
case B_PACKAGE_INFO_GROUPS:
|
||||
_ParseStringList(&packageInfo->fGroups);
|
||||
break;
|
||||
|
||||
case B_PACKAGE_INFO_PROVIDES:
|
||||
_ParseResolvableList(&packageInfo->fProvidesList);
|
||||
break;
|
||||
|
@ -79,6 +79,7 @@ private:
|
||||
GlobalSettingsFileInfoList* infos);
|
||||
void _ParseUserSettingsFileInfos(
|
||||
UserSettingsFileInfoList* infos);
|
||||
void _ParseUsers(UserList* users);
|
||||
|
||||
void _Parse(BPackageInfo* packageInfo);
|
||||
|
||||
|
@ -175,6 +175,37 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void _WriteListElement(const BUser* value)
|
||||
{
|
||||
_WriteMaybeQuoted(value->Name());
|
||||
|
||||
if (!value->RealName().IsEmpty()) {
|
||||
_Write(" real-name ");
|
||||
_WriteMaybeQuoted(value->RealName());
|
||||
}
|
||||
|
||||
if (!value->Home().IsEmpty()) {
|
||||
_Write(" home ");
|
||||
_WriteMaybeQuoted(value->Home());
|
||||
}
|
||||
|
||||
if (!value->Shell().IsEmpty()) {
|
||||
_Write(" shell ");
|
||||
_WriteMaybeQuoted(value->Shell());
|
||||
}
|
||||
|
||||
if (!value->Groups().IsEmpty()) {
|
||||
_Write(" groups ");
|
||||
BString groups = value->Groups().Join(" ");
|
||||
if (groups.IsEmpty()) {
|
||||
if (fError == B_OK)
|
||||
fError = B_NO_MEMORY;
|
||||
return;
|
||||
}
|
||||
_Write(groups);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool _IsValueEmpty(const char* value)
|
||||
{
|
||||
return value[0] == '\0';
|
||||
|
118
src/kits/package/User.cpp
Normal file
118
src/kits/package/User.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <package/User.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
|
||||
|
||||
BUser::BUser()
|
||||
:
|
||||
fName(),
|
||||
fRealName(),
|
||||
fHome(),
|
||||
fShell(),
|
||||
fGroups()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BUser::BUser(const BString& name, const BString& realName, const BString& home,
|
||||
const BString& shell, const BStringList& groups)
|
||||
:
|
||||
fName(name),
|
||||
fRealName(realName),
|
||||
fHome(home),
|
||||
fShell(shell),
|
||||
fGroups(groups)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BUser::~BUser()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUser::InitCheck() const
|
||||
{
|
||||
if (fName.IsEmpty())
|
||||
return B_NO_INIT;
|
||||
if (!IsValidUserName(fName))
|
||||
return B_BAD_VALUE;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BUser::Name() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BUser::RealName() const
|
||||
{
|
||||
return fRealName;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BUser::Home() const
|
||||
{
|
||||
return fHome;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BUser::Shell() const
|
||||
{
|
||||
return fShell;
|
||||
}
|
||||
|
||||
|
||||
const BStringList&
|
||||
BUser::Groups() const
|
||||
{
|
||||
return fGroups;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUser::SetTo(const BString& name, const BString& realName, const BString& home,
|
||||
const BString& shell, const BStringList& groups)
|
||||
{
|
||||
fName = name;
|
||||
fRealName = realName;
|
||||
fHome = home;
|
||||
fShell = shell;
|
||||
fGroups = groups;
|
||||
|
||||
return fGroups.CountStrings() == groups.CountStrings() ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
BUser::IsValidUserName(const char* name)
|
||||
{
|
||||
if (name[0] == '\0')
|
||||
return false;
|
||||
|
||||
for (; name[0] != '\0'; name++) {
|
||||
if (!isalnum(name[0]) && name[0] != '_')
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace BPackageKit
|
@ -402,6 +402,69 @@ ReaderImplBase::UserSettingsFileInfoAttributeHandler::HandleAttribute(
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - UserAttributeHandler
|
||||
|
||||
|
||||
ReaderImplBase::UserAttributeHandler::UserAttributeHandler(
|
||||
BPackageInfoAttributeValue& packageInfoValue)
|
||||
:
|
||||
PackageInfoAttributeHandlerBase(packageInfoValue),
|
||||
fGroups()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReaderImplBase::UserAttributeHandler::HandleAttribute(
|
||||
AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
|
||||
AttributeHandler** _handler)
|
||||
{
|
||||
switch (id) {
|
||||
case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME:
|
||||
fPackageInfoValue.user.realName = value.string;
|
||||
break;
|
||||
|
||||
case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME:
|
||||
fPackageInfoValue.user.home = value.string;
|
||||
break;
|
||||
|
||||
case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL:
|
||||
fPackageInfoValue.user.shell = value.string;
|
||||
break;
|
||||
|
||||
case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP:
|
||||
if (!fGroups.Add(value.string))
|
||||
return B_NO_MEMORY;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (context->ignoreUnknownAttributes)
|
||||
break;
|
||||
|
||||
context->errorOutput->PrintError("Error: Invalid package "
|
||||
"attribute section: unexpected package attribute id %d "
|
||||
"encountered when parsing user settings file info\n",
|
||||
id);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReaderImplBase::UserAttributeHandler::Delete(AttributeHandlerContext* context)
|
||||
{
|
||||
if (!fGroups.IsEmpty()) {
|
||||
fPackageInfoValue.user.groups = fGroups.Elements();
|
||||
fPackageInfoValue.user.groupCount = fGroups.Count();
|
||||
}
|
||||
|
||||
return PackageInfoAttributeHandlerBase::Delete(context);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - PackageAttributeHandler
|
||||
|
||||
|
||||
@ -569,6 +632,21 @@ ReaderImplBase::PackageAttributeHandler::HandleAttribute(
|
||||
}
|
||||
break;
|
||||
|
||||
case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER:
|
||||
fPackageInfoValue.user.name = value.string;
|
||||
fPackageInfoValue.attributeID = B_PACKAGE_INFO_USERS;
|
||||
if (_handler != NULL) {
|
||||
*_handler = new(std::nothrow) UserAttributeHandler(
|
||||
fPackageInfoValue);
|
||||
if (*_handler == NULL)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
break;
|
||||
|
||||
case B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP:
|
||||
fPackageInfoValue.SetTo(B_PACKAGE_INFO_GROUPS, value.string);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (context->ignoreUnknownAttributes)
|
||||
break;
|
||||
|
@ -480,6 +480,36 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
|
||||
}
|
||||
}
|
||||
|
||||
// user list
|
||||
const BObjectList<BUser>& users = packageInfo.Users();
|
||||
for (int32 i = 0; i < users.CountItems(); ++i) {
|
||||
const BUser* user = users.ItemAt(i);
|
||||
PackageAttribute* attribute = _AddStringAttribute(
|
||||
B_HPKG_ATTRIBUTE_ID_PACKAGE_USER, user->Name(), attributeList);
|
||||
|
||||
_AddStringAttributeIfNotEmpty(
|
||||
B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME, user->RealName(),
|
||||
attribute->children);
|
||||
_AddStringAttributeIfNotEmpty(
|
||||
B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME, user->Home(),
|
||||
attribute->children);
|
||||
_AddStringAttributeIfNotEmpty(
|
||||
B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL, user->Shell(),
|
||||
attribute->children);
|
||||
|
||||
for (int32 k = 0; k < user->Groups().CountStrings(); k++) {
|
||||
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP,
|
||||
user->Groups().StringAt(k), attribute->children);
|
||||
}
|
||||
}
|
||||
|
||||
// group list
|
||||
const BStringList& groups = packageInfo.Groups();
|
||||
for (int32 i = 0; i < groups.CountStrings(); i++) {
|
||||
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP,
|
||||
groups.StringAt(i), attributeList);
|
||||
}
|
||||
|
||||
// checksum (optional, only exists in repositories)
|
||||
if (packageInfo.Checksum().Length() > 0) {
|
||||
PackageAttribute* checksum = new PackageAttribute(
|
||||
@ -740,6 +770,18 @@ WriterImplBase::RawWriteBuffer(const void* buffer, size_t size, off_t offset)
|
||||
}
|
||||
|
||||
|
||||
WriterImplBase::PackageAttribute*
|
||||
WriterImplBase::_AddStringAttribute(BHPKGAttributeID id, const BString& value,
|
||||
DoublyLinkedList<PackageAttribute>& list)
|
||||
{
|
||||
PackageAttribute* attribute = new PackageAttribute(id,
|
||||
B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE);
|
||||
attribute->string = fPackageStringCache.Get(value);
|
||||
list.Add(attribute);
|
||||
return attribute;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WriterImplBase::_WritePackageAttributes(
|
||||
const PackageAttributeList& packageAttributes)
|
||||
|
Loading…
Reference in New Issue
Block a user