tdnf/client/resolve.c

452 lines
12 KiB
C

/*
* Copyright (C) 2015-2017 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.
*/
/*
* Module : resolve.c
*
* Abstract :
*
* tdnfclientlib
*
* client library
*
* Authors : Priyesh Padmavilasom (ppadmavilasom@vmware.com)
*/
#include "includes.h"
uint32_t
TDNFAddNotResolved(
char** ppszPkgsNotResolved,
const char* pszPkgName
)
{
uint32_t dwError = 0 ;
int nIndex = 0;
if(!ppszPkgsNotResolved ||
IsNullOrEmptyString(pszPkgName))
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
while(ppszPkgsNotResolved[nIndex++]);
dwError = TDNFAllocateString(
pszPkgName,
&ppszPkgsNotResolved[--nIndex]);
BAIL_ON_TDNF_ERROR(dwError);
cleanup:
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFPrepareAllPackages(
PTDNF pTdnf,
TDNF_ALTERTYPE* pAlterType,
char** ppszPkgsNotResolved,
Queue* queueGoal
)
{
uint32_t dwError = 0;
PTDNF_CMD_ARGS pCmdArgs = NULL;
int nCmdIndex = 0;
int nPkgIndex = 0;
int nIsFile = 0;
int nDummy = 0;
char* pszPkgName = NULL;
char* pszName = NULL;
Queue queueLocal = {0};
char* pszSeverity = NULL;
uint32_t dwSecurity = 0;
char** ppszPkgArray = NULL;
uint32_t dwCount = 0;
uint32_t dwRebootRequired = 0;
TDNF_ALTERTYPE nAlterType = 0;
if(!pTdnf || !pTdnf->pSack ||
!pTdnf->pArgs || !ppszPkgsNotResolved || !queueGoal || !pAlterType)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
queue_init(&queueLocal);
pCmdArgs = pTdnf->pArgs;
nAlterType = *pAlterType;
if(nAlterType == ALTER_DOWNGRADEALL ||
nAlterType == ALTER_AUTOERASE)
{
dwError = TDNFFilterPackages(
pTdnf,
nAlterType,
ppszPkgsNotResolved,
queueGoal);
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFGetSecuritySeverityOption(
pTdnf,
&dwSecurity,
&pszSeverity);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFGetRebootRequiredOption(
pTdnf,
&dwRebootRequired);
BAIL_ON_TDNF_ERROR(dwError);
if ((nAlterType == ALTER_UPGRADEALL ||
nAlterType == ALTER_UPGRADE) &&
(dwSecurity || pszSeverity || dwRebootRequired))
{
//pAlterType is changed to ALTER_UPGRADE and later used in TDNFGoal() to add exclude the
// list of packages that are added in --exclude option.
*pAlterType = ALTER_UPGRADE;
dwError = TDNFGetUpdatePkgs(pTdnf, &ppszPkgArray, &dwCount);
BAIL_ON_TDNF_ERROR(dwError);
for(nPkgIndex = 0; (uint32_t)nPkgIndex < dwCount; ++nPkgIndex)
{
dwError = TDNFPrepareAndAddPkg(
pTdnf,
ppszPkgArray[nPkgIndex],
*pAlterType,
ppszPkgsNotResolved,
queueGoal);
BAIL_ON_TDNF_ERROR(dwError);
}
}
else
{
for(nCmdIndex = 1; nCmdIndex < pCmdArgs->nCmdCount; ++nCmdIndex)
{
pszPkgName = pCmdArgs->ppszCmds[nCmdIndex];
if(TDNFIsGlob(pszPkgName))
{
queue_empty(&queueLocal);
dwError = TDNFGetGlobPackages(
pTdnf->pSack,
pszPkgName,
&queueLocal);
BAIL_ON_TDNF_ERROR(dwError);
if(queueLocal.count == 0)
{
dwError = TDNFAddNotResolved(ppszPkgsNotResolved, pszPkgName);
BAIL_ON_TDNF_ERROR(dwError);
}
else
{
nPkgIndex = 0;
for(nPkgIndex = 0; nPkgIndex < queueLocal.count; nPkgIndex++)
{
dwError = SolvGetPkgNameFromId(
pTdnf->pSack,
queueLocal.elements[nPkgIndex],
&pszName);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFPrepareAndAddPkg(
pTdnf,
pszName,
nAlterType,
ppszPkgsNotResolved,
queueGoal);
BAIL_ON_TDNF_ERROR(dwError);
TDNF_SAFE_FREE_MEMORY(pszName);
pszName = NULL;
}
}
}
else
{
dwError = TDNFIsFileOrSymlink(pszPkgName, &nIsFile);
BAIL_ON_TDNF_ERROR(dwError);
if (nIsFile)
{
continue;
}
dwError = TDNFUriIsRemote(pszPkgName, &nDummy);
if (dwError == 0)
{
/* URL => cmd line pkg, already handled */
dwError = 0;
continue;
}
else if (dwError == ERROR_TDNF_URL_INVALID)
{
dwError = 0;
}
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFPrepareAndAddPkg(
pTdnf,
pszPkgName,
nAlterType,
ppszPkgsNotResolved,
queueGoal);
BAIL_ON_TDNF_ERROR(dwError);
}
}
}
cleanup:
TDNF_SAFE_FREE_MEMORY(pszSeverity);
TDNF_SAFE_FREE_MEMORY(pszName);
queue_free(&queueLocal);
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFFilterPackages(
PTDNF pTdnf,
TDNF_ALTERTYPE nAlterType,
char** ppszPkgsNotResolved,
Queue* queueGoal)
{
uint32_t dwError = 0;
Id dwInstalledId = 0;
uint32_t dwPkgIndex = 0;
uint32_t dwSize = 0;
PSolvPackageList pInstalledPkgList = NULL;
char* pszName = NULL;
PSolvSack pSack = NULL;
if(!pTdnf || !pTdnf->pSack || !queueGoal || !ppszPkgsNotResolved)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pSack = pTdnf->pSack;
dwError = SolvFindAllInstalled(pSack, &pInstalledPkgList);
if(dwError == ERROR_TDNF_NO_MATCH)
{
dwError = 0;
}
dwError = SolvGetPackageListSize(pInstalledPkgList, &dwSize);
BAIL_ON_TDNF_ERROR(dwError);
for(dwPkgIndex = 0; dwPkgIndex < dwSize; dwPkgIndex++)
{
dwError = SolvGetPackageId(pInstalledPkgList, dwPkgIndex, &dwInstalledId);
BAIL_ON_TDNF_ERROR(dwError);
dwError = SolvGetPkgNameFromId(pSack,
dwInstalledId,
&pszName);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFPrepareAndAddPkg(
pTdnf,
pszName,
nAlterType,
ppszPkgsNotResolved,
queueGoal);
BAIL_ON_TDNF_ERROR(dwError);
TDNF_SAFE_FREE_MEMORY(pszName);
pszName = NULL;
}
cleanup:
TDNF_SAFE_FREE_MEMORY(pszName);
if(pInstalledPkgList)
{
SolvFreePackageList(pInstalledPkgList);
}
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFPrepareAndAddPkg(
PTDNF pTdnf,
const char* pszPkgName,
TDNF_ALTERTYPE nAlterType,
char** ppszPkgsNotResolved,
Queue* queueGoal
)
{
uint32_t dwError = 0;
if( !pTdnf ||
IsNullOrEmptyString(pszPkgName) ||
!ppszPkgsNotResolved ||
!queueGoal)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFPrepareSinglePkg(
pTdnf,
pszPkgName,
nAlterType,
ppszPkgsNotResolved,
queueGoal);
BAIL_ON_TDNF_ERROR(dwError);
cleanup:
return dwError;
error:
goto cleanup;
}
uint32_t
TDNFPrepareSinglePkg(
PTDNF pTdnf,
const char* pszPkgName,
TDNF_ALTERTYPE nAlterType,
char** ppszPkgsNotResolved,
Queue* queueGoal
)
{
uint32_t dwError = 0;
PSolvPackageList pInstalledPkgList = NULL;
uint32_t dwCount = 0;
PSolvSack pSack = NULL;
if(!pTdnf ||
!pTdnf->pSack ||
!ppszPkgsNotResolved ||
IsNullOrEmptyString(pszPkgName) ||
!queueGoal)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
pSack = pTdnf->pSack;
//Check if this is a known package. If not add to unresolved
dwError = SolvCountPkgByName(pSack, pszPkgName, &dwCount);
BAIL_ON_TDNF_ERROR(dwError);
if (dwCount == 0)
{
dwError = ERROR_TDNF_NO_SEARCH_RESULTS;
BAIL_ON_TDNF_ERROR(dwError);
}
if(nAlterType == ALTER_REINSTALL)
{
dwError = TDNFMatchForReinstall(
pSack,
pszPkgName,
queueGoal);
BAIL_ON_TDNF_ERROR(dwError);
}
if(nAlterType == ALTER_ERASE ||
nAlterType == ALTER_AUTOERASE)
{
dwError = SolvFindInstalledPkgByName(
pSack,
pszPkgName,
&pInstalledPkgList);
if(dwError == ERROR_TDNF_NO_MATCH)
{
dwError = ERROR_TDNF_ERASE_NEEDS_INSTALL;
}
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFAddPackagesForErase(
pSack,
queueGoal,
pszPkgName);
BAIL_ON_TDNF_ERROR(dwError);
}
else if (nAlterType == ALTER_INSTALL)
{
dwError = TDNFAddPackagesForInstall(
pSack,
queueGoal,
pszPkgName);
BAIL_ON_TDNF_ERROR(dwError);
}
else if (nAlterType == ALTER_UPGRADE)
{
dwError = TDNFAddPackagesForUpgrade(
pSack,
queueGoal,
pszPkgName);
BAIL_ON_TDNF_ERROR(dwError);
}
else if (nAlterType == ALTER_DOWNGRADE ||
nAlterType == ALTER_DOWNGRADEALL)
{
dwError = TDNFAddPackagesForDowngrade(
pSack,
queueGoal,
pszPkgName);
BAIL_ON_TDNF_ERROR(dwError);
}
cleanup:
if(pInstalledPkgList)
{
SolvFreePackageList(pInstalledPkgList);
}
return dwError;
error:
if(dwError == ERROR_TDNF_ALREADY_INSTALLED)
{
int nShowAlreadyInstalled = 1;
//dont show already installed errors in the check path
if(pTdnf && pTdnf->pArgs)
{
if(!strcmp(pTdnf->pArgs->ppszCmds[0], "check"))
{
nShowAlreadyInstalled = 0;
}
}
dwError = 0;
if(nShowAlreadyInstalled)
{
fprintf(stderr, "Package %s is already installed.\n", pszPkgName);
}
}
if(dwError == ERROR_TDNF_NO_UPGRADE_PATH)
{
dwError = 0;
fprintf(stderr, "There is no upgrade path for %s.\n", pszPkgName);
}
if(dwError == ERROR_TDNF_NO_DOWNGRADE_PATH)
{
dwError = 0;
fprintf(stderr, "There is no downgrade path for %s.\n", pszPkgName);
}
if(dwError == ERROR_TDNF_NO_SEARCH_RESULTS)
{
dwError = 0;
if(TDNFAddNotResolved(ppszPkgsNotResolved, pszPkgName))
{
fprintf(stderr, "Error while adding not resolved packages\n");
}
}
if(dwError == ERROR_TDNF_ERASE_NEEDS_INSTALL)
{
dwError = 0;
//TODO: maybe restore solvedinfo based processing here.
}
goto cleanup;
}