How to use:
- edit
build.sh
, tune the path to your libsolv headers & library - 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 |
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)
(Sorry about that, but we can’t show files that are this big right now.)