diff --git a/client/api.c b/client/api.c index e5cf543..7444c68 100644 --- a/client/api.c +++ b/client/api.c @@ -812,7 +812,7 @@ TDNFAddCmdLinePackages( pTdnf, pszPkgName, basename(pszCopyOfPkgName), - "@cmdline", + CMDLINE_REPO_NAME, &pszRPMPath ); BAIL_ON_TDNF_ERROR(dwError); @@ -1063,7 +1063,7 @@ TDNFRepoSync( /* count enabled repos */ for (pRepo = pTdnf->pRepos; pRepo; pRepo = pRepo->pNext) { - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; @@ -1250,7 +1250,7 @@ TDNFRepoSync( marker file */ for (pRepo = pTdnf->pRepos; pRepo; pRepo = pRepo->pNext) { - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; @@ -1280,7 +1280,7 @@ TDNFRepoSync( { for (pRepo = pTdnf->pRepos; pRepo; pRepo = pRepo->pNext) { - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; diff --git a/client/defines.h b/client/defines.h index 8acdacb..7cb16b8 100644 --- a/client/defines.h +++ b/client/defines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 VMware, Inc. All Rights Reserved. + * 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 @@ -49,6 +49,8 @@ typedef enum } \ } while(0) +#define STR_IS_TRUE(s) ((s) && (!strcmp((s), "1") || !strcasecmp((s), "true"))) + //Misc #define TDNF_RPM_EXT ".rpm" #define TDNF_NAME "tdnf" @@ -136,7 +138,8 @@ typedef enum #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 172800 // 48 hours in seconds +#define TDNF_REPO_DEFAULT_METADATA_EXPIRE_STR STRINGIFYX(TDNF_REPO_DEFAULT_METADATA_EXPIRE) // var names #define TDNF_VAR_RELEASEVER "$releasever" diff --git a/client/init.c b/client/init.c index 92316fc..7157614 100644 --- a/client/init.c +++ b/client/init.c @@ -254,7 +254,7 @@ TDNFRefreshSack( { /* skip the @cmdline repo - options do not apply, and it is initialized. */ - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; @@ -271,7 +271,7 @@ TDNFRefreshSack( for(pRepo = pTdnf->pRepos; pRepo; pRepo = pRepo->pNext) { - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; diff --git a/client/prototypes.h b/client/prototypes.h index 2ede795..ba1b07a 100644 --- a/client/prototypes.h +++ b/client/prototypes.h @@ -753,6 +753,19 @@ TDNFCreateCmdLineRepo( PTDNF_REPO_DATA_INTERNAL* ppRepo ); +uint32_t +TDNFCreateRepoFromPath( + PTDNF_REPO_DATA_INTERNAL* ppRepo, + const char *pzsId, + const char *pszPath + ); + +uint32_t +TDNFCreateRepo( + PTDNF_REPO_DATA_INTERNAL* ppRepo, + const char *pszId + ); + uint32_t TDNFLoadRepoData( PTDNF pTdnf, diff --git a/client/repo.c b/client/repo.c index 65754e1..8465d11 100644 --- a/client/repo.c +++ b/client/repo.c @@ -195,7 +195,7 @@ TDNFInitCmdLineRepo( (void**)&pSolvRepoInfo); BAIL_ON_TDNF_ERROR(dwError); - pRepo = repo_create(pPool, "@cmdline"); + pRepo = repo_create(pPool, CMDLINE_REPO_NAME); if (!pRepo) { dwError = ERROR_TDNF_INVALID_PARAMETER; diff --git a/client/repolist.c b/client/repolist.c index b19a24d..75eb70a 100644 --- a/client/repolist.c +++ b/client/repolist.c @@ -34,12 +34,14 @@ TDNFLoadRepoData( PTDNF_REPO_DATA_INTERNAL pReposTemp = NULL; PTDNF_REPO_DATA_INTERNAL pRepos = NULL; PTDNF_CONF pConf = NULL; + PTDNF_CMD_OPT pSetOpt = NULL; DIR *pDir = NULL; struct dirent *pEnt = NULL; int nLen = 0; int nLenRepoExt = 0; + char **ppszUrlIdTuple = NULL; - if(!pTdnf || !pTdnf->pConf || !ppReposAll) + if(!pTdnf || !pTdnf->pConf || !pTdnf->pArgs || !ppReposAll) { dwError = ERROR_TDNF_INVALID_PARAMETER; BAIL_ON_TDNF_ERROR(dwError); @@ -49,6 +51,28 @@ TDNFLoadRepoData( dwError = TDNFCreateCmdLineRepo(&pReposAll); BAIL_ON_TDNF_ERROR(dwError); + for(pSetOpt = pTdnf->pArgs->pSetOpt; + pSetOpt; + pSetOpt = pSetOpt->pNext) + { + if(strcmp(pSetOpt->pszOptName, "repofrompath") == 0) + { + TDNFSplitStringToArray(pSetOpt->pszOptValue, ",", &ppszUrlIdTuple); + if ((ppszUrlIdTuple[0] == NULL) || ppszUrlIdTuple[1] == NULL) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + dwError = TDNFCreateRepoFromPath(&pReposAll, + ppszUrlIdTuple[0], + ppszUrlIdTuple[1]); + BAIL_ON_TDNF_ERROR(dwError); + + TDNF_SAFE_FREE_STRINGARRAY(ppszUrlIdTuple); + ppszUrlIdTuple = NULL; + } + } + pDir = opendir(pConf->pszRepoDir); if(pDir == NULL) { @@ -111,6 +135,7 @@ cleanup: closedir(pDir); } TDNF_SAFE_FREE_MEMORY(pszRepoFilePath); + TDNF_SAFE_FREE_STRINGARRAY(ppszUrlIdTuple); return dwError; error: @@ -139,17 +164,120 @@ TDNFCreateCmdLineRepo( BAIL_ON_TDNF_ERROR(dwError); } + dwError = TDNFCreateRepo(&pRepo, CMDLINE_REPO_NAME); + BAIL_ON_TDNF_ERROR(dwError); + + dwError = TDNFSafeAllocateString(CMDLINE_REPO_NAME, &pRepo->pszName); + BAIL_ON_TDNF_ERROR(dwError); + + *ppRepo = pRepo; +cleanup: + return dwError; +error: + if(pRepo) + { + TDNFFreeReposInternal(pRepo); + } + goto cleanup; +} + +uint32_t +TDNFCreateRepoFromPath( + PTDNF_REPO_DATA_INTERNAL* ppRepo, + const char *pszId, + const char *pszPath + ) +{ + uint32_t dwError = 0; + PTDNF_REPO_DATA_INTERNAL pRepo = NULL; + int nIsDir = 0; + int nDummy = 0; + + if(!ppRepo || !pszId || !pszPath) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + + dwError = TDNFCreateRepo(&pRepo, pszId); + BAIL_ON_TDNF_ERROR(dwError); + + /* we want it enabled, or there was no point in adding it */ + pRepo->nEnabled = 1; + + dwError = TDNFSafeAllocateString(pszId, &pRepo->pszName); + BAIL_ON_TDNF_ERROR(dwError); + + /* '/some/dir' => 'file:///some/dir */ + if (pszPath[0] == '/') + { + dwError = TDNFIsDir(pszPath, &nIsDir); + BAIL_ON_TDNF_ERROR(dwError); + + if (nIsDir) + { + dwError = TDNFAllocateStringPrintf(&pRepo->pszBaseUrl, "file://%s", pszPath); + BAIL_ON_TDNF_ERROR(dwError); + } + } + else + { + /* valid prefixes including file:// will not return an error */ + dwError = TDNFUriIsRemote(pszPath, &nDummy); + BAIL_ON_TDNF_ERROR(dwError); + + dwError = TDNFSafeAllocateString(pszPath, &pRepo->pszBaseUrl); + BAIL_ON_TDNF_ERROR(dwError); + } + *ppRepo = pRepo; +cleanup: + return dwError; +error: + if(ppRepo) + { + *ppRepo = NULL; + } + if(pRepo) + { + TDNFFreeReposInternal(pRepo); + } + goto cleanup; +} + +uint32_t +TDNFCreateRepo( + PTDNF_REPO_DATA_INTERNAL* ppRepo, + const char *pszId + ) +{ + uint32_t dwError = 0; + PTDNF_REPO_DATA_INTERNAL pRepo = NULL; + + if(!ppRepo || !pszId) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + dwError = TDNFAllocateMemory( 1, sizeof(TDNF_REPO_DATA_INTERNAL), (void**)&pRepo); BAIL_ON_TDNF_ERROR(dwError); - dwError = TDNFSafeAllocateString("@cmdline", &pRepo->pszName); + dwError = TDNFSafeAllocateString(pszId, &pRepo->pszId); BAIL_ON_TDNF_ERROR(dwError); - dwError = TDNFSafeAllocateString("@cmdline", &pRepo->pszId); - BAIL_ON_TDNF_ERROR(dwError); + pRepo->nEnabled = TDNF_REPO_DEFAULT_ENABLED; + pRepo->nSkipIfUnavailable = TDNF_REPO_DEFAULT_SKIP; + pRepo->nGPGCheck = TDNF_REPO_DEFAULT_GPGCHECK; + pRepo->nSSLVerify = TDNF_REPO_DEFAULT_SSLVERIFY; + pRepo->lMetadataExpire = TDNF_REPO_DEFAULT_METADATA_EXPIRE; + pRepo->nPriority = TDNF_REPO_DEFAULT_PRIORITY; + pRepo->nTimeout = TDNF_REPO_DEFAULT_TIMEOUT; + pRepo->nMinrate = TDNF_REPO_DEFAULT_MINRATE; + pRepo->nThrottle = TDNF_REPO_DEFAULT_THROTTLE; + pRepo->nRetries = TDNF_REPO_DEFAULT_RETRIES; *ppRepo = pRepo; cleanup: @@ -400,7 +528,7 @@ TDNFLoadReposFromFile( dwError = TDNFReadKeyValue( pSections, TDNF_REPO_KEY_METADATA_EXPIRE, - TDNF_REPO_DEFAULT_METADATA_EXPIRE, + TDNF_REPO_DEFAULT_METADATA_EXPIRE_STR, &pszMetadataExpire); BAIL_ON_TDNF_ERROR(dwError); @@ -451,6 +579,7 @@ TDNFRepoListFinalize( uint32_t dwError = 0; PTDNF_CMD_OPT pSetOpt = NULL; PTDNF_REPO_DATA_INTERNAL pRepo = NULL; + int nRepoidSeen = 0; if(!pTdnf || !pTdnf->pArgs || !pTdnf->pRepos) { @@ -472,8 +601,23 @@ TDNFRepoListFinalize( pSetOpt->nType == CMDOPT_ENABLEREPO, pSetOpt->pszOptValue); BAIL_ON_TDNF_ERROR(dwError); - } - pSetOpt = pSetOpt->pNext; + } + else if(strcmp(pSetOpt->pszOptName, "repoid") == 0) + { + if (!nRepoidSeen) + { + dwError = TDNFAlterRepoState( + pTdnf->pRepos, 0, "*"); + BAIL_ON_TDNF_ERROR(dwError); + nRepoidSeen = 1; + } + dwError = TDNFAlterRepoState( + pTdnf->pRepos, + 1, + pSetOpt->pszOptValue); + BAIL_ON_TDNF_ERROR(dwError); + } + pSetOpt = pSetOpt->pNext; } //Now that the overrides are applied, replace config vars diff --git a/common/defines.h b/common/defines.h index 494c1ec..656566b 100644 --- a/common/defines.h +++ b/common/defines.h @@ -20,6 +20,9 @@ #pragma once +#define STRINGIFYX(N) STRINGIFY(N) +#define STRINGIFY(N) #N + #define MAX_CONFIG_LINE_LENGTH 1024 #define TDNF_SAFE_FREE_PKGINFO(pPkgInfo) \ diff --git a/solv/defines.h b/solv/defines.h index 283df9f..c2a4493 100644 --- a/solv/defines.h +++ b/solv/defines.h @@ -2,7 +2,7 @@ #define __SOLV_DEFINES_H__ #define SYSTEM_REPO_NAME "@System" -#define CMDLINE_REPO_NAME "@commandline" +#define CMDLINE_REPO_NAME "@cmdline" #define SOLV_COOKIE_IDENT "tdnf" #define TDNF_SOLVCACHE_DIR_NAME "solvcache" #define SOLV_COOKIE_LEN 32 diff --git a/tools/cli/lib/parseargs.c b/tools/cli/lib/parseargs.c index 7365df8..a022e13 100644 --- a/tools/cli/lib/parseargs.c +++ b/tools/cli/lib/parseargs.c @@ -84,6 +84,9 @@ static struct option pstOptions[] = {"debugsolver", no_argument, &_opt.nDebugSolver, 1}, //--debugsolver {"disablerepo", required_argument, 0, 0}, //--disablerepo {"enablerepo", required_argument, 0, 0}, //--enablerepo + {"repo", required_argument, 0, 0}, //--repo + {"repoid", required_argument, 0, 0}, //--repoid (same as --repo) + {"repofrompath", required_argument, 0, 0}, //--repofrompath {"errorlevel", required_argument, 0, 'e'}, //-e --errorlevel {"help", no_argument, 0, 'h'}, //-h --help {"installroot", required_argument, 0, 'i'}, //--installroot @@ -390,7 +393,8 @@ ParseOption( } else if ((!strcasecmp(pszName, "metadata-path")) || (!strcasecmp(pszName, "download-path")) || - (!strcasecmp(pszName, "arch"))) + (!strcasecmp(pszName, "arch")) || + (!strcasecmp(pszName, "repofrompath"))) { dwError = AddSetOptWithValues(pCmdArgs, CMDOPT_KEYVALUE, @@ -398,6 +402,15 @@ ParseOption( optarg); BAIL_ON_CLI_ERROR(dwError); } + else if ((!strcasecmp(pszName, "repoid")) || + (!strcasecmp(pszName, "repo"))) + { + dwError = AddSetOptWithValues(pCmdArgs, + CMDOPT_KEYVALUE, + "repoid", + optarg); + BAIL_ON_CLI_ERROR(dwError); + } else if (!strcasecmp(pszName, "setopt")) { if (!optarg)