Expanding the package install utilities for Security Baseline to use the right package managers for all our current supported distros (#643)
This commit is contained in:
Родитель
351cc427c8
Коммит
b376be53e6
|
@ -10,6 +10,7 @@ add_library(commonutils STATIC
|
|||
DeviceInfoUtils.c
|
||||
FileUtils.c
|
||||
OtherUtils.c
|
||||
PackageUtils.c
|
||||
ProxyUtils.c
|
||||
SocketUtils.c
|
||||
SshUtils.c
|
||||
|
|
|
@ -490,103 +490,6 @@ int CheckFileSystemMountingOption(const char* mountFileName, const char* mountDi
|
|||
return status;
|
||||
}
|
||||
|
||||
static int CheckOrInstallPackage(const char* commandTemplate, const char* packageName, void* log)
|
||||
{
|
||||
char* command = NULL;
|
||||
size_t packageNameLength = 0;
|
||||
int status = ENOENT;
|
||||
|
||||
if ((NULL == commandTemplate) || (NULL == packageName) || ((0 == (packageNameLength = strlen(packageName)))))
|
||||
{
|
||||
OsConfigLogError(log, "CheckOrInstallPackage called with invalid arguments");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
packageNameLength += strlen(commandTemplate) + 1;
|
||||
|
||||
if (NULL == (command = (char*)malloc(packageNameLength)))
|
||||
{
|
||||
OsConfigLogError(log, "CheckOrInstallPackage: out of memory");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
memset(command, 0, packageNameLength);
|
||||
snprintf(command, packageNameLength, commandTemplate, packageName);
|
||||
|
||||
status = ExecuteCommand(NULL, command, false, false, 0, 0, NULL, NULL, log);
|
||||
|
||||
FREE_MEMORY(command);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int CheckPackageInstalled(const char* packageName, void* log)
|
||||
{
|
||||
const char* commandTemplate = "dpkg -l %s | grep ^ii";
|
||||
int status = ENOENT;
|
||||
|
||||
if (0 == (status = CheckOrInstallPackage(commandTemplate, packageName, log)))
|
||||
{
|
||||
OsConfigLogInfo(log, "CheckPackageInstalled: '%s' is installed", packageName);
|
||||
}
|
||||
else if (EINVAL != status)
|
||||
{
|
||||
OsConfigLogInfo(log, "CheckPackageInstalled: '%s' is not installed", packageName);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int InstallPackage(const char* packageName, void* log)
|
||||
{
|
||||
const char* commandTemplate = "apt-get install -y %s";
|
||||
int status = 0;
|
||||
|
||||
if (0 != (status = CheckPackageInstalled(packageName, log)))
|
||||
{
|
||||
if ((0 == (status = CheckOrInstallPackage(commandTemplate, packageName, log))) &&
|
||||
(0 == (status = CheckPackageInstalled(packageName, log))))
|
||||
{
|
||||
OsConfigLogInfo(log, "InstallPackage: '%s' was successfully installed", packageName);
|
||||
}
|
||||
else
|
||||
{
|
||||
OsConfigLogError(log, "InstallPackage: installation of '%s' failed with %d", packageName, status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OsConfigLogInfo(log, "InstallPackage: '%s' is already installed", packageName);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int UninstallPackage(const char* packageName, void* log)
|
||||
{
|
||||
const char* commandTemplate = "apt-get remove -y --purge %s";
|
||||
int status = 0;
|
||||
|
||||
if (0 == (status = CheckPackageInstalled(packageName, log)))
|
||||
{
|
||||
if (0 == (status = CheckOrInstallPackage(commandTemplate, packageName, log)))
|
||||
{
|
||||
OsConfigLogInfo(log, "UninstallPackage: '%s' was successfully uninstalled", packageName);
|
||||
}
|
||||
else
|
||||
{
|
||||
OsConfigLogError(log, "UninstallPackage: uninstallation of '%s' failed with %d", packageName, status);
|
||||
}
|
||||
}
|
||||
else if (EINVAL != status)
|
||||
{
|
||||
// Nothing to uninstall
|
||||
status = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static unsigned int GetNumberOfCharacterInstancesInFile(const char* fileName, char what)
|
||||
{
|
||||
unsigned int numberOf = 0;
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "Internal.h"
|
||||
|
||||
const char* g_aptGet = "apt-get";
|
||||
const char* g_dpkg = "dpkg";
|
||||
const char* g_tdnf = "tdnf";
|
||||
const char* g_dnf = "dnf";
|
||||
const char* g_yum = "yum";
|
||||
const char* g_zypper = "zypper";
|
||||
|
||||
static int IsPresent(const char* what, void* log)
|
||||
{
|
||||
const char* commandTemplate = "command -v %s";
|
||||
char* command = NULL;
|
||||
int status = ENOENT;
|
||||
|
||||
if (NULL == what)
|
||||
{
|
||||
OsConfigLogError(log, "IsPresent called with invalid argument");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (NULL != (command = FormatAllocateString(commandTemplate, what)))
|
||||
{
|
||||
status = ExecuteCommand(NULL, command, false, false, 0, 0, NULL, NULL, log);
|
||||
}
|
||||
else
|
||||
{
|
||||
OsConfigLogError(log, "IsPresent: FormatAllocateString failed");
|
||||
status = ENOMEM;
|
||||
}
|
||||
|
||||
FREE_MEMORY(command);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int CheckOrInstallPackage(const char* commandTemplate, const char* packageManager, const char* packageName, void* log)
|
||||
{
|
||||
char* command = NULL;
|
||||
int status = ENOENT;
|
||||
|
||||
if ((NULL == commandTemplate) || (NULL == packageManager) || (NULL == packageName) || ((0 == strlen(packageName))))
|
||||
{
|
||||
OsConfigLogError(log, "CheckOrInstallPackage called with invalid arguments");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (NULL == (command = FormatAllocateString(commandTemplate, packageManager, packageName)))
|
||||
{
|
||||
OsConfigLogError(log, "CheckOrInstallPackage: FormatAllocateString failed");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
status = ExecuteCommand(NULL, command, false, false, 0, 0, NULL, NULL, log);
|
||||
|
||||
FREE_MEMORY(command);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int CheckPackageInstalled(const char* packageName, void* log)
|
||||
{
|
||||
const char* commandTemplateDpkg = "%s -l %s | grep ^ii";
|
||||
const char* commandTemplateAllElse = "%s list installed %s";
|
||||
const char* commandTemplateZypper = "%s se -x %s";
|
||||
int status = ENOENT;
|
||||
|
||||
if (0 == (status = IsPresent(g_dpkg, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateDpkg, g_dpkg, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_tdnf, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateAllElse, g_tdnf, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_dnf, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateAllElse, g_dnf, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_yum, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateAllElse, g_yum, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_zypper, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateZypper, g_zypper, packageName, log);
|
||||
}
|
||||
|
||||
if (0 == status)
|
||||
{
|
||||
OsConfigLogInfo(log, "CheckPackageInstalled: '%s' is installed", packageName);
|
||||
}
|
||||
else
|
||||
{
|
||||
OsConfigLogInfo(log, "CheckPackageInstalled: '%s' is not found", packageName);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int InstallPackage(const char* packageName, void* log)
|
||||
{
|
||||
const char* commandTemplate = "%s install -y %s";
|
||||
int status = ENOENT;
|
||||
|
||||
if (0 != (status = CheckPackageInstalled(packageName, log)))
|
||||
{
|
||||
if (0 == (status = IsPresent(g_aptGet, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplate, g_aptGet, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_tdnf, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplate, g_tdnf, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_dnf, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplate, g_dnf, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_yum, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplate, g_yum, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_zypper, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplate, g_zypper, packageName, log);
|
||||
}
|
||||
|
||||
if (0 == status)
|
||||
{
|
||||
status = CheckPackageInstalled(packageName, log);
|
||||
}
|
||||
|
||||
if (0 == status)
|
||||
{
|
||||
OsConfigLogInfo(log, "InstallPackage: '%s' was successfully installed", packageName);
|
||||
}
|
||||
else
|
||||
{
|
||||
OsConfigLogError(log, "InstallPackage: installation of '%s' failed with %d", packageName, status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OsConfigLogInfo(log, "InstallPackage: '%s' is already installed", packageName);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int UninstallPackage(const char* packageName, void* log)
|
||||
{
|
||||
const char* commandTemplateAptGet = "%s remove -y --purge %s";
|
||||
const char* commandTemplateAllElse = "% remove -y %s";
|
||||
int status = ENOENT;
|
||||
|
||||
if (0 == (status = CheckPackageInstalled(packageName, log)))
|
||||
{
|
||||
if (0 == (status = IsPresent(g_aptGet, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateAptGet, g_aptGet, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_tdnf, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateAllElse, g_tdnf, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_dnf, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateAllElse, g_dnf, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_yum, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateAllElse, g_yum, packageName, log);
|
||||
}
|
||||
else if (0 == (status = IsPresent(g_zypper, log)))
|
||||
{
|
||||
status = CheckOrInstallPackage(commandTemplateAllElse, g_zypper, packageName, log);
|
||||
}
|
||||
|
||||
if ((0 == status) && (0 == CheckPackageInstalled(packageName, log)))
|
||||
{
|
||||
status = ENOENT;
|
||||
}
|
||||
|
||||
if (0 == status)
|
||||
{
|
||||
OsConfigLogInfo(log, "UninstallPackage: '%s' was successfully uninstalled", packageName);
|
||||
}
|
||||
else
|
||||
{
|
||||
OsConfigLogError(log, "UninstallPackage: uninstallation of '%s' failed with %d", packageName, status);
|
||||
}
|
||||
}
|
||||
else if (EINVAL != status)
|
||||
{
|
||||
OsConfigLogInfo(log, "InstallPackage: '%s' is not found", packageName);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
|
@ -1171,36 +1171,6 @@ TEST_F(CommonUtilsTest, CheckFileSystemMountingOption)
|
|||
EXPECT_TRUE(Cleanup(m_path));
|
||||
}
|
||||
|
||||
TEST_F(CommonUtilsTest, CheckInstallUninstallPackage)
|
||||
{
|
||||
EXPECT_EQ(EINVAL, CheckPackageInstalled(nullptr, nullptr));
|
||||
EXPECT_EQ(EINVAL, InstallPackage(nullptr, nullptr));
|
||||
EXPECT_EQ(EINVAL, UninstallPackage(nullptr, nullptr));
|
||||
|
||||
EXPECT_EQ(EINVAL, CheckPackageInstalled("", nullptr));
|
||||
EXPECT_EQ(EINVAL, InstallPackage("", nullptr));
|
||||
EXPECT_EQ(EINVAL, UninstallPackage("", nullptr));
|
||||
|
||||
if (0 == CheckPackageInstalled("apt", nullptr))
|
||||
{
|
||||
EXPECT_EQ(0, CheckPackageInstalled("ap*", nullptr));
|
||||
|
||||
EXPECT_NE(0, CheckPackageInstalled("~package_that_does_not_exist", nullptr));
|
||||
EXPECT_NE(0, InstallPackage("~package_that_does_not_exist", nullptr));
|
||||
|
||||
// Nothing to uninstall
|
||||
EXPECT_EQ(0, UninstallPackage("~package_that_does_not_exist", nullptr));
|
||||
|
||||
EXPECT_NE(0, CheckPackageInstalled("*~package_that_does_not_exist", nullptr));
|
||||
EXPECT_NE(0, CheckPackageInstalled("~package_that_does_not_exist*", nullptr));
|
||||
EXPECT_NE(0, CheckPackageInstalled("*~package_that_does_not_exist*", nullptr));
|
||||
|
||||
EXPECT_EQ(0, InstallPackage("rolldice", nullptr));
|
||||
EXPECT_EQ(0, CheckPackageInstalled("rolldice", nullptr));
|
||||
EXPECT_EQ(0, UninstallPackage("rolldice", nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CommonUtilsTest, GetNumberOfLinesInFile)
|
||||
{
|
||||
EXPECT_EQ(0, GetNumberOfLinesInFile(nullptr));
|
||||
|
@ -1688,4 +1658,37 @@ TEST_F(CommonUtilsTest, RepairBrokenEolCharactersIfAny)
|
|||
|
||||
EXPECT_STREQ("\n\\Test\\123\n", value = RepairBrokenEolCharactersIfAny("\n\\Test\\123\\n"));
|
||||
FREE_MEMORY(value);
|
||||
}
|
||||
|
||||
TEST_F(CommonUtilsTest, CheckInstallUninstallPackage)
|
||||
{
|
||||
EXPECT_EQ(EINVAL, CheckPackageInstalled(nullptr, nullptr));
|
||||
EXPECT_EQ(EINVAL, InstallPackage(nullptr, nullptr));
|
||||
EXPECT_EQ(EINVAL, UninstallPackage(nullptr, nullptr));
|
||||
|
||||
EXPECT_EQ(EINVAL, CheckPackageInstalled("", nullptr));
|
||||
EXPECT_EQ(EINVAL, InstallPackage("", nullptr));
|
||||
EXPECT_EQ(EINVAL, UninstallPackage("", nullptr));
|
||||
|
||||
EXPECT_NE(0, CheckPackageInstalled("~package_that_does_not_exist", nullptr));
|
||||
EXPECT_NE(0, InstallPackage("~package_that_does_not_exist", nullptr));
|
||||
|
||||
// Nothing to uninstall
|
||||
EXPECT_EQ(0, UninstallPackage("~package_that_does_not_exist", nullptr));
|
||||
|
||||
EXPECT_NE(0, CheckPackageInstalled("*~package_that_does_not_exist", nullptr));
|
||||
EXPECT_NE(0, CheckPackageInstalled("~package_that_does_not_exist*", nullptr));
|
||||
EXPECT_NE(0, CheckPackageInstalled("*~package_that_does_not_exist*", nullptr));
|
||||
|
||||
if (0 == InstallPackage("rolldice", nullptr))
|
||||
{
|
||||
EXPECT_EQ(0, UninstallPackage("rolldice", nullptr));
|
||||
EXPECT_NE(0, CheckPackageInstalled("rolldice", nullptr));
|
||||
EXPECT_EQ(0, InstallPackage("rolldice", nullptr));
|
||||
EXPECT_EQ(0, CheckPackageInstalled("rolldice", nullptr));
|
||||
EXPECT_EQ(0, UninstallPackage("rolldice", nullptr));
|
||||
}
|
||||
EXPECT_NE(0, CheckPackageInstalled("rolldice", nullptr));
|
||||
|
||||
EXPECT_EQ(0, CheckPackageInstalled("gcc", nullptr));
|
||||
}
|
Загрузка…
Ссылка в новой задаче