/** * Retrieve trigger type info. * @param h header * @retval td tag data container * @return 1 on success */ static int triggertypeTag(Header h, rpmtd td, headerGetFlags hgflags) { int i; char ** conds; struct rpmtd_s indices, flags, scripts; if (!headerGet(h, RPMTAG_TRIGGERINDEX, &indices, HEADERGET_MINMEM)) { return 0; } headerGet(h, RPMTAG_TRIGGERFLAGS, &flags, HEADERGET_MINMEM); headerGet(h, RPMTAG_TRIGGERSCRIPTS, &scripts, HEADERGET_MINMEM); td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->count = rpmtdCount(&scripts); td->data = conds = xmalloc(sizeof(*conds) * td->count); td->type = RPM_STRING_ARRAY_TYPE; while ((i = rpmtdNext(&scripts)) >= 0) { rpm_flag_t *flag; rpmtdInit(&indices); rpmtdInit(&flags); while (rpmtdNext(&indices) >= 0 && rpmtdNext(&flags) >= 0) { if (*rpmtdGetUint32(&indices) != i) continue; flag = rpmtdGetUint32(&flags); if (*flag & RPMSENSE_TRIGGERPREIN) conds[i] = xstrdup("prein"); else if (*flag & RPMSENSE_TRIGGERIN) conds[i] = xstrdup("in"); else if (*flag & RPMSENSE_TRIGGERUN) conds[i] = xstrdup("un"); else if (*flag & RPMSENSE_TRIGGERPOSTUN) conds[i] = xstrdup("postun"); else conds[i] = xstrdup(""); break; } } rpmtdFreeData(&indices); rpmtdFreeData(&flags); rpmtdFreeData(&scripts); return 1; }
static int addPrefixes(Header h, rpmRelocation *relocations, int numRelocations) { struct rpmtd_s validRelocs; const char *validprefix; const char ** actualRelocations; int numActual = 0; headerGet(h, RPMTAG_PREFIXES, &validRelocs, HEADERGET_MINMEM); /* * If no relocations are specified (usually the case), then return the * original header. If there are prefixes, however, then INSTPREFIXES * should be added for RPM_INSTALL_PREFIX environ variables in scriptlets, * but, since relocateFileList() can be called more than once for * the same header, don't bother if already present. */ if (relocations == NULL || numRelocations == 0) { if (rpmtdCount(&validRelocs) > 0) { if (!headerIsEntry(h, RPMTAG_INSTPREFIXES)) { rpmtdSetTag(&validRelocs, RPMTAG_INSTPREFIXES); headerPut(h, &validRelocs, HEADERPUT_DEFAULT); } rpmtdFreeData(&validRelocs); } return 0; } actualRelocations = xmalloc(rpmtdCount(&validRelocs) * sizeof(*actualRelocations)); rpmtdInit(&validRelocs); while ((validprefix = rpmtdNextString(&validRelocs))) { int j; for (j = 0; j < numRelocations; j++) { if (relocations[j].oldPath == NULL || /* XXX can't happen */ !rstreq(validprefix, relocations[j].oldPath)) continue; /* On install, a relocate to NULL means skip the path. */ if (relocations[j].newPath) { actualRelocations[numActual] = relocations[j].newPath; numActual++; } break; } if (j == numRelocations) { actualRelocations[numActual] = validprefix; numActual++; } } rpmtdFreeData(&validRelocs); if (numActual) { headerPutStringArray(h, RPMTAG_INSTPREFIXES, actualRelocations, numActual); } free(actualRelocations); /* When any relocations are present there'll be more work to do */ return 1; }
void rpmRelocationBuild(Header h, rpmRelocation *rawrelocs, int *rnrelocs, rpmRelocation **rrelocs, uint8_t **rbadrelocs) { int i; struct rpmtd_s validRelocs; rpmRelocation * relocs = NULL; uint8_t *badrelocs = NULL; int nrelocs = 0; for (rpmRelocation *r = rawrelocs; r->oldPath || r->newPath; r++) nrelocs++; headerGet(h, RPMTAG_PREFIXES, &validRelocs, HEADERGET_MINMEM); relocs = xmalloc(sizeof(*relocs) * (nrelocs+1)); /* Build sorted relocation list from raw relocations. */ for (i = 0; i < nrelocs; i++) { char * t; /* * Default relocations (oldPath == NULL) are handled in the UI, * not rpmlib. */ if (rawrelocs[i].oldPath == NULL) continue; /* XXX can't happen */ /* FIXME: Trailing /'s will confuse us greatly. Internal ones will too, but those are more trouble to fix up. :-( */ t = xstrdup(rawrelocs[i].oldPath); relocs[i].oldPath = (t[0] == '/' && t[1] == '\0') ? t : stripTrailingChar(t, '/'); /* An old path w/o a new path is valid, and indicates exclusion */ if (rawrelocs[i].newPath) { int valid = 0; const char *validprefix; t = xstrdup(rawrelocs[i].newPath); relocs[i].newPath = (t[0] == '/' && t[1] == '\0') ? t : stripTrailingChar(t, '/'); /* FIX: relocations[i].oldPath == NULL */ /* Verify that the relocation's old path is in the header. */ rpmtdInit(&validRelocs); while ((validprefix = rpmtdNextString(&validRelocs))) { if (rstreq(validprefix, relocs[i].oldPath)) { valid = 1; break; } } if (!valid) { if (badrelocs == NULL) badrelocs = xcalloc(nrelocs, sizeof(*badrelocs)); badrelocs[i] = 1; } } else { relocs[i].newPath = NULL; } } relocs[i].oldPath = NULL; relocs[i].newPath = NULL; sortRelocs(relocs, nrelocs); rpmtdFreeData(&validRelocs); *rrelocs = relocs; *rnrelocs = nrelocs; *rbadrelocs = badrelocs; }
/** * Retrieve trigger type info. * @param mode type of trigger (see tMode_e) * @param h header * @retval td tag data container * @param hgflags header get flags * @return 1 on success */ static int triggertypeTagFor(tMode mode, Header h, rpmtd td, headerGetFlags hgflags) { int i; char ** conds; struct rpmtd_s indices, flags, scripts; rpmTagVal triggerindex, triggerflags, triggerscripts; switch (mode) { case NORMALTRIGGER: triggerindex = RPMTAG_TRIGGERINDEX; triggerflags = RPMTAG_TRIGGERFLAGS; triggerscripts = RPMTAG_TRIGGERSCRIPTS; break; case FILETRIGGER: triggerindex = RPMTAG_FILETRIGGERINDEX; triggerflags = RPMTAG_FILETRIGGERFLAGS; triggerscripts = RPMTAG_FILETRIGGERSCRIPTS; break; case TRANSFILETRIGGER: triggerindex = RPMTAG_TRANSFILETRIGGERINDEX; triggerflags = RPMTAG_TRANSFILETRIGGERFLAGS; triggerscripts = RPMTAG_TRANSFILETRIGGERSCRIPTS; break; default: return 0; } if (!headerGet(h, triggerindex, &indices, HEADERGET_MINMEM)) { return 0; } headerGet(h, triggerflags, &flags, HEADERGET_MINMEM); headerGet(h, triggerscripts, &scripts, HEADERGET_MINMEM); td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->count = rpmtdCount(&scripts); td->data = conds = xmalloc(sizeof(*conds) * td->count); td->type = RPM_STRING_ARRAY_TYPE; while ((i = rpmtdNext(&scripts)) >= 0) { rpm_flag_t *flag; rpmtdInit(&indices); rpmtdInit(&flags); while (rpmtdNext(&indices) >= 0 && rpmtdNext(&flags) >= 0) { if (*rpmtdGetUint32(&indices) != i) continue; flag = rpmtdGetUint32(&flags); if (*flag & RPMSENSE_TRIGGERPREIN) conds[i] = xstrdup("prein"); else if (*flag & RPMSENSE_TRIGGERIN) conds[i] = xstrdup("in"); else if (*flag & RPMSENSE_TRIGGERUN) conds[i] = xstrdup("un"); else if (*flag & RPMSENSE_TRIGGERPOSTUN) conds[i] = xstrdup("postun"); else conds[i] = xstrdup(""); break; } } rpmtdFreeData(&indices); rpmtdFreeData(&flags); rpmtdFreeData(&scripts); return 1; }
/** * Retrieve trigger info. * @param mode type of trigger (see tMode_e) * @param h header * @retval td tag data container * @param hgflags header get flags * @return 1 on success */ static int triggercondsTagFor(tMode mode, Header h, rpmtd td, headerGetFlags hgflags) { uint32_t * indices; int i, j; char ** conds; struct rpmtd_s nametd, indextd, flagtd, versiontd, scripttd; int hgeflags = HEADERGET_MINMEM; rpmTagVal triggername, triggerindex, triggerflags; rpmTagVal triggerversion, triggerscripts; switch (mode) { case NORMALTRIGGER: triggername = RPMTAG_TRIGGERNAME; triggerindex = RPMTAG_TRIGGERINDEX; triggerflags = RPMTAG_TRIGGERFLAGS; triggerversion = RPMTAG_TRIGGERVERSION; triggerscripts = RPMTAG_TRIGGERSCRIPTS; break; case FILETRIGGER: triggername = RPMTAG_FILETRIGGERNAME; triggerindex = RPMTAG_FILETRIGGERINDEX; triggerflags = RPMTAG_FILETRIGGERFLAGS; triggerversion = RPMTAG_FILETRIGGERVERSION; triggerscripts = RPMTAG_FILETRIGGERSCRIPTS; break; case TRANSFILETRIGGER: triggername = RPMTAG_TRANSFILETRIGGERNAME; triggerindex = RPMTAG_TRANSFILETRIGGERINDEX; triggerflags = RPMTAG_TRANSFILETRIGGERFLAGS; triggerversion = RPMTAG_TRANSFILETRIGGERVERSION; triggerscripts = RPMTAG_TRANSFILETRIGGERSCRIPTS; break; default: return 0; } if (!headerGet(h, triggername, &nametd, hgeflags)) { return 0; } headerGet(h, triggerindex, &indextd, hgeflags); headerGet(h, triggerflags, &flagtd, hgeflags); headerGet(h, triggerversion, &versiontd, hgeflags); headerGet(h, triggerscripts, &scripttd, hgeflags); td->type = RPM_STRING_ARRAY_TYPE; td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->data = conds = xmalloc(sizeof(*conds) * rpmtdCount(&scripttd)); td->count = rpmtdCount(&scripttd); indices = indextd.data; while ((i = rpmtdNext(&scripttd)) >= 0) { rpm_flag_t *flag; char *flagStr, *item; ARGV_t items = NULL; rpmtdInit(&nametd); rpmtdInit(&flagtd); rpmtdInit(&versiontd); while ((j = rpmtdNext(&nametd)) >= 0) { /* flag and version arrays match name array size always */ rpmtdNext(&flagtd); rpmtdNext(&versiontd); if (indices[j] != i) continue; flag = rpmtdGetUint32(&flagtd); if (flag && *flag & RPMSENSE_SENSEMASK) { flagStr = rpmtdFormat(&flagtd, RPMTD_FORMAT_DEPFLAGS, NULL); rasprintf(&item, "%s %s %s", rpmtdGetString(&nametd), flagStr, rpmtdGetString(&versiontd)); free(flagStr); } else { item = xstrdup(rpmtdGetString(&nametd)); } argvAdd(&items, item); free(item); } conds[i] = argvJoin(items, ", "); argvFree(items); } rpmtdFreeData(&nametd); rpmtdFreeData(&versiontd); rpmtdFreeData(&flagtd); rpmtdFreeData(&indextd); rpmtdFreeData(&scripttd); return 1; }
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; }
rpmRC rpmInstallSourcePackage(rpmts ts, FD_t fd, char ** specFilePtr, char ** cookie) { rpmfi fi = NULL; char * specFile = NULL; const char *rootdir = rpmtsRootDir(ts); Header h = NULL; rpmpsm psm = NULL; rpmte te = NULL; rpmRC rpmrc; int specix = -1; struct rpmtd_s filenames; rpmtdReset(&filenames); rpmrc = rpmReadPackageFile(ts, fd, NULL, &h); switch (rpmrc) { case RPMRC_NOTTRUSTED: case RPMRC_NOKEY: case RPMRC_OK: break; default: goto exit; break; } if (h == NULL) goto exit; rpmrc = RPMRC_FAIL; /* assume failure */ if (!headerIsSource(h)) { rpmlog(RPMLOG_ERR, _("source package expected, binary found\n")); goto exit; } /* src.rpm install can require specific rpmlib features, check them */ if (!rpmlibDeps(h)) goto exit; if (headerGet(h, RPMTAG_BASENAMES, &filenames, HEADERGET_ALLOC)) { struct rpmtd_s td; const char *str; const char *_cookie = headerGetString(h, RPMTAG_COOKIE); if (cookie && _cookie) *cookie = xstrdup(_cookie); /* Try to find spec by file flags */ if (_cookie && headerGet(h, RPMTAG_FILEFLAGS, &td, HEADERGET_MINMEM)) { rpmfileAttrs *flags; while (specix < 0 && (flags = rpmtdNextUint32(&td))) { if (*flags & RPMFILE_SPECFILE) specix = rpmtdGetIndex(&td); } } /* Still no spec? Look by filename. */ while (specix < 0 && (str = rpmtdNextString(&filenames))) { if (rpmFileHasSuffix(str, ".spec")) specix = rpmtdGetIndex(&filenames); } } if (rootdir && rstreq(rootdir, "/")) rootdir = NULL; /* Macros need to be added before trying to create directories */ rpmInstallLoadMacros(h); if (specix >= 0) { const char *bn; headerDel(h, RPMTAG_BASENAMES); headerDel(h, RPMTAG_DIRNAMES); headerDel(h, RPMTAG_DIRINDEXES); rpmtdInit(&filenames); for (int i = 0; (bn = rpmtdNextString(&filenames)); i++) { int spec = (i == specix); char *fn = rpmGenPath(rpmtsRootDir(ts), spec ? "%{_specdir}" : "%{_sourcedir}", bn); headerPutString(h, RPMTAG_OLDFILENAMES, fn); if (spec) specFile = xstrdup(fn); free(fn); } headerConvert(h, HEADERCONV_COMPRESSFILELIST); } else { rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n")); goto exit; }; if (rpmtsAddInstallElement(ts, h, NULL, 0, NULL)) { goto exit; } te = rpmtsElement(ts, 0); if (te == NULL) { /* XXX can't happen */ goto exit; } rpmteSetFd(te, fd); rpmteSetHeader(te, h); fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); h = headerFree(h); if (fi == NULL) { goto exit; } fi->apath = filenames.data; /* Ick */ rpmteSetFI(te, fi); fi = rpmfiFree(fi); if (rpmMkdirs(rpmtsRootDir(ts), "%{_topdir}:%{_sourcedir}:%{_specdir}")) { goto exit; } { /* set all files to be installed */ rpmfs fs = rpmteGetFileStates(te); int i; unsigned int fc = rpmfiFC(fi); for (i=0; i<fc; i++) rpmfsSetAction(fs, i, FA_CREATE); } psm = rpmpsmNew(ts, te); psm->goal = PKG_INSTALL; /* FIX: psm->fi->dnl should be owned. */ if (rpmpsmStage(psm, PSM_PROCESS) == RPMRC_OK) rpmrc = RPMRC_OK; (void) rpmpsmStage(psm, PSM_FINI); rpmpsmFree(psm); exit: if (specFilePtr && specFile && rpmrc == RPMRC_OK) *specFilePtr = specFile; else free(specFile); headerFree(h); rpmfiFree(fi); /* XXX nuke the added package(s). */ rpmtsClean(ts); return rpmrc; }
/* * Create a spec file object from a spec file * @param [String] filename Spec file path * @return [Spec] */ static VALUE spec_s_open(VALUE klass, VALUE filename) { #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) Spec rspec; #else rpmts ts = NULL; #endif if (TYPE(filename) != T_STRING) { rb_raise(rb_eTypeError, "illegal argument type"); } #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) switch (parseSpec(&rspec, RSTRING_PTR(filename), "/", NULL, 0, "", NULL, 1, 1)) { case 0: if (rspec != NULL) { break; } default: rb_raise(rb_eRuntimeError, "specfile `%s' parsing failed", RSTRING_PTR(filename)); } return Data_Wrap_Struct(klass, NULL, spec_free, rspec); #else ts = rpmtsCreate(); #if RPM_VERSION_CODE < RPM_VERSION(4,4,8) switch (parseSpec(ts, RSTRING_PTR(filename), "/", NULL, 0, "", NULL, 1, 1)) { #elif RPM_VERSION_CODE < RPM_VERSION(4,5,90) switch (parseSpec(ts, RSTRING_PTR(filename), "/", 0, "", NULL, 1, 1, 0)) { #elif RPM_VERSION_CODE < RPM_VERSION(5,0,0) switch (parseSpec(ts, RSTRING_PTR(filename), "/", NULL, 0, "", NULL, 1, 1)) { #else switch (parseSpec(ts, RSTRING_PTR(filename), "/", 0, "", NULL, 1, 1, 0)) { #endif case 0: if (ts != NULL) { break; } default: rb_raise(rb_eRuntimeError, "specfile `%s' parsing failed", RSTRING_PTR(filename)); } return Data_Wrap_Struct(klass, NULL, ts_free, ts); #endif } /* * * Alias for Spec#open */ VALUE rpm_spec_open(const char* filename) { return spec_s_open(rpm_cSpec, rb_str_new2(filename)); } /* * @return [String] Return Build root defined in the spec file */ VALUE rpm_spec_get_buildroot(VALUE spec) { #if RPM_VERSION_CODE < RPM_VERSION(4,5,90) if (RPM_SPEC(spec)->buildRootURL) { return rb_str_new2(RPM_SPEC(spec)->buildRootURL); } #elif RPM_VERSION_CODE < RPM_VERSION(4,5,90) if (RPM_SPEC(spec)->rootURL) { return rb_str_new2(RPM_SPEC(spec)->rootURL); } #elif RPM_VERSION_CODE < RPM_VERSION(5,0,0) if (RPM_SPEC(spec)->buildRoot) { return rb_str_new2(RPM_SPEC(spec)->buildRoot); } #else const char *buildRootURL = rpmGenPath(RPM_SPEC(spec)->rootURL, "%{?buildroot}", NULL); VALUE result = rb_str_new2(buildRootURL); buildRootURL = _free(buildRootURL); return result; #endif return Qnil; } /* * @return [String] Return Build subdirectory defined in the spec file */ VALUE rpm_spec_get_buildsubdir(VALUE spec) { if (RPM_SPEC(spec)->buildSubdir) { return rb_str_new2(RPM_SPEC(spec)->buildSubdir); } return Qnil; } /* * @return [Array<String>] Return Build architectures defined in the spec file */ VALUE rpm_spec_get_buildarchs(VALUE spec) { VALUE ba = rb_ivar_get(spec, id_ba); if (NIL_P(ba)) { register int i; ba = rb_ary_new(); for (i = 0; i < RPM_SPEC(spec)->BACount; i++) { rb_ary_push(ba, rb_str_new2(RPM_SPEC(spec)->BANames[i])); } rb_ivar_set(spec, id_ba, ba); } return ba; } /* * @return [Array<RPM::Require>] Return Build requires defined in the spec file */ VALUE rpm_spec_get_buildrequires(VALUE spec) { VALUE br = rb_ivar_get(spec, id_br); #if RPM_VERSION_CODE < RPM_VERSION(4,6,0) || RPM_VERSION_CODE >= RPM_VERSION(5,0,0) if (NIL_P(br)) { const char** names; const char** vers; int_32* flags; int_32 count; rpmTagType nt, vt, type; register int i; br = rb_ary_new(); if (!headerGetEntryMinMemory(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIRENAME, (hTYP_t)&nt, (hPTR_t*)&names, (hCNT_t)&count)) { goto leave; } get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIREVERSION, &vt, (void*)&vers); get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIREFLAGS, &type, (void*)&flags); for (i = 0; i < count; i++) { rb_ary_push(br, rpm_require_new(names[i], rpm_version_new(vers[i]), flags[i], spec)); } release_entry(nt, names); release_entry(vt, vers); rb_ivar_set(spec, id_br, br); } leave: return br; #else rpmtd nametd = rpmtdNew(); rpmtd versiontd = rpmtdNew(); rpmtd flagtd = rpmtdNew(); if (NIL_P(br)) { br = rb_ary_new(); if (!headerGet(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIRENAME, nametd, HEADERGET_MINMEM)) { goto leave; } get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIREVERSION, versiontd); get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_REQUIREFLAGS, flagtd); rpmtdInit(nametd); while ( rpmtdNext(nametd) != -1 ) { rb_ary_push(br, rpm_require_new(rpmtdGetString(nametd), rpm_version_new(rpmtdNextString(versiontd)), *rpmtdNextUint32(flagtd), spec)); } rb_ivar_set(spec, id_br, br); } leave: rpmtdFree(nametd); rpmtdFree(versiontd); rpmtdFree(flagtd); return br; #endif } /* * @return [Array<RPM::Conflict>] Return Build conflicts defined in the spec file */ VALUE rpm_spec_get_buildconflicts(VALUE spec) { VALUE bc = rb_ivar_get(spec, id_bc); #if RPM_VERSION_CODE < RPM_VERSION(4,6,0) || RPM_VERSION_CODE >= RPM_VERSION(5,0,0) if (NIL_P(bc)) { const char** names; const char** vers; int_32* flags; int_32 count; rpmTagType nt, vt, type; register int i; bc = rb_ary_new(); if (!headerGetEntryMinMemory(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTNAME, (hTYP_t)&nt, (hPTR_t*)&names, (hCNT_t)&count)) { goto leave; } get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTVERSION, &vt, (void*)&vers); get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTFLAGS, &type, (void*)&flags); for (i = 0; i < count; i++) { rb_ary_push(bc, rpm_conflict_new(names[i], rpm_version_new(vers[i]), flags[i], spec)); } release_entry(nt, names); release_entry(vt, vers); rb_ivar_set(spec, id_bc, bc); } leave: return bc; #else rpmtd nametd = rpmtdNew(); rpmtd versiontd = rpmtdNew(); rpmtd flagtd = rpmtdNew(); if (NIL_P(bc)) { bc = rb_ary_new(); if (!headerGet(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTNAME, nametd, HEADERGET_MINMEM)) { goto leave; } get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTVERSION, versiontd); get_entry(RPM_SPEC(spec)->buildRestrictions, RPMTAG_CONFLICTFLAGS, flagtd); rpmtdInit(nametd); while ( rpmtdNext(nametd) != -1) { rb_ary_push(bc, rpm_conflict_new(rpmtdGetString(nametd), rpm_version_new(rpmtdNextString(versiontd)), *rpmtdNextUint32(flagtd), spec)); } rb_ivar_set(spec, id_bc, bc); } leave: rpmtdFree(nametd); rpmtdFree(versiontd); rpmtdFree(flagtd); return bc; #endif }