use llconf for config parsing

This commit is contained in:
Oliver Kurth 2022-03-31 23:59:34 +00:00 committed by Oliver Kurth
parent acc0398bc2
commit 29504ab949
17 changed files with 968 additions and 1251 deletions

View File

@ -20,12 +20,10 @@
#include "includes.h"
static
uint32_t
_TDNFConfigReadPluginSettings(
PCONF_SECTION pSection,
PTDNF pTdnf
);
#include "../llconf/nodes.h"
#include "../llconf/modules.h"
#include "../llconf/entry.h"
#include "../llconf/ini.h"
int
TDNFConfGetRpmVerbosity(
@ -40,6 +38,12 @@ TDNFConfGetRpmVerbosity(
return nLogLevel;
}
static
int isTrue(const char *str)
{
return strcasecmp(str, "true") == 0 || atoi(str) != 0;
}
uint32_t
TDNFReadConfig(
PTDNF pTdnf,
@ -49,13 +53,19 @@ TDNFReadConfig(
{
uint32_t dwError = 0;
PTDNF_CONF pConf = NULL;
PCONF_DATA pData = NULL;
PCONF_SECTION pSection = NULL;
char *pszConfFileCopy = NULL;
char *pszMinVersionsDir = NULL;
char *pszConfFileCopy2 = NULL;
char *pszPkgLocksDir = NULL;
const char *pszProxyUser = NULL;
const char *pszProxyPass = NULL;
struct cnfnode *cn_conf, *cn_top, *cn;
struct cnfmodule *mod_ini;
int nPluginSet = 0;
if(!pTdnf ||
IsNullOrEmptyString(pszConfFile) ||
IsNullOrEmptyString(pszGroup))
@ -64,116 +74,169 @@ TDNFReadConfig(
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadConfigFile(pszConfFile, 0, &pData);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateMemory(
1,
sizeof(TDNF_CONF),
(void**)&pConf);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFConfigGetSection(pData, pszGroup, &pSection);
BAIL_ON_TDNF_ERROR(dwError);
/* defaults */
pConf->nGPGCheck = 0;
pConf->nInstallOnlyLimit = 1;
pConf->nCleanRequirementsOnRemove = 0;
pConf->nKeepCache = 0;
pConf->nOpenMax = TDNF_DEFAULT_OPENMAX;
dwError = TDNFReadKeyValueInt(
pSection,
TDNF_CONF_KEY_INSTALLONLY_LIMIT,
1,
&pConf->nInstallOnlyLimit);
BAIL_ON_TDNF_ERROR(dwError);
register_ini(NULL);
mod_ini = find_cnfmodule("ini");
if (mod_ini == NULL) {
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadKeyValueBoolean(
pSection,
TDNF_CONF_KEY_CLEAN_REQ_ON_REMOVE,
0,
&pConf->nCleanRequirementsOnRemove);
BAIL_ON_TDNF_ERROR(dwError);
cn_conf = cnfmodule_parse_file(mod_ini, pszConfFile);
if (cn_conf == NULL)
{
if (errno != 0)
{
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}
else
{
dwError = ERROR_TDNF_CONF_FILE_LOAD;
BAIL_ON_TDNF_ERROR(dwError);
}
}
dwError = TDNFReadKeyValueBoolean(
pSection,
TDNF_CONF_KEY_GPGCHECK,
0,
&pConf->nGPGCheck);
BAIL_ON_TDNF_ERROR(dwError);
/* cn_conf == NULL => we will not reach here */
/* coverity[var_deref_op] */
cn_top = cn_conf->first_child;
dwError = TDNFReadKeyValueBoolean(
pSection,
TDNF_CONF_KEY_KEEP_CACHE,
0,
&pConf->nKeepCache);
BAIL_ON_TDNF_ERROR(dwError);
for(cn = cn_top->first_child; cn; cn = cn->next)
{
if ((cn->name[0] == '.') || (cn->value == NULL))
continue;
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_REPODIR,
TDNF_DEFAULT_REPO_LOCATION,
&pConf->pszRepoDir);
BAIL_ON_TDNF_ERROR(dwError);
if (strcmp(cn->name, TDNF_CONF_KEY_INSTALLONLY_LIMIT) == 0)
{
pConf->nInstallOnlyLimit = atoi(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_CLEAN_REQ_ON_REMOVE) == 0)
{
pConf->nCleanRequirementsOnRemove = isTrue(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_GPGCHECK) == 0)
{
pConf->nGPGCheck = isTrue(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_KEEP_CACHE) == 0)
{
pConf->nKeepCache = isTrue(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_REPODIR) == 0)
{
pConf->pszRepoDir = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_CACHEDIR) == 0)
{
pConf->pszCacheDir = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_PERSISTDIR) == 0)
{
pConf->pszPersistDir = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_DISTROVERPKG) == 0)
{
pConf->pszDistroVerPkg = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_EXCLUDE) == 0)
{
dwError = TDNFSplitStringToArray(cn->value,
" ", &pConf->ppszExcludes);
BAIL_ON_TDNF_ERROR(dwError);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_MINVERSIONS) == 0)
{
dwError = TDNFSplitStringToArray(cn->value,
" ", &pConf->ppszMinVersions);
BAIL_ON_TDNF_ERROR(dwError);
}
if (strcmp(cn->name, TDNF_CONF_KEY_OPENMAX) == 0)
{
pConf->nOpenMax = atoi(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_CHECK_UPDATE_COMPAT) == 0)
{
pConf->nCheckUpdateCompat = isTrue(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_DISTROSYNC_REINSTALL_CHANGED) == 0)
{
pConf->nDistroSyncReinstallChanged = isTrue(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_PROXY) == 0)
{
pConf->pszProxy = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_PROXY_USER) == 0)
{
pszProxyUser = cn->value;
}
else if (strcmp(cn->name, TDNF_CONF_KEY_PROXY_PASS) == 0)
{
pszProxyPass = cn->value;
}
else if (strcmp(cn->name, TDNF_CONF_KEY_PLUGINS) == 0)
{
/* presence of option disables plugins, no matter the value */
if(!isTrue(cn->value)) {
dwError = TDNFSetOpt(
pTdnf->pArgs,
TDNF_CONF_KEY_NO_PLUGINS, "1");
BAIL_ON_TDNF_ERROR(dwError);
}
nPluginSet = 1;
}
else if (strcmp(cn->name, TDNF_CONF_KEY_PLUGIN_CONF_PATH) == 0)
{
dwError = TDNFSetOpt(pTdnf->pArgs, TDNF_CONF_KEY_PLUGIN_CONF_PATH, cn->value);
BAIL_ON_TDNF_ERROR(dwError);
}
else if (strcmp(cn->name, TDNF_CONF_KEY_PLUGIN_PATH) == 0)
{
dwError = TDNFSetOpt(pTdnf->pArgs, TDNF_CONF_KEY_PLUGIN_PATH, cn->value);
BAIL_ON_TDNF_ERROR(dwError);
}
}
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_CACHEDIR,
TDNF_DEFAULT_CACHE_LOCATION,
&pConf->pszCacheDir);
BAIL_ON_TDNF_ERROR(dwError);
/* if plugins are not enabled explicitely,
we have to disable them because it's the default */
if (!nPluginSet) {
/* no plugins by default */
dwError = TDNFSetOpt(
pTdnf->pArgs,
TDNF_CONF_KEY_NO_PLUGINS, "1");
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_PERSISTDIR,
TDNF_DEFAULT_DB_LOCATION,
&pConf->pszPersistDir);
BAIL_ON_TDNF_ERROR(dwError);
if (pszProxyUser && pszProxyPass)
{
dwError = TDNFAllocateStringPrintf(
&pConf->pszProxyUserPass,
"%s:%s",
pszProxyUser,
pszProxyPass);
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_DISTROVERPKG,
TDNF_DEFAULT_DISTROVERPKG,
&pConf->pszDistroVerPkg);
BAIL_ON_TDNF_ERROR(dwError);
destroy_cnftree(cn_conf);
dwError = TDNFReadKeyValueStringArray(
pSection,
TDNF_CONF_KEY_EXCLUDE,
&pConf->ppszExcludes);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueStringArray(
pSection,
TDNF_CONF_KEY_MINVERSIONS,
&pConf->ppszMinVersions);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueInt(
pSection,
TDNF_CONF_KEY_OPENMAX,
TDNF_DEFAULT_OPENMAX,
&pConf->nOpenMax);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSection,
TDNF_CONF_KEY_CHECK_UPDATE_COMPAT,
0,
&pConf->nCheckUpdateCompat);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSection,
TDNF_CONF_KEY_DISTROSYNC_REINSTALL_CHANGED,
0,
&pConf->nDistroSyncReinstallChanged);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFConfigReadProxySettings(
pSection,
pConf);
BAIL_ON_TDNF_ERROR(dwError);
dwError = _TDNFConfigReadPluginSettings(
pSection,
pTdnf);
BAIL_ON_TDNF_ERROR(dwError);
if (pConf->pszRepoDir == NULL)
pConf->pszRepoDir = strdup(TDNF_DEFAULT_REPO_LOCATION);
if (pConf->pszCacheDir == NULL)
pConf->pszCacheDir = strdup(TDNF_DEFAULT_CACHE_LOCATION);
if (pConf->pszDistroVerPkg == NULL)
pConf->pszDistroVerPkg = strdup(TDNF_DEFAULT_DISTROVERPKG);
/* We need a copy of pszConfFile because dirname() modifies its argument */
dwError = TDNFAllocateString(pszConfFile, &pszConfFileCopy);
@ -197,10 +260,6 @@ TDNFReadConfig(
pTdnf->pConf = pConf;
cleanup:
if(pData)
{
TDNFFreeConfigData(pData);
}
TDNF_SAFE_FREE_MEMORY(pszConfFileCopy);
TDNF_SAFE_FREE_MEMORY(pszConfFileCopy2);
TDNF_SAFE_FREE_MEMORY(pszMinVersionsDir);
@ -265,79 +324,6 @@ error:
goto cleanup;
}
uint32_t
TDNFConfigReadProxySettings(
PCONF_SECTION pSection,
PTDNF_CONF pConf)
{
uint32_t dwError = 0;
char* pszProxyUser = NULL;
char* pszProxyPass = NULL;
if(!pSection || !pConf)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
//optional proxy server
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_PROXY,
NULL,
&pConf->pszProxy);
if(dwError == ERROR_TDNF_NO_DATA)
{
dwError = 0;
}
BAIL_ON_TDNF_ERROR(dwError);
if(!IsNullOrEmptyString(pConf->pszProxy))
{
//optional proxy user
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_PROXY_USER,
NULL,
&pszProxyUser);
if(dwError == ERROR_TDNF_NO_DATA)
{
dwError = 0;
}
BAIL_ON_TDNF_ERROR(dwError);
//optional proxy pass
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_PROXY_PASS,
NULL,
&pszProxyPass);
if(dwError == ERROR_TDNF_NO_DATA)
{
dwError = 0;
}
BAIL_ON_TDNF_ERROR(dwError);
if(!IsNullOrEmptyString(pszProxyUser) &&
!IsNullOrEmptyString(pszProxyPass))
{
dwError = TDNFAllocateStringPrintf(
&pConf->pszProxyUserPass,
"%s:%s",
pszProxyUser,
pszProxyPass);
BAIL_ON_TDNF_ERROR(dwError);
}
}
cleanup:
TDNF_SAFE_FREE_MEMORY(pszProxyUser);
TDNF_SAFE_FREE_MEMORY(pszProxyPass);
return dwError;
error:
goto cleanup;
}
void
TDNFFreeConfig(
PTDNF_CONF pConf
@ -413,94 +399,6 @@ error:
goto cleanup;
}
/*
* Read the following settings from tdnf.conf
* plugins - 0/1. 0 = no plugins. default is 0
* pluginpath - path to look for plugin libraries. default /usr/lib/tdnf-plugins
* pluginconfpath - path to look for plugin config files. default /etc/tdnf/pluginconf.d
*/
static
uint32_t
_TDNFConfigReadPluginSettings(
PCONF_SECTION pSection,
PTDNF pTdnf
)
{
uint32_t dwError = 0;
char *pszValue = NULL;
int nPlugins = 0;
if(!pSection || !pTdnf)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
/* if there is a command line override to deactivate plugins, exit early */
dwError = TDNFHasOpt(pTdnf->pArgs, TDNF_CONF_KEY_NO_PLUGINS, &nPlugins);
BAIL_ON_TDNF_ERROR(dwError);
if (nPlugins)
{
goto cleanup;
}
/* plugins option to enable or deactivate plugins. default 0 */
dwError = TDNFReadKeyValueInt(
pSection,
TDNF_CONF_KEY_PLUGINS,
TDNF_DEFAULT_PLUGINS_ENABLED,
&nPlugins);
BAIL_ON_TDNF_ERROR(dwError);
/*
* config file having a plugins=0 setting is the same as
* --noplugins from cmd line
*/
if (nPlugins == 0)
{
dwError = TDNFSetOpt(
pTdnf->pArgs,
TDNF_CONF_KEY_NO_PLUGINS, "1");
BAIL_ON_TDNF_ERROR(dwError);
/* no further reads required */
goto cleanup;
}
/* plugin conf path - default to /etc/tdnf/pluginconf.d */
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_PLUGIN_CONF_PATH,
TDNF_DEFAULT_PLUGIN_CONF_PATH,
&pszValue);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFSetOpt(pTdnf->pArgs, TDNF_CONF_KEY_PLUGIN_CONF_PATH, pszValue);
BAIL_ON_TDNF_ERROR(dwError);
TDNFFreeMemory(pszValue);
pszValue = NULL;
/* plugin path - default to /usr/lib/tdnf-plugins */
dwError = TDNFReadKeyValue(
pSection,
TDNF_CONF_KEY_PLUGIN_PATH,
TDNF_DEFAULT_PLUGIN_PATH,
&pszValue);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFSetOpt(pTdnf->pArgs, TDNF_CONF_KEY_PLUGIN_PATH, pszValue);
BAIL_ON_TDNF_ERROR(dwError);
cleanup:
TDNF_SAFE_FREE_MEMORY(pszValue);
return dwError;
error:
goto cleanup;
}
/*
* Read all minimal versions files from pszDir, and store results into
* string array pointed to by pppszLines. pppszLines may already

View File

@ -56,6 +56,7 @@
#include "defines.h"
#include "structs.h"
#include "../common/config.h"
#include "../common/structs.h"
#include "../common/prototypes.h"
#include "prototypes.h"

View File

@ -9,6 +9,11 @@
#include "includes.h"
#include <dlfcn.h>
#include "../llconf/nodes.h"
#include "../llconf/modules.h"
#include "../llconf/entry.h"
#include "../llconf/ini.h"
struct plugin_config
{
PTDNF_CMD_ARGS pArgs;
@ -218,6 +223,12 @@ _TDNFFreePlugin(
}
}
static
int isTrue(const char *str)
{
return strcasecmp(str, "true") == 0 || atoi(str) != 0;
}
/* read config file */
static
uint32_t
@ -228,8 +239,8 @@ _TDNFLoadPluginConfig(
{
uint32_t dwError = 0;
PTDNF_PLUGIN pPlugin = NULL;
PCONF_DATA pData = NULL;
PCONF_SECTION pSection = NULL;
struct cnfnode *cn_conf, *cn_section, *cn;
struct cnfmodule *mod_ini;
if(IsNullOrEmptyString(pszConfigFile) || !ppPlugin)
{
@ -237,34 +248,53 @@ _TDNFLoadPluginConfig(
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadConfigFile(pszConfigFile, 0, &pData);
BAIL_ON_TDNF_ERROR(dwError);
mod_ini = find_cnfmodule("ini");
if (mod_ini == NULL) {
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
cn_conf = cnfmodule_parse_file(mod_ini, pszConfigFile);
if (cn_conf == NULL)
{
if (errno != 0)
{
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}
else
{
dwError = ERROR_TDNF_CONF_FILE_LOAD;
BAIL_ON_TDNF_ERROR(dwError);
}
}
dwError = TDNFAllocateMemory(1, sizeof(*pPlugin), (void **)&pPlugin);
BAIL_ON_TDNF_ERROR(dwError);
for(pSection = pData->pSections; pSection; pSection = pSection->pNext)
/* cn_conf == NULL => we will not reach here */
/* coverity[var_deref_op] */
for(cn_section = cn_conf->first_child; cn_section; cn_section = cn_section->next)
{
/* look for main section only */
if (strcmp(pSection->pszName, TDNF_PLUGIN_CONF_MAIN_SECTION) != 0)
{
if (cn_section->name[0] == '.')
continue;
if (strcmp(cn_section->name, TDNF_PLUGIN_CONF_MAIN_SECTION) == 0)
{
for(cn = cn_section->first_child; cn; cn = cn->next)
{
if ((cn->name[0] == '.') || (cn->value == NULL))
continue;
if (strcmp(cn->name, TDNF_PLUGIN_CONF_KEY_ENABLED) == 0)
{
pPlugin->nEnabled = isTrue(cn->value);
}
}
}
dwError = TDNFReadKeyValueBoolean(
pSection,
TDNF_PLUGIN_CONF_KEY_ENABLED,
0,
&pPlugin->nEnabled);
BAIL_ON_TDNF_ERROR(dwError);
}
*ppPlugin = pPlugin;
cleanup:
if(pData)
{
TDNFFreeConfigData(pData);
}
return dwError;
error:

View File

@ -20,6 +20,10 @@
#include "includes.h"
#include "../llconf/nodes.h"
#include "../llconf/modules.h"
#include "../llconf/entry.h"
#include "../llconf/ini.h"
uint32_t
TDNFLoadRepoData(
@ -373,13 +377,13 @@ error:
uint32_t
TDNFEventRepoReadConfigEnd(
PTDNF pTdnf,
PCONF_SECTION pSection
struct cnfnode *cn_section
)
{
uint32_t dwError = 0;
TDNF_EVENT_CONTEXT stContext = {0};
if (!pTdnf || !pSection)
if (!pTdnf || !cn_section)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
@ -391,7 +395,7 @@ TDNFEventRepoReadConfigEnd(
TDNF_PLUGIN_EVENT_PHASE_END);
dwError = TDNFAddEventDataPtr(&stContext,
TDNF_EVENT_ITEM_REPO_SECTION,
pSection);
cn_section);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFPluginRaiseEvent(pTdnf, &stContext);
@ -407,13 +411,13 @@ error:
uint32_t
TDNFEventRepoReadConfigStart(
PTDNF pTdnf,
PCONF_SECTION pSection
struct cnfnode *cn_section
)
{
uint32_t dwError = 0;
TDNF_EVENT_CONTEXT stContext = {0};
if (!pTdnf || !pSection)
if (!pTdnf || !cn_section)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
@ -425,7 +429,7 @@ TDNFEventRepoReadConfigStart(
TDNF_PLUGIN_EVENT_PHASE_START);
dwError = TDNFAddEventDataPtr(&stContext,
TDNF_EVENT_ITEM_REPO_SECTION,
pSection);
cn_section);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFPluginRaiseEvent(pTdnf, &stContext);
@ -438,6 +442,12 @@ error:
goto cleanup;
}
static
int isTrue(const char *str)
{
return strcasecmp(str, "true") == 0 || atoi(str) != 0;
}
uint32_t
TDNFLoadReposFromFile(
PTDNF pTdnf,
@ -445,213 +455,163 @@ TDNFLoadReposFromFile(
PTDNF_REPO_DATA* ppRepos
)
{
char *pszRepo = NULL;
uint32_t dwError = 0;
char *pszMetadataExpire = NULL;
PTDNF_REPO_DATA pRepos = NULL;
PTDNF_REPO_DATA pRepo = NULL;
PCONF_DATA pData = NULL;
PCONF_SECTION pSections = NULL;
struct cnfnode *cn_conf, *cn_section, *cn;
struct cnfmodule *mod_ini;
dwError = TDNFReadConfigFile(pszRepoFile, 0, &pData);
BAIL_ON_TDNF_ERROR(dwError);
mod_ini = find_cnfmodule("ini");
if (mod_ini == NULL) {
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pSections = pData->pSections;
for(; pSections; pSections = pSections->pNext)
cn_conf = cnfmodule_parse_file(mod_ini, pszRepoFile);
if (cn_conf == NULL)
{
if (errno != 0)
{
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}
else
{
dwError = ERROR_TDNF_CONF_FILE_LOAD;
BAIL_ON_TDNF_ERROR(dwError);
}
}
/* cn_conf == NULL => we will not reach here */
/* coverity[var_deref_op] */
for(cn_section = cn_conf->first_child; cn_section; cn_section = cn_section->next)
{
if ((cn_section->name[0] == '.'))
continue;
dwError = TDNFCreateRepo(&pRepo, cn_section->name);
BAIL_ON_TDNF_ERROR(dwError);
/* plugin event repo readconfig start */
dwError = TDNFEventRepoReadConfigStart(pTdnf, pSections);
dwError = TDNFEventRepoReadConfigStart(pTdnf, cn_section);
BAIL_ON_TDNF_ERROR(dwError);
pszRepo = pSections->pszName;
dwError = TDNFAllocateMemory(
1,
sizeof(TDNF_REPO_DATA),
(void**)&pRepo);
BAIL_ON_TDNF_ERROR(dwError);
pRepo->nHasMetaData = 1;
dwError = TDNFAllocateString(pszRepo, &pRepo->pszId);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSections,
TDNF_REPO_KEY_ENABLED,
TDNF_REPO_DEFAULT_ENABLED,
&pRepo->nEnabled);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSections,
TDNF_REPO_KEY_NAME,
pszRepo,
&pRepo->pszName);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueStringArray(
pSections,
TDNF_REPO_KEY_BASEURL,
&pRepo->ppszBaseUrls);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSections,
TDNF_REPO_KEY_METALINK,
NULL,
&pRepo->pszMetaLink);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSections,
TDNF_REPO_KEY_SKIP,
TDNF_REPO_DEFAULT_SKIP,
&pRepo->nSkipIfUnavailable);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSections,
TDNF_REPO_KEY_GPGCHECK,
TDNF_REPO_DEFAULT_GPGCHECK,
&pRepo->nGPGCheck);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueStringArray(
pSections,
TDNF_REPO_KEY_GPGKEY,
&pRepo->ppszUrlGPGKeys);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSections,
TDNF_REPO_KEY_USERNAME,
NULL,
&pRepo->pszUser);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSections,
TDNF_REPO_KEY_PASSWORD,
NULL,
&pRepo->pszPass);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueInt(
pSections,
TDNF_REPO_KEY_PRIORITY,
TDNF_REPO_DEFAULT_PRIORITY,
&pRepo->nPriority);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueInt(
pSections,
TDNF_REPO_KEY_TIMEOUT,
TDNF_REPO_DEFAULT_TIMEOUT,
&pRepo->nTimeout);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueInt(
pSections,
TDNF_REPO_KEY_RETRIES,
TDNF_REPO_DEFAULT_RETRIES,
&pRepo->nRetries);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueInt(
pSections,
TDNF_REPO_KEY_MINRATE,
TDNF_REPO_DEFAULT_MINRATE,
&pRepo->nMinrate);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueInt(
pSections,
TDNF_REPO_KEY_THROTTLE,
TDNF_REPO_DEFAULT_THROTTLE,
&pRepo->nThrottle);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSections,
TDNF_REPO_KEY_SSL_VERIFY,
TDNF_REPO_DEFAULT_SSLVERIFY,
&pRepo->nSSLVerify);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSections,
TDNF_REPO_KEY_SSL_CA_CERT,
NULL,
&pRepo->pszSSLCaCert);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSections,
TDNF_REPO_KEY_SSL_CLI_CERT,
NULL,
&pRepo->pszSSLClientCert);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSections,
TDNF_REPO_KEY_SSL_CLI_KEY,
NULL,
&pRepo->pszSSLClientKey);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSections,
TDNF_REPO_KEY_METADATA_EXPIRE,
TDNF_REPO_DEFAULT_METADATA_EXPIRE_STR,
&pszMetadataExpire);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFParseMetadataExpire(
pszMetadataExpire,
&pRepo->lMetadataExpire);
BAIL_ON_TDNF_ERROR(dwError);
TDNF_SAFE_FREE_MEMORY(pszMetadataExpire);
pszMetadataExpire = NULL;
dwError = TDNFReadKeyValueBoolean(
pSections,
TDNF_REPO_KEY_SKIP_MD_FILELISTS,
TDNF_REPO_DEFAULT_SKIP_MD_FILELISTS,
&pRepo->nSkipMDFileLists);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSections,
TDNF_REPO_KEY_SKIP_MD_UPDATEINFO,
TDNF_REPO_DEFAULT_SKIP_MD_UPDATEINFO,
&pRepo->nSkipMDUpdateInfo);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSections,
TDNF_REPO_KEY_SKIP_MD_OTHER,
TDNF_REPO_DEFAULT_SKIP_MD_OTHER,
&pRepo->nSkipMDOther);
BAIL_ON_TDNF_ERROR(dwError);
for(cn = cn_section->first_child; cn; cn = cn->next)
{
if ((cn->name[0] == '.') || (cn->value == NULL))
continue;
if (strcmp(cn->name, TDNF_REPO_KEY_ENABLED) == 0)
{
pRepo->nEnabled = isTrue(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_NAME) == 0)
{
pRepo->pszName = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_BASEURL) == 0)
{
dwError = TDNFSplitStringToArray(cn->value,
" ", &pRepo->ppszBaseUrls);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_METALINK) == 0)
{
pRepo->pszMetaLink = strdup(cn->value);
}
if (strcmp(cn->name, TDNF_REPO_KEY_SKIP) == 0)
{
pRepo->nSkipIfUnavailable = isTrue(cn->value);
}
if (strcmp(cn->name, TDNF_REPO_KEY_GPGCHECK) == 0)
{
pRepo->nGPGCheck = isTrue(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_GPGKEY) == 0)
{
dwError = TDNFSplitStringToArray(cn->value,
" ", &pRepo->ppszUrlGPGKeys);
BAIL_ON_TDNF_ERROR(dwError);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_USERNAME) == 0)
{
pRepo->pszUser = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_PASSWORD) == 0)
{
pRepo->pszPass = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_PRIORITY) == 0)
{
pRepo->nPriority = atoi(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_TIMEOUT) == 0)
{
pRepo->nTimeout = atoi(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_RETRIES) == 0)
{
pRepo->nRetries = atoi(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_MINRATE) == 0)
{
pRepo->nMinrate = atoi(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_THROTTLE) == 0)
{
pRepo->nThrottle = atoi(cn->value);
}
if (strcmp(cn->name, TDNF_REPO_KEY_SSL_VERIFY) == 0)
{
pRepo->nSSLVerify = isTrue(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_SSL_CA_CERT) == 0)
{
pRepo->pszSSLCaCert = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_SSL_CLI_CERT) == 0)
{
pRepo->pszSSLClientCert = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_SSL_CLI_KEY) == 0)
{
pRepo->pszSSLClientKey = strdup(cn->value);
}
else if (strcmp(cn->name, TDNF_REPO_KEY_METADATA_EXPIRE) == 0)
{
dwError = TDNFParseMetadataExpire(
cn->value,
&pRepo->lMetadataExpire);
BAIL_ON_TDNF_ERROR(dwError);
}
if (strcmp(cn->name, TDNF_REPO_KEY_SKIP_MD_FILELISTS) == 0)
{
pRepo->nSkipMDFileLists = isTrue(cn->value);
}
if (strcmp(cn->name, TDNF_REPO_KEY_SKIP_MD_UPDATEINFO) == 0)
{
pRepo->nSkipMDUpdateInfo = isTrue(cn->value);
}
if (strcmp(cn->name, TDNF_REPO_KEY_SKIP_MD_OTHER) == 0)
{
pRepo->nSkipMDOther = isTrue(cn->value);
}
}
/* plugin event repo readconfig end */
dwError = TDNFEventRepoReadConfigEnd(pTdnf, pSections);
dwError = TDNFEventRepoReadConfigEnd(pTdnf, cn_section);
BAIL_ON_TDNF_ERROR(dwError);
pRepo->pNext = pRepos;
pRepos = pRepo;
pRepo = NULL;
}
destroy_cnftree(cn_conf);
*ppRepos = pRepos;
cleanup:
if(pData)
{
TDNFFreeConfigData(pData);
}
TDNF_SAFE_FREE_MEMORY(pszMetadataExpire);
return dwError;

View File

@ -9,7 +9,6 @@
include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(${LIB_TDNF_COMMON} STATIC
configreader.c
memory.c
setopt.c
strings.c

121
common/config.h Normal file
View File

@ -0,0 +1,121 @@
#define STR_IS_TRUE(s) ((s) && (!strcmp((s), "1") || !strcasecmp((s), "true")))
//Misc
#define TDNF_RPM_EXT ".rpm"
#define TDNF_NAME "tdnf"
#define DIR_SEPARATOR '/'
#define SOLV_PATCH_MARKER "patch:"
//repomd type
#define TDNF_REPOMD_TYPE_PRIMARY "primary"
#define TDNF_REPOMD_TYPE_FILELISTS "filelists"
#define TDNF_REPOMD_TYPE_UPDATEINFO "updateinfo"
#define TDNF_REPOMD_TYPE_OTHER "other"
//Repo defines
#define TDNF_REPO_EXT ".repo"
#define TDNF_CONF_FILE "/etc/tdnf/tdnf.conf"
#define TDNF_CONF_GROUP "main"
//Conf file key names
#define TDNF_CONF_KEY_GPGCHECK "gpgcheck"
#define TDNF_CONF_KEY_INSTALLONLY_LIMIT "installonly_limit"
#define TDNF_CONF_KEY_CLEAN_REQ_ON_REMOVE "clean_requirements_on_remove"
#define TDNF_CONF_KEY_REPODIR "repodir"
#define TDNF_CONF_KEY_CACHEDIR "cachedir"
#define TDNF_CONF_KEY_PERSISTDIR "persistdir"
#define TDNF_CONF_KEY_PROXY "proxy"
#define TDNF_CONF_KEY_PROXY_USER "proxy_username"
#define TDNF_CONF_KEY_PROXY_PASS "proxy_password"
#define TDNF_CONF_KEY_KEEP_CACHE "keepcache"
#define TDNF_CONF_KEY_DISTROVERPKG "distroverpkg"
#define TDNF_CONF_KEY_DISTROARCHPKG "distroarchpkg"
#define TDNF_CONF_KEY_MAX_STRING_LEN "maxstringlen"
#define TDNF_CONF_KEY_PLUGINS "plugins"
#define TDNF_CONF_KEY_NO_PLUGINS "noplugins"
#define TDNF_CONF_KEY_PLUGIN_PATH "pluginpath"
#define TDNF_CONF_KEY_PLUGIN_CONF_PATH "pluginconfpath"
#define TDNF_PLUGIN_CONF_KEY_ENABLED "enabled"
#define TDNF_CONF_KEY_EXCLUDE "excludepkgs"
#define TDNF_CONF_KEY_MINVERSIONS "minversions"
#define TDNF_CONF_KEY_OPENMAX "openmax"
#define TDNF_CONF_KEY_CHECK_UPDATE_COMPAT "dnf_check_update_compat"
#define TDNF_CONF_KEY_DISTROSYNC_REINSTALL_CHANGED "distrosync_reinstall_changed"
//Repo file key names
#define TDNF_REPO_KEY_BASEURL "baseurl"
#define TDNF_REPO_KEY_ENABLED "enabled"
#define TDNF_REPO_KEY_METALINK "metalink"
#define TDNF_REPO_KEY_NAME "name"
#define TDNF_REPO_KEY_SKIP "skip_if_unavailable"
#define TDNF_REPO_KEY_GPGCHECK "gpgcheck"
#define TDNF_REPO_KEY_GPGKEY "gpgkey"
#define TDNF_REPO_KEY_USERNAME "username"
#define TDNF_REPO_KEY_PASSWORD "password"
#define TDNF_REPO_KEY_PRIORITY "priority"
#define TDNF_REPO_KEY_METADATA_EXPIRE "metadata_expire"
#define TDNF_REPO_KEY_TIMEOUT "timeout"
#define TDNF_REPO_KEY_RETRIES "retries"
#define TDNF_REPO_KEY_MINRATE "minrate"
#define TDNF_REPO_KEY_THROTTLE "throttle"
#define TDNF_REPO_KEY_SSL_VERIFY "sslverify"
#define TDNF_REPO_KEY_SSL_CA_CERT "sslcacert"
#define TDNF_REPO_KEY_SSL_CLI_CERT "sslclientcert"
#define TDNF_REPO_KEY_SSL_CLI_KEY "sslclientkey"
#define TDNF_REPO_KEY_SKIP_MD_FILELISTS "skip_md_filelists"
#define TDNF_REPO_KEY_SKIP_MD_UPDATEINFO "skip_md_updateinfo"
#define TDNF_REPO_KEY_SKIP_MD_OTHER "skip_md_other"
//setopt keys
#define TDNF_SETOPT_KEY_REPOSDIR "reposdir"
//file names
#define TDNF_REPO_METADATA_MARKER "lastrefresh"
#define TDNF_REPO_METADATA_FILE_PATH "repodata/repomd.xml"
#define TDNF_REPO_METADATA_FILE_NAME "repomd.xml"
#define TDNF_REPO_METALINK_FILE_NAME "metalink"
#define TDNF_REPO_BASEURL_FILE_NAME "baseurl"
#define TDNF_AUTOINSTALLED_FILE "autoinstalled"
#define TDNF_HISTORY_DB_FILE "history.db"
#define TDNF_DEFAULT_DATA_LOCATION "/var/lib/tdnf"
// repo defaults
#define TDNF_DEFAULT_REPO_LOCATION "/etc/yum.repos.d"
#define TDNF_DEFAULT_CACHE_LOCATION "/var/cache/tdnf"
#define TDNF_DEFAULT_DISTROVERPKG "system-release"
#define TDNF_DEFAULT_DISTROARCHPKG "x86_64"
#define TDNF_RPM_CACHE_DIR_NAME "rpms"
#define TDNF_REPODATA_DIR_NAME "repodata"
#define TDNF_SOLVCACHE_DIR_NAME "solvcache"
#define TDNF_REPO_METADATA_EXPIRE_NEVER "never"
#define TDNF_DEFAULT_OPENMAX 1024
// repo default settings
#define TDNF_REPO_DEFAULT_ENABLED 0
#define TDNF_REPO_DEFAULT_SKIP 0
#define TDNF_REPO_DEFAULT_GPGCHECK 1
#define TDNF_REPO_DEFAULT_MINRATE 0
#define TDNF_REPO_DEFAULT_THROTTLE 0
#define TDNF_REPO_DEFAULT_TIMEOUT 0
#define TDNF_REPO_DEFAULT_SSLVERIFY 1
#define TDNF_REPO_DEFAULT_RETRIES 10
#define TDNF_REPO_DEFAULT_PRIORITY 50
#define TDNF_REPO_DEFAULT_METADATA_EXPIRE 172800 // 48 hours in seconds
#define TDNF_REPO_DEFAULT_METADATA_EXPIRE_STR STRINGIFYX(TDNF_REPO_DEFAULT_METADATA_EXPIRE)
#define TDNF_REPO_DEFAULT_SKIP_MD_FILELISTS 0
#define TDNF_REPO_DEFAULT_SKIP_MD_UPDATEINFO 0
#define TDNF_REPO_DEFAULT_SKIP_MD_OTHER 0
// var names
#define TDNF_VAR_RELEASEVER "$releasever"
#define TDNF_VAR_BASEARCH "$basearch"
/* dummy setopt values */
#define TDNF_SETOPT_NAME_DUMMY "opt.dummy.name"
#define TDNF_SETOPT_VALUE_DUMMY "opt.dummy.value"
/* plugin defines */
#define TDNF_DEFAULT_PLUGINS_ENABLED 0
#define TDNF_DEFAULT_PLUGIN_PATH SYSTEM_LIBDIR"/tdnf-plugins"
#define TDNF_DEFAULT_PLUGIN_CONF_PATH "/etc/tdnf/pluginconf.d"
#define TDNF_PLUGIN_CONF_EXT ".conf"
#define TDNF_PLUGIN_CONF_EXT_LEN 5
#define TDNF_PLUGIN_CONF_MAIN_SECTION "main"

View File

@ -1,697 +0,0 @@
/*
* Copyright (C) 2015-2021 VMware, Inc. All Rights Reserved.
*
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
* you may not use this file except in compliance with the License. The terms
* of the License are located in the COPYING file of this distribution.
*/
#include "includes.h"
uint32_t TDNFConfSectionDefault(
PCONF_DATA pData,
const char *pszSection
);
uint32_t TDNFConfKeyvalueDefault(
PCONF_DATA pData,
const char *psKey,
const char *pszValue
);
static PFN_CONF_SECTION_CB pfnConfSectionCB = TDNFConfSectionDefault;
static PFN_CONF_KEYVALUE_CB pfnConfKeyValueCB = TDNFConfKeyvalueDefault;
void
TDNFPrintConfigData(
PCONF_DATA pData
)
{
PCONF_SECTION pSection = NULL;
PKEYVALUE pKeyValue = NULL;
if(!pData) return;
pr_info("File: %s\n", pData->pszConfFile);
pSection = pData->pSections;
while(pSection)
{
pr_info("[%s]\n", pSection->pszName);
pKeyValue = pSection->pKeyValues;
while(pKeyValue)
{
pr_info("%s=%s\n", pKeyValue->pszKey, pKeyValue->pszValue);
pKeyValue = pKeyValue->pNext;
}
pSection = pSection->pNext;
}
}
uint32_t
TDNFGetSectionBoundaries(
const char *pszLine,
const char **ppszStart,
const char **ppszEnd
)
{
uint32_t dwError = 0;
const char *pszEnd = NULL;
const char *pszStart = NULL;
pszStart = strchr(pszLine, '[');
if(!pszStart)
{
dwError = ENOENT;
BAIL_ON_TDNF_ERROR(dwError);
}
pszEnd = strrchr(pszLine, ']');
if(!pszEnd)
{
dwError = ENOENT;
BAIL_ON_TDNF_ERROR(dwError);
}
if(pszEnd < pszStart)
{
dwError = ENOENT;
BAIL_ON_TDNF_ERROR(dwError);
}
*ppszStart = pszStart;
*ppszEnd = pszEnd;
cleanup:
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFGetSection(
const char *pszLine,
char **ppszSection
)
{
uint32_t dwError = 0;
char *pszSection = NULL;
const char *pszStart = NULL;
const char *pszEnd = NULL;
dwError = TDNFGetSectionBoundaries(pszLine, &pszStart, &pszEnd);
BAIL_ON_TDNF_ERROR(dwError);
pszStart = TDNFLeftTrim(pszStart + 1);
pszEnd = TDNFRightTrim(pszStart, pszEnd - 1);
dwError = TDNFAllocateMemory(
pszEnd - pszStart + 2,
1,
(void**)&pszSection);
BAIL_ON_TDNF_ERROR(dwError);
memcpy(pszSection, pszStart, pszEnd - pszStart + 1);
*ppszSection = pszSection;
cleanup:
return dwError;
error:
if(ppszSection)
{
*ppszSection = NULL;
}
goto cleanup;
}
uint32_t
TDNFIsSection(
const char *pszLine,
int *pnSection
)
{
uint32_t dwError = 0;
const char *pszStart = NULL;
const char *pszEnd = NULL;
dwError = TDNFGetSectionBoundaries(pszLine, &pszStart, &pszEnd);
BAIL_ON_TDNF_ERROR(dwError);
*pnSection = 1;
cleanup:
return dwError;
error:
if(pnSection)
{
*pnSection = 0;
}
if(dwError == ENOENT)
{
dwError = 0;
}
goto cleanup;
}
void
TDNFFreeKeyValues(
PKEYVALUE pKeyValue
)
{
if(!pKeyValue)
{
return;
}
while(pKeyValue)
{
PKEYVALUE pKeyValueTemp = pKeyValue->pNext;
TDNF_SAFE_FREE_MEMORY(pKeyValue->pszKey);
TDNF_SAFE_FREE_MEMORY(pKeyValue->pszValue);
TDNF_SAFE_FREE_MEMORY(pKeyValue);
pKeyValue = pKeyValueTemp;
}
}
void
TdnfFreeConfigSections(
PCONF_SECTION pSection
)
{
if(!pSection)
{
return;
}
while(pSection)
{
PCONF_SECTION pSectionTemp = pSection->pNext;
TDNFFreeKeyValues(pSection->pKeyValues);
TDNF_SAFE_FREE_MEMORY(pSection->pszName);
TDNF_SAFE_FREE_MEMORY(pSection);
pSection = pSectionTemp;
}
}
void
TDNFFreeConfigData(
PCONF_DATA pData
)
{
if(!pData)
{
return;
}
TdnfFreeConfigSections(pData->pSections);
TDNF_SAFE_FREE_MEMORY(pData->pszConfFile);
TDNF_SAFE_FREE_MEMORY(pData);
}
uint32_t
TDNFConfSectionDefault(
PCONF_DATA pData,
const char *pszSection
)
{
uint32_t dwError = 0;
PCONF_SECTION pNewSection = NULL;
PCONF_SECTION pSection = NULL;
if(!pData || IsNullOrEmptyString(pszSection))
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pSection = pData->pSections;
while(pSection && pSection->pNext) pSection = pSection->pNext;
dwError = TDNFAllocateMemory(1, sizeof(CONF_SECTION), (void **)&pNewSection);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateString(pszSection, &pNewSection->pszName);
BAIL_ON_TDNF_ERROR(dwError);
if(pSection)
{
pSection->pNext = pNewSection;
}
else
{
pData->pSections = pNewSection;
}
pNewSection = NULL;
cleanup:
return dwError;
error:
if(pNewSection)
{
TdnfFreeConfigSections(pNewSection);
}
goto cleanup;
}
uint32_t
TDNFConfKeyvalueDefault(
PCONF_DATA pData,
const char *pszKey,
const char *pszValue
)
{
uint32_t dwError = 0;
char *pszEq = NULL;
PCONF_SECTION pSection = NULL;
PKEYVALUE pNewKeyValue = NULL;
PKEYVALUE pKeyValue = NULL;
const char *pszTemp = NULL;
const char *pszTempEnd = NULL;
//Allow for empty values
if(!pData || IsNullOrEmptyString(pszKey))
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pszEq = strchr(pszKey, '=');
if(!pszEq)
{
pr_err("keyvalue lines must be of format key=value\n");
dwError = EDOM;
BAIL_ON_TDNF_ERROR(dwError);
}
pSection = pData->pSections;
for(;pSection && pSection->pNext; pSection = pSection->pNext);
if(!pSection)
{
pr_err("conf file must start with a section");
dwError = EINVAL;
BAIL_ON_TDNF_ERROR(dwError);
}
pKeyValue = pSection->pKeyValues;
for(;pKeyValue && pKeyValue->pNext; pKeyValue = pKeyValue->pNext);
pszTemp = TDNFRightTrim(pszValue, pszEq - 1);
pszTemp++;
dwError = TDNFAllocateMemory(sizeof(KEYVALUE), 1, (void**)&pNewKeyValue);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateMemory(
pszTemp - pszValue + 1,
1,
(void**)&pNewKeyValue->pszKey);
BAIL_ON_TDNF_ERROR(dwError);
strncpy(pNewKeyValue->pszKey, pszValue, pszTemp - pszValue);
pszTemp = TDNFLeftTrim(pszEq + 1);
pszTempEnd = TDNFRightTrim(pszTemp, pszTemp + strlen(pszTemp) - 1);
dwError = TDNFAllocateMemory(
pszTempEnd - pszTemp + 2,
1,
(void**)&pNewKeyValue->pszValue);
BAIL_ON_TDNF_ERROR(dwError);
strncpy(pNewKeyValue->pszValue, pszTemp, pszTempEnd - pszTemp + 1);
if(pKeyValue)
{
pKeyValue->pNext = pNewKeyValue;
}
else
{
pSection->pKeyValues = pNewKeyValue;
}
cleanup:
return dwError;
error:
TDNFFreeKeyValues(pNewKeyValue);
goto cleanup;
}
uint32_t
TDNFProcessConfigLine(
const char *pszLine,
PCONF_DATA pData
)
{
uint32_t dwError = 0;
int nSection = 0;
if(IsNullOrEmptyString(pszLine) || !pData)
{
dwError = EINVAL;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFIsSection(pszLine, &nSection);
BAIL_ON_TDNF_ERROR(dwError);
if(nSection && pfnConfSectionCB)
{
char *pszSection = NULL;
dwError = TDNFGetSection(pszLine, &pszSection);
BAIL_ON_TDNF_ERROR(dwError);
dwError = pfnConfSectionCB(pData, pszSection);
BAIL_ON_TDNF_ERROR(dwError);
TDNF_SAFE_FREE_MEMORY(pszSection);
}
else if(pfnConfKeyValueCB)
{
if(strchr(pszLine, '='))
{
dwError = pfnConfKeyValueCB(pData, pszLine, pszLine);
BAIL_ON_TDNF_ERROR(dwError);
}
}
cleanup:
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFReadConfigFile(
const char *pszFile,
const int nLineLength,
PCONF_DATA *ppData
)
{
uint32_t dwError = 0;
FILE *fp = NULL;
char *pszLine = NULL;
PCONF_DATA pData = NULL;
int nMaxLineLength = 0;
if(IsNullOrEmptyString(pszFile) || !ppData)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
fp = fopen(pszFile, "r");
if(!fp)
{
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}
dwError = TDNFAllocateMemory(1, sizeof(CONF_DATA), (void **)&pData);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateString(pszFile, &pData->pszConfFile);
BAIL_ON_TDNF_ERROR(dwError);
nMaxLineLength = nLineLength > MAX_CONFIG_LINE_LENGTH ?
nLineLength : MAX_CONFIG_LINE_LENGTH;
dwError = TDNFAllocateMemory(1, nMaxLineLength, (void **)&pszLine);
BAIL_ON_TDNF_ERROR(dwError);
if(fp)
{
while(fgets(pszLine, nMaxLineLength, fp) != NULL)
{
const char *pszTrimmedLine = TDNFLeftTrim(pszLine);
//ignore empty lines, comments
if(IsNullOrEmptyString(pszTrimmedLine) || *pszTrimmedLine == '#')
{
continue;
}
dwError = TDNFProcessConfigLine(pszTrimmedLine, pData);
BAIL_ON_TDNF_ERROR(dwError);
}
}
*ppData = pData;
cleanup:
TDNF_SAFE_FREE_MEMORY(pszLine);
if(fp)
{
fclose(fp);
}
return dwError;
error:
if(ppData)
{
*ppData = NULL;
}
TDNFFreeConfigData (pData);
goto cleanup;
}
uint32_t
TDNFConfigGetSection(
PCONF_DATA pData,
const char *pszGroup,
PCONF_SECTION *ppSection
)
{
uint32_t dwError = 0;
PCONF_SECTION pSections = NULL;
PCONF_SECTION pSection = NULL;
if(!pData || IsNullOrEmptyString(pszGroup) || !ppSection)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pSections = pData->pSections;
for(; pSections; pSections = pSections->pNext)
{
if(!strcmp(pszGroup, pSections->pszName))
{
pSection = pSections;
break;
}
}
if(!pSection)
{
dwError = ENOENT;
BAIL_ON_TDNF_ERROR(dwError);
}
*ppSection = pSection;
cleanup:
return dwError;
error:
if(ppSection)
{
*ppSection = NULL;
}
goto cleanup;
}
uint32_t
TDNFReadKeyValueBoolean(
PCONF_SECTION pSection,
const char* pszKeyName,
int nDefault,
int* pnValue
)
{
uint32_t dwError = 0;
char* pszValue = NULL;
int nValue = 0;
if(!pSection || !pszKeyName || !pnValue)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadKeyValue(
pSection,
pszKeyName,
NULL,
&pszValue);
BAIL_ON_TDNF_ERROR(dwError);
if(pszValue)
{
if(!strcmp(pszValue, "1") || !strcasecmp(pszValue, "true"))
{
nValue = 1;
}
}
else
{
nValue = nDefault;
}
*pnValue = nValue;
cleanup:
TDNF_SAFE_FREE_MEMORY(pszValue);
return dwError;
error:
if(pnValue)
{
*pnValue = 0;
}
goto cleanup;
}
uint32_t
TDNFReadKeyValueInt(
PCONF_SECTION pSection,
const char* pszKeyName,
int nDefault,
int* pnValue
)
{
uint32_t dwError = 0;
char* pszValue = NULL;
int nValue = 0;
if(!pSection || !pszKeyName || !pnValue)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadKeyValue(
pSection,
pszKeyName,
NULL,
&pszValue);
BAIL_ON_TDNF_ERROR(dwError);
if(pszValue)
{
nValue = atoi(pszValue);
}
else
{
nValue = nDefault;
}
*pnValue = nValue;
cleanup:
TDNF_SAFE_FREE_MEMORY(pszValue);
return dwError;
error:
if(pnValue)
{
*pnValue = 0;
}
goto cleanup;
}
uint32_t
TDNFReadKeyValueStringArray(
PCONF_SECTION pSection,
const char* pszKeyName,
char*** pppszValueList
)
{
uint32_t dwError = 0;
char** ppszValList = NULL;
PKEYVALUE pKeyValues = NULL;
if (!pSection || !pszKeyName || !pppszValueList)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pKeyValues = pSection->pKeyValues;
for (; pKeyValues; pKeyValues = pKeyValues->pNext)
{
if (strcmp(pszKeyName, pKeyValues->pszKey) == 0)
{
dwError = TDNFSplitStringToArray(pKeyValues->pszValue,
" ", &ppszValList);
BAIL_ON_TDNF_ERROR(dwError);
*pppszValueList = ppszValList;
break;
}
}
cleanup:
return dwError;
error:
if(pppszValueList)
{
*pppszValueList = NULL;
}
goto cleanup;
}
uint32_t
TDNFReadKeyValue(
PCONF_SECTION pSection,
const char* pszKeyName,
const char* pszDefault,
char** ppszValue
)
{
uint32_t dwError = 0;
char* pszVal = NULL;
char* pszValue = NULL;
PKEYVALUE pKeyValues = NULL;
if(!pSection || !pszKeyName || !ppszValue)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pKeyValues = pSection->pKeyValues;
for(; pKeyValues; pKeyValues = pKeyValues->pNext)
{
if(strcmp(pszKeyName, pKeyValues->pszKey) == 0)
{
dwError = TDNFAllocateString(pKeyValues->pszValue, &pszVal);
BAIL_ON_TDNF_ERROR(dwError);
break;
}
}
if(pszVal)
{
dwError = TDNFAllocateString(
pszVal,
&pszValue);
BAIL_ON_TDNF_ERROR(dwError);
}
else if(pszDefault)
{
dwError = TDNFAllocateString(
pszDefault,
&pszValue);
BAIL_ON_TDNF_ERROR(dwError);
}
*ppszValue = pszValue;
cleanup:
TDNF_SAFE_FREE_MEMORY(pszVal);
return dwError;
error:
if(ppszValue)
{
*ppszValue = NULL;
}
TDNF_SAFE_FREE_MEMORY(pszValue);
goto cleanup;
}

View File

@ -143,62 +143,6 @@ TDNFStringArraySort(
char **ppszArray
);
//configreader.c
void
TDNFPrintConfigData(
PCONF_DATA pData
);
uint32_t
TDNFReadConfigFile(
const char *pszFile,
const int nMaxLineLength,
PCONF_DATA *ppData
);
uint32_t
TDNFConfigGetSection(
PCONF_DATA pData,
const char *pszGroup,
PCONF_SECTION *ppSection
);
uint32_t
TDNFReadKeyValue(
PCONF_SECTION pSection,
const char* pszKeyName,
const char* pszDefault,
char** ppszValue
);
uint32_t
TDNFReadKeyValueBoolean(
PCONF_SECTION pSection,
const char* pszKeyName,
int nDefault,
int* pnValue
);
uint32_t
TDNFReadKeyValueInt(
PCONF_SECTION pSection,
const char* pszKeyName,
int nDefault,
int* pnValue
);
uint32_t
TDNFReadKeyValueStringArray(
PCONF_SECTION pSection,
const char* pszKeyName,
char*** pppszValueList
);
void
TDNFFreeConfigData(
PCONF_DATA pData
);
//utils.c
uint32_t
TDNFCreateAndWriteToFile(

View File

@ -262,7 +262,7 @@ struct confline *unparse_ini_subsection(struct cnfnode *cn, struct confline *cl_
struct cnfnode *cn_line;
unsigned int i;
for(i = 0; (i < level*8) && (i < sizeof(buf)-1); i++){
for(i = 0; (i < level*8) && (i < sizeof(ident)-1); i++){
ident[i] = ' ';
}
ident[i] = 0;

View File

@ -277,10 +277,13 @@ int cnfmodule_register_plugin(const char *name, const char *path, struct cnfnode
if((dlerr = dlerror()) == NULL)
fe_reg_func(opt_root);
else{
dlclose(dlh);
return -2;
}
}else{
return -1;
}
/* Technically correct coverity issue (dlh is leaked), but low impact */
/* coverity[leaked_storage] */
return 0;
}

View File

@ -295,6 +295,10 @@ int compare_cnftree(const struct cnfnode *cn_root1, const struct cnfnode *cn_roo
return 3;
}
}
/* Coverity false positive 'Dereferencing null pointer "cn1".':
if cn1 xor cn2 is NULL, compare_cnftree will
return != 0, exiting the loop */
/* coverity[var_deref_op] */
for(cn1 = cn_root1->first_child, cn2 = cn_root2->first_child; cn1 || cn2; cn1 = cn1->next, cn2 = cn2->next){
if((ret = compare_cnftree(cn1, cn2)) != 0)
return ret;

View File

@ -66,6 +66,8 @@ void unlink_node(struct cnfnode *cn);
and returns 1st node with matching name */
struct cnfnode *find_node(struct cnfnode *cn_list, const char *name);
#define find_child(cn_parent, name) find_node(cn_parent->first_child, name)
int compare_cnfnode(const struct cnfnode *cn1, const struct cnfnode *cn2);
int compare_cnftree(const struct cnfnode *cn_root1, const struct cnfnode *cn_root2);
int compare_cnftree_children(const struct cnfnode *cn_root1, const struct cnfnode *cn_root2);

View File

@ -8,6 +8,8 @@
#include "includes.h"
#include "../../llconf/nodes.h"
static
uint32_t
TDNFHasRepo(
@ -49,7 +51,7 @@ TDNFMetalinkReadConfig(
{
uint32_t dwError = 0;
char *pszMetalink = NULL;
PCONF_SECTION pSection = NULL;
struct cnfnode *cn_section = NULL, *cn;
PTDNF_METALINK_DATA pData = NULL;
if (!pHandle || !pHandle->pTdnf || !pContext)
@ -62,15 +64,19 @@ TDNFMetalinkReadConfig(
dwError = TDNFEventContextGetItemPtr(
pContext,
TDNF_EVENT_ITEM_REPO_SECTION,
(const void **)&pSection);
(const void **)&cn_section);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValue(
pSection,
TDNF_REPO_CONFIG_METALINK_KEY,
NULL,
&pszMetalink);
BAIL_ON_TDNF_ERROR(dwError);
for(cn = cn_section->first_child; cn; cn = cn->next)
{
if ((cn->name[0] == '.') || (cn->value == NULL))
continue;
if (strcmp(cn->name, TDNF_REPO_CONFIG_METALINK_KEY) == 0)
{
pszMetalink = strdup(cn->value);
}
}
/*
* if metalink is set, keep this repo id
@ -81,7 +87,7 @@ TDNFMetalinkReadConfig(
dwError = TDNFAllocateMemory(sizeof(*pData), 1, (void **)&pData);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateString(pSection->pszName, &pData->pszRepoId);
dwError = TDNFAllocateString(cn_section->name, &pData->pszRepoId);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateString(pszMetalink, &pData->pszMetalink);

View File

@ -9,6 +9,8 @@
#include "includes.h"
#include <gpgme.h>
#include "../../llconf/nodes.h"
static
uint32_t
_TDNFVerifyResult(
@ -310,6 +312,12 @@ error:
goto cleanup;
}
static
int isTrue(const char *str)
{
return strcasecmp(str, "true") == 0 || atoi(str) != 0;
}
uint32_t
TDNFRepoGPGCheckReadConfig(
PTDNF_PLUGIN_HANDLE pHandle,
@ -318,7 +326,7 @@ TDNFRepoGPGCheckReadConfig(
{
uint32_t dwError = 0;
int nEnabled = 0;
PCONF_SECTION pSection = NULL;
struct cnfnode *cn_section = NULL, *cn;
PTDNF_REPO_GPG_CHECK_DATA pData = NULL;
if (!pHandle || !pHandle->pTdnf || !pContext)
@ -331,15 +339,19 @@ TDNFRepoGPGCheckReadConfig(
dwError = TDNFEventContextGetItemPtr(
pContext,
TDNF_EVENT_ITEM_REPO_SECTION,
(const void **)&pSection);
(const void **)&cn_section);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadKeyValueBoolean(
pSection,
TDNF_REPO_CONFIG_REPO_GPGCHECK_KEY,
0,
&nEnabled);
BAIL_ON_TDNF_ERROR(dwError);
for(cn = cn_section->first_child; cn; cn = cn->next)
{
if ((cn->name[0] == '.') || (cn->value == NULL))
continue;
if (strcmp(cn->name, TDNF_REPO_CONFIG_REPO_GPGCHECK_KEY) == 0)
{
nEnabled = isTrue(cn->value);
}
}
/*
* if repo_gpgcheck is enabled, keep this repo id
@ -350,7 +362,7 @@ TDNFRepoGPGCheckReadConfig(
dwError = TDNFAllocateMemory(sizeof(*pData), 1, (void **)&pData);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAllocateString(pSection->pszName, &pData->pszRepoId);
dwError = TDNFAllocateString(cn_section->name, &pData->pszRepoId);
BAIL_ON_TDNF_ERROR(dwError);
pData->pNext = pHandle->pData;

View File

@ -7,3 +7,4 @@
#
add_subdirectory("cli")
add_subdirectory("config")

View File

@ -0,0 +1,24 @@
#
# Copyright (C) 2020 VMware, Inc. All Rights Reserved.
#
# Licensed under the GNU General Public License v2 (the "License");
# you may not use this file except in compliance with the License. The terms
# of the License are located in the COPYING file of this distribution.
#
set(TDNF_CONFIG_BIN tdnf-config-bin)
add_executable(${TDNF_CONFIG_BIN}
main.c
)
target_link_libraries(${TDNF_CONFIG_BIN}
${LIB_TDNF_LLCONF}
${CMAKE_DL_LIBS}
)
set_target_properties(${TDNF_CONFIG_BIN} PROPERTIES OUTPUT_NAME tdnf-config)
install(TARGETS ${TDNF_CONFIG_BIN} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT binary)
#add_subdirectory("lib")

409
tools/config/main.c Normal file
View File

@ -0,0 +1,409 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <getopt.h>
#include <glob.h>
#include "../../common/config.h"
#include "../../llconf/nodes.h"
#include "../../llconf/modules.h"
#include "../../llconf/entry.h"
#include "../../llconf/ini.h"
#include "../../llconf/strutils.h"
#define ERR_CMDLINE 1
#define ERR_SYSTEM 2
#define ERR_NO_REPO 3
#define ERR_NO_SETTING 4
#define ERR_REPO_EXISTS 5
#define pr_err(fmt, ...) \
fprintf(stderr, fmt, ##__VA_ARGS__)
#define fail(rc, fmt, ...) { \
pr_err(fmt, ##__VA_ARGS__); \
exit(rc); \
}
#define check_cond(COND) if(!(COND)) { \
pr_err("check_cond failed in %s line %d\n", \
__FUNCTION__, __LINE__); \
rc = -1; \
((void)(rc)); /* suppress "set but not used" warning */ \
goto error; \
}
#define check_ptr(ptr) if(!(ptr)) { \
pr_err("check_ptr failed in %s line %d\n", \
__FUNCTION__, __LINE__); \
rc = -1; \
((void)(rc)); /* suppress "set but not used" warning */ \
goto error; \
}
#define safe_free(ptr) { if ((ptr) != NULL) { free(ptr); ptr = NULL; }}
struct cnfmodule *mod_ini = NULL;
static void
set_key_value(struct cnfnode *cn_repo, const char *keyval)
{
const char *p = keyval;
char key[256], *q = key;
struct cnfnode *cn_keyval = NULL;
/* parse key */
while(*p &&
(!isspace(*p) && (*p != '=')) &&
q < key+sizeof(key)-1)
*(q++) = *(p++);
*q = 0;
skip_spaces(&p);
if(*p == '=') {
p++;
skip_spaces(&p);
/* p is now pointing to the value */
cn_keyval = find_child(cn_repo, key);
if (cn_keyval == NULL) {
cn_keyval = create_cnfnode(key);
cnfnode_setval(cn_keyval, p);
append_node(cn_repo, cn_keyval);
} else {
cnfnode_setval(cn_keyval, p);
}
} else
fail(ERR_CMDLINE, "expected '=' after key %s\n", key);
}
static void
set_key_values(struct cnfnode *cn_root, const char *repo, char *kv[])
{
struct cnfnode *cn_repo = find_child(cn_root, repo);
if (cn_repo) {
for (int i = 0; kv[i]; i++) {
set_key_value(cn_repo, kv[i]);
}
}
}
static
void remove_keys(struct cnfnode *cn_root, const char *repo, char *keys[])
{
struct cnfnode *cn_repo = find_child(cn_root, repo);
if (cn_repo) {
for (int i = 0; keys[i]; i++) {
struct cnfnode *cn_keyval = find_child(cn_repo, keys[i]);
if (cn_keyval) {
unlink_node(cn_keyval);
destroy_cnfnode(cn_keyval);
} else
fail(ERR_NO_SETTING, "key '%s' not found\n", keys[i]);
}
} else
fail(ERR_NO_REPO, "repo '%s' not found\n", repo);
}
static
void remove_repo(struct cnfnode *cn_root, const char *repo)
{
struct cnfnode *cn_repo = find_child(cn_root, repo);
if (cn_repo) {
unlink_node(cn_repo);
destroy_cnfnode(cn_repo);
} else
fail(ERR_NO_REPO, "repo '%s' not found\n", repo);
}
static
char *get_repodir(const char *main_config)
{
char *repodir = NULL;
struct cnfnode *cn_root = cnfmodule_parse_file(mod_ini, main_config);
if (cn_root) {
struct cnfnode *cn_main = find_child(cn_root, "main");
if (cn_main) {
struct cnfnode *cn_repodir = find_child(cn_main, TDNF_CONF_KEY_REPODIR);
if (cn_repodir) {
repodir = strdup(cnfnode_getval(cn_repodir));
}
}
}
if (repodir == NULL)
repodir = strdup(TDNF_DEFAULT_REPO_LOCATION);
if (cn_root)
destroy_cnftree(cn_root);
return repodir;
}
static
struct cnfnode *find_repo(const char *repodir, const char *repo, char **pfilename)
{
struct cnfnode *cn_root = NULL;
char pattern[256];
glob_t globbuf = {0};
int i, rc = 0;
snprintf(pattern, sizeof(pattern), "%s/*.repo", repodir);
rc = glob(pattern, 0, NULL, &globbuf);
check_cond(rc == 0 || rc == GLOB_NOMATCH);
if (rc == 0) {
for (i = 0; globbuf.gl_pathv[i]; i++) {
struct cnfnode *cn_repo = NULL;
cn_root = cnfmodule_parse_file(mod_ini, globbuf.gl_pathv[i]);
check_ptr(cn_root);
cn_repo = find_child(cn_root, repo);
if (cn_repo) {
if (pfilename)
*pfilename = strdup(globbuf.gl_pathv[i]);
break;
}
destroy_cnftree(cn_root);
cn_root = NULL;
}
}
error:
if (rc && cn_root) {
destroy_cnftree(cn_root);
cn_root = NULL;
}
globfree(&globbuf);
return cn_root;
}
static
struct cnfnode *get_repo_root(const char *main_config, const char *repo, char **pfilename)
{
struct cnfnode *cn_root = NULL;
if (strcmp(repo, "main") == 0) {
cn_root = cnfmodule_parse_file(mod_ini, main_config);
if (cn_root == NULL)
fail(ERR_SYSTEM, "could not parse config file %s\n", main_config);
if (pfilename)
*pfilename = strdup(main_config);
} else {
char *repodir = get_repodir(main_config);
cn_root = find_repo(repodir, repo, pfilename);
if (cn_root == NULL)
fail(ERR_NO_REPO, "repo '%s' not found\n", repo);
}
return cn_root;
}
static
int write_file(struct cnfnode *cn_root, const char *filename)
{
int rc = 0;
char buf[256];
snprintf(buf, sizeof(buf), "%s.tmp", filename);
rc = cnfmodule_unparse_file(mod_ini, buf, cn_root);
check_cond(rc == 0);
rc = rename(buf, filename);
check_cond(rc == 0);
error:
return rc;
}
int main(int argc, char *argv[])
{
char *main_config = TDNF_CONF_FILE;
char *repo_config = NULL;
int rc = 0;
while(1) {
int c;
static struct option long_options[] = {
{"config", 1, 0, 'c'},
{"file", 1, 0, 'f'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "c:f:",
long_options, NULL);
if (c == -1)
break;
switch(c){
case 'c':
main_config = optarg;
break;
case 'f':
repo_config = optarg;
printf("repo_config=%s\n", repo_config);
break;
case '?':
default:
/* If it's an error, getopt has already produced an error message. */
//usage();
return 1;
}
}
register_ini(NULL);
mod_ini = find_cnfmodule("ini");
/*
* Process the action(s).
*/
if (optind < argc) {
int argcount = 0;
char *action = NULL;
char *repo = NULL;
char *filename = NULL;
struct cnfnode *cn_root = NULL;
while (optind + argcount < argc)
argcount++;
/*
* Find the action.
*/
action = argv[optind];
if(strcmp(action, "edit") == 0 || strcmp(action, "create") == 0) {
if (argcount < 2)
fail(ERR_CMDLINE, "expected main or repo name\n");
repo = argv[optind+1];
if (argcount < 3)
fail(ERR_CMDLINE, "Expected at least one setting.");
if (strcmp(action, "edit") == 0)
cn_root = get_repo_root(main_config, repo, &filename);
else { /* create repo config */
if(strcmp(repo, "main") != 0) {
char buf[256];
char *repodir = get_repodir(main_config);
if (!find_repo(repodir, repo, NULL)) {
struct cnfnode *cn_repo = create_cnfnode(repo);
if (repo_config == NULL) {
cn_root = create_cnfnode("(root)");
snprintf(buf, sizeof(buf), "%s/%s.repo", repodir, repo);
filename = strdup(buf);
} else {
cn_root = cnfmodule_parse_file(mod_ini, repo_config);
if (cn_root == NULL) {
if (errno == ENOENT)
cn_root = create_cnfnode("(root)");
else
fail(ERR_SYSTEM, "could not parse config file %s\n", repo_config);
}
filename = strdup(repo_config);
}
append_node(cn_root, cn_repo);
} else
fail(ERR_REPO_EXISTS, "repo '%s' already exists\n", repo);
} else
fail(ERR_CMDLINE, "invalid repo name 'main'\n");
}
if (cn_root) {
set_key_values(cn_root, repo, &argv[optind+2]);
if (filename) {
rc = write_file(cn_root, filename);
if (rc != 0)
fail(ERR_SYSTEM, "failed to write file '%s': %s (%d)", filename, strerror(errno), errno);
safe_free(filename);
} else
cnfmodule_unparse(mod_ini, stdout, cn_root);
destroy_cnftree(cn_root);
}
} else if (strcmp(action, "get") == 0) {
if (argcount < 2)
fail(ERR_CMDLINE, "expected main or repo name\n");
repo = argv[optind+1];
if (argcount < 3)
fail(ERR_CMDLINE, "expected one setting\n");
cn_root = get_repo_root(main_config, repo, NULL);
if (cn_root) {
struct cnfnode *cn_repo = find_child(cn_root, repo);
if (cn_repo) {
struct cnfnode *cn_keyval = find_child(cn_repo, argv[optind+2]);
if (cn_keyval)
printf("%s\n", cn_keyval->value);
else
fail(ERR_NO_SETTING, "'%s' not found in '%s'\n", argv[optind+2], repo);
} else
fail(ERR_NO_REPO, "repo '%s' not found\n", repo);
destroy_cnftree(cn_root);
}
} else if (strcmp(action, "remove") == 0) {
if (argcount < 2)
fail(ERR_CMDLINE, "expected main or repo name\n");
repo = argv[optind+1];
if (argcount < 3)
fail(ERR_CMDLINE, "expected one setting\n");
cn_root = get_repo_root(main_config, repo, &filename);
if (cn_root) {
remove_keys(cn_root, repo, &argv[optind+2]);
if (filename) {
rc = write_file(cn_root, filename);
if (rc != 0)
fail(ERR_SYSTEM, "failed to write file '%s': %s (%d)", filename, strerror(errno), errno);
safe_free(filename);
} else
cnfmodule_unparse(mod_ini, stdout, cn_root);
destroy_cnftree(cn_root);
}
} else if (strcmp(action, "removerepo") == 0) {
if (argcount < 2)
fail(ERR_CMDLINE, "expected main or repo name\n");
repo = argv[optind+1];
cn_root = get_repo_root(main_config, repo, &filename);
if (cn_root) {
remove_repo(cn_root, repo);
if (filename) {
if (cn_root->first_child) {
rc = write_file(cn_root, filename);
if (rc != 0)
fail(ERR_SYSTEM, "failed to write file '%s': %s (%d)", filename, strerror(errno), errno);
} else {
rc = unlink(filename);
if (rc != 0)
fail(ERR_SYSTEM, "failed to remove file '%s': %s (%d)", filename, strerror(errno), errno);
}
safe_free(filename);
} else
cnfmodule_unparse(mod_ini, stdout, cn_root);
destroy_cnftree(cn_root);
}
} else
fail(ERR_CMDLINE, "Unknown command '%s'\n", action);
}
}