You are not logged in.

#1 2023-01-20 17:56:11

mamograg17
Member
Registered: 2022-02-08
Posts: 36

[SOLVED]get a package description using alpm

I am trying to use alpm to get a package description from /var/lib/pacman/sync, but i still can't figure out how.
this is the current code:

alpm_handle_t *handle = alpm_initialize("/", "/var/lib/pacman/sync",nullptr);
alpm_list_t *db_list = alpm_get_syncdbs(handle);
alpm_pkg_t *pkg = alpm_pkg_find(db_list,"pacman");
if(pkg != NULL) {
    const char *description = alpm_pkg_get_desc(pkg);
    printf("Description: %s\n", description);
} else {
    printf("Package not found\n");
}

    alpm_release(handle);
    return 0;

any idea please

Last edited by mamograg17 (2023-01-21 14:42:16)

Offline

#2 2023-01-20 18:17:22

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,802
Website

Re: [SOLVED]get a package description using alpm

It'd be worth reporting the current results that the package is not found, so trying to get a description is a moot point.  The actual problem is that alpm_pkg_find takes a list of packages as it's first parameter, not a list of databases - you are skipping steps (not to mention those already skipped in registering the sync dbs).

Last edited by Trilby (2023-01-20 18:28:01)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#3 2023-01-20 18:23:05

mamograg17
Member
Registered: 2022-02-08
Posts: 36

Re: [SOLVED]get a package description using alpm

Trilby wrote:

It'd be worth reporting the current results that the package is not found, so trying to get a description is a moot point.

when removing the if statement, and i output the description, it says:
Description: (null)

Trilby wrote:

The actual problem is that alpm_pkg_find takes a list of packages as it's first parameter, not a list of databases - you are skipping steps.

sorry but i found no tutorials for alpm, so i tried to figure out a way to make the work done

Offline

#4 2023-01-20 18:29:10

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,802
Website

Re: [SOLVED]get a package description using alpm

mamograg17 wrote:

when removing the if statement

Don't remove the if statement!  You are not even getting a package, so trying to print the description of a non-existent package is nonsense.

mamograg17 wrote:

sorry but i found no tutorials for alpm, so i tried to figure out a way to make the work done

I don't know of any other than reading pacman's code.  But you should at least be reading the man pages which would indicate a couple obvious problems with your code.  The fact that you need to register sync dbs is not obvious from the man pages (and for that you'd likely need to read pacman's code).

Last edited by Trilby (2023-01-20 18:30:44)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#5 2023-01-20 18:30:09

mamograg17
Member
Registered: 2022-02-08
Posts: 36

Re: [SOLVED]get a package description using alpm

Trilby wrote:
mamograg17 wrote:

when removing the if statement

Don't remove the if statement!  You are not even getting a package, so trying to print the description of a non-existent package is nonsense.

ok sorry, but how can i solve this.

Offline

#6 2023-01-20 18:41:43

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,802
Website

Re: [SOLVED]get a package description using alpm

Read pacman's code.

I've never used libalpm before, but from a quick glance at pacman's code, here's a start:

#include <alpm.h>

int main() {
	alpm_handle_t *handle;
	alpm_list_t *dbs, *db;
	alpm_pkg_t *pkg = NULL;

	handle = alpm_initialize("/", "/var/lib/pacman", NULL);

	// TODO read pacman.conf into handle here ...

	dbs = alpm_get_syncdbs(handle);
	for (db = dbs; db && !pkg; db = alpm_list_next(db))
		pkg = alpm_pkg_find(db,"pacman");   // or should this be 'db->data' in place of 'db'?
	if (pkg)
		printf("Description: %s\n", alpm_pkg_get_desc(pkg));
	else
		printf("Package not found\n");

	alpm_release(handle);
	return 0;
}

But note the "TODO" - this will not work as-is as yet.

Last edited by Trilby (2023-01-20 19:20:23)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#7 2023-01-20 19:08:24

mamograg17
Member
Registered: 2022-02-08
Posts: 36

Re: [SOLVED]get a package description using alpm

Trilby wrote:

Read pacman's code.

I've never used libalpm before, but from a quick glance at pacman's code, here's a start:

#include <alpm.h>

int main() {
	alpm_handle_t *handle;
	alpm_list_t *dbs, *db;
	alpm_pkg_t *pkg;

	handle = alpm_initialize("/", "/var/lib/pacman/sync", NULL);

	// TODO read pacman.conf into handle here ...

	dbs = alpm_get_syncdbs(handle);
	for (db = dbs; db && !pkg; db = alpm_list_next(db))
		pkg = alpm_pkg_find(db,"pacman");   // or should this be 'db->data' in place of 'db'?
	if (pkg)
		printf("Description: %s\n", alpm_pkg_get_desc(pkg));
	else
		printf("Package not found\n");

	alpm_release(handle);
	return 0;
}

But note the "TODO" - this will not work as-is as yet.

it exits with a segmentation fault (core dumped)  error, i have no experience with alpm, i don't know how to solve it.
I checked pacman.conf and the path there is var/lib/pacman/, so o changed the path but it is still the same.

Last edited by mamograg17 (2023-01-20 19:17:28)

Offline

#8 2023-01-20 19:18:30

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,802
Website

Re: [SOLVED]get a package description using alpm

Yeah, I forgot to initilize pkg to NULL.  I fixed that.  But still the main problem is that it does not yet have any actual databases.  You can check the lenth of "dbs" and see that it is 0, the TODO needs to be filled in for this to work.  And I've not read enough of pacman's code to know what's actually needed to initialize the syncdbs.

I also didn't even question the initialize function - but you have (and my code previously had) the wrong path there.

EDIT: actually the path error of the initialize was one of the main hurdles.  Once that was fixed, all that's needed is registering the repos.  Working code coming momentarily.  EDIT: nope, scratch that, there are yet other issues.

Given that you clearly have no experience with libalpm, and that you are also not using it for any other purposes in this program, why are you trying to use it at all?  You can get the information you want directly from the db file, e.g.:

zcat /var/lib/pacman/sync/*.db | sed -n '/%NAME%/{n;h;};/%DESC%/{n;x;s/^pacman$//;ta;bb;:a;x;p;:b;}'

And this could be generalized for other packages:

pkgname=pacman
zcat /var/lib/pacman/sync/*.db | sed -n '/%NAME%/{n;h;};/%DESC%/{n;x;s/^'$pkgname'$//;ta;bb;:a;x;p;:b;}'

EDIT: oops, I suppose I only tested the "zcat | sed" solution on the core.db.  Running it on community ends up being horribly inefficient.

Last edited by Trilby (2023-01-20 19:47:30)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#9 2023-01-20 20:40:49

progandy
Member
Registered: 2012-05-17
Posts: 5,068

Re: [SOLVED]get a package description using alpm

The source for pacinfo should be easier to understand than pacman if you want to extract from that.
https://github.com/andrewgregory/pacutils

Or just use the pacutils library as part of your project and start with the code snippet in the synopsis.

By the way, this is what I did in luajit  a few years ago. Not the best, but it still works:

pacman=alpm.Alpm.initialize('/', '/var/lib/pacman', errno)
dbs = {}
for l in io.lines("/etc/pacman.conf") do
    local s = l:match("^%s*%[%s*([^%]%s]*)%s*]%s*$")
    if s and s ~= 'options' and s ~= 'aur' then
        dbs[#dbs+1] = alpm.alpm_register_syncdb(pacman, s, 0)
    end
end

Some other shell script options:
With pacutils:

pacinfo --short linux | sed -n '2s/^ *//p'

With expac:

expac -S "%d" linux

Last edited by progandy (2023-01-20 20:53:39)


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#10 2023-01-20 21:39:41

mamograg17
Member
Registered: 2022-02-08
Posts: 36

Re: [SOLVED]get a package description using alpm

Trilby wrote:

Given that you clearly have no experience with libalpm, and that you are also not using it for any other purposes in this program, why are you trying to use it at all?  You can get the information you want directly from the db file, e.g.:

zcat /var/lib/pacman/sync/*.db | sed -n '/%NAME%/{n;h;};/%DESC%/{n;x;s/^pacman$//;ta;bb;:a;x;p;:b;}'

And this could be generalized for other packages:

pkgname=pacman
zcat /var/lib/pacman/sync/*.db | sed -n '/%NAME%/{n;h;};/%DESC%/{n;x;s/^'$pkgname'$//;ta;bb;:a;x;p;:b;}'

EDIT: oops, I suppose I only tested the "zcat | sed" solution on the core.db.  Running it on community ends up being horribly inefficient.

unfortunately, i need it to get other info, the problem is that i have some code that is coded in rust an searches for an application in the database, but i don't know how to write in in c++, here it is:

for db in handle.syncdbs() {
        // look for a package named "pacman" in each databse
        // the database is implemented as a hashmap so this is faster than iterating
        if let Ok(pkg) = db.pkg("pacman") {
            println!("{} {}", pkg.name(), pkg.desc().unwrap_or("None"));
        }
    }

i found it in a a webpage.

Offline

#11 2023-01-20 21:46:50

mamograg17
Member
Registered: 2022-02-08
Posts: 36

Re: [SOLVED]get a package description using alpm

progandy wrote:

The source for pacinfo should be easier to understand than pacman if you want to extract from that.
https://github.com/andrewgregory/pacutils

Or just use the pacutils library as part of your project and start with the code snippet in the synopsis.

It is somehow the same as alpm, no documentation or examples, i think i just need to write this rust code in c++, it will solve the problem:

for db in handle.syncdbs() {
        // look for a package named "pacman" in each databse
        // the database is implemented as a hashmap so this is faster than iterating
        if let Ok(pkg) = db.pkg("pacman") {
            println!("{} {}", pkg.name(), pkg.desc().unwrap_or("None"));
        }
    }

Offline

#12 2023-01-20 22:03:54

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,802
Website

Re: [SOLVED]get a package description using alpm

You can't just translate that code out of context as you've left out all the parts of that code that initialize and populate the databases.

What's really missing is everything that the rust code does that isn't in the fragment you posted.  As the literal translation of that fragment would be just the following:

for (db = syncdbs; db && !pkg; db = alpm_list_next(db))
   pkg = alpm_pkg_find(db->data,"pacman");   // still not entirely sure about db->data vs db
printf("pacman %s\n", pkg ? alpm_pkg_get_desc(pkg) : "None");

Of course this code is useless without syncdbs being initialized to something useful.

Last edited by Trilby (2023-01-20 22:05:10)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#13 2023-01-20 22:24:54

progandy
Member
Registered: 2012-05-17
Posts: 5,068

Re: [SOLVED]get a package description using alpm

Yes, the documentation for pacutils is out of date, but it handles all that annoying pacman config parsing you'd have to do otherwise.
With a bit of fiddling I got it to compile

// gcc -o pkgdesc -lalpm -lpacutils pkgdesc.c
#include <stdio.h>
#include <alpm.h>
#include <pacutils.h>

int main(int argc, char *argv[]) {
	if (argc < 2) {
		return 1;
	}
	const char *pkgname = argv[1];

	pu_config_t *config = pu_config_new();
	pu_ui_config_load(config, "/etc/pacman.conf");
	alpm_handle_t *handle = pu_initialize_handle_from_config(config);
	alpm_list_t *sync_dbs = pu_register_syncdbs(handle, config->repos);


	/* do something with handle... */
	for (alpm_list_t *db = sync_dbs; db; db = alpm_list_next(db)) {
		alpm_pkg_t *pkg = alpm_db_get_pkg(db->data, pkgname);
		if (pkg) {
			puts(alpm_pkg_get_desc(pkg));
		}
	}

	alpm_release(handle);
	alpm_list_free(sync_dbs);
	pu_config_free(config);

	return 0;
}
Trilby wrote:
for (db = syncdbs; db && !pkg; db = alpm_list_next(db))
   pkg = alpm_pkg_find(db->data,"pacman");   // still not entirely sure about db->data vs db

alpm_pkg_find works on an alpm_list_t* that contains packages (alpm_pkg_t*), not dbs.You want alpm_db_get_pkg instead.
In this for loop, db is an entry of the syncdbs list. db->data is the pointer to the database that is stored in that list element. You'll want to use that for alpm_db_get_pkg

Last edited by progandy (2023-01-20 22:43:35)


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#14 2023-01-21 12:00:37

mamograg17
Member
Registered: 2022-02-08
Posts: 36

Re: [SOLVED]get a package description using alpm

progandy wrote:

Yes, the documentation for pacutils is out of date, but it handles all that annoying pacman config parsing you'd have to do otherwise.
With a bit of fiddling I got it to compile

// gcc -o pkgdesc -lalpm -lpacutils pkgdesc.c
#include <stdio.h>
#include <alpm.h>
#include <pacutils.h>

int main(int argc, char *argv[]) {
	if (argc < 2) {
		return 1;
	}
	const char *pkgname = argv[1];

	pu_config_t *config = pu_config_new();
	pu_ui_config_load(config, "/etc/pacman.conf");
	alpm_handle_t *handle = pu_initialize_handle_from_config(config);
	alpm_list_t *sync_dbs = pu_register_syncdbs(handle, config->repos);


	/* do something with handle... */
	for (alpm_list_t *db = sync_dbs; db; db = alpm_list_next(db)) {
		alpm_pkg_t *pkg = alpm_db_get_pkg(db->data, pkgname);
		if (pkg) {
			puts(alpm_pkg_get_desc(pkg));
		}
	}

	alpm_release(handle);
	alpm_list_free(sync_dbs);
	pu_config_free(config);

	return 0;
}

it shows an error argument of type "void *" is incompatible with parameter of type "alpm_db_t * for this line: alpm_pkg_t *pkg = alpm_db_get_pkg(db->data, pkgname);

Trilby wrote:

You can't just translate that code out of context as you've left out all the parts of that code that initialize and populate the databases.

What's really missing is everything that the rust code does that isn't in the fragment you posted.  As the literal translation of that fragment would be just the following:

for (db = syncdbs; db && !pkg; db = alpm_list_next(db))
   pkg = alpm_pkg_find(db->data,"pacman");   // still not entirely sure about db->data vs db
printf("pacman %s\n", pkg ? alpm_pkg_get_desc(pkg) : "None");

Of course this code is useless without syncdbs being initialized to something useful.

this is the code for rust program:

use alpm::{Alpm, PackageReason, SigLevel};

fn main() {
    let handle = Alpm::new("/", "tests/db").unwrap();

    handle
        .register_syncdb("core", SigLevel::USE_DEFAULT)
        .unwrap();
    handle
        .register_syncdb("extra", SigLevel::USE_DEFAULT)
        .unwrap();
    handle
        .register_syncdb("community", SigLevel::USE_DEFAULT)
        .unwrap();

    // iterate through each database
    for db in handle.syncdbs() {
        // search each database for packages matching the regex "linux-[a-z]" AND "headers"
        for pkg in db.search(["linux-[a-z]", "headers"].iter()).unwrap() {
            println!("{} {}", pkg.name(), pkg.desc().unwrap_or("None"));
        }
    }

Offline

#15 2023-01-21 14:06:53

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 27,802
Website

Re: [SOLVED]get a package description using alpm

progandy wrote:

alpm_pkg_find works on an alpm_list_t* that contains packages (alpm_pkg_t*), not dbs.You want alpm_db_get_pkg instead.

Oops!  That was my first comment in this thread, but when I went to make my own code sample I just copied and forgot to replace that.  And it turns out that was the only thing wrong with my last attempt which now works:

#include <alpm.h>

int main() {
	alpm_handle_t *handle;
	alpm_list_t *dbs, *db;
	alpm_pkg_t *pkg = NULL;

	handle = alpm_initialize("/", "/var/lib/pacman", NULL);

	alpm_register_syncdb(handle, "core", ALPM_DB_USAGE_SEARCH);
	alpm_register_syncdb(handle, "extra", ALPM_DB_USAGE_SEARCH);
	alpm_register_syncdb(handle, "community", ALPM_DB_USAGE_SEARCH);

	dbs = alpm_get_syncdbs(handle);
	for (db = dbs; db && !pkg; db = alpm_list_next(db))
		pkg = alpm_db_get_pkg(db->data, "pacman");
	if (pkg)
		printf("Description: %s\n", alpm_pkg_get_desc(pkg));
	else
		printf("Package not found\n");

	alpm_release(handle);
	return 0;
}

But keep in mind this doesn't parse pacman.conf at all.  It just assumes the three "typical" repos are there and that's all that you'd care about.

Last edited by Trilby (2023-01-21 14:15:53)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#16 2023-01-21 14:37:34

progandy
Member
Registered: 2012-05-17
Posts: 5,068

Re: [SOLVED]get a package description using alpm

mamograg17 wrote:

it shows an error argument of type "void *" is incompatible with parameter of type "alpm_db_t * for this line: alpm_pkg_t *pkg = alpm_db_get_pkg(db->data, pkgname);

That is perfectly valid c, are you using a c++ compiler?


| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#17 2023-01-21 14:39:20

mamograg17
Member
Registered: 2022-02-08
Posts: 36

Re: [SOLVED]get a package description using alpm

Thank you'll for help, i managed find a working code, i found this thread https://bbs.archlinux.org/viewtopic.php?id=269716 ,i grabbed the code and tweaked it for my program, it was looking for the package in only one repo and barely working and it also has a lot of unnecessary code, so i edited it and here is the final working one:

 
#include <alpm.h>
#include <string>
#include <iostream>

std::string search(alpm_db_t* repo, std::string name)
{
    alpm_pkg_t* pkg = alpm_db_get_pkg(repo, name.c_str());
    std::string description;
    if (pkg)
    {
        const char* desc = alpm_pkg_get_desc(pkg);
        description = desc;
    }
   
    
    return description;
}

int main(int argc, char *argv[]) {
    alpm_errno_t err;
    alpm_handle_t * handle = alpm_initialize("/", "/var/lib/pacman", &err);

    std::cout << "ERROR: " << alpm_strerror(err) << std::endl;

    alpm_db_t* localdb = alpm_get_localdb(handle);
    alpm_list_t* syncdb = alpm_get_syncdbs(handle);

    alpm_db_t* core_repo = alpm_register_syncdb(handle, "core", ALPM_DB_USAGE_ALL);
    alpm_db_t* community_repo = alpm_register_syncdb(handle, "community", ALPM_DB_USAGE_ALL);
    alpm_db_t* extra_repo = alpm_register_syncdb(handle, "extra", ALPM_DB_USAGE_ALL);
    alpm_db_t* multilib_repo = alpm_register_syncdb(handle, "multilib", ALPM_DB_USAGE_ALL);

    std::cout << search(core_repo,"pacman") << std::endl;
    std::cout << search(community_repo,"pacman") << std::endl;
    std::cout << search(extra_repo,"pacman") << std::endl;
    std::cout << search(multilib_repo,"pacman") << std::endl;
    alpm_release(handle);
    return 0;
}

it outputs now:

ERROR: unexpected error
A library-based package manager with dependency support

thank you.

Last edited by mamograg17 (2023-01-21 14:41:35)

Offline

Board footer

Powered by FluxBB