New custom configuration file format that does not need confuse.

This commit is contained in:
Juan RP 2014-02-25 16:42:52 +01:00
parent 1ad01b952a
commit f74bf1c1c8
13 changed files with 388 additions and 324 deletions

4
NEWS
View File

@ -1,5 +1,9 @@
xbps-0.33 (???): xbps-0.33 (???):
* New configuration file format with a custom C parser, simpler
and does not need any additional external dependency. confuse is
not necessary anymore.
* Only allow a single writer to the pkgdb to avoid concurrency issues * Only allow a single writer to the pkgdb to avoid concurrency issues
when performing multiple write transactions (install, update or remove). when performing multiple write transactions (install, update or remove).
The implementation relies on a POSIX named semaphore. The implementation relies on a POSIX named semaphore.

View File

@ -41,7 +41,6 @@ To build this you'll need:
- [zlib](http://www.zlib.net) - [zlib](http://www.zlib.net)
- [openssl](http://www.openssl.org) - [openssl](http://www.openssl.org)
- [libarchive >= 2.8.0](http://www.libarchive.org) - [libarchive >= 2.8.0](http://www.libarchive.org)
- [confuse >= 2.7](http://www.nongnu.org/confuse)
and optionally: and optionally:

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2011-2013 Juan Romero Pardines. * Copyright (c) 2011-2014 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -37,11 +37,9 @@ state_cb(struct xbps_state_cb_data *xscd, void *cbdata _unused)
xbps_dictionary_t pkgd; xbps_dictionary_t pkgd;
const char *instver, *newver; const char *instver, *newver;
char *pkgname; char *pkgname;
bool syslog_enabled = false;
int rv = 0; int rv = 0;
if (xscd->xhp->flags & XBPS_FLAG_SYSLOG) { if (xscd->xhp->syslog) {
syslog_enabled = true;
openlog("xbps-install", LOG_CONS, LOG_USER); openlog("xbps-install", LOG_CONS, LOG_USER);
} }
@ -105,24 +103,27 @@ state_cb(struct xbps_state_cb_data *xscd, void *cbdata _unused)
break; break;
case XBPS_STATE_INSTALL_DONE: case XBPS_STATE_INSTALL_DONE:
printf("%s: installed successfully.\n", xscd->arg); printf("%s: installed successfully.\n", xscd->arg);
if (syslog_enabled) if (xscd->xhp->syslog) {
syslog(LOG_NOTICE, "Installed `%s' successfully " syslog(LOG_NOTICE, "Installed `%s' successfully "
"(rootdir: %s).", xscd->arg, "(rootdir: %s).", xscd->arg,
xscd->xhp->rootdir); xscd->xhp->rootdir);
}
break; break;
case XBPS_STATE_UPDATE_DONE: case XBPS_STATE_UPDATE_DONE:
printf("%s: updated successfully.\n", xscd->arg); printf("%s: updated successfully.\n", xscd->arg);
if (syslog_enabled) if (xscd->xhp->syslog) {
syslog(LOG_NOTICE, "Updated `%s' successfully " syslog(LOG_NOTICE, "Updated `%s' successfully "
"(rootdir: %s).", xscd->arg, "(rootdir: %s).", xscd->arg,
xscd->xhp->rootdir); xscd->xhp->rootdir);
}
break; break;
case XBPS_STATE_REMOVE_DONE: case XBPS_STATE_REMOVE_DONE:
printf("%s: removed successfully.\n", xscd->arg); printf("%s: removed successfully.\n", xscd->arg);
if (syslog_enabled) if (xscd->xhp->syslog) {
syslog(LOG_NOTICE, "Removed `%s' successfully " syslog(LOG_NOTICE, "Removed `%s' successfully "
"(rootdir: %s).", xscd->arg, "(rootdir: %s).", xscd->arg,
xscd->xhp->rootdir); xscd->xhp->rootdir);
}
break; break;
case XBPS_STATE_REPO_KEY_IMPORT: case XBPS_STATE_REPO_KEY_IMPORT:
printf("%s\n", xscd->desc); printf("%s\n", xscd->desc);
@ -139,8 +140,9 @@ state_cb(struct xbps_state_cb_data *xscd, void *cbdata _unused)
case XBPS_STATE_REPOSYNC_FAIL: case XBPS_STATE_REPOSYNC_FAIL:
case XBPS_STATE_CONFIG_FILE_FAIL: case XBPS_STATE_CONFIG_FILE_FAIL:
xbps_error_printf("%s\n", xscd->desc); xbps_error_printf("%s\n", xscd->desc);
if (syslog_enabled) if (xscd->xhp->syslog) {
syslog(LOG_ERR, "%s", xscd->desc); syslog(LOG_ERR, "%s", xscd->desc);
}
break; break;
case XBPS_STATE_REMOVE_FILE_FAIL: case XBPS_STATE_REMOVE_FILE_FAIL:
case XBPS_STATE_REMOVE_FILE_HASH_FAIL: case XBPS_STATE_REMOVE_FILE_HASH_FAIL:
@ -150,8 +152,9 @@ state_cb(struct xbps_state_cb_data *xscd, void *cbdata _unused)
return 0; return 0;
xbps_error_printf("%s\n", xscd->desc); xbps_error_printf("%s\n", xscd->desc);
if (syslog_enabled) if (xscd->xhp->syslog) {
syslog(LOG_ERR, "%s", xscd->desc); syslog(LOG_ERR, "%s", xscd->desc);
}
break; break;
default: default:
xbps_dbg_printf(xscd->xhp, xbps_dbg_printf(xscd->xhp,

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2012-2013 Juan Romero Pardines. * Copyright (c) 2012-2014 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -53,10 +53,7 @@ usage(bool fail)
static int static int
state_cb(struct xbps_state_cb_data *xscd, void *cbd _unused) state_cb(struct xbps_state_cb_data *xscd, void *cbd _unused)
{ {
bool syslog_enabled = false; if (xscd->xhp->syslog) {
if (xscd->xhp->flags & XBPS_FLAG_SYSLOG) {
syslog_enabled = true;
openlog("xbps-reconfigure", LOG_CONS, LOG_USER); openlog("xbps-reconfigure", LOG_CONS, LOG_USER);
} }
@ -64,19 +61,19 @@ state_cb(struct xbps_state_cb_data *xscd, void *cbd _unused)
/* notifications */ /* notifications */
case XBPS_STATE_CONFIGURE: case XBPS_STATE_CONFIGURE:
printf("%s: configuring ...\n", xscd->arg); printf("%s: configuring ...\n", xscd->arg);
if (syslog_enabled) if (xscd->xhp->syslog)
syslog(LOG_NOTICE, "%s: configuring ...", xscd->arg); syslog(LOG_NOTICE, "%s: configuring ...", xscd->arg);
break; break;
case XBPS_STATE_CONFIGURE_DONE: case XBPS_STATE_CONFIGURE_DONE:
printf("%s: configured successfully.\n", xscd->arg); printf("%s: configured successfully.\n", xscd->arg);
if (syslog_enabled) if (xscd->xhp->syslog)
syslog(LOG_NOTICE, syslog(LOG_NOTICE,
"%s: configured successfully.", xscd->arg); "%s: configured successfully.", xscd->arg);
break; break;
/* errors */ /* errors */
case XBPS_STATE_CONFIGURE_FAIL: case XBPS_STATE_CONFIGURE_FAIL:
xbps_error_printf("%s\n", xscd->desc); xbps_error_printf("%s\n", xscd->desc);
if (syslog_enabled) if (xscd->xhp->syslog)
syslog(LOG_ERR, "%s", xscd->desc); syslog(LOG_ERR, "%s", xscd->desc);
break; break;
default: default:

View File

@ -65,10 +65,7 @@ usage(bool fail)
static int static int
state_cb_rm(struct xbps_state_cb_data *xscd, void *cbdata _unused) state_cb_rm(struct xbps_state_cb_data *xscd, void *cbdata _unused)
{ {
bool syslog_enabled = false; if (xscd->xhp->syslog) {
if (xscd->xhp->flags & XBPS_FLAG_SYSLOG) {
syslog_enabled = true;
openlog("xbps-remove", LOG_CONS, LOG_USER); openlog("xbps-remove", LOG_CONS, LOG_USER);
} }
@ -85,16 +82,18 @@ state_cb_rm(struct xbps_state_cb_data *xscd, void *cbdata _unused)
break; break;
case XBPS_STATE_REMOVE_DONE: case XBPS_STATE_REMOVE_DONE:
printf("Removed `%s' successfully.\n", xscd->arg); printf("Removed `%s' successfully.\n", xscd->arg);
if (syslog_enabled) if (xscd->xhp->syslog) {
syslog(LOG_NOTICE, "Removed `%s' successfully " syslog(LOG_NOTICE, "Removed `%s' successfully "
"(rootdir: %s).", xscd->arg, "(rootdir: %s).", xscd->arg,
xscd->xhp->rootdir); xscd->xhp->rootdir);
}
break; break;
/* errors */ /* errors */
case XBPS_STATE_REMOVE_FAIL: case XBPS_STATE_REMOVE_FAIL:
xbps_error_printf("%s\n", xscd->desc); xbps_error_printf("%s\n", xscd->desc);
if (syslog_enabled) if (xscd->xhp->syslog) {
syslog(LOG_ERR, "%s", xscd->desc); syslog(LOG_ERR, "%s", xscd->desc);
}
break; break;
case XBPS_STATE_REMOVE_FILE_FAIL: case XBPS_STATE_REMOVE_FILE_FAIL:
case XBPS_STATE_REMOVE_FILE_HASH_FAIL: case XBPS_STATE_REMOVE_FILE_HASH_FAIL:
@ -104,8 +103,9 @@ state_cb_rm(struct xbps_state_cb_data *xscd, void *cbdata _unused)
return 0; return 0;
xbps_error_printf("%s\n", xscd->desc); xbps_error_printf("%s\n", xscd->desc);
if (syslog_enabled) if (xscd->xhp->syslog) {
syslog(LOG_ERR, "%s", xscd->desc); syslog(LOG_ERR, "%s", xscd->desc);
}
break; break;
default: default:
xbps_dbg_printf(xscd->xhp, xbps_dbg_printf(xscd->xhp,

15
configure vendored
View File

@ -644,21 +644,6 @@ else
>>$CONFIG_MK >>$CONFIG_MK
fi fi
#
# confuse >= 2.7 with pkg-config support is required.
#
printf "Checking for confuse via pkg-config ..."
if ! $PKGCONFIG_BIN --exists libconfuse; then
echo "libconfuse.pc not found, exiting."
exit 1
else
echo "found version $($PKGCONFIG_BIN --modversion libconfuse)."
echo "CFLAGS += $($PKGCONFIG_BIN --cflags libconfuse)" >>$CONFIG_MK
echo "LDFLAGS += $($PKGCONFIG_BIN --libs libconfuse)" >>$CONFIG_MK
echo "STATIC_LIBS += $($PKGCONFIG_BIN --libs --static libconfuse)" \
>>$CONFIG_MK
fi
# #
# OpenSSL libssl with pkg-config support is required when building # OpenSSL libssl with pkg-config support is required when building
# the static binaries. # the static binaries.

View File

@ -1,58 +1,56 @@
# Configuration file for XBPS. # Configuration file for XBPS.
# ============================
# #
# Root directory. # - Lines starting with # are ignored.
#RootDir = / # - Values are set after the equal sign, and don't accept blanks nor newlines.
#
# Cache directory to store downloaded binary packages.
# If string begins with '/' it will be treated as full path,
# otherwise it will be treated as relative to the root-directory.
#CacheDir = var/cache/xbps
#
# Default global limit of cached connections when fetching files.
#FetchCacheConnections = 10
#
# Default per-host limit of cached connections when fetching files.
#FetchCacheConnectionsPerHost = 3
#
# Default timeout limit for connections, in seconds.
#FetchTimeoutConnection = 30
#
# Enable syslog messages, set the value to false or 0 to disable.
#Syslog = true
# Repositories. # Set root directory, by default set to /. This expects an absolute path.
# #rootdir=/
# You can specify here your list of repositories, the first
# repository matching a package expression will be used for most
# targets in xbps-install(8) and xbps-query(8).
#
# Optionally a non default HTTP port can also be specified such as:
# http://foo.local:8080/xbps-repo
#
# By default we use the official "public" repositories. You can add
# your own repositories by specifying the path to the directory
# where the <arch>-repodata file is stored.
#
# Repositories not matching the host architecture are simply ignored.
#
repositories = {
http://repo.voidlinux.eu/current,
#http://repo.voidlinux.eu/current/nonfree,
#
# MIRRORS
#
#http://xbps.nopcode.org/repos/current,
#http://xbps.nopcode.org/repos/current/nonfree
}
# Virtual packages. # Set cache directory, if starts with / it's an absolute path,
# otherwise it's relative to rootdir.
#cachedir=var/cache/xbps
# comment it out to disable syslog logging.
syslog=true
## REPOSITORIES
# #
# The following syntax is used: # Local or remote repositories are accepted.
# virtual-package <realpkgname> { targets = <virtualpkgname-version> }
# #
# If a package supports multiple virtual packages these can be # - Local repositories expect an absolute path to the directory that stores
# specified in the 'targets' option such as: # the <arch>-repodata file.
# - Accepted protocols for remote repositories: ftp, http or https.
# - Repositories are added in the order in which are specified (top->bottom).
# #
# virtual-package foo { targets = blah-0, baz-1, ... } repository=http://repo.voidlinux.eu/current
# Uncomment this one for "non-free" packages.
#repository=http://repo.voidlinux.eu/current/nonfree
# REPOSITORY MIRRORS
#repository=http://xbps.nopcode.org/repos/current
#repository=http://xbps.nopcode.org/repos/current/nonfree
## VIRTUAL PACKAGES
# #
# Virtual package overrides. You can set your own list of preferred virtual
# packages in your system. This expects two arguments separated by a colon:
# <vpkgver>:<realpkgname>.
#
# - <vpkgver> means "virtual package name" and "version/revision"
# separated by a dash, i.e 'foo-1.0_1".
# - <realpkgname> means a real package name (without any version).
#
# By default we prefer the `dcron` package as default cron daemon.
virtualpkg=cron-daemon-0_1:dcron
# Sets the virtual package directory looking for .conf files with
# virtual package settings.
#
# If starts with / it's an absolute path, otherwise it's relative to rootdir.
# By default it's set to <rootdir>/etc/xbps/virtualpkg.d.
#virtualpkgdir=etc/xbps/virtualpkg.d
# You can also include additional files by using the "include" keyword.
# This expects an absolute path to a file.
#include=/path/to/another/file.conf

View File

@ -42,7 +42,7 @@
#include <archive.h> #include <archive.h>
#include <archive_entry.h> #include <archive_entry.h>
#define XBPS_MAXPATH 256 #define XBPS_MAXPATH 512
/** /**
* @file include/xbps.h * @file include/xbps.h
@ -50,7 +50,7 @@
* *
* This header documents the full API for the XBPS Library. * This header documents the full API for the XBPS Library.
*/ */
#define XBPS_API_VERSION "20140223" #define XBPS_API_VERSION "20140225"
#ifndef XBPS_VERSION #ifndef XBPS_VERSION
#define XBPS_VERSION "UNSET" #define XBPS_VERSION "UNSET"
@ -66,6 +66,15 @@
" API: " XBPS_API_VERSION \ " API: " XBPS_API_VERSION \
" GIT: " XBPS_GIT " GIT: " XBPS_GIT
/**
* @def XBPS_SYSCONF_PATH
* Default configuration PATH to find XBPS_CONF_PLIST.
*/
#define XBPS_SYSDIR "/xbps"
#ifndef XBPS_SYSCONF_PATH
#define XBPS_SYSCONF_PATH "/etc" XBPS_SYSDIR
#endif
/** /**
* @def XBPS_META_PATH * @def XBPS_META_PATH
* Default root PATH to store metadata info. * Default root PATH to store metadata info.
@ -78,6 +87,12 @@
*/ */
#define XBPS_CACHE_PATH "var/cache/xbps" #define XBPS_CACHE_PATH "var/cache/xbps"
/**
* @def XBPS_VPKG_PATH
* Default virtualpkg PATH to store virtualpkg overrides.
*/
#define XBPS_VPKG_PATH XBPS_SYSCONF_PATH "/virtualpkg.d"
/** /**
* @def XBPS_PKGDB * @def XBPS_PKGDB
* Filename for the package database. * Filename for the package database.
@ -114,15 +129,6 @@
*/ */
#define XBPS_REPOIDX_META "index-meta.plist" #define XBPS_REPOIDX_META "index-meta.plist"
/**
* @def XBPS_SYSCONF_PATH
* Default configuration PATH to find XBPS_CONF_PLIST.
*/
#define XBPS_SYSDIR "/xbps"
#ifndef XBPS_SYSCONF_PATH
#define XBPS_SYSCONF_PATH "/etc" XBPS_SYSDIR
#endif
/** /**
* @def XBPS_CONF_DEF * @def XBPS_CONF_DEF
* Filename for the XBPS plist configuration file. * Filename for the XBPS plist configuration file.
@ -152,13 +158,6 @@
*/ */
#define XBPS_FLAG_FORCE_REMOVE_FILES 0x00000004 #define XBPS_FLAG_FORCE_REMOVE_FILES 0x00000004
/**
* @def XBPS_FLAG_SYSLOG
* Enable syslog logging flag. To make clients aware that syslog
* will be used.
*/
#define XBPS_FLAG_SYSLOG 0x00000008
/** /**
* @def XBPS_FLAG_INSTALL_AUTO * @def XBPS_FLAG_INSTALL_AUTO
* Enabled automatic install mode for a package and all dependencies * Enabled automatic install mode for a package and all dependencies
@ -449,10 +448,6 @@ struct xbps_unpack_cb_data {
bool entry_is_conf; bool entry_is_conf;
}; };
#ifndef LIBXBPS_PRIVATE
typedef void *cfg_t;
#endif
/** /**
* @struct xbps_handle xbps.h "xbps.h" * @struct xbps_handle xbps.h "xbps.h"
* @brief Generic XBPS structure handler for initialization. * @brief Generic XBPS structure handler for initialization.
@ -465,9 +460,9 @@ struct xbps_handle {
/** /**
* @private * @private
*/ */
cfg_t *cfg;
xbps_dictionary_t pkg_metad; xbps_dictionary_t pkg_metad;
xbps_dictionary_t pkgdb_revdeps; xbps_dictionary_t pkgdb_revdeps;
xbps_dictionary_t vpkgd;
/** /**
* @var pkgdb * @var pkgdb
* *
@ -564,6 +559,14 @@ struct xbps_handle {
* If unset, defaults to \a XBPS_CACHE_PATH (relative to rootdir). * If unset, defaults to \a XBPS_CACHE_PATH (relative to rootdir).
*/ */
char metadir[XBPS_MAXPATH-1]; char metadir[XBPS_MAXPATH-1];
/**
* @var virtualpkgdir
*
* Virtual packages directory, with configuration files to override
* system virtual packages.
* If unset, defaults to \a XBPS_VPKG_PATH (relative to rootdir).
*/
char virtualpkgdir[XBPS_MAXPATH-1];
/** /**
* @var native_arch * @var native_arch
* *
@ -571,14 +574,6 @@ struct xbps_handle {
* if XBPS_ARCH is not set from environment. * if XBPS_ARCH is not set from environment.
*/ */
char native_arch[16]; char native_arch[16];
/**
* @var fetch_timeout
*
* Unsigned integer to specify libfetch's timeout limit.
* If not set, it defaults to 30 (in seconds). This is set internally
* by the API from a setting in configuration file.
*/
uint16_t fetch_timeout;
/** /**
* @var flags * @var flags
* *
@ -587,10 +582,15 @@ struct xbps_handle {
* - XBPS_FLAG_FORCE_CONFIGURE * - XBPS_FLAG_FORCE_CONFIGURE
* - XBPS_FLAG_FORCE_REMOVE_FILES * - XBPS_FLAG_FORCE_REMOVE_FILES
* - XBPS_FLAG_DEBUG * - XBPS_FLAG_DEBUG
* - XBPS_FLAG_SYSLOG
* - XBPS_FLAG_INSTALL_AUTO * - XBPS_FLAG_INSTALL_AUTO
*/ */
int flags; int flags;
/**
* @var syslog
*
* Set it to true to enable syslog logging.
*/
bool syslog;
}; };
void xbps_dbg_printf(struct xbps_handle *, const char *, ...); void xbps_dbg_printf(struct xbps_handle *, const char *, ...);

View File

@ -29,7 +29,6 @@
#include <assert.h> #include <assert.h>
#include <confuse.h> #include <confuse.h>
#define LIBXBPS_PRIVATE
#include "xbps.h" #include "xbps.h"
/* /*
@ -92,6 +91,10 @@
#endif #endif
#ifndef __arraycount
#define __arraycount(x) (sizeof(x) / sizeof(*x))
#endif
/** /**
* @private * @private
* From lib/external/dewey.c * From lib/external/dewey.c

View File

@ -110,7 +110,6 @@ xbps_fetch_file(struct xbps_handle *xhp, const char *uri, const char *flags)
/* Extern vars declared in libfetch */ /* Extern vars declared in libfetch */
fetchLastErrCode = 0; fetchLastErrCode = 0;
fetchTimeout = xhp->fetch_timeout;
if ((url = fetchParseURL(uri)) == NULL) if ((url = fetchParseURL(uri)) == NULL)
return -1; return -1;

View File

@ -30,16 +30,14 @@
#define _BSD_SOURCE /* required by strlcpy with musl */ #define _BSD_SOURCE /* required by strlcpy with musl */
#include <string.h> #include <string.h>
#undef _BSD_SOURCE #undef _BSD_SOURCE
#include <strings.h>
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <dirent.h> #include <dirent.h>
#include <ctype.h>
#include "xbps_api_impl.h" #include "xbps_api_impl.h"
#ifdef __clang__
#pragma clang diagnostic ignored "-Wformat-nonliteral"
#endif
/** /**
* @file lib/initend.c * @file lib/initend.c
* @brief Initialization and finalization routines * @brief Initialization and finalization routines
@ -48,50 +46,225 @@
* Use these functions to initialize some parameters before start * Use these functions to initialize some parameters before start
* using libxbps and finalize usage to release resources at the end. * using libxbps and finalize usage to release resources at the end.
*/ */
static int static void
cb_validate_virtual(cfg_t *cfg, cfg_opt_t *opt) store_vpkg(struct xbps_handle *xhp, const char *path, size_t line, char *vpkg_s)
{ {
for (unsigned int i = 0; i < cfg_size(cfg, "virtual-package"); i++) { /*
cfg_t *sec = cfg_opt_getnsec(opt, i); * Append virtual package overrides to our vpkgd dictionary:
if (cfg_getstr(sec, "targets") == 0) { *
cfg_error(cfg, "targets must be set for " * <key>vpkgver</key>
"virtual-package %s", cfg_title(sec)); * <string>realpkgname</string>
return -1; */
char *vpkg, *rpkg, *tc;
size_t vpkglen;
if (xhp->vpkgd == NULL)
xhp->vpkgd = xbps_dictionary_create();
/* real pkg after ':' */
vpkg = vpkg_s;
rpkg = strchr(vpkg_s, ':');
if (rpkg == NULL || *rpkg == '\0') {
xbps_dbg_printf(xhp, "%s: ignoring invalid "
"virtualpkg option at line %zu\n", path, line);
return;
}
/* vpkg until ':' */
tc = strchr(vpkg_s, ':');
vpkglen = strlen(vpkg_s) - strlen(tc);
vpkg[vpkglen] = '\0';
/* skip ':' */
rpkg++;
xbps_dictionary_set_cstring(xhp->vpkgd, vpkg, rpkg);
xbps_dbg_printf(xhp, "%s: added vpkg %s for %s\n", path, vpkg, rpkg);
}
static bool
store_repo(struct xbps_handle *xhp, const char *repo)
{
/*
* Append repositories to our proplib array.
*/
if (xhp->repositories == NULL)
xhp->repositories = xbps_array_create();
/*
* Do not add duplicates.
*/
for (unsigned int i = 0; i < xbps_array_count(xhp->repositories); i++) {
const char *srepo;
xbps_array_get_cstring_nocopy(xhp->repositories, i, &srepo);
if (strcmp(repo, srepo) == 0)
return false;
}
xbps_array_add_cstring(xhp->repositories, repo);
return true;
}
static bool
parse_option(char *buf, char **k, char **v)
{
size_t klen;
char *key, *value;
const char *keys[] = {
"rootdir",
"cachedir",
"syslog",
"repository",
"virtualpkgdir",
"virtualpkg",
"include"
};
bool found = false;
for (unsigned int i = 0; i < __arraycount(keys); i++) {
key = __UNCONST(keys[i]);
klen = strlen(key);
if (strncmp(buf, key, klen) == 0) {
found = true;
break;
} }
} }
/* non matching option */
if (!found)
return false;
/* check if next char is the equal sign */
if (buf[klen] != '=')
return false;
/* skip equal sign */
value = buf + klen + 1;
/* eat blanks */
while (isblank((unsigned char)*value))
value++;
/* eat final newline */
value[strlen(value)-1] = '\0';
/* option processed successfully */
*k = key;
*v = value;
return true;
}
static int
parse_file(struct xbps_handle *xhp, const char *path, bool nested, bool vpkgconf)
{
FILE *fp;
size_t len, nlines = 0;
ssize_t read;
char *line = NULL;
int rv = 0;
if ((fp = fopen(path, "r")) == NULL) {
rv = errno;
xbps_dbg_printf(xhp, "cannot read configuration file %s: %s\n", path, strerror(rv));
return rv;
}
if (!vpkgconf) {
xbps_dbg_printf(xhp, "Parsing configuration file: %s\n", path);
}
while ((read = getline(&line, &len, fp)) != -1) {
char *p, *k, *v;
nlines++;
p = line;
/* eat blanks */
while (isblank((unsigned char)*p))
p++;
/* ignore comments or empty lines */
if (*p == '#' || *p == '\n')
continue;
if (!parse_option(p, &k, &v)) {
xbps_dbg_printf(xhp, "%s: ignoring invalid option at "
"line %zu\n", path, nlines);
continue;
}
if (strcmp(k, "rootdir") == 0) {
xbps_dbg_printf(xhp, "%s: rootdir set to %s\n",
path, v);
snprintf(xhp->rootdir, sizeof(xhp->rootdir), "%s", v);
} else if (strcmp(k, "cachedir") == 0) {
xbps_dbg_printf(xhp, "%s: cachedir set to %s\n",
path, v);
snprintf(xhp->cachedir, sizeof(xhp->cachedir), "%s", v);
} else if (strcmp(k, "virtualpkgdir") == 0) {
xbps_dbg_printf(xhp, "%s: virtualpkgdir set to %s\n",
path, v);
snprintf(xhp->virtualpkgdir, sizeof(xhp->virtualpkgdir), "%s", v);
} else if (strcmp(k, "syslog") == 0) {
if (strcasecmp(v, "true") == 0) {
xhp->syslog = true;
xbps_dbg_printf(xhp, "%s: syslog enabled\n", path);
}
} else if (strcmp(k, "repository") == 0) {
if (store_repo(xhp, v))
xbps_dbg_printf(xhp, "%s: added repository %s\n", path, v);
} else if (strcmp(k, "virtualpkg") == 0) {
store_vpkg(xhp, path, nlines, v);
}
/* Avoid double-nested parsing, only allow it once */
if (nested)
continue;
if (strcmp(k, "include"))
continue;
if ((rv = parse_file(xhp, v, true, false)) != 0)
break;
}
free(line);
fclose(fp);
return rv;
}
static int
parse_vpkgdir(struct xbps_handle *xhp)
{
DIR *dirp;
struct dirent *dp;
char *ext;
int rv = 0;
if ((dirp = opendir(xhp->virtualpkgdir)) == NULL)
return 0; return 0;
xbps_dbg_printf(xhp, "Parsing virtualpkg directory: %s\n", xhp->virtualpkgdir);
while ((dp = readdir(dirp)) != NULL) {
if ((strcmp(dp->d_name, "..") == 0) ||
(strcmp(dp->d_name, ".") == 0))
continue;
/* only process .vpkg files, ignore something else */
if ((ext = strrchr(dp->d_name, '.')) == NULL)
continue;
if (strcmp(ext, ".vpkg") == 0) {
char *path;
path = xbps_xasprintf("%s/%s", xhp->virtualpkgdir, dp->d_name);
if ((rv = parse_file(xhp, path, false, true)) != 0) {
free(path);
break;
}
free(path);
}
}
closedir(dirp);
return rv;
} }
int int
xbps_init(struct xbps_handle *xhp) xbps_init(struct xbps_handle *xhp)
{ {
cfg_opt_t vpkg_opts[] = {
CFG_STR_LIST(__UNCONST("targets"), NULL, CFGF_NONE),
CFG_END()
};
cfg_opt_t opts[] = {
/* Defaults if not set in configuration file */
CFG_STR(__UNCONST("rootdir"), __UNCONST("/"), CFGF_NONE),
CFG_STR(__UNCONST("cachedir"),
__UNCONST(XBPS_CACHE_PATH), CFGF_NONE),
CFG_INT(__UNCONST("FetchCacheConnections"),
XBPS_FETCH_CACHECONN, CFGF_NONE),
CFG_INT(__UNCONST("FetchCacheConnectionsPerHost"),
XBPS_FETCH_CACHECONN_HOST, CFGF_NONE),
CFG_INT(__UNCONST("FetchTimeoutConnection"),
XBPS_FETCH_TIMEOUT, CFGF_NONE),
CFG_BOOL(__UNCONST("syslog"), true, CFGF_NONE),
CFG_STR_LIST(__UNCONST("repositories"), NULL, CFGF_MULTI),
CFG_SEC(__UNCONST("virtual-package"),
vpkg_opts, CFGF_MULTI|CFGF_TITLE),
CFG_FUNC(__UNCONST("include"), &cfg_include),
CFG_END()
};
struct utsname un; struct utsname un;
char *buf; char *buf;
const char *repodir, *native_arch; const char *repodir, *native_arch;
int rv, cc, cch; int rv;
bool syslog_enabled = false;
assert(xhp != NULL); assert(xhp != NULL);
@ -99,39 +272,16 @@ xbps_init(struct xbps_handle *xhp)
xhp->conffile = XBPS_CONF_DEF; xhp->conffile = XBPS_CONF_DEF;
/* parse configuration file */ /* parse configuration file */
xhp->cfg = cfg_init(opts, CFGF_NOCASE); if ((rv = parse_file(xhp, xhp->conffile, false, false)) != 0) {
cfg_set_validate_func(xhp->cfg, "virtual-package", &cb_validate_virtual); xbps_dbg_printf(xhp, "failed to read configuration file %s: %s\n",
xhp->conffile, strerror(rv));
if ((rv = cfg_parse(xhp->cfg, xhp->conffile)) != CFG_SUCCESS) { xbps_dbg_printf(xhp, "Using built-in defaults\n");
if (rv == CFG_FILE_ERROR) { rv = 0;
/*
* Don't error out if config file not found.
* If a default repository is set, use it; otherwise
* use defaults (no repos and no virtual packages).
*/
if (errno != ENOENT)
return rv;
} else if (rv == CFG_PARSE_ERROR) {
/*
* Parser error from configuration file.
*/
return ENOTSUP;
} }
}
xbps_dbg_printf(xhp, "Configuration file: %s\n",
xhp->conffile ? xhp->conffile : "not found");
/* Set rootdir */ /* Set rootdir */
if (xhp->rootdir[0] == '\0') { if (xhp->rootdir[0] == '\0') {
if (xhp->cfg != NULL) {
strlcpy(xhp->rootdir,
cfg_getstr(xhp->cfg, "rootdir"),
sizeof(xhp->rootdir));
} else {
xhp->rootdir[0] = '/'; xhp->rootdir[0] = '/';
xhp->rootdir[1] = '\0'; xhp->rootdir[1] = '\0';
}
} else if (xhp->rootdir[0] != '/') { } else if (xhp->rootdir[0] != '/') {
/* relative path */ /* relative path */
char path[PATH_MAX-1]; char path[PATH_MAX-1];
@ -148,7 +298,7 @@ xbps_init(struct xbps_handle *xhp)
if (xhp->cachedir[0] == '\0') { if (xhp->cachedir[0] == '\0') {
snprintf(xhp->cachedir, sizeof(xhp->cachedir), snprintf(xhp->cachedir, sizeof(xhp->cachedir),
"%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", "%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "",
xhp->cfg ? cfg_getstr(xhp->cfg, "cachedir") : XBPS_CACHE_PATH); XBPS_CACHE_PATH);
} else if (xhp->cachedir[0] != '/') { } else if (xhp->cachedir[0] != '/') {
/* relative path */ /* relative path */
buf = strdup(xhp->cachedir); buf = strdup(xhp->cachedir);
@ -168,6 +318,21 @@ xbps_init(struct xbps_handle *xhp)
"%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", buf); "%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", buf);
free(buf); free(buf);
} }
/* Set virtualpkgdir */
if (xhp->virtualpkgdir[0] == '\0') {
snprintf(xhp->virtualpkgdir, sizeof(xhp->virtualpkgdir),
"%s%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "",
XBPS_VPKG_PATH);
} else if (xhp->virtualpkgdir[0] != '/') {
/* relative path */
buf = strdup(xhp->virtualpkgdir);
snprintf(xhp->virtualpkgdir, sizeof(xhp->virtualpkgdir),
"%s/%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", buf);
free(buf);
}
/* parse virtualpkgdir */
if ((rv = parse_vpkgdir(xhp)))
return rv;
xhp->target_arch = getenv("XBPS_TARGET_ARCH"); xhp->target_arch = getenv("XBPS_TARGET_ARCH");
if ((native_arch = getenv("XBPS_ARCH")) != NULL) { if ((native_arch = getenv("XBPS_ARCH")) != NULL) {
@ -178,44 +343,16 @@ xbps_init(struct xbps_handle *xhp)
} }
assert(xhp->native_arch); assert(xhp->native_arch);
if (xhp->cfg == NULL) { xbps_fetch_set_cache_connection(XBPS_FETCH_CACHECONN, XBPS_FETCH_CACHECONN_HOST);
xhp->flags |= XBPS_FLAG_SYSLOG;
xhp->fetch_timeout = XBPS_FETCH_TIMEOUT;
cc = XBPS_FETCH_CACHECONN;
cch = XBPS_FETCH_CACHECONN_HOST;
} else {
if (cfg_getbool(xhp->cfg, "syslog"))
xhp->flags |= XBPS_FLAG_SYSLOG;
xhp->fetch_timeout = cfg_getint(xhp->cfg, "FetchTimeoutConnection");
cc = cfg_getint(xhp->cfg, "FetchCacheConnections");
cch = cfg_getint(xhp->cfg, "FetchCacheConnectionsPerHost");
}
if (xhp->flags & XBPS_FLAG_SYSLOG)
syslog_enabled = true;
xbps_fetch_set_cache_connection(cc, cch); xbps_dbg_printf(xhp, "rootdir=%s\n", xhp->rootdir);
xbps_dbg_printf(xhp, "metadir=%s\n", xhp->metadir);
xbps_dbg_printf(xhp, "Rootdir=%s\n", xhp->rootdir); xbps_dbg_printf(xhp, "cachedir=%s\n", xhp->cachedir);
xbps_dbg_printf(xhp, "Metadir=%s\n", xhp->metadir); xbps_dbg_printf(xhp, "virtualpkgdir=%s\n", xhp->virtualpkgdir);
xbps_dbg_printf(xhp, "Cachedir=%s\n", xhp->cachedir); xbps_dbg_printf(xhp, "syslog=%s\n", xhp->syslog ? "true" : "false");
xbps_dbg_printf(xhp, "FetchTimeout=%u\n", xhp->fetch_timeout);
xbps_dbg_printf(xhp, "FetchCacheconn=%u\n", cc);
xbps_dbg_printf(xhp, "FetchCacheconnHost=%u\n", cch);
xbps_dbg_printf(xhp, "Syslog=%u\n", syslog_enabled);
xbps_dbg_printf(xhp, "Architecture: %s\n", xhp->native_arch); xbps_dbg_printf(xhp, "Architecture: %s\n", xhp->native_arch);
xbps_dbg_printf(xhp, "Target Architecture: %s\n", xhp->target_arch); xbps_dbg_printf(xhp, "Target Architecture: %s\n", xhp->target_arch);
/*
* Append repository list specified in configuration file.
*/
for (unsigned int i = 0; i < cfg_size(xhp->cfg, "repositories"); i++) {
if (xhp->repositories == NULL)
xhp->repositories = xbps_array_create();
xbps_array_add_cstring_nocopy(xhp->repositories,
cfg_getnstr(xhp->cfg, "repositories", i));
}
if (xhp->flags & XBPS_FLAG_DEBUG) { if (xhp->flags & XBPS_FLAG_DEBUG) {
for (unsigned int i = 0; i < xbps_array_count(xhp->repositories); i++) { for (unsigned int i = 0; i < xbps_array_count(xhp->repositories); i++) {
xbps_array_get_cstring_nocopy(xhp->repositories, i, &repodir); xbps_array_get_cstring_nocopy(xhp->repositories, i, &repodir);
@ -236,7 +373,6 @@ xbps_end(struct xbps_handle *xhp)
xbps_object_release(xhp->pkgdb_revdeps); xbps_object_release(xhp->pkgdb_revdeps);
xbps_fetch_unset_cache_connection(); xbps_fetch_unset_cache_connection();
cfg_free(xhp->cfg);
} }
static void static void

View File

@ -33,10 +33,6 @@
#include "xbps_api_impl.h" #include "xbps_api_impl.h"
#ifndef __arraycount
# define __arraycount(a) (sizeof(a) / sizeof(*(a)))
#endif
static bool static bool
check_remove_pkg_files(struct xbps_handle *xhp, check_remove_pkg_files(struct xbps_handle *xhp,
xbps_dictionary_t pkgd, const char *pkgver) xbps_dictionary_t pkgd, const char *pkgver)

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2008-2013 Juan Romero Pardines. * Copyright (c) 2008-2014 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -34,9 +34,6 @@
#include "xbps_api_impl.h" #include "xbps_api_impl.h"
static pthread_mutex_t cfg_mtx = PTHREAD_MUTEX_INITIALIZER;
static bool cfg_vpkgs_init;
static xbps_dictionary_t static xbps_dictionary_t
get_pkg_in_array(xbps_array_t array, const char *str, bool virtual) get_pkg_in_array(xbps_array_t array, const char *str, bool virtual)
{ {
@ -183,80 +180,29 @@ match_pkg_by_pattern(xbps_dictionary_t repod, const char *p)
return d; return d;
} }
static void
config_inject_vpkgs(struct xbps_handle *xh)
{
DIR *dirp;
struct dirent *dp;
char *ext, *vpkgdir;
FILE *fp;
if (strcmp(xh->rootdir, "/"))
vpkgdir = xbps_xasprintf("%s/etc/xbps/virtualpkg.d",
xh->rootdir);
else
vpkgdir = strdup("/etc/xbps/virtualpkg.d");
if ((dirp = opendir(vpkgdir)) == NULL) {
free(vpkgdir);
return;
}
while ((dp = readdir(dirp)) != NULL) {
if ((strcmp(dp->d_name, "..") == 0) ||
(strcmp(dp->d_name, ".") == 0))
continue;
/* only process .conf files, ignore something else */
if ((ext = strrchr(dp->d_name, '.')) == NULL)
continue;
if (strcmp(ext, ".conf") == 0) {
char *path;
path = xbps_xasprintf("%s/%s", vpkgdir, dp->d_name);
fp = fopen(path, "r");
assert(fp);
if (cfg_parse_fp(xh->cfg, fp) != 0) {
xbps_error_printf("Failed to parse "
"vpkg conf file %s:\n", dp->d_name);
}
fclose(fp);
xbps_dbg_printf(xh, "Injected vpkgs from %s\n", path);
free(path);
}
}
closedir(dirp);
free(vpkgdir);
cfg_vpkgs_init = true;
}
const char HIDDEN * const char HIDDEN *
vpkg_user_conf(struct xbps_handle *xhp, vpkg_user_conf(struct xbps_handle *xhp,
const char *vpkg, const char *vpkg,
bool bypattern) bool bypattern)
{ {
xbps_object_t obj;
xbps_object_iterator_t iter;
xbps_string_t rpkg;
const char *vpkgver, *pkg = NULL; const char *vpkgver, *pkg = NULL;
char *vpkgname = NULL, *tmp; char *vpkgname = NULL, *tmp;
unsigned int cnt;
if (xhp->cfg == NULL) if (xhp->vpkgd == NULL)
return NULL; return NULL;
/* inject virtual packages from sysconfdir */ iter = xbps_dictionary_iterator(xhp->vpkgd);
pthread_mutex_lock(&cfg_mtx); assert(iter);
if (!cfg_vpkgs_init)
config_inject_vpkgs(xhp);
pthread_mutex_unlock(&cfg_mtx);
if ((cnt = cfg_size(xhp->cfg, "virtual-package")) == 0) { while ((obj = xbps_object_iterator_next(iter))) {
/* no virtual packages configured */ vpkgver = xbps_dictionary_keysym_cstring_nocopy(obj);
return NULL; rpkg = xbps_dictionary_get_keysym(xhp->vpkgd, obj);
} pkg = xbps_string_cstring_nocopy(rpkg);
for (unsigned int i = 0; i < cnt; i++) {
cfg_t *sec = cfg_getnsec(xhp->cfg, "virtual-package", i);
for (unsigned int j = 0; j < cfg_size(sec, "targets"); j++) {
tmp = NULL; tmp = NULL;
vpkgver = cfg_getnstr(sec, "targets", j);
if (strchr(vpkgver, '_') == NULL) { if (strchr(vpkgver, '_') == NULL) {
tmp = xbps_xasprintf("%s_1", vpkgver); tmp = xbps_xasprintf("%s_1", vpkgver);
vpkgname = xbps_pkg_name(tmp); vpkgname = xbps_pkg_name(tmp);
@ -277,15 +223,13 @@ vpkg_user_conf(struct xbps_handle *xhp,
continue; continue;
} }
} }
/* virtual package matched in conffile */ xbps_dbg_printf(xhp, "matched vpkg `%s' with `%s (provides %s)`\n",
pkg = cfg_title(sec); vpkg, pkg, vpkgver);
xbps_dbg_printf(xhp,
"matched vpkg in conf `%s' for %s\n",
pkg, vpkg);
free(vpkgname); free(vpkgname);
break; break;
} }
} xbps_object_iterator_release(iter);
return pkg; return pkg;
} }