Skip to content

Instantly share code, notes, and snippets.

@flavio
Created December 17, 2012 11:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flavio/4317541 to your computer and use it in GitHub Desktop.
Save flavio/4317541 to your computer and use it in GitHub Desktop.
libsolv Bug

How to use:

  1. edit build.sh, tune the path to your libsolv headers & library
  2. run: mkdir build && cd build && ../build.sh && make && cd .. && ./build/bug
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "helpers.h"
int load_solv_files(Pool *pool, Logger logger)
{
if (load_solv_file("solv_files/sles11_sp1_x86_64.solv", "sles11_sp1_x86_64", 99, pool) == -1) {
logger->error(logger, "solv_files/sles11_sp1_x86_64.solv");
return -1;
}
if (load_solv_file("solv_files/sles11_sp1_updates_x86_64.solv", "sles11_sp1_updates_x86_64", 99, pool) == -1) {
logger->error(logger, "solv_files/sles11_sp1_updates_x86_64.solv");
return -1;
}
if (load_solv_file("solv_files/sle11_sp1_sdk_x86_64.solv", "sle11_sp1_sdk_x86_64", 1, pool) == -1) {
logger->error(logger, "solv_files/sle11_sp1_sdk_x86_64.solv");
return -1;
}
if (load_solv_file("solv_files/sle11_sp1_sdk_updates_x86_64.solv", "sle11_sp1_sdk_updates_x86_64", 1, pool) == -1) {
logger->error(logger, "solv_files/sle11_sp1_sdk_updates_x86_64.solv");
return -1;
}
if (load_solv_file("solv_files/sles11_sp2_updates_x86_64.solv", "sles11_sp2_updates_x86_64", 99, pool) == -1) {
logger->error(logger, "solv_files/sles11_sp2_updates_x86_64.solv");
return -1;
}
if (load_solv_file("solv_files/sles11_sp2_x86_64.solv", "sles11_sp2_x86_64", 99, pool) == -1) {
logger->error(logger, "solv_files/sles11_sp2_x86_64.solv");
return -1;
}
if (load_solv_file("solv_files/sle11_sp2_sdk_updates_x86_64.solv", "sle11_sp2_sdk_updates_x86_64", 1, pool) == -1) {
logger->error(logger, "solv_files/sle11_sp2_sdk_updates_x86_64.solv");
return -1;
}
if (load_solv_file("solv_files/sle11_sp2_sdk_x86_64.solv", "sle11_sp2_sdk_x86_64", 1, pool) == -1) {
logger->error(logger, "solv_files/sle11_sp2_sdk_x86_64.solv");
return -1;
}
return 0;
}
void load_packages(const char *arch, Pool *pool, Queue *rules, Logger logger)
{
int len;
char line[80];
FILE *file = fopen ("pkgs", "rt");
while(fgets(line, 80, file) != NULL) {
len = strlen(line);
if(line[len-1] == '\n')
line[len-1] = '\0';
require_package(line, NULL, arch, NULL, pool, rules, logger);
}
fclose(file);
}
void cleanup_pool(Pool *pool)
{
pool_freeallrepos(pool, 0);
pool_freewhatprovides(pool);
pool_free(pool);
pool = NULL;
}
int main() {
const char *arch = "x86_64";
const char *lang = "en";
Pool *pool = pool_create();
Solver *solver = NULL;
Logger logger = newLogger();
if (load_solv_files(pool, logger) == -1) {
cleanup_pool(pool);
freeLogger(logger);
exit(1);
}
Repo *empty_installed = repo_create(pool, "empty");
pool_set_installed(pool, empty_installed);
logger->debug(logger, "Empty installed");
pool_setarch(pool, arch);
pool_addfileprovides(pool);
pool_createwhatprovides(pool);
pool_set_flag(pool, POOL_FLAG_PROMOTEEPOCH, 1);
solver = solver_create(pool);
solver_set_flag(solver, SOLVER_FLAG_ALLOW_DOWNGRADE, 1);
solver_set_flag(solver, SOLVER_FLAG_ALLOW_UNINSTALL, 1);
solver_set_flag(solver, SOLVER_FLAG_ALLOW_ARCHCHANGE, 1);
solver_set_flag(solver, SOLVER_FLAG_NO_UPDATEPROVIDE, 0);
solver_set_flag(solver, SOLVER_FLAG_ALLOW_VENDORCHANGE, 1);
solver_set_flag(solver, SOLVER_FLAG_NO_INFARCHCHECK, 1);
solver_set_flag(solver, SOLVER_FLAG_IGNORE_RECOMMENDED, 1);
Queue resolution_rules;
queue_init(&resolution_rules);
load_packages(arch, pool, &resolution_rules, logger);
logger->debug(logger, "resolution started");
int problem_count = solver_solve(solver, &resolution_rules);
if (problem_count > 0) {
logger->debug(logger, "Resolution has %i problems", problem_count);
Id solution;
Id problem = 0;
int counter = 0;
while ((problem = solver_next_problem(solver, problem)) != 0) {
logger->debug(logger, "Processing problem %i/%i", ++counter,
problem_count);
Id probr;
probr = solver_findproblemrule(solver, problem);
Id dep, source, target;
solver_ruleinfo(solver, probr, &source, &target, &dep);
logger->debug(logger, "Looking for solutions for problem %i", counter);
solution = 0;
while ((solution = solver_next_solution(solver, problem, solution)) != 0)
{
logger->debug(logger, "Processing solution for problem #%i", counter);
Id p, rp, what, how, select;
Id element = 0;
while ((element = solver_next_solutionelement(solver, problem, solution, element, &p, &rp)) != 0) {
// do something, not relevant in this case
}
}
}
} else {
logger->debug(logger, "No problem found, getting resolved dependencies");
}
solver_free(solver);
cleanup_pool(pool);
queue_free(&resolution_rules);
freeLogger(logger);
return 0;
}
#!/bin/sh
cmake -DLIBSOLV_INSTALL=/home/flavio/hacking/libsolv/build_install ..
PROJECT (bug)
CMAKE_MINIMUM_REQUIRED (VERSION 2.4)
FIND_LIBRARY(LIBSOLV_LIBRAY NAMES libsolv solv
HINTS "${LIBSOLV_INSTALL}/lib" "${LIBSOLV_INSTALL}/lib64")
FIND_PATH(LIBSOLV_INCLUDE NAMES solver.h
HINTS "${LIBSOLV_INSTALL}/include/solv")
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${LIBSOLV_INCLUDE})
ADD_EXECUTABLE (bug bug.c logger.c helpers.c)
TARGET_LINK_LIBRARIES (bug ${LIBSOLV_LIBRAY})
#include "helpers.h"
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
void find_all_pkg_ids(const char *pkg_name, const char *pkg_version,
const char *repo_name, Pool *pool,
Queue* pkgs_queue, Logger logger)
{
Solvable *s;
Id id = pool_str2id(pool, pkg_name, 1);
int i = 1;
int end = pool->nsolvables;
for (; i < end; i++)
{
s = pool->solvables + i;
if (!pool_installable(pool, s))
continue;
if (s->name != id)
continue;
if (repo_name != NULL)
{
logger->debug(logger, "s->repo->name: %s", s->repo->name);
if (strcmp(s->repo->name, repo_name) != 0)
continue;
}
if (pkg_version != NULL)
{
const char *sver = pool_id2str(pool, s->evr);
if (strrchr(pkg_version,'-') != NULL)
{
/* We've been given a version with an EVR construct */
if (pool_evrcmp_str(pool, pkg_version, sver, EVRCMP_COMPARE) != 0) // wrong version
continue;
}
else
{
const char *svere = strrchr(sver, '-');
if (!svere)
svere = sver + strlen(sver);
if (solv_vercmp(pkg_version, pkg_version + strlen(pkg_version), sver, svere))
continue;
}
}
queue_push(pkgs_queue, i);
}
}
Id find_pkg_id(const char *pkg_name, const char *pkg_version,
const char *arch, const char *repo_name,
Pool *pool, Logger logger)
{
Id pkg_id;
Queue pkgs_queue;
queue_init(&pkgs_queue);
logger->debug(logger, "Searching for %s %s %s in %s", pkg_name, pkg_version,
arch, repo_name);
find_all_pkg_ids(pkg_name, pkg_version, repo_name, pool, &pkgs_queue, logger);
if (pkgs_queue.count == 0) {
logger->warn(logger, "find_all_ids came back null");
queue_free(&pkgs_queue);
return STRID_NULL;
}
int i;
int bestMatch = -1;
for (i = 0; i < pkgs_queue.count; ++i)
{
Solvable *s = pool_id2solvable(pool, pkgs_queue.elements[i]);
if (strcmp(pool_id2str(pool, s->arch), arch) == 0) {
bestMatch = i;
logger->debug(logger, "Arch match found, going to use:");
}
logger->debug(logger, "Queue: %s %s %s", pool_id2str(pool, s->name),
pool_id2str(pool, s->arch),
pool_id2str(pool, s->evr));
}
if (bestMatch != -1)
pkg_id = pkgs_queue.elements[bestMatch];
else {
logger->warn(logger, "No arch match found, going to use the first solvable of the array.");
pkg_id = pkgs_queue.elements[0];
}
queue_free(&pkgs_queue);
return pkg_id;
}
int require_package(const char *pkg_name, const char *pkg_version, const char *arch,
const char *repo_name, Pool *pool, Queue *queue,
Logger logger)
{
Id pkg_id = STRID_NULL;
Id id = STRID_NULL;
if ((pkg_version == NULL) && (repo_name == NULL))
id = pool_str2id(pool, pkg_name, 0);
else
pkg_id = find_pkg_id(pkg_name, pkg_version, arch, repo_name, pool, logger);
if ((pkg_id != STRID_NULL) || (id != STRID_NULL)) {
if (id != STRID_NULL) {
queue_push(queue, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES);
queue_push(queue, id);
} else {
queue_push(queue, SOLVER_INSTALL|SOLVER_SOLVABLE);
queue_push(queue, pkg_id);
}
} else {
return -1;
}
return 0;
}
int load_solv_file(char* solv_file, char *repo_name, int repo_priority, Pool *pool) {
Repo *repo = NULL;
int fd;
FILE *fp;
fd = open(solv_file, O_RDONLY);
if(fd == -1)
return -1;
fp = fdopen(fd, "r");
if (fp == NULL)
return -1;
repo = repo_create(pool, repo_name);
repo->priority = repo_priority;
repo_add_solv(repo, fp, 0);
repo_internalize(repo);
fclose(fp);
close(fd);
return 0;
}
#ifndef HELPERS_H
#define HELPERS_H
#include "logger.h"
#include <evr.h>
#include <repo.h>
#include <repo_solv.h>
#include <solver.h>
#include <queue.h>
/*
* Find all package IDs based on the name and architecture.
* @param [const char*] pkg_name: name of the package.
* @param [const char*] pkg_version: version of the package.
* @param [const char*] repo_name: name of the repository where the package is being looked.
* @param [Pool*] pool: pool used to perform the resolution.
* @param [Queue*] pkgs_queue: queue where all the ids are going to be stored.
* @param [Logger] logger: logging facility.
*/
void find_all_pkg_ids(const char *pkg_name, const char *pkg_version,
const char *repo_name, Pool *pool,
Queue* pkgs_queue, Logger logger);
/*
* Find the package ID based on the name and architecture.
* @param [const char*] pkg_name: name of the package.
* @param [const char*] pkg_version: version of the package.
* @param [const char*] arch: architecture used to perform the resolution.
* @param [const char*] repo_name: name of the repository where the package is being looked.
* @param [Pool*] pool: pool used to perform the resolution.
* @param [Logger] logger: logging facility.
* @return [Id] id of the package, STRID_NULL if no match is found.
*/
Id find_pkg_id(const char *pkg_name, const char *pkg_version,
const char *arch, const char *repo_name,
Pool *pool, Logger logger);
/*
* Adds a package to the list of rpms to install.
* @param [char*] pkg_name: name of the package.
* @param [char*] pkg_version: version of the package.
* @param [char*] arch: architecture to use during the whole resolution.
* @param [char*] repo_name: name of the repository that must provide the package.
* @param [Pool*] pool: pool used during the resolution.
* @param [Queue*] queue: queue where the package is going to be added.
* @param [Logger] logger: logging facility.
* @returns [int]: -1 when the package is not found, 0 otherwise.
*/
int require_package(const char *pkg_name, const char *pkg_version, const char *arch,
const char *repo_name, Pool *pool, Queue *queue,
Logger logger);
/*
* Adds a solv file to the resolution pool.
* @param [char*] solv_file: full path to the solv file to load.
* @param [char*] repo_name: name of the repository associated to this solv file.
* @param [char*] repo_priority: priority give to this solv file during the resolution.
* @param [Pool*] pool: pool used during the resolution.
* @returns [int]: -1 when the solv file cannot be read, 0 otherwise.
*/
int load_solv_file(char* solv_file, char *repo_name, int repo_priority, Pool *pool);
#endif //HELPERS_H
#include "logger.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
const char* currentTime() {
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
char *str = asctime(timeinfo);
str[strlen(str) - 1] = '\0';
return str;
}
void logMessage(const char *level, const char *fmt, va_list args) {
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);
char *timestr = asctime(timeinfo);
timestr[strlen(timestr) - 1] = '\0';
char *tmp_str;
if (vasprintf(&tmp_str, fmt, args) == -1) {
printf ("Something went wrong while allocating string inside of logMessage\n");
return;
}
printf("%s - [%s] - %s\n", timestr, level, tmp_str);
free(tmp_str);
}
void loggerFatal(const void* self, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
logMessage("fatal", fmt, args);
va_end(args);
}
void loggerError(const void* self, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
logMessage("error", fmt, args);
va_end(args);
}
void loggerWarn(const void* self, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
logMessage("warn", fmt, args);
va_end(args);
}
void loggerInfo(const void* self, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
logMessage("info", fmt, args);
va_end(args);
}
void loggerDebug(const void* self, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
logMessage("debug", fmt, args);
va_end(args);
}
Logger newLogger()
{
Logger self = (Logger)malloc(sizeof(struct Logger_Struct));
self->fatal = &loggerFatal;
self->error = &loggerError;
self->warn = &loggerWarn;
self->info = &loggerInfo;
self->debug = &loggerDebug;
return self;
}
Logger freeLogger(Logger logger)
{
free(logger);
return NULL;
}
#ifndef LOGGER_H
#define LOGGER_H
#include <stdarg.h>
typedef struct Logger_Struct* Logger;
struct Logger_Struct
{
void (*fatal) (const void* self, const char* fmt, ...);
void (*error) (const void* self, const char* fmt, ...);
void (*warn) (const void* self, const char* fmt, ...);
void (*info) (const void* self, const char* fmt, ...);
void (*debug) (const void* self, const char* fmt, ...);
};
Logger newLogger();
Logger freeLogger(Logger logger);
#endif //LOGGER_H
selfphp
php5-zlib
php5-zip
php5-xsl
php5-xmlwriter
php5-xmlrpc
php5-xmlreader
php5-wddx
php5-tokenizer
php5-pear-mail_mime
php5-pear-mail
php5-pear-log
php5-pear-file
php5-pear-db
php5-pear-date
php5-pear-auth_sasl
php5-pear
php5-pdo
php5-pcntl
php5-openssl
php5-odbc
php5-ncurses
php5-mysql
php5-mcrypt
php5-mbstring
php5-ldap
php5-json
php5-imap
php5-iconv
php5-hash
php5-gmp
php5-gettext
php5-gd
php5-ftp
php5-fastcgi
php5-exif
php5-dom
php5-devel
php5-dbase
php5-dba
php5-curl
php5-ctype
php5-calendar
php5-bz2
php5-bcmath
php53-zlib
php53-zip
php53-xsl
php53-xmlwriter
php53-xmlrpc
php53-xmlreader
php53-wddx
php53-tokenizer
php53-tidy
php53-sysvshm
php53-sysvsem
php53-sysvmsg
php53-suhosin
php53-sqlite
php53-sockets
php53-soap
php53-snmp
php53-shmop
php53-readline
php53-pspell
php53-posix
php53-pgsql
php53-pear
php53-pdo
php53-pcntl
php53-openssl
php53-odbc
php53-mysql
php53-mcrypt
php53-mbstring
php5-tidy
php5-sysvshm
php5-sysvsem
php5-sysvmsg
php5-suhosin
php5-sqlite
php5-sockets
php5-soap
php5-snmp
php5-shmop
php5-readline
php5-pspell
php5-posix
php5-pgsql
php53-ldap
php53-json
php53-intl
php53-imap
php53-iconv
php53-gmp
php53-gettext
php53-gd
php53-ftp
php53-fileinfo
php53-fastcgi
php53-exif
php53-dom
php53-devel
php53-dba
php53-curl
php53-ctype
php53-calendar
php53-bz2
php53-bcmath
php53
apache2-mod_php53
apache2-mod_php5
php5
iputils
openssl-certs
perl-satsolver
tar
suse-sam-data
suse-sam
yast2-firstboot
syslog-ng
mdadm
yast2-ncurses
yast2
less
vim
zypper
kernel-default
SuSEfirewall2
pattern:base
bootsplash-branding-SLES
This file has been truncated, but you can view the full file.
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment