mirror of https://github.com/vmware/tdnf.git
use llconf for config parsing
This commit is contained in:
parent
acc0398bc2
commit
29504ab949
434
client/config.c
434
client/config.c
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
add_library(${LIB_TDNF_COMMON} STATIC
|
||||
configreader.c
|
||||
memory.c
|
||||
setopt.c
|
||||
strings.c
|
||||
|
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,3 +7,4 @@
|
|||
#
|
||||
|
||||
add_subdirectory("cli")
|
||||
add_subdirectory("config")
|
||||
|
|
|
@ -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")
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue