int lr_yum_download_repo(lr_Handle handle, lr_YumRepo repo, lr_YumRepoMd repomd) { int ret = LRE_OK; char *destdir; /* Destination dir */ lr_CurlTargetList targets = lr_curltargetlist_new(); destdir = handle->destdir; DEBUGASSERT(destdir); DEBUGASSERT(strlen(destdir)); for (int x = 0; x < repomd->nor; x++) { int fd; char *path; lr_CurlTarget target; lr_YumRepoMdRecord record = repomd->records[x]; if (!lr_yum_repomd_record_enabled(handle, record->type)) continue; path = lr_pathconcat(destdir, record->location_href, NULL); fd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0660); if (fd < 0) { DPRINTF("%s: Cannot create/open %s (%s)\n", __func__, path, strerror(errno)); lr_free(path); return LRE_IO; } target = lr_curltarget_new(); target->path = lr_strdup(record->location_href); target->fd = fd; target->checksum_type = lr_checksum_type(record->checksum_type); target->checksum = lr_strdup(record->checksum); lr_curltargetlist_append(targets, target); /* Becouse path may already exists in repo (while update) */ lr_yum_repo_update(repo, record->type, path); lr_free(path); } if (lr_curltargetlist_len(targets) > 0) ret = lr_curl_multi_download(handle, targets); lr_curltargetlist_free(targets); return ret; }
/* Do not duplicate repoata, just locate the local one */ static gboolean lr_yum_use_local(LrHandle *handle, LrResult *result, GError **err) { char *baseurl; LrYumRepo *repo; LrYumRepoMd *repomd; assert(!err || *err == NULL); g_debug("%s: Locating repo..", __func__); // Shortcuts repo = result->yum_repo; repomd = result->yum_repomd; baseurl = handle->urls[0]; // Skip "file://" prefix if present if (g_str_has_prefix(baseurl, "file://")) baseurl += 7; else if (g_str_has_prefix(baseurl, "file:")) baseurl += 5; // Check sanity if (strstr(baseurl, "://")) { g_set_error(err, LR_YUM_ERROR, LRE_NOTLOCAL, "URL: %s doesn't seem to be a local repository", baseurl); return FALSE; } if (!handle->update) { // Load repomd.xml and mirrorlist+metalink if locally available if (!lr_yum_use_local_load_base(handle, result, repo, repomd, baseurl, err)) return FALSE; } // Locate rest of metadata files for (GSList *elem = repomd->records; elem; elem = g_slist_next(elem)) { _cleanup_free_ char *path = NULL; LrYumRepoMdRecord *record = elem->data; assert(record); if (!lr_yum_repomd_record_enabled(handle, record->type)) continue; // Caller isn't interested in this record type if (lr_yum_repo_path(repo, record->type)) continue; // This path already exists in repo path = lr_pathconcat(baseurl, record->location_href, NULL); if (access(path, F_OK) == -1) { // A repo file is missing if (!handle->ignoremissing) { g_debug("%s: Incomplete repository - %s is missing", __func__, path); g_set_error(err, LR_YUM_ERROR, LRE_INCOMPLETEREPO, "Incomplete repository - %s is missing", path); return FALSE; } continue; } lr_yum_repo_append(repo, record->type, path); } g_debug("%s: Repository was successfully located", __func__); return TRUE; }
static gboolean lr_yum_download_repo(LrHandle *handle, LrYumRepo *repo, LrYumRepoMd *repomd, GError **err) { gboolean ret = TRUE; char *destdir; /* Destination dir */ GSList *targets = NULL; GSList *cbdata_list = NULL; GError *tmp_err = NULL; destdir = handle->destdir; assert(destdir); assert(strlen(destdir)); assert(!err || *err == NULL); for (GSList *elem = repomd->records; elem; elem = g_slist_next(elem)) { int fd; char *path; LrDownloadTarget *target; LrYumRepoMdRecord *record = elem->data; CbData *cbdata = NULL; assert(record); if (!lr_yum_repomd_record_enabled(handle, record->type)) continue; path = lr_pathconcat(destdir, record->location_href, NULL); fd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0666); if (fd < 0) { g_debug("%s: Cannot create/open %s (%s)", __func__, path, g_strerror(errno)); g_set_error(err, LR_YUM_ERROR, LRE_IO, "Cannot create/open %s: %s", path, g_strerror(errno)); lr_free(path); g_slist_free_full(targets, (GDestroyNotify) lr_downloadtarget_free); return FALSE; } GSList *checksums = NULL; if (handle->checks & LR_CHECK_CHECKSUM) { // Select proper checksum type only if checksum check is enabled LrDownloadTargetChecksum *checksum; checksum = lr_downloadtargetchecksum_new( lr_checksum_type(record->checksum_type), record->checksum); checksums = g_slist_prepend(checksums, checksum); } if (handle->user_cb || handle->hmfcb) { cbdata = cbdata_new(handle->user_data, handle->user_cb, handle->hmfcb, record->type); cbdata_list = g_slist_append(cbdata_list, cbdata); } target = lr_downloadtarget_new(handle, record->location_href, record->location_base, fd, NULL, checksums, 0, 0, NULL, cbdata, NULL, NULL, NULL, 0, 0); targets = g_slist_append(targets, target); /* Because path may already exists in repo (while update) */ lr_yum_repo_update(repo, record->type, path); lr_free(path); } if (!targets) return TRUE; ret = lr_download_single_cb(targets, FALSE, (cbdata_list) ? progresscb : NULL, (cbdata_list) ? hmfcb : NULL, &tmp_err); // Error handling assert((ret && !tmp_err) || (!ret && tmp_err)); if (tmp_err) { g_propagate_prefixed_error(err, tmp_err, "Downloading error: "); } else { int code = LRE_OK; char *error_summary = NULL; for (GSList *elem = targets; elem; elem = g_slist_next(elem)) { LrDownloadTarget *target = elem->data; if (target->rcode != LRE_OK) { if (code == LRE_OK) { // First failed download target found code = target->rcode; error_summary = g_strconcat(target->path, " - ", target->err, NULL); } else { error_summary = g_strconcat(error_summary, "; ", target->path, " - ", target->err, NULL); } } close(target->fd); } if (code != LRE_OK) { // At least one target failed ret = FALSE; g_set_error(err, LR_DOWNLOADER_ERROR, code, "Downloading error(s): %s", error_summary); g_free(error_summary); } } g_slist_free_full(cbdata_list, (GDestroyNotify)cbdata_free); g_slist_free_full(targets, (GDestroyNotify)lr_downloadtarget_free); return ret; }
int lr_yum_use_local(lr_Handle handle, lr_Result result) { char *path; int rc = LRE_OK; int fd; char *baseurl; lr_YumRepo repo; lr_YumRepoMd repomd; DPRINTF("%s: Locating repo..\n", __func__); repo = result->yum_repo; repomd = result->yum_repomd; baseurl = handle->baseurl; /* Do not duplicate repoata, just locate the local one */ if (strncmp(baseurl, "file://", 7)) { if (strstr(baseurl, "://")) return LRE_NOTLOCAL; } else { /* Skip file:// in baseurl */ baseurl = baseurl+7; } if (!handle->update) { /* Open and parse repomd */ char *sig; path = lr_pathconcat(baseurl, "repodata/repomd.xml", NULL); fd = open(path, O_RDONLY); if (fd < 0) { DPRINTF("%s: open(%s): %s\n", __func__, path, strerror(errno)); lr_free(path); return LRE_IO; } DPRINTF("%s: Parsing repomd.xml\n", __func__); rc = lr_yum_repomd_parse_file(repomd, fd); if (rc != LRE_OK) { DPRINTF("%s: Parsing unsuccessful (%d)\n", __func__, rc); lr_free(path); return rc; } close(fd); /* Fill result object */ result->destdir = lr_strdup(baseurl); repo->destdir = lr_strdup(baseurl); repo->repomd = path; /* Check if signature file exists */ sig = lr_pathconcat(baseurl, "repodata/repomd.xml.asc", NULL); if (access(sig, F_OK) == 0) repo->signature = sig; // File with key exists else lr_free(sig); /* Signature checking */ if (handle->checks & LR_CHECK_GPG && repo->signature) { rc = lr_gpg_check_signature(repo->signature, repo->repomd, NULL); if (rc != LRE_OK) { DPRINTF("%s: GPG signature verification failed\n", __func__); return rc; } } DPRINTF("%s: Repomd revision: %s\n", __func__, repomd->revision); } /* Locate rest of metadata files */ for (int x = 0; x < repomd->nor; x++) { char *path; lr_YumRepoMdRecord record = repomd->records[x]; if (!lr_yum_repomd_record_enabled(handle, record->type)) continue; if (lr_yum_repo_path(repo, record->type)) continue; /* This path already exists in repo */ path = lr_pathconcat(baseurl, record->location_href, NULL); if (path) { if (access(path, F_OK) == -1) { /* A repo file is missing */ if (!handle->ignoremissing) { DPRINTF("%s: Incomplete repository\n", __func__); lr_free(path); return LRE_INCOMPLETEREPO; } } else lr_yum_repo_append(repo, record->type, path); lr_free(path); } } DPRINTF("%s: Repository was successfully located\n", __func__); return LRE_OK; }