1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Add user module for managing system users/groups.

Centralize the management of users and groups.

Also update Posix storage driver where users/groups were already in use.
This commit is contained in:
David Steele 2019-09-08 20:11:51 -04:00
parent d957acb36b
commit 1049632873
7 changed files with 221 additions and 15 deletions

View File

@ -87,6 +87,7 @@ my @stryCFile =
'common/type/variant.c',
'common/type/variantList.c',
'common/type/xml.c',
'common/user.c',
'common/wait.c',
'config/config.c',
'config/define.c',

View File

@ -122,6 +122,7 @@ SRCS = \
common/type/variant.c \
common/type/variantList.c \
common/type/xml.c \
common/user.c \
common/wait.c \
config/config.c \
config/define.c \
@ -443,6 +444,9 @@ common/type/variantList.o: common/type/variantList.c build.auto.h common/assert.
common/type/xml.o: common/type/xml.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/list.h common/type/string.h common/type/xml.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/type/xml.c -o common/type/xml.o
common/user.o: common/user.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/string.h common/user.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/user.c -o common/user.o
common/wait.o: common/wait.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/convert.h common/wait.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/wait.c -o common/wait.o
@ -563,7 +567,7 @@ storage/helper.o: storage/helper.c build.auto.h common/assert.h common/debug.h c
storage/posix/read.o: storage/posix/read.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h storage/info.h storage/posix/read.h storage/posix/storage.h storage/posix/storage.intern.h storage/read.h storage/read.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c storage/posix/read.c -o storage/posix/read.o
storage/posix/storage.o: storage/posix/storage.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h storage/info.h storage/posix/read.h storage/posix/storage.h storage/posix/storage.intern.h storage/posix/write.h storage/read.h storage/read.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h
storage/posix/storage.o: storage/posix/storage.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/user.h storage/info.h storage/posix/read.h storage/posix/storage.h storage/posix/storage.intern.h storage/posix/write.h storage/read.h storage/read.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c storage/posix/storage.c -o storage/posix/storage.o
storage/posix/write.o: storage/posix/write.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h storage/info.h storage/posix/storage.h storage/posix/storage.intern.h storage/posix/write.h storage/read.h storage/read.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h

136
src/common/user.c Normal file
View File

@ -0,0 +1,136 @@
/***********************************************************************************************************************************
System User/Group Management
***********************************************************************************************************************************/
#include "build.auto.h"
#include <grp.h>
#include <pwd.h>
#include <unistd.h>
#include "common/debug.h"
#include "common/memContext.h"
#include "common/user.h"
/***********************************************************************************************************************************
User group info
***********************************************************************************************************************************/
struct
{
MemContext *memContext; // Mem context to store data in this struct
uid_t userId; // Real user id of the calling process from getuid()
bool userRoot; // Is this the root user?
const String *userName; // User name if it exists
gid_t groupId; // Real group id of the calling process from getgid()
const String *groupName; // Group name if it exists
} userLocalData;
/***********************************************************************************************************************************/
static void
userInitInternal(void)
{
FUNCTION_TEST_VOID();
MEM_CONTEXT_BEGIN(memContextTop())
{
userLocalData.memContext = memContextNew("UserLocalData");
}
MEM_CONTEXT_END();
MEM_CONTEXT_BEGIN(userLocalData.memContext)
{
userLocalData.userId = getuid();
userLocalData.userName = userNameFromId(userLocalData.userId);
userLocalData.userRoot = userLocalData.userId == 0;
userLocalData.groupId = getgid();
userLocalData.groupName = groupNameFromId(userLocalData.groupId);
}
MEM_CONTEXT_END();
FUNCTION_TEST_RETURN_VOID();
}
void
userInit(void)
{
FUNCTION_TEST_VOID();
if (!userLocalData.memContext)
userInitInternal();
FUNCTION_TEST_RETURN_VOID();
}
/**********************************************************************************************************************************/
gid_t
groupId(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(userLocalData.groupId);
}
/**********************************************************************************************************************************/
const String *
groupName(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(userLocalData.groupName);
}
/**********************************************************************************************************************************/
String *
groupNameFromId(gid_t groupId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(UINT, groupId);
FUNCTION_TEST_END();
struct group *groupData = getgrgid(groupId);
if (groupData != NULL)
FUNCTION_TEST_RETURN(strNew(groupData->gr_name));
FUNCTION_TEST_RETURN(NULL);
}
/**********************************************************************************************************************************/
uid_t
userId(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(userLocalData.userId);
}
/**********************************************************************************************************************************/
const String *
userName(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(userLocalData.userName);
}
/**********************************************************************************************************************************/
String *
userNameFromId(uid_t userId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(UINT, userId);
FUNCTION_TEST_END();
struct passwd *userData = getpwuid(userId);
if (userData != NULL)
FUNCTION_TEST_RETURN(strNew(userData->pw_name));
FUNCTION_TEST_RETURN(NULL);
}
/**********************************************************************************************************************************/
bool
userRoot(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(userLocalData.userRoot);
}

36
src/common/user.h Normal file
View File

@ -0,0 +1,36 @@
/***********************************************************************************************************************************
System User/Group Management
***********************************************************************************************************************************/
#ifndef COMMON_USER_H
#define COMMON_USER_H
#include "common/type/string.h"
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
// Call this initializer before using any of the functions below. Safe to call more than once.
void userInit(void);
// Get the primary group id of the current user
gid_t groupId(void);
// Get the primary group name of the current user. Returns NULL if there is no mapping.
const String *groupName(void);
// Get the group name from a group id. Returns NULL if the group id is invalid or there is no mapping.
String *groupNameFromId(gid_t groupId);
// Get the id of the current user
uid_t userId(void);
// Get the name of the current user. Returns NULL if there is no mapping.
const String *userName(void);
// Get the user name from a user id. Returns NULL if the user id is invalid or there is no mapping.
String *userNameFromId(uid_t userId);
// Is the current user the root user?
bool userRoot(void);
#endif

View File

@ -6,9 +6,7 @@ Posix Storage
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
@ -18,6 +16,7 @@ Posix Storage
#include "common/log.h"
#include "common/memContext.h"
#include "common/regExp.h"
#include "common/user.h"
#include "storage/posix/read.h"
#include "storage/posix/storage.intern.h"
#include "storage/posix/write.h"
@ -109,21 +108,11 @@ storagePosixInfo(THIS_VOID, const String *file, bool followLink)
{
result.exists = true;
result.groupId = statFile.st_gid;
result.group = groupNameFromId(result.groupId);
result.userId = statFile.st_uid;
result.user = userNameFromId(result.userId);
result.timeModified = statFile.st_mtime;
// Get user name if it exists
struct passwd *userData = getpwuid(result.userId);
if (userData != NULL)
result.user = strNew(userData->pw_name);
// Get group name if it exists
struct group *groupData = getgrgid(result.groupId);
if (groupData != NULL)
result.group = strNew(groupData->gr_name);
if (S_ISREG(statFile.st_mode))
{
result.type = storageTypeFile;
@ -679,6 +668,9 @@ storagePosixNewInternal(
ASSERT(modeFile != 0);
ASSERT(modePath != 0);
// Initialze user module
userInit();
// Create the object
Storage *this = NULL;

View File

@ -213,6 +213,13 @@ unit:
coverage:
common/type/xml: full
# ----------------------------------------------------------------------------------------------------------------------------
- name: user
total: 1
coverage:
common/user: full
# ----------------------------------------------------------------------------------------------------------------------------
- name: io
total: 4

View File

@ -0,0 +1,30 @@
/***********************************************************************************************************************************
Test System User/Group Management
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun(void)
{
FUNCTION_HARNESS_VOID();
// *****************************************************************************************************************************
if (testBegin("all"))
{
TEST_RESULT_VOID(userInit(), "initialize info");
TEST_RESULT_VOID(userInit(), "initialize info again");
TEST_RESULT_UINT(userId(), getuid(), "check user id");
TEST_RESULT_STR_Z(userName(), testUser(), "check user name");
TEST_RESULT_STR_Z(userNameFromId(77777), NULL, "invalid user name by id");
TEST_RESULT_BOOL(userRoot(), false, "check user is root");
TEST_RESULT_UINT(groupId(), getgid(), "check group id");
TEST_RESULT_STR_Z(groupName(), testGroup(), "check name name");
TEST_RESULT_STR_Z(groupNameFromId(77777), NULL, "invalid group name by id");
}
FUNCTION_HARNESS_RESULT_VOID();
}