in src/extensions/download_handlers/plugin_examples/microsoft_delta_download_handler/source_update_cache/src/source_update_cache_utils.c [151:265]
ADUC_Result ADUC_SourceUpdateCacheUtils_MoveToUpdateCache(
const ADUC_WorkflowHandle workflowHandle, const char* updateCacheBasePath)
{
ADUC_Result result = { .ResultCode = ADUC_Result_Failure };
int res = -1;
ADUC_FileEntity fileEntity;
memset(&fileEntity, 0, sizeof(fileEntity));
STRING_HANDLE sandboxUpdatePayloadFile = NULL;
ADUC_UpdateId* updateId = NULL;
STRING_HANDLE updateCacheFilePath = NULL;
char dirPath[1024] = "";
size_t countPayloads = workflow_get_update_files_count(workflowHandle);
for (size_t index = 0; index < countPayloads; ++index)
{
if (!workflow_get_update_file(workflowHandle, index, &fileEntity))
{
Log_Error("get update file %d", index);
goto done;
}
workflow_get_entity_workfolder_filepath(workflowHandle, &fileEntity, &sandboxUpdatePayloadFile);
result = workflow_get_expected_update_id(workflowHandle, &updateId);
if (IsAducResultCodeFailure(result.ResultCode))
{
Log_Error("get updateId, erc 0x%08x", result.ExtendedResultCode);
goto done;
}
// When update is already installed, payloads would not be downloaded but it would still
// attempt to move to cache with OnUpdateWorkflowCompleted contract call because overall
// is it Apply Success result, so guard against non-existent sandbox file.
if (!SystemUtils_IsFile(STRING_c_str(sandboxUpdatePayloadFile), NULL))
{
result.ExtendedResultCode = ADUC_ERC_MISSING_SOURCE_SANDBOX_FILE;
goto done;
}
const char* provider = updateId->Provider;
const char* hash = (fileEntity.Hash[0]).value;
const char* alg = (fileEntity.Hash[0]).type;
updateCacheFilePath =
ADUC_SourceUpdateCacheUtils_CreateSourceUpdateCachePath(provider, hash, alg, updateCacheBasePath);
if (updateCacheFilePath == NULL)
{
result.ExtendedResultCode = ADUC_ERC_MOVE_CREATE_CACHE_PATH;
goto done;
}
if (strcpy_s(dirPath, ARRAY_SIZE(dirPath), STRING_c_str(updateCacheFilePath)) != 0)
{
result.ExtendedResultCode = ADUC_ERC_NOTRECOVERABLE;
goto done;
}
const char* dirPathCache = dirname(dirPath); // free() not needed
if (dirPathCache == NULL)
{
result.ExtendedResultCode = ADUC_ERC_NOTRECOVERABLE;
goto done;
}
if (ADUC_SystemUtils_MkDirRecursiveDefault(dirPathCache) != 0)
{
result.ExtendedResultCode = ADUC_ERC_MOVE_CREATE_CACHE_PATH;
goto done;
}
// First try to move the file.
// errno EXDEV would be common if copying across different mount points.
// For any failure, it falls back to copy.
Log_Debug("moving '%s' -> '%s'", STRING_c_str(sandboxUpdatePayloadFile), STRING_c_str(updateCacheFilePath));
res = ADUCPAL_rename(STRING_c_str(sandboxUpdatePayloadFile), STRING_c_str(updateCacheFilePath));
if (res != 0)
{
Log_Warn("rename, errno %d", errno);
// fallback to copy
//
if (ADUC_SystemUtils_CopyFileToDir(
STRING_c_str(sandboxUpdatePayloadFile), dirPathCache, false /* overwriteExistingFile */)
!= 0)
{
Log_Error("Copy Failed");
result.ExtendedResultCode = ADUC_ERC_MOVE_COPYFALLBACK;
goto done;
}
}
ADUC_FileEntity_Uninit(&fileEntity);
ADUC_UpdateId_UninitAndFree(updateId);
updateId = NULL;
STRING_delete(updateCacheFilePath);
updateCacheFilePath = NULL;
STRING_delete(sandboxUpdatePayloadFile);
sandboxUpdatePayloadFile = NULL;
}
result.ResultCode = ADUC_Result_Success;
done:
ADUC_FileEntity_Uninit(&fileEntity);
ADUC_UpdateId_UninitAndFree(updateId);
STRING_delete(sandboxUpdatePayloadFile);
STRING_delete(updateCacheFilePath);
return result;
}