etc:20-lpm-gui
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| etc:20-lpm-gui [2022/05/13 22:02] – wikiadmin | etc:20-lpm-gui [2022/07/28 18:13] (current) – wikiadmin | ||
|---|---|---|---|
| Line 7: | Line 7: | ||
| * the basic rules of lpm | * the basic rules of lpm | ||
| * how the local package repository looks | * how the local package repository looks | ||
| - | * how lpm accesses package catalogues | ||
| * how an lpk package looks | * how an lpk package looks | ||
| + | * how lpm accesses package catalogues | ||
| ===== 1. LPM rules ===== | ===== 1. LPM rules ===== | ||
| Line 15: | Line 15: | ||
| * Any software destined to be installed must be contained in an lpk package. | * Any software destined to be installed must be contained in an lpk package. | ||
| - | * An lpk package is basically defined by a name, a version | + | * An lpk package is basically defined by a name, a version, optionally |
| * Any package name can only be installed once locally. | * Any package name can only be installed once locally. | ||
| - | * A variant defines an alternative | + | * A variant defines an alternative |
| + | * A package can only be installed if all its dependencies are also installed | ||
| * No package can overwrite a file already installed by another package | * No package can overwrite a file already installed by another package | ||
| * Only one package can be installed at the same time | * Only one package can be installed at the same time | ||
| Line 45: | Line 46: | ||
| * desc.txt: contains the basic info of the currently installed package version | * desc.txt: contains the basic info of the currently installed package version | ||
| * inst.txt: contains information about when and why (per explicit request or as a dependency) the package was installed or updated. | * inst.txt: contains information about when and why (per explicit request or as a dependency) the package was installed or updated. | ||
| + | |||
| + | There are usually some other files concerning file checksums, symlink information, | ||
| + | |||
| + | ===== 3. Format of an lpk package ===== | ||
| + | |||
| + | lpm's native package format is called lpk. Like other package format such as dpkg or rpm, it basically is implemented as an archive containing all the files to be installed, some package description and optional scripts to be run after installation or deletion. | ||
| + | |||
| + | As archive format, lpk uses gzip compressed cpio, prepended by a header containing the package information. The prepended header looks like this: | ||
| + | |||
| + | * 11 bytes made from 5 bytes containing the version signature (ELPM20) and 6 bytes containing the zero-padded size of the following header | ||
| + | * The package description, | ||
| + | |||
| + | Right after, the gzipped cpio archive starts. It is divided into so-called forks, top-level directories of different meaning: | ||
| + | |||
| + | * info: this forks contains again the package description called desc.txt, plus optionally \\ - perm.txt, if special file-permisions (such as set-uid bits) have to be set \\ - link.txt, if any symbolic links have to be set | ||
| + | * data: this fork contains all files that should be installed by the package, except config files | ||
| + | * conf: this fork contains all config files that should be installed by the package. They are handled separately due to different rules on updates. | ||
| + | * init: this fork contains any scripts that should be run before or after package installation or removal | ||
| + | * dump: files in this fork are just copied into the package' | ||
| + | * hash: this fork contains one file per fork containing the sha1 checksums for each file in the fork. This is used to ensure complete package extraction and installation. | ||
| + | |||
| + | The difference of the package description in the header and in the archive is that the header contains the package' | ||
| + | |||
| + | A package description looks like this: | ||
| + | |||
| + | < | ||
| + | elpmVersion: | ||
| + | elpkName: xfce4-terminal | ||
| + | elpkVersion: | ||
| + | elpkCreator: | ||
| + | elpkArchitecture: | ||
| + | elpkDependency: | ||
| + | elpkDependency: | ||
| + | elpkDependency: | ||
| + | elpkDescription: | ||
| + | elpkDataSize: | ||
| + | elpkRsaSigSubj:: | ||
| + | | ||
| + | elpkRsaSigData:: | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | </ | ||
| + | |||
| + | The used text format is basically ldif, as described [[https:// | ||
| + | |||
| + | ==== 3.1 Package scripts ==== | ||
| + | |||
| + | A package can contains several scripts in its init fork that should be run when the package is installed, updated or removed. They are: | ||
| + | |||
| + | * 00-add.sh: if present, this will be run before an actual installation or update. If it does not return 0, the action will be aborted. | ||
| + | * 00-del.sh: if present, this will be run before an actual removal. If it does not return 0, the action will be aborted. | ||
| + | * 99-add.sh: This will be run after an actual installation or update, also aborting if unsucessful. | ||
| + | * 99-del.sh: You get the idea | ||
| + | * 99-cfg.ch: This will run after after an actual installation or update, but never abort the action. | ||
| + | |||
| + | ===== 4. Package catalogues ===== | ||
| + | |||
| + | While some other package managers handle the retrieval of packages via a wrapper over the actual package manager (apt for dpkg, yum/dnf for rpm), lpm goes an other way by directly integrating so-called package catalogues.This was actually one of the main motivations for creating lpm. | ||
| + | |||
| + | Package catalogues are implemented as plugins that have to implement a set of fuctions which are then called by lpm at the appropriate time. A local lpm installation can only load exactly one lpc plugin, as defined in / | ||
| + | |||
| + | Apart from the shared library, an lpc catalouge may also have separate config files and programs to manage the catalogue. | ||
| + | |||
| + | Any lpc must implement the following functions: | ||
| + | < | ||
| + | |||
| + | LPC *lpc_connect(struct s_ekva **lpm_sys_conf, | ||
| + | int lpc_refresh(LPC *lpc) | ||
| + | int lpc_findpkg(LPC *lpc, char *name, char *variant, | ||
| + | int lpc_readpkg(LPC *lpc,LPI *lpi, FILE *dest_file) | ||
| + | int lpc_release(LPC *lpc) | ||
| + | |||
| + | </ | ||
| + | |||
| + | * lpc_connect is used to connect lpm to the catalogue, so it can then be used to find and retrieve packages | ||
| + | * lpc_findpkg is used to find packages in the catalogue, matching the specified criterias. it has to return the number of packages, plus their package descriptions as a list. | ||
| + | * lpc_readpkg is used to retrieve exactly one package, as defined in the description and have it stored in the specified FILE * | ||
| + | * lpc_refresh is used to refresh the contents of the catalogue. | ||
| + | * lpc_release will disconnect lpm from the catalogue | ||
| + | |||
| + | Per default, lpm brings along a simple directory-based lpc called lpc-dirs, which is great for testing purposes and also for an initial distro installation. As part of its source code, lpm also contains the lpc-http lpc, which allows to access remote package catalogues over http and also ftp. | ||
| + | |||
| + | ===== 5. Basic information for creating lpm frontends ===== | ||
| + | |||
| + | In order to create an lpm frontend, you first have to download its complete source code, as there is no separate development package with only the needed parts available. This can be done via git: | ||
| < | < | ||
| Line 52: | Line 141: | ||
| </ | </ | ||
| + | |||
| + | After building lpm successfully, | ||
| + | |||
| + | The main lpm frontend program (main.c) also implements all its functionality using those two files. | ||
| + | |||
| + | When creating another frontend for lpm, it is however advisable to only implement the non-prvileged parts directly and use the privileged plpm program for any actual package installations or updates. This is due to the fact that installs and updates require root privileges, and all gui frameworks strongly discourage running gui programs as root. | ||
| + | |||
| + | plpm is a reduced commandline program always running as root, but only allowing to be used by members of a defined group. It is therefore the preferred method to let a gui program perform any privileged action. It also implements a simple call to check if the user is allowed to use it, so a gui frontend can find out early on if the used is allowed to install packages. | ||
| + | |||
| + | ===== 6. The sample lpmsh frontend ===== | ||
| + | |||
| + | In the subdirectoey guix, there is a file called lpmsh.c, implementing a sample lpm frontend in form as a shell. The shell example was chosen, as it: | ||
| + | |||
| + | * needs minimal additional code for its implementation | ||
| + | * has a division of startup code and a loop implementing several functions | ||
| + | |||
| + | It therefore might server as a good reference of how a gui might call the lpm funcions and process their data. | ||
| + | |||
| + | ===== 7. plplm usage ===== | ||
| + | |||
| + | plpm implements the following commands: | ||
| + | |||
| + | * allowed: This takes no argument and will return 0 if the user is allowed to use plpm. | ||
| + | * refresh: This takes no argument and will refresh the currently used package catalogue | ||
| + | * cleanup: This takes no argument and will clean the stagearea from package files | ||
| + | * install: This takes arguments described below and will install new packages | ||
| + | * upgrade: This may take arguments and will update installed packages | ||
| + | |||
| + | If upgrade is called without arguments, it will update all packages where a new version is available | ||
| + | |||
| + | Otherwise, both upgrade and install may be called with one or more package names to be installed or updated | ||
| + | |||
| + | If only one package is specified, the caller may also first specify a specific version and/or variant to be used. | ||
| + | |||
| + | The usage is then as follows: | ||
| + | |||
| + | < | ||
| + | plpm install|upgrade -o version=$my_version, | ||
| + | |||
| + | </ | ||
| + | |||
| + | In all other cases, the usage is: | ||
| + | < | ||
| + | |||
| + | plpm install|upgrade $package_1 $package_2 ... | ||
| + | |||
| + | </ | ||
| + | |||
| + | The function plpm_exec in lpmsh.c provides a working example on how to call plpm in all cases. | ||
| + | |||
| + | ===== 8. Important frontend data structures ===== | ||
| + | |||
| + | ==== 8.1 LPI ==== | ||
| + | |||
| + | Most relevant structures and functions are defined in the header file lpm.h, the most important structure is: | ||
| + | < | ||
| + | |||
| + | struct s_lpk_info { | ||
| + | char *name; | ||
| + | char *variant; | ||
| + | char *version; | ||
| + | char *creator; | ||
| + | int arch; | ||
| + | char *desc; | ||
| + | char *clog; | ||
| + | char **deps; | ||
| + | int removable; | ||
| + | unsigned long datasize; | ||
| + | /* The next two are only for repository packages */ | ||
| + | unsigned long filesize; | ||
| + | char *filehash; | ||
| + | char *abs_uri; | ||
| + | char *rel_uri; | ||
| + | /* These three are only for locally installed packages */ | ||
| + | time_t install_time; | ||
| + | char install_type; | ||
| + | char *install_head; | ||
| + | time_t *update_time; | ||
| + | /* The next three are for the signature */ | ||
| + | char *rsa_sig_subj; | ||
| + | char *rsa_sig_data_buf; | ||
| + | int rsa_sig_data_len; | ||
| + | int rsa_verified; | ||
| + | /* Now follows a ekva with any further extended attributes */ | ||
| + | struct s_ekva **ext_attributes; | ||
| + | }; | ||
| + | |||
| + | typedef struct s_lpk_info LPI; | ||
| + | |||
| + | </ | ||
| + | |||
| + | LPI is used throughout lpm for any package information, | ||
| + | |||
| + | The meaning of its members are: | ||
| + | |||
| + | |name|the package name| | ||
| + | |variant|the package variant, can be NULL| | ||
| + | |version|the package version| | ||
| + | |creator|name and mail address of the package creator| | ||
| + | |arch|either i686, | ||
| + | |desc|the package description| | ||
| + | |clog|the package' | ||
| + | |deps|an array of names of the package' | ||
| + | |removable|boolean of package is removable, absolutely unused| | ||
| + | |datasize|the sum of bytes in the data part of a package| | ||
| + | |filesize|the filesize of a package in lpc catalogue| | ||
| + | |abs_uri|the absolute uri of a package in lpc catalogue| | ||
| + | |rel_url|the relative uri of a package in lpc catalogue| | ||
| + | |install_time|the installation unix time of an installed package| | ||
| + | |install_type| \\ X for an installed package if explicitely installed, D if installed as a dependency| | ||
| + | |install_head|if installed as a dependency, the name of the package having required it| | ||
| + | |update_time|an array of unix time when the package was updated, can be NULL| | ||
| + | |rsa_sig_data|the buffer and it's size containing the package' | ||
| + | |rsa_sig_subj|the subject dn of the package signer| | ||
| + | |rsa_verified|a flag containing the vefication status| | ||
| + | |ext_attributes|an EKVA of other package attributes, currently unused| | ||
| + | | | | | ||
| + | |||
| + | ==== 8.2 EKVA ==== | ||
| + | |||
| + | EKVA is an array of stuctures containg a pointer to a key and to a value and is defined in stuff/ | ||
| + | < | ||
| + | |||
| + | struct s_ekva { | ||
| + | char *key; | ||
| + | char *val; | ||
| + | }; | ||
| + | |||
| + | typedef struct s_ekva EKVA; | ||
| + | |||
| + | </ | ||
| + | |||
| + | EKVA arrays are used extensively throughout lpm as text-based keyword-value stores, with multiple values for one keyword possible depending on its initialisation. As their first element, they hold a header containing their current size an mode, allowing for automatic growing and management of multiple values. | ||
| + | |||
| + | EKVA arrays are created, filled, read and deleted by a set of functions defined in ekva.h, the most important ones being: | ||
| + | |||
| + | - ekva_new: to create a new EKVA array \\ - ekva_addval: | ||
| + | |||
| + | ==== 8.3 LPA ==== | ||
| + | |||
| + | LPA arrays are used to store information about available updates in an easily parsable form: | ||
| + | |||
| + | < | ||
| + | struct s_lpa { | ||
| + | char action; | ||
| + | char status; | ||
| + | LPI *lpi; | ||
| + | char *candidate; | ||
| + | }; | ||
| + | typedef struct s_lpa LPA; | ||
| + | |||
| + | </ | ||
| + | |||
| + | - action is ' | ||
| + | |||
| + | ===== 9. important frontend functions ===== | ||
| + | |||
| + | All frontend functions are defined int lpm.h, the ones relevant to a frontend using plpm for privileged actions are: | ||
| + | |||
| + | - lpm_open: " | ||
| + | |||
| + | - lpmui_init: initializes the internally used lpmui, necessary, but has no effect… | ||
| + | |||
| + | - lpm_lpc_load: | ||
| + | |||
| + | - lpm_lpc_connect: | ||
| + | |||
| + | - lpm_lpc_cache_fill: | ||
| + | |||
| + | - lpm_lpc_release: | ||
| + | |||
| + | - lpm_cache_free: | ||
| + | |||
| + | - lpk_info_ekva: | ||
| + | |||
| + | - lpm_list_lpi: | ||
| + | |||
| + | - lpm_lpf_info: | ||
| + | |||
| + | - lpm_findpkg_new: | ||
| + | |||
| + | - lconf_read: reads the lpm config file | ||
| + | |||
| + | - log_init: initializes the internal logging mechanism, necessary | ||
| + | |||
| + | - lpm_pre_update: | ||
| + | |||
| + | - lpm_lpa_list_add_lpt: | ||
| + | |||
| + | ===== 10. Required globals ===== | ||
| + | |||
| + | In order for the frontend to be able to use all further funtions correctly, it has to define a set of global variables: | ||
| + | |||
| + | < | ||
| + | void *lpc_backend_handle; | ||
| + | EKVA **lpm_sys_conf = NULL; | ||
| + | LPC *lpc; | ||
| + | |||
| + | int dry_run = 0; | ||
| + | int vote_mode = LPM_VOTE_DEFAULT; | ||
| + | LPMUI *lpmui = NULL; | ||
| + | struct s_llog *llog; | ||
| + | |||
| + | LPI **lpc_cache; | ||
| + | |||
| + | </ | ||
| + | |||
| + | ===== 11. Required initialization sequence ===== | ||
| + | |||
| + | Maybe in later releases, the initialisation sequence will be simplyfied and merged into some lpm_init function, but for the moment, the code from line 490 - 542 from lpmsh.c can be copied for that purpose. | ||
etc/20-lpm-gui.1652472169.txt.gz · Last modified: by wikiadmin
