Skip to content

Commit

Permalink
Add cache directory out of memory check.
Browse files Browse the repository at this point in the history
  • Loading branch information
prestonsn committed Jul 11, 2022
1 parent 0a98a83 commit 021bba6
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 42 deletions.
9 changes: 8 additions & 1 deletion client/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,7 @@ TDNFResolve(
Queue queueGoal = {0};
char** ppszPkgsNotResolved = NULL;
PTDNF_SOLVED_PKG_INFO pSolvedPkgInfo = NULL;
uint64_t qwAvailCacheBytes = 0;

if(!pTdnf || !ppSolvedPkgInfo)
{
Expand Down Expand Up @@ -1634,9 +1635,15 @@ TDNFResolve(
pSolvedPkgInfo->pPkgsToDowngrade ||
pSolvedPkgInfo->pPkgsToReinstall;

dwError = TDNFCalculateTotalDownloadSize(pSolvedPkgInfo);
dwError = TDNFGetAvailableCacheBytes(pTdnf->pConf, &qwAvailCacheBytes);
BAIL_ON_TDNF_ERROR(dwError);

if (pSolvedPkgInfo->nNeedDownload)
{
dwError = TDNFCheckDownloadCacheBytes(pSolvedPkgInfo, qwAvailCacheBytes);
BAIL_ON_TDNF_ERROR(dwError);
}

pSolvedPkgInfo->ppszPkgsNotResolved = ppszPkgsNotResolved;
*ppSolvedPkgInfo = pSolvedPkgInfo;

Expand Down
15 changes: 1 addition & 14 deletions client/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,24 +233,11 @@ typedef enum
"ERROR_TDNF_DOWNGRADE_NOT_ALLOWED",\
"a downgrade is not allowed below the minimal version. Check 'minversions' in the configuration."},\
{ERROR_TDNF_PERM, "ERROR_TDNF_PERM", "Operation not permitted. You have to be root."},\
{ERROR_TDNF_INVALID_PARAMETER, "ERROR_TDNF_INVALID_PARAMETER", "Invalid argument."},\
{ERROR_TDNF_OUT_OF_MEMORY, "ERROR_TDNF_OUT_OF_MEMORY", "Out of memory."},\
{ERROR_TDNF_NO_DATA, "ERROR_TDNF_NO_DATA", "No data available."},\
{ERROR_TDNF_FILE_NOT_FOUND, "ERROR_TDNF_FILE_NOT_FOUND", "File not found."},\
{ERROR_TDNF_ACCESS_DENIED, "ERROR_TDNF_ACCESS_DENIED", "Permission denied."},\
{ERROR_TDNF_ALREADY_EXISTS, "ERROR_TDNF_ALREADY_EXISTS", "File exists."},\
{ERROR_TDNF_INVALID_ADDRESS, "ERROR_TDNF_INVALID_ADDRESS", "Bad address."},\
{ERROR_TDNF_CALL_INTERRUPTED, "ERROR_TDNF_CALL_INTERRUPTED", "Interrupted syscall."},\
{ERROR_TDNF_FILESYS_IO, "ERROR_TDNF_FILESYS_IO", "Filesystem I/O error."},\
{ERROR_TDNF_SYM_LOOP, "ERROR_TDNF_SYM_LOOP", "Too many links."},\
{ERROR_TDNF_NAME_TOO_LONG, "ERROR_TDNF_NAME_TOO_LONG", "File name too long."},\
{ERROR_TDNF_CALL_NOT_SUPPORTED, "ERROR_TDNF_CALL_NOT_SUPPORTED", "Invalid syscall number."},\
{ERROR_TDNF_INVALID_DIR, "ERROR_TDNF_INVALID_DIR", "Not a directory."},\
{ERROR_TDNF_OVERFLOW, "ERROR_TDNF_OVERFLOW", "Value too large for defined data type."},\
{ERROR_TDNF_OPT_NOT_FOUND, "ERROR_TDNF_OPT_NOT_FOUND", "A required option was not found"},\
{ERROR_TDNF_OPERATION_ABORTED, "ERROR_TDNF_OPERATION_ABORTED", "Operation aborted."},\
{ERROR_TDNF_INVALID_INPUT, "ERROR_TDNF_INVALID_INPUT", "Invalid input."},\
{ERROR_TDNF_CACHE_DISABLED, "ERROR_TDNF_CACHE_DISABLED", "cache only is set, but no repo data found"},\
{ERROR_TDNF_CACHE_DIR_OUT_OF_DISK_SPACE, "ERROR_TDNF_CACHE_DIR_OUT_OF_DISK_SPACE", "Insufficient disk space at cache directory /var/cache/tdnf (unless specified differently in config). Try freeing space first."},\
{ERROR_TDNF_EVENT_CTXT_ITEM_NOT_FOUND, "ERROR_TDNF_EVENT_CTXT_ITEM_NOT_FOUND", "An event context item was not found. This is usually related to plugin events. Try --noplugins to deactivate all plugins or --disableplugin=<plugin> to deactivate a specific one. You can permanently deactivate an offending plugin by setting enable=0 in the plugin config file."},\
{ERROR_TDNF_EVENT_CTXT_ITEM_INVALID_TYPE, "ERROR_TDNF_EVENT_CTXT_ITEM_INVALID_TYPE", "An event item type had a mismatch. This is usually related to plugin events. Try --noplugins to deactivate all plugins or --disableplugin=<plugin> to deactivate a specific one. You can permanently deactivate an offending plugin by setting enable=0 in the plugin config file."},\
{ERROR_TDNF_NO_GPGKEY_CONF_ENTRY, "ERROR_TDNF_NO_GPGKEY_CONF_ENTRY", "gpgkey entry is missing for this repo. please add gpgkey in repo file or use --nogpgcheck to ignore."}, \
Expand Down
2 changes: 2 additions & 0 deletions client/includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <sys/file.h>
#include <time.h>
#include <sys/utsname.h>
#include <sys/vfs.h>
#include <sys/types.h>

#include <dirent.h>
#include <pthread.h>
Expand Down
54 changes: 43 additions & 11 deletions client/packageutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,24 +945,53 @@ TDNFCheckProtectedPkgs(
}

uint32_t
TDNFCalculateTotalDownloadSize(
PTDNF_SOLVED_PKG_INFO pSolvedPkgInfo
TDNFGetAvailableCacheBytes(
PTDNF_CONF pConf,
uint64_t* pqwAvailCacheDirBytes
)
{
uint32_t dwError = 0;
uint32_t dwTotalDownloadSizeBytes = 0;
uint8_t byPkgIndex = 0;
PTDNF_PKG_INFO pPkgInfo = NULL;
struct statfs tmpStatfsBuffer = {0};

if(!pSolvedPkgInfo)
if(!pConf || !pConf->pszCacheDir || !pqwAvailCacheDirBytes)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}

if(!pSolvedPkgInfo->nNeedDownload)
if (statfs(pConf->pszCacheDir, &tmpStatfsBuffer) != 0)
{
pSolvedPkgInfo->dwTotalDownloadSizeBytes = 0;
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}

*pqwAvailCacheDirBytes = tmpStatfsBuffer.f_bsize * tmpStatfsBuffer.f_bavail;

cleanup:
return dwError;

error:
if(pqwAvailCacheDirBytes)
{
*pqwAvailCacheDirBytes = 0;
}
goto cleanup;
}

uint32_t
TDNFCheckDownloadCacheBytes(
PTDNF_SOLVED_PKG_INFO pSolvedPkgInfo,
uint64_t qwAvailCacheBytes
)
{
uint32_t dwError = 0;
uint64_t qwTotalDownloadSizeBytes = 0;
uint8_t byPkgIndex = 0;
PTDNF_PKG_INFO pPkgInfo = NULL;

if(!pSolvedPkgInfo)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}

Expand All @@ -977,13 +1006,16 @@ TDNFCalculateTotalDownloadSize(
{
pPkgInfo = ppPkgsNeedDownload[byPkgIndex];
while(pPkgInfo) {
dwTotalDownloadSizeBytes += pPkgInfo->dwDownloadSizeBytes;
qwTotalDownloadSizeBytes += pPkgInfo->dwDownloadSizeBytes;
if (qwTotalDownloadSizeBytes > qwAvailCacheBytes)
{
dwError = ERROR_TDNF_CACHE_DIR_OUT_OF_DISK_SPACE;
BAIL_ON_TDNF_ERROR(dwError);
}
pPkgInfo = pPkgInfo->pNext;
}
}

pSolvedPkgInfo->dwTotalDownloadSizeBytes = dwTotalDownloadSizeBytes;

error:
return dwError;
}
Expand Down
12 changes: 10 additions & 2 deletions client/prototypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,18 @@ TDNFCheckProtectedPkgs(
);

uint32_t
TDNFCalculateTotalDownloadSize(
PTDNF_SOLVED_PKG_INFO pSolvedPkgInfo
TDNFGetAvailableCacheBytes(
PTDNF_CONF pConf,
uint64_t* pqwAvailCacheBytes
);

uint32_t
TDNFCheckDownloadCacheBytes(
PTDNF_SOLVED_PKG_INFO pSolvedPkgInfo,
uint64_t qwAvailCacheBytes
);


uint32_t
TDNFPopulatePkgInfoArrayDependencies(
PSolvSack pSack,
Expand Down
2 changes: 1 addition & 1 deletion common/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ TDNFUtilsFormatSize(
dwError = TDNFAllocateMemory(1, nMaxSize, (void**)&pszFormattedSize);
BAIL_ON_TDNF_ERROR(dwError);

if(sprintf(pszFormattedSize, "%6.2f%c", dSize, pszSizes[nIndex]) < 0)
if(snprintf(pszFormattedSize, nMaxSize, "%6.2f%c", dSize, pszSizes[nIndex]) >= nMaxSize)
{
dwError = ERROR_TDNF_OUT_OF_MEMORY;
BAIL_ON_TDNF_ERROR(dwError);
Expand Down
2 changes: 2 additions & 0 deletions include/tdnferror.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ extern "C" {
// cache only set, but no cache available
#define ERROR_TDNF_CACHE_DISABLED 1034
#define ERROR_TDNF_DOWNGRADE_NOT_ALLOWED 1035
// cache directory out of memory
#define ERROR_TDNF_CACHE_DIR_OUT_OF_DISK_SPACE 1036

//curl errors
#define ERROR_TDNF_CURL_INIT 1200
Expand Down
1 change: 0 additions & 1 deletion include/tdnftypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ typedef struct _TDNF_SOLVED_PKG_INFO
{
int nNeedAction;
int nNeedDownload;
uint32_t dwTotalDownloadSizeBytes;
TDNF_ALTERTYPE nAlterType;
PTDNF_PKG_INFO pPkgsNotAvailable;
PTDNF_PKG_INFO pPkgsExisting;
Expand Down
11 changes: 9 additions & 2 deletions pytests/tests/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ def setup_test(utils):


def teardown_test(utils):
pkgname = utils.config["sglversion_pkgname"]
utils.run(['tdnf', 'erase', '-y', pkgname])
run_cmd = ['tdnf', 'erase', '-y']
pkg_list = [
utils.config["mulversion_pkgname"],
utils.config["sglversion_pkgname"],
utils.config["sglversion2_pkgname"],
]
for pkgname in pkg_list:
utils.erase_package(pkgname)
utils.run(run_cmd)


def clean_cache(utils):
Expand Down
8 changes: 8 additions & 0 deletions tools/cli/lib/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ TDNFCliInfoCommand(
CHECK_JD_RC(jd_map_add_string(jd_pkg, "Repo", pPkg->pszRepoName));
CHECK_JD_RC(jd_map_add_string(jd_pkg, "Url", pPkg->pszURL));
CHECK_JD_RC(jd_map_add_int(jd_pkg, "InstallSize", pPkg->dwInstallSizeBytes));
if (pPkg->dwDownloadSizeBytes)
{
CHECK_JD_RC(jd_map_add_int(jd_pkg, "DownloadSize", pPkg->dwDownloadSizeBytes));
}
CHECK_JD_RC(jd_map_add_string(jd_pkg, "Summary", pPkg->pszSummary));
CHECK_JD_RC(jd_map_add_string(jd_pkg, "License", pPkg->pszLicense));
CHECK_JD_RC(jd_map_add_string(jd_pkg, "Description", pPkg->pszDescription));
Expand All @@ -319,6 +323,10 @@ TDNFCliInfoCommand(
pr_crit("Version : %s\n", pPkg->pszVersion);
pr_crit("Release : %s\n", pPkg->pszRelease);
pr_crit("Install Size : %s (%u)\n", pPkg->pszFormattedSize, pPkg->dwInstallSizeBytes);
if (pPkg->dwDownloadSizeBytes)
{
pr_crit("Download Size : %s (%u)\n", pPkg->pszFormattedDownloadSize, pPkg->dwDownloadSizeBytes);
}
pr_crit("Repo : %s\n", pPkg->pszRepoName);
pr_crit("Summary : %s\n", pPkg->pszSummary);
pr_crit("URL : %s\n", pPkg->pszURL);
Expand Down
16 changes: 6 additions & 10 deletions tools/cli/lib/installcmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,21 +713,17 @@ PrintAction(
pPkgInfo = pPkgInfo->pNext;
}

TDNFUtilsFormatSize(dwTotalInstallSize, &pszTotalInstallSize);
dwError = TDNFUtilsFormatSize(dwTotalInstallSize, &pszTotalInstallSize);
BAIL_ON_TDNF_ERROR(dwError);
pr_info("\nTotal installed size: %s\n", pszTotalInstallSize);

TDNFUtilsFormatSize(dwTotalDownloadSize, &pszTotalDownloadSize);
dwError = TDNFUtilsFormatSize(dwTotalDownloadSize, &pszTotalDownloadSize);
BAIL_ON_TDNF_ERROR(dwError);
pr_info("Total download size: %s\n", pszTotalDownloadSize);

cleanup:
if (pszTotalInstallSize)
{
free(pszTotalInstallSize);
}
if (pszTotalDownloadSize)
{
free(pszTotalDownloadSize);
}
TDNFFreeMemory(pszTotalInstallSize);
TDNFFreeMemory(pszTotalDownloadSize);
return dwError;

error:
Expand Down

0 comments on commit 021bba6

Please sign in to comment.