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); } } }
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)); } }
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; }