コード例 #1
0
ファイル: yum.c プロジェクト: sourcejedi/librepo
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;
}
コード例 #2
0
ファイル: yum.c プロジェクト: akozumpl/librepo
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;
}
コード例 #3
0
ファイル: yum.c プロジェクト: sourcejedi/librepo
static gboolean
lr_yum_use_local_load_base(LrHandle *handle,
                           LrResult *result,
                           LrYumRepo *repo,
                           LrYumRepoMd *repomd,
                           const gchar *baseurl,
                           GError **err)
{
    gboolean ret;
    GError *tmp_err = NULL;
    _cleanup_free_ gchar *path = NULL;
    _cleanup_free_ gchar *sig = NULL;
    _cleanup_file_close_ int fd = -1;

    if (handle->mirrorlist_fd != -1) {
        // Locate mirrorlist if available.
        gchar *mrl_fn = lr_pathconcat(baseurl, "mirrorlist", NULL);
        if (g_file_test(mrl_fn, G_FILE_TEST_IS_REGULAR)) {
            g_debug("%s: Found local mirrorlist: %s", __func__, mrl_fn);
            repo->mirrorlist = mrl_fn;
        } else {
            repo->mirrorlist = NULL;
            lr_free(mrl_fn);
        }
    }

    if (handle->metalink_fd != -1) {
        // Locate metalink.xml if available.
        gchar *mtl_fn = lr_pathconcat(baseurl, "metalink.xml", NULL);
        if (g_file_test(mtl_fn, G_FILE_TEST_IS_REGULAR)) {
            g_debug("%s: Found local metalink: %s", __func__, mtl_fn);
            repo->metalink = mtl_fn;
        } else {
            repo->metalink = NULL;
            lr_free(mtl_fn);
        }
    }

    // Open repomd.xml
    path = lr_pathconcat(baseurl, "repodata/repomd.xml", NULL);
    fd = open(path, O_RDONLY);
    if (fd < 0) {
        g_debug("%s: open(%s): %s", __func__, path, g_strerror(errno));
        g_set_error(err, LR_YUM_ERROR, LRE_IO,
                    "Cannot open %s: %s", path, g_strerror(errno));
        return FALSE;
    }

    // Parse repomd.xml
    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);
    if (!ret) {
        g_debug("%s: Parsing unsuccessful: %s", __func__, tmp_err->message);
        g_propagate_prefixed_error(err, tmp_err,
                                   "repomd.xml parser error: ");
        return FALSE;
    }

    // Fill result object
    result->destdir = g_strdup(baseurl);
    repo->destdir = g_strdup(baseurl);
    repo->repomd = g_strdup(path);

    // Check if signature file exists
    sig = lr_pathconcat(baseurl, "repodata/repomd.xml.asc", NULL);
    if (access(sig, F_OK) == 0)
        repo->signature = g_strdup(sig);

    // Signature checking
    if (handle->checks & LR_CHECK_GPG) {

        if (!repo->signature) {
            // Signature doesn't exist
            g_debug("%s: GPG signature doesn't exists", __func__);
            g_set_error(err, LR_YUM_ERROR, LRE_BADGPG,
                        "GPG verification is enabled, but GPG signature "
                        "repomd.xml.asc is not available");
            return FALSE;
        }

        ret = lr_gpg_check_signature(repo->signature,
                                     repo->repomd,
                                     handle->gnupghomedir,
                                     &tmp_err);
        if (!ret) {
            g_debug("%s: repomd.xml GPG signature verification failed: %s",
                    __func__, tmp_err->message);
            g_propagate_prefixed_error(err, tmp_err,
                        "repomd.xml GPG signature verification failed: ");
            return FALSE;
        }
    }

    // Done - repomd is loaded and checked
    g_debug("%s: Repomd revision: %s", __func__, repomd->revision);

    return TRUE;
}
コード例 #4
0
ファイル: yum.c プロジェクト: akozumpl/librepo
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;
}