static gboolean lr_yum_download_remote(LrHandle *handle, LrResult *result, GError **err) { int rc; gboolean ret = TRUE; int fd; int create_repodata_dir = 1; char *path_to_repodata; LrYumRepo *repo; LrYumRepoMd *repomd; GError *tmp_err = NULL; assert(!err || *err == NULL); repo = result->yum_repo; repomd = result->yum_repomd; g_debug("%s: Downloading/Copying repo..", __func__); path_to_repodata = lr_pathconcat(handle->destdir, "repodata", NULL); if (handle->update) { /* Check if should create repodata/ subdir */ struct stat buf; if (stat(path_to_repodata, &buf) != -1) if (S_ISDIR(buf.st_mode)) create_repodata_dir = 0; } if (create_repodata_dir) { /* Prepare repodata/ subdir */ rc = mkdir(path_to_repodata, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); if (rc == -1) { g_debug("%s: Cannot create dir: %s (%s)", __func__, path_to_repodata, g_strerror(errno)); g_set_error(err, LR_YUM_ERROR, LRE_CANNOTCREATEDIR, "Cannot create directory: %s: %s", path_to_repodata, g_strerror(errno)); lr_free(path_to_repodata); return FALSE; } } lr_free(path_to_repodata); if (!handle->update) { char *path; /* Store mirrorlist file(s) */ if (handle->mirrorlist_fd != -1) { char *ml_file_path = lr_pathconcat(handle->destdir, "mirrorlist", NULL); fd = open(ml_file_path, O_CREAT|O_TRUNC|O_RDWR, 0666); if (fd < 0) { g_debug("%s: Cannot create: %s", __func__, ml_file_path); g_set_error(err, LR_YUM_ERROR, LRE_IO, "Cannot create %s: %s", ml_file_path, g_strerror(errno)); lr_free(ml_file_path); return FALSE; } rc = lr_copy_content(handle->mirrorlist_fd, fd); close(fd); if (rc != 0) { g_debug("%s: Cannot copy content of mirrorlist file", __func__); g_set_error(err, LR_YUM_ERROR, LRE_IO, "Cannot copy content of mirrorlist file %s: %s", ml_file_path, g_strerror(errno)); lr_free(ml_file_path); return FALSE; } repo->mirrorlist = ml_file_path; } if (handle->metalink_fd != -1) { char *ml_file_path = lr_pathconcat(handle->destdir, "metalink.xml", NULL); fd = open(ml_file_path, O_CREAT|O_TRUNC|O_RDWR, 0666); if (fd < 0) { g_debug("%s: Cannot create: %s", __func__, ml_file_path); g_set_error(err, LR_YUM_ERROR, LRE_IO, "Cannot create %s: %s", ml_file_path, g_strerror(errno)); lr_free(ml_file_path); return FALSE; } rc = lr_copy_content(handle->metalink_fd, fd); close(fd); if (rc != 0) { g_debug("%s: Cannot copy content of metalink file", __func__); g_set_error(err, LR_YUM_ERROR, LRE_IO, "Cannot copy content of metalink file %s: %s", ml_file_path, g_strerror(errno)); lr_free(ml_file_path); return FALSE; } repo->metalink = ml_file_path; } /* Prepare repomd.xml file */ path = lr_pathconcat(handle->destdir, "/repodata/repomd.xml", NULL); fd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0666); if (fd == -1) { g_set_error(err, LR_YUM_ERROR, LRE_IO, "Cannot open %s: %s", path, g_strerror(errno)); lr_free(path); return FALSE; } /* Download repomd.xml */ ret = lr_yum_download_repomd(handle, handle->metalink, fd, err); if (!ret) { close(fd); lr_free(path); return FALSE; } /* Check repomd.xml.asc if available. * Try to download and verify GPG signature (repomd.xml.asc). * Try to download only from the mirror where repomd.xml iself was * downloaded. It is because most of yum repositories are not signed * and try every mirror for signature is non effective. * Every mirror would be tried because mirrorded_download function have * no clue if 404 for repomd.xml.asc means that no signature exists or * it is just error on the mirror and should try the next one. **/ if (handle->checks & LR_CHECK_GPG) { int fd_sig; char *url, *signature; signature = lr_pathconcat(handle->destdir, "repodata/repomd.xml.asc", NULL); fd_sig = open(signature, O_CREAT|O_TRUNC|O_RDWR, 0666); if (fd_sig == -1) { g_debug("%s: Cannot open: %s", __func__, signature); g_set_error(err, LR_YUM_ERROR, LRE_IO, "Cannot open %s: %s", signature, g_strerror(errno)); close(fd); lr_free(path); lr_free(signature); return FALSE; } url = lr_pathconcat(handle->used_mirror, "repodata/repomd.xml.asc", NULL); ret = lr_download_url(handle, url, fd_sig, &tmp_err); lr_free(url); close(fd_sig); if (!ret) { // Signature doesn't exist g_debug("%s: GPG signature doesn't exists: %s", __func__, tmp_err->message); g_set_error(err, LR_YUM_ERROR, LRE_BADGPG, "GPG verification is enabled, but GPG signature " "repomd.xml.asc is not available: %s", tmp_err->message); g_clear_error(&tmp_err); unlink(signature); lr_free(signature); return FALSE; } else { // Signature downloaded repo->signature = g_strdup(signature); ret = lr_gpg_check_signature(signature, path, handle->gnupghomedir, &tmp_err); if (!ret) { g_debug("%s: GPG signature verification failed: %s", __func__, tmp_err->message); g_propagate_prefixed_error(err, tmp_err, "repomd.xml GPG signature verification error: "); close(fd); lr_free(path); lr_free(signature); return FALSE; } g_debug("%s: GPG signature successfully verified", __func__); } } lseek(fd, 0, SEEK_SET); /* Parse repomd */ g_debug("%s: Parsing repomd.xml", __func__); ret = lr_yum_repomd_parse_file(repomd, fd, lr_xml_parser_warning_logger, "Repomd xml parser", &tmp_err); close(fd); if (!ret) { g_debug("%s: Parsing unsuccessful: %s", __func__, tmp_err->message); g_propagate_prefixed_error(err, tmp_err, "repomd.xml parser error: "); lr_free(path); return FALSE; } /* Fill result object */ result->destdir = g_strdup(handle->destdir); repo->destdir = g_strdup(handle->destdir); repo->repomd = path; if (handle->used_mirror) repo->url = g_strdup(handle->used_mirror); else repo->url = g_strdup(handle->urls[0]); g_debug("%s: Repomd revision: %s", repomd->revision, __func__); } /* Download rest of metadata files */ ret = lr_yum_download_repo(handle, repo, repomd, &tmp_err); assert((ret && !tmp_err) || (!ret && tmp_err)); if (!ret) { g_debug("%s: Repository download error: %s", __func__, tmp_err->message); g_propagate_prefixed_error(err, tmp_err, "Yum repo downloading error: "); return FALSE; } return TRUE; }
int lr_yum_download_remote(lr_Handle handle, lr_Result result) { int rc = LRE_OK; int fd; int create_repodata_dir = 1; char *path_to_repodata; lr_YumRepo repo; lr_YumRepoMd repomd; DPRINTF("%s: Downloading/Copying repo..\n", __func__); rc = lr_handle_prepare_internal_mirrorlist(handle, "repodata/repomd.xml"); if (rc != LRE_OK) return rc; repo = result->yum_repo; repomd = result->yum_repomd; path_to_repodata = lr_pathconcat(handle->destdir, "repodata", NULL); if (handle->update) { /* Check if should create repodata/ subdir */ struct stat buf; if (stat(path_to_repodata, &buf) != -1) if (S_ISDIR(buf.st_mode)) create_repodata_dir = 0; } if (create_repodata_dir) { /* Prepare repodata/ subdir */ rc = mkdir(path_to_repodata, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); if (rc == -1) { DPRINTF("%s: Cannot create dir: %s (%s)\n", __func__, path_to_repodata, strerror(errno)); lr_free(path_to_repodata); return LRE_CANNOTCREATEDIR; } } lr_free(path_to_repodata); if (!handle->update) { /* Prepare repomd.xml file */ char *path; path = lr_pathconcat(handle->destdir, "/repodata/repomd.xml", NULL); fd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0660); if (fd == -1) { lr_free(path); return LRE_IO; } /* Download repomd.xml */ rc = lr_yum_download_repomd(handle, handle->metalink, fd); if (rc != LRE_OK) { close(fd); lr_free(path); return rc; } /* Check repomd.xml.asc if available. * Try to download and verify GPG signature (repomd.xml.asc). * Try to download only from the mirror where repomd.xml iself was * downloaded. It is because most of yum repositories are not signed * and try every mirror for signature is non effective. * Every mirror would be tried because mirrorded_download function have * no clue if 404 for repomd.xml.asc means that no signature exists or * it is just error on the mirror and should try the next one. **/ if (handle->checks & LR_CHECK_GPG) { int fd_sig; char *url, *signature; signature = lr_pathconcat(handle->destdir, "repodata/repomd.xml.asc", NULL); fd_sig = open(signature, O_CREAT|O_TRUNC|O_RDWR, 0660); if (fd_sig == -1) { DPRINTF("%s: Cannot open: %s\n", __func__, signature); close(fd); lr_free(path); lr_free(signature); return LRE_IO; } url = lr_pathconcat(handle->used_mirror, "repodata/repomd.xml.asc", NULL); rc = lr_curl_single_download(handle, url, fd_sig); lr_free(url); close(fd_sig); if (rc != LRE_OK) { // Signature doesn't exist DPRINTF("%s: GPG signature doesn't exists\n", __func__); unlink(signature); lr_free(signature); } else { // Signature downloaded repo->signature = lr_strdup(signature); rc = lr_gpg_check_signature(signature, path, NULL); if (rc != LRE_OK) { DPRINTF("%s: GPG signature verification failed\n", __func__); close(fd); lr_free(path); lr_free(signature); return rc; } DPRINTF("%s: GPG signature successfully verified\n", __func__); } } lseek(fd, 0, SEEK_SET); /* Parse repomd */ DPRINTF("%s: Parsing repomd.xml\n", __func__); rc = lr_yum_repomd_parse_file(repomd, fd); close(fd); if (rc != LRE_OK) { DPRINTF("%s: Parsing unsuccessful (%d)\n", __func__, rc); lr_free(path); return rc; } /* Fill result object */ result->destdir = lr_strdup(handle->destdir); repo->destdir = lr_strdup(handle->destdir); repo->repomd = path; if (handle->used_mirror) repo->url = lr_strdup(handle->used_mirror); else repo->url = lr_strdup(handle->baseurl); DPRINTF("%s: Repomd revision: %s\n", repomd->revision, __func__); } /* Download rest of metadata files */ if ((rc = lr_yum_download_repo(handle, repo, repomd)) != LRE_OK) return rc; DPRINTF("%s: Repository was successfully downloaded\n", __func__); return LRE_OK; }