diff --git a/client/api.c b/client/api.c index 01104336..43120966 100644 --- a/client/api.c +++ b/client/api.c @@ -502,11 +502,13 @@ TDNFOpenHandle( dwError = TDNFCloneCmdArgs(pArgs, &pTdnf->pArgs); BAIL_ON_TDNF_ERROR(dwError); - dwError = TDNFReadConfig(TDNF_CONF_FILE, TDNF_CONF_GROUP, &pTdnf->pConf); + dwError = TDNFReadConfig(pTdnf, + TDNF_CONF_FILE, + TDNF_CONF_GROUP); BAIL_ON_TDNF_ERROR(dwError); dwError = TDNFLoadRepoData( - pTdnf->pConf, + pTdnf, REPOLISTFILTER_ENABLED, &pTdnf->pRepos); BAIL_ON_TDNF_ERROR(dwError); @@ -623,7 +625,7 @@ TDNFRepoList( BAIL_ON_TDNF_ERROR(dwError); } - dwError = TDNFLoadRepoData(pTdnf->pConf, nFilter, &pReposAll); + dwError = TDNFLoadRepoData(pTdnf, nFilter, &pReposAll); BAIL_ON_TDNF_ERROR(dwError); *ppReposAll = pReposAll; diff --git a/client/config.c b/client/config.c index 97b3b8a2..975104d6 100644 --- a/client/config.c +++ b/client/config.c @@ -35,9 +35,9 @@ TDNFConfGetRpmVerbosity( uint32_t TDNFReadConfig( + PTDNF pTdnf, char* pszFile, - char* pszGroup, - PTDNF_CONF* ppConf + char* pszGroup ) { uint32_t dwError = 0; @@ -47,6 +47,14 @@ TDNFReadConfig( PTDNF_CONF pConf = NULL; + if(!pTdnf || + IsNullOrEmptyString(pszFile) || + IsNullOrEmptyString(pszGroup)) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + pKeyFile = g_key_file_new(); if(!pKeyFile) { @@ -135,6 +143,21 @@ TDNFReadConfig( &pConf->pszCacheDir); BAIL_ON_TDNF_ERROR(dwError); + dwError = TDNFReadKeyValue( + pKeyFile, + pszGroup, + TDNF_CONF_KEY_DISTROVERPKG, + TDNF_DEFAULT_DISTROVERPKG, + &pConf->pszDistroVerPkg); + if(dwError == ERROR_TDNF_NO_DATA) + { + dwError = TDNFAllocateString( + TDNF_DEFAULT_DISTROVERPKG, + &pConf->pszDistroVerPkg); + BAIL_ON_TDNF_ERROR(dwError); + } + BAIL_ON_TDNF_ERROR(dwError); + dwError = TDNFConfigReadProxySettings( pKeyFile, pszGroup, @@ -143,7 +166,7 @@ TDNFReadConfig( } - *ppConf = pConf; + pTdnf->pConf = pConf; cleanup: if(pKeyFile) @@ -157,9 +180,9 @@ TDNFReadConfig( return dwError; error: - if(ppConf) + if(pTdnf) { - *ppConf = NULL; + pTdnf->pConf = NULL; } if(pConf) { @@ -168,6 +191,44 @@ TDNFReadConfig( goto cleanup; } +uint32_t +TDNFConfigExpandVars( + PTDNF pTdnf + ) +{ + uint32_t dwError = 0; + PTDNF_CONF pConf = NULL; + + if(!pTdnf || !pTdnf->pConf) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + pConf = pTdnf->pConf; + + if(!pConf->pszVarReleaseVer && + !IsNullOrEmptyString(pConf->pszDistroVerPkg)) + { + dwError = TDNFRawGetPackageVersion( + pTdnf->pArgs->pszInstallRoot, + pConf->pszDistroVerPkg, + &pConf->pszVarReleaseVer); + BAIL_ON_TDNF_ERROR(dwError); + } + + if(!pConf->pszVarBaseArch) + { + dwError = TDNFGetKernelArch(&pConf->pszVarBaseArch); + BAIL_ON_TDNF_ERROR(dwError); + } + +cleanup: + return dwError; + +error: + goto cleanup; +} + uint32_t TDNFConfigReadProxySettings( GKeyFile* pKeyFile, @@ -279,7 +340,7 @@ TDNFReadKeyValue( pszVal = g_strdup(pszDefault); if(!pszVal) { - dwError = ERROR_TDNF_OUT_OF_MEMORY; + dwError = ERROR_TDNF_OUT_OF_MEMORY; BAIL_ON_TDNF_ERROR(dwError); } } @@ -320,6 +381,66 @@ TDNFFreeConfig( TDNF_SAFE_FREE_MEMORY(pConf->pszProxyUserPass); TDNF_SAFE_FREE_MEMORY(pConf->pszRepoDir); TDNF_SAFE_FREE_MEMORY(pConf->pszCacheDir); + TDNF_SAFE_FREE_MEMORY(pConf->pszDistroVerPkg); + TDNF_SAFE_FREE_MEMORY(pConf->pszVarReleaseVer); + TDNF_SAFE_FREE_MEMORY(pConf->pszVarBaseArch); TDNF_SAFE_FREE_MEMORY(pConf); } } + +uint32_t +TDNFConfigReplaceVars( + PTDNF pTdnf, + char** ppszString + ) +{ + uint32_t dwError = 0; + char* pszDst = NULL; + char* pszReplacedTemp = NULL; + PTDNF_CONF pConf = NULL; + + if(!pTdnf || !ppszString || IsNullOrEmptyString(*ppszString)) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + + //fill variable values such as release and basearch + //if required + if(strstr(*ppszString, TDNF_VAR_RELEASEVER) || + strstr(*ppszString, TDNF_VAR_BASEARCH)) + { + dwError = TDNFConfigExpandVars(pTdnf); + BAIL_ON_TDNF_ERROR(dwError); + } + else + { + goto cleanup; + } + + pConf = pTdnf->pConf; + dwError = TDNFReplaceString( + *ppszString, + TDNF_VAR_RELEASEVER, + pConf->pszVarReleaseVer, + &pszReplacedTemp); + BAIL_ON_TDNF_ERROR(dwError); + + dwError = TDNFReplaceString( + pszReplacedTemp, + TDNF_VAR_BASEARCH, + pConf->pszVarBaseArch, + &pszDst); + BAIL_ON_TDNF_ERROR(dwError); + + TDNFFreeMemory(*ppszString); + *ppszString = pszDst; + +cleanup: + TDNF_SAFE_FREE_MEMORY(pszReplacedTemp); + return dwError; + +error: + TDNF_SAFE_FREE_MEMORY(pszDst); + goto cleanup; +} diff --git a/client/defines.h b/client/defines.h index 15cb1560..a85f72a8 100644 --- a/client/defines.h +++ b/client/defines.h @@ -99,6 +99,8 @@ typedef enum #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" //Repo file key names #define TDNF_REPO_KEY_BASEURL "baseurl" #define TDNF_REPO_KEY_ENABLED "enabled" @@ -113,8 +115,13 @@ typedef enum //Repo defaults #define TDNF_DEFAULT_REPO_LOCATION "/etc/yum.repos.d" #define TDNF_DEFAULT_CACHE_LOCATION "/var/cache/tdnf" +#define TDNF_DEFAULT_DISTROVERPKG "photon-release" +#define TDNF_DEFAULT_DISTROARCHPKG "x86_64" #define TDNF_RPM_CACHE_DIR_NAME "rpms" #define TDNF_REPODATA_DIR_NAME "repodata" +//var names +#define TDNF_VAR_RELEASEVER "$releasever" +#define TDNF_VAR_BASEARCH "$basearch" #define TDNF_UNKNOWN_ERROR_STRING "Unknown error" #define TDNF_ERROR_TABLE \ @@ -128,6 +135,8 @@ typedef enum {ERROR_TDNF_NO_MATCH, "ERROR_TDNF_NO_MATCH", "No matching packages"}, \ {ERROR_TDNF_SET_PROXY, "ERROR_TDNF_SET_PROXY", "There was an error setting the proxy server."}, \ {ERROR_TDNF_SET_PROXY_USERPASS, "ERROR_TDNF_SET_PROXY_USERPASS", "There was an error setting the proxy server user and pass"}, \ + {ERROR_TDNF_NO_DISTROVERPKG, "ERROR_TDNF_NO_DISTROVERPKG", "distroverpkg config entry is set to a package that is not installed. Check /etc/tdnf/tdnf.conf"}, \ + {ERROR_TDNF_DISTROVERPKG_READ, "ERROR_TDNF_DISTROVERPKG_READ", "There was an error reading version of distroverpkg"}, \ {ERROR_TDNF_NO_ENABLED_REPOS, "ERROR_TDNF_NO_ENABLED_REPOS", "There are no enabled repos.\n Run ""tdnf repolist all"" to see the repos you have.\n You can enable repos by editing repo files in your repodir(usually /etc/yum.repos.d)"}, \ {ERROR_TDNF_PACKAGELIST_EMPTY, "ERROR_TDNF_PACKAGELIST_EMPTY", "Packagelist was empty"}, \ {ERROR_TDNF_GOAL_CREATE, "ERROR_TDNF_GOAL_CREATE", "Error creating goal"}, \ diff --git a/client/includes.h b/client/includes.h index 49cbcfe9..557b6e9c 100644 --- a/client/includes.h +++ b/client/includes.h @@ -26,6 +26,9 @@ #include #include #include +#include +// +#include //glib #include #include @@ -54,6 +57,7 @@ #include #include #include +#include #include diff --git a/client/prototypes.h b/client/prototypes.h index 524c5253..52039d91 100644 --- a/client/prototypes.h +++ b/client/prototypes.h @@ -355,9 +355,14 @@ TDNFReadKeyValue( uint32_t TDNFReadConfig( + PTDNF pTdnf, char* pszConfFile, - char* pszConfGroup, - PTDNF_CONF* ppConf + char* pszConfGroup + ); + +uint32_t +TDNFConfigExpandVars( + PTDNF pTdnf ); uint32_t @@ -371,6 +376,12 @@ TDNFFreeConfig( PTDNF_CONF pConf ); +uint32_t +TDNFConfigReplaceVars( + PTDNF pTdnf, + char** pszString + ); + //repo.c uint32_t TDNFPrintRepoMetadata( @@ -407,13 +418,14 @@ TDNFGetRepoById( //repolist.c uint32_t TDNFLoadReposFromFile( + PTDNF pTdnf, char* pszRepoFile, PTDNF_REPO_DATA* ppRepos ); uint32_t TDNFLoadRepoData( - PTDNF_CONF pConf, + PTDNF pTdnf, TDNF_REPOLISTFILTER nFilter, PTDNF_REPO_DATA* ppReposAll ); @@ -684,6 +696,21 @@ TDNFAllocateStringPrintf( const char* pszFmt, ... ); + +uint32_t +TDNFAllocateStringN( + const char* pszSrc, + uint32_t dwNumElements, + char** ppszDst + ); + +uint32_t +TDNFReplaceString( + const char* pszSource, + const char* pszSearch, + const char* pszReplace, + char** ppszDst + ); //updateinfo.c uint32_t TDNFGetUpdateInfoPackages( @@ -733,6 +760,18 @@ TDNFUtilsMakeDirs( const char* pszPath ); +uint32_t +TDNFRawGetPackageVersion( + const char* pszRootDir, + const char* pszPkg, + char** ppszVersion + ); + +uint32_t +TDNFGetKernelArch( + char** ppszArch + ); + //validate.c uint32_t TDNFValidateCmdArgs( diff --git a/client/repolist.c b/client/repolist.c index a30a4e68..3528e7d2 100644 --- a/client/repolist.c +++ b/client/repolist.c @@ -23,7 +23,7 @@ uint32_t TDNFLoadRepoData( - PTDNF_CONF pConf, + PTDNF pTdnf, TDNF_REPOLISTFILTER nFilter, PTDNF_REPO_DATA* ppReposAll ) @@ -35,14 +35,16 @@ TDNFLoadRepoData( PTDNF_REPO_DATA pReposAll = NULL; PTDNF_REPO_DATA pReposTemp = NULL; PTDNF_REPO_DATA pRepos = NULL; + PTDNF_CONF pConf = NULL; GDir* pDir = NULL; - if(!pConf || !ppReposAll) + if(!pTdnf || !pTdnf->pConf || !ppReposAll) { dwError = ERROR_TDNF_INVALID_PARAMETER; BAIL_ON_TDNF_ERROR(dwError); } + pConf = pTdnf->pConf; pDir = g_dir_open(pConf->pszRepoDir, 0, NULL); if(!pDir) @@ -59,7 +61,7 @@ TDNFLoadRepoData( } pszRepoFilePath = g_build_filename(pConf->pszRepoDir, pszFile, NULL); - dwError = TDNFLoadReposFromFile(pszRepoFilePath, &pRepos); + dwError = TDNFLoadReposFromFile(pTdnf, pszRepoFilePath, &pRepos); BAIL_ON_TDNF_ERROR(dwError); g_free(pszRepoFilePath); @@ -116,6 +118,7 @@ TDNFLoadRepoData( uint32_t TDNFLoadReposFromFile( + PTDNF pTdnf, char* pszRepoFile, PTDNF_REPO_DATA* ppRepos ) @@ -235,6 +238,21 @@ TDNFLoadReposFromFile( &pRepo->pszPass); BAIL_ON_TDNF_ERROR(dwError); + if(pRepo->nEnabled) + { + if(pRepo->pszBaseUrl) + { + dwError = TDNFConfigReplaceVars(pTdnf, &pRepo->pszBaseUrl); + BAIL_ON_TDNF_ERROR(dwError); + } + + if(pRepo->pszMetaLink) + { + dwError = TDNFConfigReplaceVars(pTdnf, &pRepo->pszMetaLink); + BAIL_ON_TDNF_ERROR(dwError); + } + } + pRepo->pNext = pRepos; pRepos = pRepo; pRepo = NULL; diff --git a/client/strings.c b/client/strings.c index ee3a4fcd..dce4e11b 100644 --- a/client/strings.c +++ b/client/strings.c @@ -155,3 +155,113 @@ TDNFFreeStringArray( TDNFFreeMemory(ppszArray); } } + +uint32_t +TDNFAllocateStringN( + const char* pszSrc, + uint32_t dwNumElements, + char** ppszDst + ) +{ + uint32_t dwError = 0; + char* pszDst = NULL; + uint32_t dwSrcLength = 0; + + if(!pszSrc || !ppszDst) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + + dwSrcLength = strlen(pszSrc); + if(dwNumElements > dwSrcLength) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + + dwError = TDNFAllocateMemory(dwNumElements + 1, (void**)&pszDst); + BAIL_ON_TDNF_ERROR(dwError); + + strncpy(pszDst, pszSrc, dwNumElements); + + *ppszDst = pszDst; + +cleanup: + return dwError; + +error: + if(ppszDst) + { + *ppszDst = NULL; + } + TDNF_SAFE_FREE_MEMORY(pszDst); + goto cleanup; +} + +uint32_t +TDNFReplaceString( + const char* pszSource, + const char* pszSearch, + const char* pszReplace, + char** ppszDst + ) +{ + uint32_t dwError = 0; + char* pszDst = NULL; + char* pszTemp = NULL; + char* pszTempReplace = NULL; + char* pszIndex = NULL; + int nSearchLen = 0; + + if(IsNullOrEmptyString(pszSource) || + IsNullOrEmptyString(pszSearch) || + !pszReplace || + !ppszDst) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + + nSearchLen = strlen(pszSearch); + + dwError = TDNFAllocateString(pszSource, &pszDst); + BAIL_ON_TDNF_ERROR(dwError); + + while((pszIndex = strstr(pszDst, pszSearch)) != NULL) + { + dwError = TDNFAllocateStringN( + pszDst, + pszIndex - pszDst, + &pszTemp); + BAIL_ON_TDNF_ERROR(dwError); + + dwError = TDNFAllocateStringPrintf( + &pszTempReplace, + "%s%s%s", + pszTemp, + pszReplace, + pszIndex + nSearchLen); + BAIL_ON_TDNF_ERROR(dwError); + + TDNF_SAFE_FREE_MEMORY(pszTemp); + TDNF_SAFE_FREE_MEMORY(pszDst); + pszDst = pszTempReplace; + pszTemp = NULL; + pszTempReplace = NULL; + } + + *ppszDst = pszDst; +cleanup: + return dwError; + +error: + if(ppszDst) + { + *ppszDst = NULL; + } + TDNF_SAFE_FREE_MEMORY(pszDst); + TDNF_SAFE_FREE_MEMORY(pszTemp); + TDNF_SAFE_FREE_MEMORY(pszTempReplace); + goto cleanup; +} diff --git a/client/utils.c b/client/utils.c index 80daa4f2..b80daddc 100644 --- a/client/utils.c +++ b/client/utils.c @@ -305,3 +305,133 @@ TDNFIsDir( } goto cleanup; } + +//get package version using rpmlib +uint32_t +TDNFRawGetPackageVersion( + const char* pszRootDir, + const char* pszPkg, + char** ppszVersion + ) +{ + uint32_t dwError = 0; + const char* pszVersionTemp = NULL; + char* pszVersion = NULL; + rpmts pTS = NULL; + Header pHeader = NULL; + rpmdbMatchIterator pIter = NULL; + + if(IsNullOrEmptyString(pszRootDir) || + IsNullOrEmptyString(pszPkg) || + !ppszVersion) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + + dwError = rpmReadConfigFiles(NULL, NULL); + BAIL_ON_TDNF_ERROR(dwError); + + pTS = rpmtsCreate(); + if(!pTS) + { + dwError = ERROR_TDNF_RPMTS_CREATE_FAILED; + BAIL_ON_TDNF_ERROR(dwError); + } + + if(rpmtsSetRootDir (pTS, pszRootDir)) + { + dwError = ERROR_TDNF_RPMTS_BAD_ROOT_DIR; + BAIL_ON_TDNF_ERROR(dwError); + } + + pIter = rpmtsInitIterator(pTS, RPMTAG_NAME, pszPkg, 0); + if(!pIter) + { + dwError = ERROR_TDNF_NO_DISTROVERPKG; + BAIL_ON_TDNF_ERROR(dwError); + } + + pHeader = rpmdbNextIterator(pIter); + if(!pHeader) + { + dwError = ERROR_TDNF_DISTROVERPKG_READ; + BAIL_ON_TDNF_ERROR(dwError); + } + pHeader = headerLink(pHeader); + if(!pHeader) + { + dwError = ERROR_TDNF_DISTROVERPKG_READ; + BAIL_ON_TDNF_ERROR(dwError); + } + pszVersionTemp = headerGetString(pHeader, RPMTAG_VERSION); + if(IsNullOrEmptyString(pszVersionTemp)) + { + dwError = ERROR_TDNF_DISTROVERPKG_READ; + BAIL_ON_TDNF_ERROR(dwError); + } + + dwError = TDNFAllocateString(pszVersionTemp, &pszVersion); + BAIL_ON_TDNF_ERROR(dwError); + + *ppszVersion = pszVersion; +cleanup: + if(pHeader) + { + headerFree(pHeader); + } + if(pIter) + { + rpmdbFreeIterator(pIter); + } + if(pTS) + { + rpmtsFree(pTS); + } + return dwError; + +error: + if(ppszVersion) + { + *ppszVersion = NULL; + } + TDNF_SAFE_FREE_MEMORY(pszVersion); + goto cleanup; +} + +uint32_t +TDNFGetKernelArch( + char** ppszArch + ) +{ + uint32_t dwError = 0; + char* pszArch = NULL; + struct utsname stUtsName; + + if(!ppszArch) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + if(uname(&stUtsName) != 0) + { + dwError = errno; + } + BAIL_ON_TDNF_SYSTEM_ERROR(dwError); + + dwError = TDNFAllocateString(stUtsName.machine, &pszArch); + BAIL_ON_TDNF_ERROR(dwError); + + *ppszArch = pszArch; + +cleanup: + return dwError; + +error: + if(ppszArch) + { + *ppszArch = NULL; + } + TDNF_SAFE_FREE_MEMORY(pszArch); + goto cleanup; +} diff --git a/include/tdnferror.h b/include/tdnferror.h index defae0b4..aa1f62e5 100644 --- a/include/tdnferror.h +++ b/include/tdnferror.h @@ -54,9 +54,10 @@ extern "C" { #define ERROR_TDNF_NO_DOWNGRADES 1017 #define ERROR_TDNF_AUTOERASE_UNSUPPORTED 1018 //Config settings error -#define ERROR_TDNF_SET_PROXY 1020 -#define ERROR_TDNF_SET_PROXY_USERPASS 1021 - +#define ERROR_TDNF_SET_PROXY 1020 +#define ERROR_TDNF_SET_PROXY_USERPASS 1021 +#define ERROR_TDNF_NO_DISTROVERPKG 1022 +#define ERROR_TDNF_DISTROVERPKG_READ 1023 //Hawkey errors 1300 to 1399 #define ERROR_TDNF_HAWKEY_BASE 1300 diff --git a/include/tdnftypes.h b/include/tdnftypes.h index 0f638d37..2c5c37e6 100644 --- a/include/tdnftypes.h +++ b/include/tdnftypes.h @@ -219,6 +219,10 @@ typedef struct _TDNF_CONF char* pszCacheDir; char* pszProxy; char* pszProxyUserPass; + char* pszDistroVerPkg; + char* pszBaseArch; + char* pszVarReleaseVer; + char* pszVarBaseArch; }TDNF_CONF, *PTDNF_CONF; typedef struct _TDNF_REPO_METADATA