コード例 #1
0
ファイル: xml_dump.c プロジェクト: janncker/createrepo_c
void
cr_xml_dump_files(xmlNodePtr node, cr_Package *package, int primary)
{
    if (!node || !package->files) {
        return;
    }


    GSList *element = NULL;
    for(element = package->files; element; element=element->next) {
        cr_PackageFile *entry = (cr_PackageFile*) element->data;


        // File without name or path is suspicious => Skip it

        if (!(entry->path) || !(entry->name)) {
            continue;
        }


        // String concatenation (path + basename)

        gchar *fullname;
        fullname = g_strconcat(entry->path, entry->name, NULL);

        if (!fullname) {
            continue;
        }


        // Skip a file if we want primary files and the file is not one

        if (primary && !cr_is_primary(fullname)) {
            g_free(fullname);
            continue;
        }


        // ***********************************
        // Element: file
        // ************************************

        xmlNodePtr file_node;
        file_node = cr_xmlNewTextChild(node,
                                       NULL,
                                       BAD_CAST "file",
                                       BAD_CAST fullname);
        g_free(fullname);

        // Write type (skip type if type value is empty of "file")
        if (entry->type && entry->type[0] != '\0' && strcmp(entry->type, "file")) {
            cr_xmlNewProp(file_node, BAD_CAST "type", BAD_CAST entry->type);
        }
    }
}
コード例 #2
0
ファイル: sqlite.c プロジェクト: jaroslawp/createrepo_c
static void
db_file_write (sqlite3 *db,
               sqlite3_stmt *handle,
               gint64 pkgKey,
               cr_PackageFile *file,
               GError **err)
{
    int rc;

    assert(!err || *err == NULL);

    gchar *fullpath = g_strconcat(file->path, file->name, NULL);
    if (!fullpath)
        return; // Nothing to do

    if (!cr_is_primary(fullpath)) {
        g_free(fullpath);
        return;
    }

    const char* file_type = file->type;
    if (!file_type || file_type[0] == '\0') {
        file_type = "file";
    }

    cr_sqlite3_bind_text (handle, 1, fullpath, -1, SQLITE_TRANSIENT);
    g_free(fullpath);
    cr_sqlite3_bind_text (handle, 2, file_type, -1, SQLITE_STATIC);
    sqlite3_bind_int  (handle, 3, pkgKey);

    rc = sqlite3_step (handle);
    sqlite3_reset (handle);

    if (rc != SQLITE_DONE) {
        g_critical ("Error adding package file to db: %s",
                    sqlite3_errmsg (db));
        g_set_error(err, ERR_DOMAIN, CRE_DB,
                    "Error adding package file to db: %s",
                    sqlite3_errmsg(db));
    }
}
コード例 #3
0
ファイル: parsehdr.c プロジェクト: Conan-Kudo/createrepo_c
cr_Package *
cr_package_from_header(Header hdr,
                       int changelog_limit,
                       cr_HeaderReadingFlags hdrrflags,
                       G_GNUC_UNUSED GError **err)
{
    cr_Package *pkg;

    assert(hdr);
    assert(!err || *err == NULL);

    // Create new package structure

    pkg = cr_package_new();
    pkg->loadingflags |= CR_PACKAGE_FROM_HEADER;
    pkg->loadingflags |= CR_PACKAGE_LOADED_PRI;
    pkg->loadingflags |= CR_PACKAGE_LOADED_FIL;
    pkg->loadingflags |= CR_PACKAGE_LOADED_OTH;


    // Create rpm tag data container

    rpmtd td = rpmtdNew();
    headerGetFlags flags = HEADERGET_MINMEM | HEADERGET_EXT;


    // Fill package structure

    pkg->name = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_NAME));

    gint64 is_src = headerGetNumber(hdr, RPMTAG_SOURCEPACKAGE);
    if (is_src) {
        pkg->arch = cr_safe_string_chunk_insert(pkg->chunk, "src");
    } else {
        pkg->arch = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_ARCH));
    }

    pkg->version = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_VERSION));

#define MAX_STR_INT_LEN 24
    char tmp_epoch[MAX_STR_INT_LEN];
    if (snprintf(tmp_epoch, MAX_STR_INT_LEN, "%llu", (long long unsigned int) headerGetNumber(hdr, RPMTAG_EPOCH)) <= 0) {
        tmp_epoch[0] = '\0';
    }
    pkg->epoch = g_string_chunk_insert_len(pkg->chunk, tmp_epoch, MAX_STR_INT_LEN);

    pkg->release = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_RELEASE));
    pkg->summary = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_SUMMARY));
    pkg->description = cr_safe_string_chunk_insert_null(pkg->chunk, headerGetString(hdr, RPMTAG_DESCRIPTION));
    pkg->url = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_URL));
    if (headerGet(hdr, RPMTAG_BUILDTIME, td, flags)) {
        pkg->time_build = rpmtdGetNumber(td);
    }
    pkg->rpm_license = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_LICENSE));
    pkg->rpm_vendor = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_VENDOR));
    pkg->rpm_group = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_GROUP));
    pkg->rpm_buildhost = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_BUILDHOST));
    pkg->rpm_sourcerpm = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_SOURCERPM));
    pkg->rpm_packager = cr_safe_string_chunk_insert(pkg->chunk, headerGetString(hdr, RPMTAG_PACKAGER));
    if (headerGet(hdr, RPMTAG_SIZE, td, flags)) {
        pkg->size_installed = rpmtdGetNumber(td);
    }
    if (headerGet(hdr, RPMTAG_ARCHIVESIZE, td, flags)) {
        pkg->size_archive = rpmtdGetNumber(td);
    }

    rpmtdFreeData(td);
    rpmtdFree(td);


    //
    // Fill files
    //

    rpmtd full_filenames = rpmtdNew(); // Only for filenames_hashtable
    rpmtd indexes   = rpmtdNew();
    rpmtd filenames = rpmtdNew();
    rpmtd fileflags = rpmtdNew();
    rpmtd filemodes = rpmtdNew();

    GHashTable *filenames_hashtable = g_hash_table_new(g_str_hash, g_str_equal);

    rpmtd dirnames = rpmtdNew();


    // Create list of pointer to directory names

    int dir_count;
    char **dir_list = NULL;
    if (headerGet(hdr, RPMTAG_DIRNAMES, dirnames,  flags) && (dir_count = rpmtdCount(dirnames))) {
        int x = 0;
        dir_list = malloc(sizeof(char *) * dir_count);
        while (rpmtdNext(dirnames) != -1) {
            dir_list[x] = cr_safe_string_chunk_insert(pkg->chunk, rpmtdGetString(dirnames));
            x++;
        }
        assert(x == dir_count);
    }

    if (headerGet(hdr, RPMTAG_FILENAMES,  full_filenames,  flags) &&
        headerGet(hdr, RPMTAG_DIRINDEXES, indexes,  flags) &&
        headerGet(hdr, RPMTAG_BASENAMES,  filenames, flags) &&
        headerGet(hdr, RPMTAG_FILEFLAGS,  fileflags, flags) &&
        headerGet(hdr, RPMTAG_FILEMODES,  filemodes, flags))
    {
        rpmtdInit(full_filenames);
        rpmtdInit(indexes);
        rpmtdInit(filenames);
        rpmtdInit(fileflags);
        rpmtdInit(filemodes);
        while ((rpmtdNext(full_filenames) != -1)   &&
               (rpmtdNext(indexes) != -1)   &&
               (rpmtdNext(filenames) != -1) &&
               (rpmtdNext(fileflags) != -1) &&
               (rpmtdNext(filemodes) != -1))
        {
            cr_PackageFile *packagefile = cr_package_file_new();
            packagefile->name = cr_safe_string_chunk_insert(pkg->chunk,
                                                         rpmtdGetString(filenames));
            packagefile->path = (dir_list) ? dir_list[(int) rpmtdGetNumber(indexes)] : "";

            if (S_ISDIR(rpmtdGetNumber(filemodes))) {
                // Directory
                packagefile->type = cr_safe_string_chunk_insert(pkg->chunk, "dir");
            } else if (rpmtdGetNumber(fileflags) & RPMFILE_GHOST) {
                // Ghost
                packagefile->type = cr_safe_string_chunk_insert(pkg->chunk, "ghost");
            } else {
                // Regular file
                packagefile->type = cr_safe_string_chunk_insert(pkg->chunk, "");
            }

            g_hash_table_replace(filenames_hashtable,
                                 (gpointer) rpmtdGetString(full_filenames),
                                 (gpointer) rpmtdGetString(full_filenames));
            pkg->files = g_slist_prepend(pkg->files, packagefile);
        }
        pkg->files = g_slist_reverse (pkg->files);

        rpmtdFreeData(dirnames);
        rpmtdFreeData(indexes);
        rpmtdFreeData(filenames);
        rpmtdFreeData(fileflags);
        rpmtdFreeData(filemodes);
    }

    rpmtdFree(dirnames);
    rpmtdFree(indexes);
    rpmtdFree(filemodes);

    if (dir_list) {
        free((void *) dir_list);
    }


    //
    // PCOR (provides, conflicts, obsoletes, requires)
    //

    rpmtd fileversions = rpmtdNew();

    // Struct used as value in ap_hashtable
    struct ap_value_struct {
        const char *flags;
        const char *version;
        int pre;
    };

    // Hastable with filenames from provided
    GHashTable *provided_hashtable = g_hash_table_new(g_str_hash, g_str_equal);

    // Hashtable with already processed files from requires
    GHashTable *ap_hashtable = g_hash_table_new_full(g_str_hash,
                                                     g_str_equal,
                                                     NULL,
                                                     free);

    for (int deptype=0; dep_items[deptype].type != DEP_SENTINEL; deptype++) {
        if (headerGet(hdr, dep_items[deptype].nametag, filenames, flags) &&
            headerGet(hdr, dep_items[deptype].flagstag, fileflags, flags) &&
            headerGet(hdr, dep_items[deptype].versiontag, fileversions, flags))
        {

            // Because we have to select only libc.so with highest version
            // e.g. libc.so.6(GLIBC_2.4)
            cr_Dependency *libc_require_highest = NULL;

            rpmtdInit(filenames);
            rpmtdInit(fileflags);
            rpmtdInit(fileversions);
            while ((rpmtdNext(filenames) != -1) &&
                   (rpmtdNext(fileflags) != -1) &&
                   (rpmtdNext(fileversions) != -1))
            {
                int pre = 0;
                const char *filename = rpmtdGetString(filenames);
                guint64 num_flags = rpmtdGetNumber(fileflags);
                const char *flags = cr_flag_to_str(num_flags);
                const char *full_version = rpmtdGetString(fileversions);

                // Requires specific stuff
                if (deptype == DEP_REQUIRES) {
                    // Skip requires which start with "rpmlib("
                    if (!strncmp("rpmlib(", filename, 7)) {
                        continue;
                    }

                    // Skip package primary files
                    if (g_hash_table_lookup_extended(filenames_hashtable, filename, NULL, NULL)) {
                        if (cr_is_primary(filename)) {
                            continue;
                        }
                    }

                    // Skip files which are provided
                    if (g_hash_table_lookup_extended(provided_hashtable, filename, NULL, NULL)) {
                        continue;
                    }

                    // Calculate pre value
                    if (num_flags & (RPMSENSE_PREREQ |
                                     RPMSENSE_SCRIPT_PRE |
                                     RPMSENSE_SCRIPT_POST))
                    {
                        pre = 1;
                    }

                    // Skip duplicate files
                    gpointer value;
                    if (g_hash_table_lookup_extended(ap_hashtable, filename, NULL, &value)) {
                        struct ap_value_struct *ap_value = value;
                        if (!g_strcmp0(ap_value->flags, flags) &&
                            !strcmp(ap_value->version, full_version) &&
                            (ap_value->pre == pre))
                        {
                            continue;
                        }
                    }
                }

                // Parse dep string
                cr_EVR *evr = cr_str_to_evr(full_version, pkg->chunk);
                if ((full_version && *full_version) && !evr->epoch) {
                    // NULL in epoch mean that the epoch was bad (non-numerical)
                    _cleanup_free_ gchar *pkg_nevra = cr_package_nevra(pkg);
                    g_warning("Bad epoch in version string \"%s\" for dependency \"%s\" in package \"%s\"",
                              full_version, filename, pkg_nevra);
                    g_warning("Skipping this dependency");
                    g_free(evr);
                    continue;
                }

                // Create dynamic dependency object
                cr_Dependency *dependency = cr_dependency_new();
                dependency->name = cr_safe_string_chunk_insert(pkg->chunk, filename);
                dependency->flags = cr_safe_string_chunk_insert(pkg->chunk, flags);
                dependency->epoch = evr->epoch;
                dependency->version = evr->version;
                dependency->release = evr->release;
                g_free(evr);

                switch (deptype) {
                    case DEP_PROVIDES:
                        g_hash_table_replace(provided_hashtable, dependency->name, dependency->name);
                        pkg->provides = g_slist_prepend(pkg->provides, dependency);
                        break;
                    case DEP_CONFLICTS:
                        pkg->conflicts = g_slist_prepend(pkg->conflicts, dependency);
                        break;
                    case DEP_OBSOLETES:
                        pkg->obsoletes = g_slist_prepend(pkg->obsoletes, dependency);
                        break;
                    case DEP_REQUIRES:
                        dependency->pre = pre;

                        // XXX: libc.so filtering ////////////////////////////
                        if (g_str_has_prefix(dependency->name, "libc.so.6")) {
                            if (!libc_require_highest)
                                libc_require_highest = dependency;
                            else {
                                if (cr_compare_dependency(libc_require_highest->name,
                                                       dependency->name) == 2)
                                {
                                    g_free(libc_require_highest);
                                    libc_require_highest = dependency;
                                } else
                                    g_free(dependency);
                            }
                            break;
                        }
                        // XXX: libc.so filtering - END ///////////////////////

                        pkg->requires = g_slist_prepend(pkg->requires, dependency);

                        // Add file into ap_hashtable
                        struct ap_value_struct *value = malloc(sizeof(struct ap_value_struct));
                        value->flags = flags;
                        value->version = full_version;
                        value->pre = dependency->pre;
                        g_hash_table_replace(ap_hashtable, dependency->name, value);
                        break; //case REQUIRES end
                    case DEP_SUGGESTS:
                        pkg->suggests = g_slist_prepend(pkg->suggests, dependency);
                        break;
                    case DEP_ENHANCES:
                        pkg->enhances = g_slist_prepend(pkg->enhances, dependency);
                        break;
                    case DEP_RECOMMENDS:
                        pkg->recommends = g_slist_prepend(pkg->recommends, dependency);
                        break;
                    case DEP_SUPPLEMENTS:
                        pkg->supplements = g_slist_prepend(pkg->supplements, dependency);
                        break;
#ifdef ENABLE_LEGACY_WEAKDEPS
                    case DEP_OLDSUGGESTS:
                        if ( num_flags & RPMSENSE_STRONG ) {
                            pkg->recommends = g_slist_prepend(pkg->recommends, dependency);
                        } else {
                            pkg->suggests = g_slist_prepend(pkg->suggests, dependency);
                        }
                        break;
                    case DEP_OLDENHANCES:
                        if ( num_flags & RPMSENSE_STRONG ) {
                            pkg->supplements = g_slist_prepend(pkg->supplements, dependency);
                        } else {
                            pkg->enhances = g_slist_prepend(pkg->enhances, dependency);
                        }
                        break;
#endif
                } // Switch end
            } // While end

            // XXX: libc.so filtering ////////////////////////////////
            if (deptype == DEP_REQUIRES && libc_require_highest)
                pkg->requires = g_slist_prepend(pkg->requires, libc_require_highest);
            // XXX: libc.so filtering - END ////////////////////////////////
        }

        rpmtdFreeData(filenames);
        rpmtdFreeData(fileflags);
        rpmtdFreeData(fileversions);
    }

    pkg->provides    = g_slist_reverse (pkg->provides);
    pkg->conflicts   = g_slist_reverse (pkg->conflicts);
    pkg->obsoletes   = g_slist_reverse (pkg->obsoletes);
    pkg->requires    = g_slist_reverse (pkg->requires);
    pkg->suggests    = g_slist_reverse (pkg->suggests);
    pkg->enhances    = g_slist_reverse (pkg->enhances);
    pkg->recommends  = g_slist_reverse (pkg->recommends);
    pkg->supplements = g_slist_reverse (pkg->supplements);

    g_hash_table_remove_all(filenames_hashtable);
    g_hash_table_remove_all(provided_hashtable);
    g_hash_table_remove_all(ap_hashtable);

    g_hash_table_unref(filenames_hashtable);
    g_hash_table_unref(provided_hashtable);
    g_hash_table_unref(ap_hashtable);

    rpmtdFree(filenames);
    rpmtdFree(fileflags);
    rpmtdFree(fileversions);

    rpmtdFreeData(full_filenames);
    rpmtdFree(full_filenames);


    //
    // Changelogs
    //

    rpmtd changelogtimes = rpmtdNew();
    rpmtd changelognames = rpmtdNew();
    rpmtd changelogtexts = rpmtdNew();

    if (headerGet(hdr, RPMTAG_CHANGELOGTIME, changelogtimes, flags) &&
        headerGet(hdr, RPMTAG_CHANGELOGNAME, changelognames, flags) &&
        headerGet(hdr, RPMTAG_CHANGELOGTEXT, changelogtexts, flags))
    {
        gint64 last_time = G_GINT64_CONSTANT(0);
        rpmtdInit(changelogtimes);
        rpmtdInit(changelognames);
        rpmtdInit(changelogtexts);
        while ((rpmtdNext(changelogtimes) != -1) &&
               (rpmtdNext(changelognames) != -1) &&
               (rpmtdNext(changelogtexts) != -1) &&
               (changelog_limit > 0 || changelog_limit == -1))
        {
            gint64 time = rpmtdGetNumber(changelogtimes);

            cr_ChangelogEntry *changelog = cr_changelog_entry_new();
            changelog->author    = cr_safe_string_chunk_insert(pkg->chunk,
                                            rpmtdGetString(changelognames));
            changelog->date      = time;
            changelog->changelog = cr_safe_string_chunk_insert(pkg->chunk,
                                            rpmtdGetString(changelogtexts));

            // Remove space from end of author name
            if (changelog->author) {
                size_t len, x;
                len = strlen(changelog->author);
                for (x=(len-1); x > 0; x--) {
                    if (changelog->author[x] == ' ') {
                        changelog->author[x] = '\0';
                    } else {
                        break;
                    }
                }
            }

            pkg->changelogs = g_slist_prepend(pkg->changelogs, changelog);
            if (changelog_limit != -1)
                changelog_limit--;

            // If a previous entry has the same time, increment time of the previous
            // entry by one. Ugly but works!
            if (last_time == time) {
                int tmp_time = time;
                GSList *previous = pkg->changelogs;
                while ((previous = g_slist_next(previous)) != NULL &&
                       ((cr_ChangelogEntry *) (previous->data))->date == tmp_time) {
                    ((cr_ChangelogEntry *) (previous->data))->date++;
                    tmp_time++;
                }
            } else {
                last_time = time;
            }


        }
        //pkg->changelogs = g_slist_reverse (pkg->changelogs);
    }

    rpmtdFreeData(changelogtimes);
    rpmtdFreeData(changelognames);
    rpmtdFreeData(changelogtexts);

    rpmtdFree(changelogtimes);
    rpmtdFree(changelognames);
    rpmtdFree(changelogtexts);


    //
    // Keys and hdrid (data used for caching when the --cachedir is specified)
    //

    if (hdrrflags & CR_HDRR_LOADHDRID)
        pkg->hdrid = cr_safe_string_chunk_insert(pkg->chunk,
                                                 headerGetString(hdr, RPMTAG_HDRID));

    if (hdrrflags & CR_HDRR_LOADSIGNATURES) {
        rpmtd gpgtd = rpmtdNew();
        rpmtd pgptd = rpmtdNew();

        if (headerGet(hdr, RPMTAG_SIGGPG, gpgtd, hdrrflags)
            && gpgtd->count > 0)
        {
            pkg->siggpg = cr_binary_data_new();
            pkg->siggpg->size = gpgtd->count;
            pkg->siggpg->data = g_string_chunk_insert_len(pkg->chunk,
                                                          gpgtd->data,
                                                          gpgtd->count);
        }

        if (headerGet(hdr, RPMTAG_SIGPGP, pgptd, hdrrflags)
            && pgptd->count > 0)
        {
            pkg->sigpgp = cr_binary_data_new();
            pkg->sigpgp->size = pgptd->count;
            pkg->sigpgp->data = g_string_chunk_insert_len(pkg->chunk,
                                                          pgptd->data,
                                                          pgptd->count);
        }

        rpmtdFree(gpgtd);
        rpmtdFree(pgptd);
    }

    return pkg;
}