libslapt(3)

NAME
libslapt - slapt-get library

SYNOPSIS
#define _GNU_SOURCE
#include <slapt.h>
/* initialize slapt_rc_config */
slapt_rc_config *slapt_init_config(void);
/* parse config file for sources, excludes, and working_dir*/
slapt_rc_config *config = slapt_read_rc_config("/etc/slapt-get/slapt-getrc");
/* get a list of installed packages */
struct slapt_pkg_list *installed = slapt_get_installed_pkgs();
/* parse the package data, normally using config->working_dir */
FILE *data_f = fopen("/var/slapt-get/package_data","r");
struct slapt_pkg_list *available = slapt_parse_packages_txt(data_f);
/* search for a package in a list via regex */
struct slapt_pkg_list *results = slapt_search_pkg_list(installed,"[0-9]frg");
slapt_free_pkg_list(results);
/* look for a specific package */
slapt_pkg_info_t *pkg = slapt_get_exact_pkg(available,
                                            "slapt-get",
                                            "0.9.10c-i386-1");
if (!slapt_is_excluded(config,pkg)) {
  const char *error = slapt_download_pkg(config,pkg);
  if (error == NULL) {
    if (slapt_install_pkg(config,pkg) != 0) {
      fprintf(stderr,"error installing %s\n"pkg->name);
    }
    if (slapt_upgrade_pkg(config,pkg) != 0) {
      fprintf(stderr,"error upgrading %s\n"pkg->name);
    }
    if (slapt_remove_pkg(config,pkg) != 0) {
      fprintf(stderr,"error removing %s\n"pkg->name);
    }
  }
}
slapt_free_pkg(pkg);
if (slapt_cmp_pkgs(pkg_a,pkg_b) = 0) {
  fprintf(stderr,"%s is equal to %s\n",pkg_a->version,pkg_b->version);
} elsif (slapt_cmp_pkgs(pkg_a,pkg_b) < 0) {
  fprintf(stderr,"%s is less than %s\n",pkg_a->version,pkg_b->version);
} elsif (slapt_cmp_pkgs(pkg_a,pkg_b) > 0) {
  fprintf(stderr,"%s is greater than %s\n",pkg_a->version,pkg_b->version);
}
slapt_free_pkg_list(available);
slapt_free_pkg_list(installed);
slapt_free_rc_config(config);

DESCRIPTION
This is a short overview on how to use libslapt with your C programs.

CONFIGURATION

slapt-get stores the configuration information in a slapt_rc_config object.  The configuration is parsed from the slapt-getrc which includes SOURCE, EXCLUDE, and WORKINGDIR directives.  Various runtime configuration options are also stored within the slapt_rc_config object.
      typedef struct {
        char working_dir[WORKINGDIR_TOKEN_LEN];
        struct slapt_source_list *sources;
        struct slapt_exclude_list *exclude_list;
        int (*progress_cb) (void *,double,double,double,double);
        SLAPT_BOOL_T download_only;
        SLAPT_BOOL_T dist_upgrade;
        SLAPT_BOOL_T simulate;
        SLAPT_BOOL_T no_prompt;
        SLAPT_BOOL_T re_install;
        SLAPT_BOOL_T ignore_excludes;
        SLAPT_BOOL_T no_md5_check;
        SLAPT_BOOL_T ignore_dep;
        SLAPT_BOOL_T disable_dep_check;
        SLAPT_BOOL_T print_uris;
        SLAPT_BOOL_T dl_stats;
        SLAPT_BOOL_T remove_obsolete;
        SLAPT_BOOL_T no_upgrade;
        unsigned int retry;
      } slapt_rc_config;

The slapt_rc_config is created with the slapt_read_rc_config() function by passing in the file location of the configuration to parse, or by calling slapt_init_config() to return an empty, initialized slapt_rc_config.

    slapt_rc_config *slapt_read_rc_config(const char *file_name);

    slapt_rc_config *slapt_init_config(void);

and is freed by a call to the slapt_free_rc_config() function.

    void slapt_free_rc_config(slapt_rc_config *global_config);

The progress callback is a function that is called while data is being downloaded.  It is in the format of int slapt_progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);

The struct slapt_source_list stores the package sources.  Sources can be added and removed with slapt_add_source() and slapt_remove_source().  Typically, slapt_rc_config->sources is passed as the first argument, but it could be any pointer to a struct slapt_source_list that is created by slapt_init_source_list().

      struct slapt_source_list {
        char **url;
        unsigned int count;
      };

    struct slapt_source_list *slapt_init_source_list(void);
    void slapt_add_source(struct slapt_source_list *list,const char *s);
    void slapt_remove_source (struct slapt_source_list *list, const char *s);
    void slapt_free_source_list(struct slapt_source_list *list);

The struct slapt_exclude_list stores the package excludes.  Excludes can be added and removed with slapt_add_exclude() and slapt_remove_exclude().  Typically, slapt_rc_config->excludes is passed as the first argument, but it could be any pointer to a struct slapt_exclude_list that is created by slapt_init_exclude_list().

      struct slapt_exclude_list {
        char **excludes;
        unsigned int count;
      };

    struct slapt_exclude_list *slapt_init_exclude_list(void);
    void slapt_add_exclude(struct slapt_exclude_list *list,const char *e);
    void slapt_remove_exclude(struct slapt_exclude_list *list,const char *e);
    void slapt_free_exclude_list(struct slapt_exclude_list *list);

In order to initialize the slapt_rc_config->working_dir directory, slapt_working_dir_init() must be called.  It is a fatal error to call slapt_working_dir_init() with a directory that the current process does not have privileges to read, write, and execute.

    void slapt_working_dir_init(const slapt_rc_config *global_config);

PACKAGES

slapt-get stores packages within slapt_pkg_info_t objects.

      typedef struct {
        char md5[SLAPT_MD5_STR_LEN];
        char *name;
        char *version;
        char *mirror;
        char *location;
        char *description;
        char *required;
        char *conflicts;
        char *suggests;
        char *file_ext;
        unsigned int size_c;
        unsigned int size_u;
      } slapt_pkg_info_t;

The slapt_pkg_info_t object is created and freed with slapt_init_pkg() and slapt_free_pkg().  A slapt_pkg_info_t can also be copied with slapt_copy_pkg().

    __inline slapt_pkg_info_t *slapt_init_pkg(void);
    void slapt_free_pkg(slapt_pkg_info_t *pkg);
    slapt_pkg_info_t *slapt_copy_pkg(slapt_pkg_info_t *dst,
                                     slapt_pkg_info_t *src);

Package lists are useful for grouping packages from the existing installed packages, packages available from external sources, a list of dependencies, and more.  Package lists are stored within a struct slapt_pkg_list.

      struct slapt_pkg_list {
        slapt_pkg_info_t **pkgs;
        unsigned int pkg_count;
        SLAPT_BOOL_T free_pkgs;
        SLAPT_BOOL_T ordered;
      };

If free_pkgs is set to TRUE, slapt_free_pkg_list will call slapt_free_pkg() for each slapt_pkg_info_t within the list.  Leave this to the default of FALSE if the list is populated with pointers to slapt_pkg_info_t objects that are freed elsewhere.

If ordered is is set to TRUE, the list has been sorted by qsort().

slapt_pkg_info_t objects are created by slapt_init_pkg_list() and freed by slapt_free_pkg_list().  slapt_add_pkg_to_pkg_list() is used to add a package to a list.

    struct slapt_pkg_list *slapt_init_pkg_list(void);
    void slapt_free_pkg_list(struct slapt_pkg_list *);
    void slapt_add_pkg_to_pkg_list(struct slapt_pkg_list *list, slapt_pkg_info_t *pkg);

Package lists can be parsed from PACKAGES.TXT or similar formated files (such as the working_dir/package_data file used by slapt-get) with slapt_parse_packages_txt().  A package list of the currently installed packages is returned by slapt_get_installed_pkgs().  slapt_get_available_pkgs() is a frontend to slapt_parse_packages_txt() looking for a package_data file in the current directory.  All three of the following set free_pkgs to TRUE.

    struct slapt_pkg_list *slapt_parse_packages_txt(FILE *);
    struct slapt_pkg_list *slapt_get_available_pkgs(void);
    struct slapt_pkg_list *slapt_get_installed_pkgs(void);

Finding a specific package in a package list is done through one of the following functions.  All return slapt_pkg_info_t, or NULL on error, except for slapt_search_pkg_list() which returns a list of packages as struct slapt_pkg_list.

    slapt_pkg_info_t *slapt_get_newest_pkg(struct slapt_pkg_list *,
                                           const char *);
    slapt_pkg_info_t *slapt_get_exact_pkg(struct slapt_pkg_list *list,
                                          const char *name,
                                          const char *version);
    slapt_pkg_info_t *slapt_get_pkg_by_details(struct slapt_pkg_list *list,
                                               const char *name,
                                               const char *version,
                                               const char *location);
    struct slapt_pkg_list *slapt_search_pkg_list(struct slapt_pkg_list *list,
                                                 const char *pattern);

Passing a package to installpkg, upgradepkg, and removepkg is done through the following functions.  All return 0 upon success, or non-zero on error.

    int slapt_install_pkg(const slapt_rc_config *,slapt_pkg_info_t *);
    int slapt_upgrade_pkg(const slapt_rc_config *global_config,
                          slapt_pkg_info_t *pkg);
    int slapt_remove_pkg(const slapt_rc_config *,slapt_pkg_info_t *);

Comparing package versions is done with the slapt_cmp_pkgs macro.  It calls slapt_cmp_pkg_versions() which returns just like strcmp, greater than 0 if a is greater than b, less than 0 if a is less than b, or 0 if a and b are equal.

    int slapt_cmp_pkg_versions(const char *a, const char *b);
    #define slapt_cmp_pkgs(x,y) slapt_cmp_pkg_versions(x->version,y->version)

The following functions deal with determining package dependencies and conflicts and returning them within a package list.  Some require the use of a struct slapt_pkg_err_list of slapt_pkg_err_t objects for reporting errors on which packages failed or were missing.  slapt_search_pkg_err_list() returns 0 if the package and error string combination does not already exist in the struct slapt_pkg_err_list, or 1 if found.

      typedef struct {
        char *pkg;
        char *error;
      } slapt_pkg_err_t;

      struct slapt_pkg_err_list {
        slapt_pkg_err_t **errs;
        unsigned int err_count;
      };

    struct slapt_pkg_err_list *slapt_init_pkg_err_list(void);
    void slapt_add_pkg_err_to_list(struct slapt_pkg_err_list *l,
                                   const char *pkg,const char *err);
    int slapt_search_pkg_err_list(struct slapt_pkg_err_list *l, const char *pkg,
                                  const char *err);
    void slapt_free_pkg_err_list(struct slapt_pkg_err_list *l);

slapt_get_pkg_dependencies() fills a struct slapt_pkg_list of dependencies for the specified package.  These dependencies are pulled from the available package list and the installed package lists.  Missing and conflict errors are placed in struct slapt_pkg_err_list.  deps, conflict_err, and missing_err are initialized if NULL.  slapt_get_pkg_dependencies() returns 0 on success, or -1 on error.

    int slapt_get_pkg_dependencies(const slapt_rc_config *global_config,
                                   struct slapt_pkg_list *avail_pkgs,
                                   struct slapt_pkg_list *installed_pkgs,
                                   slapt_pkg_info_t *pkg,
                                   struct slapt_pkg_list *deps,
                                   struct slapt_pkg_err_list *conflict_err,
                                   struct slapt_pkg_err_list *missing_err);

slapt_get_pkg_conflicts() returns a struct slapt_pkg_list of packages that conflict with the specified package.

    struct slapt_pkg_list *
    slapt_get_pkg_conflicts(struct slapt_pkg_list *avail_pkgs,
                            struct slapt_pkg_list *installed_pkgs,
                            slapt_pkg_info_t *pkg);

slapt_is_required_by() returns a struct slapt_pkg_list of packages that require the package specified.

    struct slapt_pkg_list *
    slapt_is_required_by(const slapt_rc_config *global_config,
                         struct slapt_pkg_list *avail,
                         slapt_pkg_info_t *pkg);

slapt_get_obsolete_pkgs() returns a struct slapt_pkg_list of packages that are no longer available from the current package sources.

    struct slapt_pkg_list *
      slapt_get_obsolete_pkgs ( const slapt_rc_config *global_config,
                                struct slapt_pkg_list *avail_pkgs,
                                struct slapt_pkg_list *installed_pkgs);

slapt_is_excluded() returns 1 if package is present in the exclude list, 0 if not.

    int slapt_is_excluded(const slapt_rc_config *,slapt_pkg_info_t *);

slapt_get_pkg_changelog() returns the package changelog entry, if any.  Otherwise returns NULL.  Assumes already chdir'd to the working directory.

    char *slapt_get_pkg_changelog(const slapt_pkg_info_t *pkg);

slapt_stringify_pkg() returns a string representation of the package.

    char *slapt_stringify_pkg(const slapt_pkg_info_t *pkg);

The working_dir, defined within the slapt_rc_config object, caches the downloaded packages.  At various times it becomes necessary to purge the package cache.  slapt_clean_pkg_dir() unlinks all packages within the specified directory location.  slapt_purge_old_cached_pkgs() unlinks only packages that are not present in the current sources and thus are no longer downloadable.

    void slapt_clean_pkg_dir(const char *dir_name);
    void slapt_purge_old_cached_pkgs(const slapt_rc_config *global_config,
                                     const char *dir_name,
                                     struct slapt_pkg_list *avail_pkgs);

The slapt_clean_description() function is used to clean the package name from the package description.  This modifies the string in place.  It is best to copy the pkg->description to a new string prior to calling slapt_clean_description().

    void slapt_clean_description (char *description, const char *name);

DOWNLOADING

Downloading packages and the package data from various sources is handled with the following functions.  Functions with integer return types return non-zero on error.  slapt_update_pkg_cache() and slapt_get_available_pkgs() assume to be chdir'd to the working directory.

    int slapt_update_pkg_cache(const slapt_rc_config *global_config);
    const char *slapt_download_pkg(const slapt_rc_config *global_config,
                           slapt_pkg_info_t *pkg);
    slapt_code_t slapt_verify_downloaded_pkg(const slapt_rc_config *global_config,
                                    slapt_pkg_info_t *pkg);

    const char *slapt_get_mirror_data_from_source(FILE *fh,
                                          const slapt_rc_config *global_config,
                                          const char *base_url,
                                          const char *filename);
    char *slapt_head_request(const char *url);
    char *slapt_head_mirror_data(const char *wurl,const char *file);
    void slapt_clear_head_cache(const char *cache_filename);
    void slapt_write_head_cache(const char *cache, const char *cache_filename);
    char *slapt_read_head_cache(const char *cache_filename);

The following functions download the PACKAGES.TXT, the patches/PACKAGES.TXT, CHECKSUMS.md5, and ChangeLog.txt.  Each sets the compressed option if a compressed version was available and retrieved.

    struct slapt_pkg_list *
    slapt_get_pkg_source_packages (const slapt_rc_config *global_config,
                                   const char *url, unsigned int *compressed);
    struct slapt_pkg_list *
    slapt_get_pkg_source_patches (const slapt_rc_config *global_config,
                                  const char *url, unsigned int *compressed);
    FILE *slapt_get_pkg_source_checksums (const slapt_rc_config *global_config,
                                          const char *url, unsigned int *compressed);
    int slapt_get_pkg_source_changelog (const slapt_rc_config *global_config,
                                          const char *url, unsigned int *compressed);

Progress callbacks make use of struct slapt_progress_data.

      struct slapt_progress_data
      {
        size_t bytes;
        time_t start;
      };

    struct slapt_progress_data *slapt_init_progress_data(void);
    void slapt_free_progress_data(struct slapt_progress_data *d);

TRANSACTIONS

Adding, removing, and upgrading packages can be wrapped in a slapt_transaction_t object.  This structure will make sure that all packages are worked on in the specific order, downloaded, and handed off to the appropriate pkgtools command via the slapt_handle_transaction() function.

      struct slapt_suggests {
        char **pkgs;
        unsigned int count;
      };

      enum slapt_action {
        USAGE = 0, UPDATE, INSTALL, REMOVE, SHOW, SEARCH, UPGRADE,
        LIST, INSTALLED, CLEAN, SHOWVERSION, AUTOCLEAN, AVAILABLE
      };

      typedef struct {
        union { slapt_pkg_info_t *i; slapt_pkg_upgrade_t *u; } pkg;
        unsigned int type; /* this is enum slapt_action */
      } slapt_queue_i;

      typedef struct {
        slapt_queue_i **pkgs;
        unsigned int count;
      } slapt_queue_t;

      typedef struct {
        slapt_pkg_info_t *installed;
        slapt_pkg_info_t *upgrade;
      } slapt_pkg_upgrade_t;

      struct slapt_pkg_upgrade_list {
        slapt_pkg_upgrade_t **pkgs;
        unsigned int pkg_count;
      };

      typedef struct {
        struct slapt_pkg_list *install_pkgs;
        struct slapt_pkg_upgrade_list *upgrade_pkgs;
        struct slapt_pkg_list *remove_pkgs;
        struct slapt_pkg_list *exclude_pkgs;
        struct slapt_suggests *suggests;
        struct slapt_pkg_err_list *conflict_err;
        struct slapt_pkg_err_list *missing_err;
        slapt_queue_t *queue;
      } slapt_transaction_t;

    slapt_transaction_t *slapt_init_transaction(void);
    void slapt_free_transaction(slapt_transaction_t *);
    int slapt_handle_transaction(const slapt_rc_config *,slapt_transaction_t *);

    void slapt_add_install_to_transaction(slapt_transaction_t *,
                                          slapt_pkg_info_t *pkg);

    void slapt_add_remove_to_transaction(slapt_transaction_t *,
                                         slapt_pkg_info_t *pkg);

    void slapt_add_upgrade_to_transaction(slapt_transaction_t *,
                                          slapt_pkg_info_t *installed_pkg,
                                          slapt_pkg_info_t *upgrade_pkg);

    void slapt_add_exclude_to_transaction(slapt_transaction_t *,
                                          slapt_pkg_info_t *pkg);

    slapt_transaction_t *slapt_remove_from_transaction(slapt_transaction_t *tran,
                                                       slapt_pkg_info_t *pkg);

    int slapt_search_transaction(slapt_transaction_t *,char *pkg_name);
    int slapt_search_transaction_by_pkg(slapt_transaction_t *tran,
                                        slapt_pkg_info_t *pkg);

    int slapt_search_upgrade_transaction(slapt_transaction_t *tran,
                                         slapt_pkg_info_t *pkg);

    int slapt_add_deps_to_trans(const slapt_rc_config *global_config,
                                slapt_transaction_t *tran,
                                struct slapt_pkg_list *avail_pkgs,
                                struct slapt_pkg_list *installed_pkgs,
                                slapt_pkg_info_t *pkg);

    slapt_pkg_info_t *slapt_is_conflicted(slapt_transaction_t *tran,
                                          struct slapt_pkg_list *avail_pkgs,
                                          struct slapt_pkg_list *installed_pkgs,
                                          slapt_pkg_info_t *pkg);

    void slapt_generate_suggestions(slapt_transaction_t *tran);

GPG

Functionality for GPG verification of package sources.

Retrieve the signature file for CHECKSUMS.md5 (or the signature for CHECKSUMS.md5.gz).  Sets compressed depending on which was found.
    FILE *slapt_get_pkg_source_checksums_signature (const slapt_rc_config *global_config,
                                                    const char *url,
                                                    unsigned int *compressed);

Retrieve the GPG-KEY file from the package source, if available.  Returns NULL if not found.
    FILE *slapt_get_pkg_source_gpg_key(const slapt_rc_config *global_config,
                                       const char *url,
                                       unsigned int *compressed);

Add the GPG-Key to the local keyring. Returns one of the following: SLAPT_GPG_KEY_IMPORTED, SLAPT_GPG_KEY_NOT_IMPORTED, or SLAPT_GPG_KEY_UNCHANGED.
    slapt_code_t slapt_add_pkg_source_gpg_key (FILE *key);

Verify the signature is valid for the compressed or uncompressed checksum.  Returns one of the following: SLAPT_CHECKSUMS_VERIFIED, SLAPT_CHECKSUMS_MISSING_KEY, or SLAPT_CHECKSUMS_NOT_VERIFIED.
    slapt_code_t slapt_gpg_verify_checksums(FILE *checksums, FILE *signature);

MISCELLANEOUS

Miscellaneous functionality within libslapt.

      typedef struct {
        regmatch_t pmatch[SLAPT_MAX_REGEX_PARTS];
        regex_t regex;
        size_t nmatch;
        int reg_return;
      } slapt_regex_t;

    FILE *slapt_open_file(const char *file_name,const char *mode);
    slapt_regex_t *slapt_init_regex(const char *regex_string);
    void slapt_execute_regex(slapt_regex_t *regex_t,const char *string);
    void slapt_free_regex(slapt_regex_t *regex_t);
    void slapt_create_dir_structure(const char *dir_name);
    void slapt_gen_md5_sum_of_file(FILE *f,char *result_sum);
    int slapt_ask_yes_no(const char *format, ...);
    char *slapt_str_replace_chr(const char *string,const char find,
                                const char replace);
    __inline void *slapt_malloc(size_t s);
    __inline void *slapt_calloc(size_t n,size_t s);

      typedef enum {
        SLAPT_OK = 0,
        SLAPT_MD5_CHECKSUM_MISMATCH,
        SLAPT_MD5_CHECKSUM_MISSING,
        #ifdef SLAPT_HAS_GPGME
        SLAPT_GPG_KEY_IMPORTED,
        SLAPT_GPG_KEY_NOT_IMPORTED,
        SLAPT_GPG_KEY_UNCHANGED,
        SLAPT_CHECKSUMS_VERIFIED,
        SLAPT_CHECKSUMS_MISSING_KEY,
        SLAPT_CHECKSUMS_NOT_VERIFIED,
        #endif
        SLAPT_DOWNLOAD_INCOMPLETE
      } slapt_code_t;

    const char *slapt_strerror(slapt_code_t code);

LINKING WITH LIBSLAPT
You must link with -lslapt and with libcurl through the curl-config script. For example: `curl-config --libs` -lslapt. Optionally, gpgme may be linked into libslapt, which requires `gpgme-config --libs`.

SEE ALSO
libcurl(3) zlib(3)

AUTHOR
Jason Woodward <woodwardj@jaos.org>