diff --git a/include/xbps.h.in b/include/xbps.h.in index 44e183d0..19e852db 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -594,6 +594,12 @@ struct xbps_handle { * Full path to the xbps configuration directory. */ char confdir[XBPS_MAXPATH+sizeof(XBPS_SYSCONF_PATH)]; + /** + * @var confdir + * + * Full path to the xbps configuration directory. + */ + char sysconfdir[XBPS_MAXPATH+sizeof(XBPS_SYSDEFCONF_PATH)]; /** * @var rootdir * diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 666c94af..27609079 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -155,5 +155,6 @@ xbps_array_t HIDDEN xbps_get_pkg_fulldeptree(struct xbps_handle *, const char *, bool); struct xbps_repo HIDDEN *xbps_regget_repo(struct xbps_handle *, const char *); +int HIDDEN xbps_conf_init(struct xbps_handle *); #endif /* !_XBPS_API_IMPL_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 6619cfba..d1afb299 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -44,6 +44,7 @@ OBJS += plist_remove.o plist_fetch.o util.o util_hash.o OBJS += repo.o repo_pkgdeps.o repo_sync.o OBJS += rpool.o cb_util.o proplib_wrapper.o OBJS += package_alternatives.o +OBJS += conf.o log.o OBJS += $(EXTOBJS) $(COMPAT_OBJS) .PHONY: all diff --git a/lib/conf.c b/lib/conf.c new file mode 100644 index 00000000..ad51f87e --- /dev/null +++ b/lib/conf.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2011-2015 Juan Romero Pardines. + * Copyright (c) 2014 Enno Boland. + * Copyright (c) 2019 Duncan Overbruck . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifdef __FreeBSD__ +#define _WITH_GETLINE /* getline() */ +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xbps_api_impl.h" + +/** + * @file lib/conf.c + * @brief Configuration parsing + * @defgroup conf Configuration parsing + * + * Functions for parsing xbps configuration files. + */ + +static void +store_vars(struct xbps_handle *xhp, xbps_dictionary_t *d, + const char *key, const char *path, size_t line, char *buf) +{ + char *lp, *rp, *tc; + size_t len; + + if (*d == NULL) + *d = xbps_dictionary_create(); + if (xhp->vpkgd_conf) + xhp->vpkgd_conf = xbps_dictionary_create(); + + /* + * Parse strings delimited by ':' i.e + * : + */ + lp = buf; + rp = strchr(buf, ':'); + if (rp == NULL || *rp == '\0') { + xbps_dbg_printf(xhp, "%s: ignoring invalid " + "%s option at line %zu\n", path, key, line); + return; + } + tc = strchr(buf, ':'); + len = strlen(buf) - strlen(tc); + lp[len] = '\0'; + + rp++; + xbps_dictionary_set_cstring(*d, lp, rp); + xbps_dictionary_set_cstring(xhp->vpkgd_conf, lp, rp); + xbps_dbg_printf(xhp, "%s: added %s %s for %s\n", path, key, lp, rp); +} + +static void +store_preserved_file(struct xbps_handle *xhp, const char *file) +{ + glob_t globbuf; + char *p = NULL, *rfile = NULL; + size_t len; + int rv = 0; + + if (xhp->preserved_files == NULL) { + xhp->preserved_files = xbps_array_create(); + assert(xhp->preserved_files); + } + + rfile = xbps_xasprintf("%s%s", xhp->rootdir, file); + + rv = glob(rfile, 0, NULL, &globbuf); + if (rv == GLOB_NOMATCH) { + if (xbps_match_string_in_array(xhp->preserved_files, file)) + goto out; + xbps_array_add_cstring(xhp->preserved_files, file); + xbps_dbg_printf(xhp, "Added preserved file: %s\n", file); + goto out; + } else if (rv != 0) { + goto out; + } + for (size_t i = 0; i < globbuf.gl_pathc; i++) { + if (xbps_match_string_in_array(xhp->preserved_files, globbuf.gl_pathv[i])) + continue; + + len = strlen(globbuf.gl_pathv[i]) - strlen(xhp->rootdir) + 1; + p = malloc(len); + assert(p); + xbps_strlcpy(p, globbuf.gl_pathv[i] + strlen(xhp->rootdir), len); + xbps_array_add_cstring(xhp->preserved_files, p); + xbps_dbg_printf(xhp, "Added preserved file: %s (expanded from %s)\n", p, file); + free(p); + } +out: + globfree(&globbuf); + free(rfile); +} + +static bool +store_repo(struct xbps_handle *xhp, const char *repo) +{ + if (xhp->flags & XBPS_FLAG_IGNORE_CONF_REPOS) + return false; + + return xbps_repo_store(xhp, repo); +} + +static void +store_ignored_pkg(struct xbps_handle *xhp, const char *pkgname) +{ + if (xhp->ignored_pkgs == NULL) { + xhp->ignored_pkgs = xbps_array_create(); + assert(xhp->ignored_pkgs); + } + xbps_array_add_cstring(xhp->ignored_pkgs, pkgname); + xbps_dbg_printf(xhp, "Added ignored package: %s\n", pkgname); +} + +enum { + KEY_ERROR = 0, + KEY_ARCHITECTURE, + KEY_BESTMATCHING, + KEY_CACHEDIR, + KEY_IGNOREPKG, + KEY_INCLUDE, + KEY_PRESERVE, + KEY_REPOSITORY, + KEY_ROOTDIR, + KEY_SYSLOG, + KEY_VIRTUALPKG, +}; + +static const struct key { + const char *str; + size_t len; + int key; +} keys[] = { + { "architecture", 12, KEY_ARCHITECTURE }, + { "bestmatching", 12, KEY_BESTMATCHING }, + { "cachedir", 8, KEY_CACHEDIR }, + { "ignorepkg", 9, KEY_IGNOREPKG }, + { "include", 7, KEY_INCLUDE }, + { "preserve", 8, KEY_PRESERVE }, + { "repository", 10, KEY_REPOSITORY }, + { "rootdir", 7, KEY_ROOTDIR }, + { "syslog", 6, KEY_SYSLOG }, + { "virtualpkg", 10, KEY_VIRTUALPKG }, +}; + +static int +parse_option(char *buf, const char **keyp, char **valp) +{ + size_t klen; + const char *key; + char *value; + int k = 0; + + for (unsigned int i = 0; i < __arraycount(keys); i++) { + key = keys[i].str; + klen = keys[i].len; + if (strncmp(buf, key, klen) == 0) { + k = keys[i].key; + break; + } + } + /* non matching option */ + if (k == 0) + return 0; + + /* check if next char is the equal sign */ + if (buf[klen] != '=') + return 0; + + /* 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 */ + *keyp = key; + *valp = value; + + return k; +} + +static int parse_file(struct xbps_handle *, const char *, bool); + +static int +parse_files_glob(struct xbps_handle *xhp, xbps_dictionary_t seen, + const char *path, const char *pat, bool nested) +{ + char tmppath[PATH_MAX]; + glob_t globbuf; + int rs, rv = 0; + + rs = snprintf(tmppath, PATH_MAX, "%s/%s", path, pat); + if (rs < 0 || rs >= PATH_MAX) + return ENOMEM; + + switch (glob(tmppath, 0, NULL, &globbuf)) { + case GLOB_ABORTED: return ENOMEM; + case GLOB_NOSPACE: return EIO; + case GLOB_NOMATCH: return 0; + } + for (size_t i = 0; i < globbuf.gl_pathc; i++) { + if (seen != NULL) { + const char *fname; + bool mask = false; + fname = basename(globbuf.gl_pathv[i]); + if (xbps_dictionary_get_bool(seen, fname, &mask) && mask) + continue; + xbps_dictionary_set_bool(seen, fname, true); + } + if ((rv = parse_file(xhp, globbuf.gl_pathv[i], nested)) != 0) + break; + } + globfree(&globbuf); + + return rv; +} + +static int +parse_file(struct xbps_handle *xhp, const char *path, bool nested) +{ + FILE *fp; + size_t len, nlines = 0; + ssize_t nread; + char *line = NULL; + int rv = 0; + int size, rs; + char *dir; + + if ((fp = fopen(path, "r")) == NULL) { + rv = errno; + xbps_dbg_printf(xhp, "cannot read configuration file %s: %s\n", path, strerror(rv)); + return rv; + } + + xbps_dbg_printf(xhp, "Parsing configuration file: %s\n", path); + + while (rv == 0 && (nread = getline(&line, &len, fp)) != -1) { + const char *key; + char *p, *val; + + nlines++; + p = line; + + /* eat blanks */ + while (isblank((unsigned char)*p)) + p++; + + /* ignore comments or empty lines */ + if (*p == '#' || *p == '\n') + continue; + + switch (parse_option(p, &key, &val)) { + case KEY_ERROR: + xbps_dbg_printf(xhp, "%s: ignoring invalid option at " + "line %zu\n", path, nlines); + continue; + case KEY_ROOTDIR: + size = sizeof xhp->rootdir; + rs = snprintf(xhp->rootdir, size, "%s", val); + if (rs < 0 || rs >= size) { + rv = ENOMEM; + break; + } + xbps_dbg_printf(xhp, "%s: rootdir set to %s\n", path, val); + break; + case KEY_CACHEDIR: + size = sizeof xhp->cachedir; + rs = snprintf(xhp->cachedir, size, "%s", val); + if (rs < 0 || rs >= size) { + rv = ENOMEM; + break; + } + xbps_dbg_printf(xhp, "%s: cachedir set to %s\n", path, val); + break; + case KEY_ARCHITECTURE: + size = sizeof xhp->native_arch; + rs = snprintf(xhp->native_arch, size, "%s", val); + if (rs < 0 || rs >= size) { + rv = ENOMEM; + break; + } + xbps_dbg_printf(xhp, "%s: native architecture set to %s\n", path, + val); + break; + case KEY_SYSLOG: + if (strcasecmp(val, "true") == 0) { + xhp->flags &= ~XBPS_FLAG_DISABLE_SYSLOG; + xbps_dbg_printf(xhp, "%s: syslog enabled\n", path); + } else { + xhp->flags |= XBPS_FLAG_DISABLE_SYSLOG; + xbps_dbg_printf(xhp, "%s: syslog disabled\n", path); + } + break; + case KEY_REPOSITORY: + if (store_repo(xhp, val)) + xbps_dbg_printf(xhp, "%s: added repository %s\n", path, val); + break; + case KEY_VIRTUALPKG: + store_vars(xhp, &xhp->vpkgd, key, path, nlines, val); + break; + case KEY_PRESERVE: + store_preserved_file(xhp, val); + break; + case KEY_BESTMATCHING: + if (strcasecmp(val, "true") == 0) { + xhp->flags |= XBPS_FLAG_BESTMATCH; + xbps_dbg_printf(xhp, "%s: pkg best matching enabled\n", path); + } else { + xhp->flags &= ~XBPS_FLAG_BESTMATCH; + xbps_dbg_printf(xhp, "%s: pkg best matching disabled\n", path); + } + break; + case KEY_IGNOREPKG: + store_ignored_pkg(xhp, val); + break; + case KEY_INCLUDE: + /* Avoid double-nested parsing, only allow it once */ + if (nested) { + xbps_dbg_printf(xhp, "%s: ignoring nested include\n", path); + continue; + } + dir = strdup(path); + if ((rv = parse_files_glob(xhp, NULL, dirname(dir), val, true)) != 0) { + free(dir); + break; + } + free(dir); + break; + } + } + free(line); + fclose(fp); + + return rv; +} + +int HIDDEN +xbps_conf_init(struct xbps_handle *xhp) +{ + xbps_dictionary_t seen; + int rv = 0; + + assert(xhp); + seen = xbps_dictionary_create(); + assert(seen); + + if (*xhp->confdir) { + xbps_dbg_printf(xhp, "Processing configuration directory: %s\n", xhp->confdir); + if ((rv = parse_files_glob(xhp, seen, xhp->confdir, "*.conf", false))) + goto out; + } + if (*xhp->sysconfdir) { + xbps_dbg_printf(xhp, "Processing system configuration directory: %s\n", xhp->sysconfdir); + if ((rv = parse_files_glob(xhp, seen, xhp->sysconfdir, "*.conf", false))) + goto out; + } + +out: + xbps_object_release(seen); + return rv; +} diff --git a/lib/initend.c b/lib/initend.c index f3ee9aa9..17a4d3b6 100644 --- a/lib/initend.c +++ b/lib/initend.c @@ -25,29 +25,12 @@ */ #include -#include -#ifdef __FreeBSD__ -#define _WITH_GETLINE /* getline() */ -#endif -#include #include #include -#include #include -#include -#include -#include -#include -#include #include "xbps_api_impl.h" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wformat-nonliteral" -#endif - -static int parse_file(struct xbps_handle *, const char *, const char *, bool); - /** * @file lib/initend.c * @brief Initialization and finalization routines @@ -57,376 +40,25 @@ static int parse_file(struct xbps_handle *, const char *, const char *, bool); * using libxbps and finalize usage to release resources at the end. */ -static void -store_vars(struct xbps_handle *xhp, xbps_dictionary_t *d, - const char *key, const char *path, size_t line, char *buf) -{ - char *lp, *rp, *tc; - size_t len; - - if (*d == NULL) - *d = xbps_dictionary_create(); - if (xhp->vpkgd_conf) - xhp->vpkgd_conf = xbps_dictionary_create(); - - /* - * Parse strings delimited by ':' i.e - * : - */ - lp = buf; - rp = strchr(buf, ':'); - if (rp == NULL || *rp == '\0') { - xbps_dbg_printf(xhp, "%s: ignoring invalid " - "%s option at line %zu\n", path, key, line); - return; - } - tc = strchr(buf, ':'); - len = strlen(buf) - strlen(tc); - lp[len] = '\0'; - - rp++; - xbps_dictionary_set_cstring(*d, lp, rp); - xbps_dictionary_set_cstring(xhp->vpkgd_conf, lp, rp); - xbps_dbg_printf(xhp, "%s: added %s %s for %s\n", path, key, lp, rp); -} - -static void -store_preserved_file(struct xbps_handle *xhp, const char *file) -{ - glob_t globbuf; - char *p = NULL, *rfile = NULL; - size_t len; - int rv = 0; - - if (xhp->preserved_files == NULL) { - xhp->preserved_files = xbps_array_create(); - assert(xhp->preserved_files); - } - - rfile = xbps_xasprintf("%s%s", xhp->rootdir, file); - - rv = glob(rfile, 0, NULL, &globbuf); - if (rv == GLOB_NOMATCH) { - if (xbps_match_string_in_array(xhp->preserved_files, file)) - goto out; - xbps_array_add_cstring(xhp->preserved_files, file); - xbps_dbg_printf(xhp, "Added preserved file: %s\n", file); - goto out; - } else if (rv != 0) { - goto out; - } - for (size_t i = 0; i < globbuf.gl_pathc; i++) { - if (xbps_match_string_in_array(xhp->preserved_files, globbuf.gl_pathv[i])) - continue; - - len = strlen(globbuf.gl_pathv[i]) - strlen(xhp->rootdir) + 1; - p = malloc(len); - assert(p); - xbps_strlcpy(p, globbuf.gl_pathv[i] + strlen(xhp->rootdir), len); - xbps_array_add_cstring(xhp->preserved_files, p); - xbps_dbg_printf(xhp, "Added preserved file: %s (expanded from %s)\n", p, file); - free(p); - } -out: - globfree(&globbuf); - free(rfile); -} - -static bool -store_repo(struct xbps_handle *xhp, const char *repo) -{ - if (xhp->flags & XBPS_FLAG_IGNORE_CONF_REPOS) - return false; - - return xbps_repo_store(xhp, repo); -} - -static void -store_ignored_pkg(struct xbps_handle *xhp, const char *pkgname) -{ - if (xhp->ignored_pkgs == NULL) { - xhp->ignored_pkgs = xbps_array_create(); - assert(xhp->ignored_pkgs); - } - xbps_array_add_cstring(xhp->ignored_pkgs, pkgname); - xbps_dbg_printf(xhp, "Added ignored package: %s\n", pkgname); -} - -static bool -parse_option(char *buf, char **k, char **v) -{ - size_t klen; - char *key, *value; - const char *keys[] = { - "rootdir", - "cachedir", - "syslog", - "repository", - "virtualpkg", - "include", - "ignorepkg", - "preserve", - "bestmatching", - "architecture" - }; - 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_files_glob(struct xbps_handle *xhp, const char *cwd, const char *path, bool nested) -{ - glob_t globbuf; - int rv = 0; - - glob(path, 0, NULL, &globbuf); - for (size_t i = 0; i < globbuf.gl_pathc; i++) { - if ((rv = parse_file(xhp, cwd, globbuf.gl_pathv[i], nested)) != 0) - break; - } - globfree(&globbuf); - - return rv; -} - -static int -parse_file(struct xbps_handle *xhp, const char *cwd, const char *path, bool nested) -{ - FILE *fp; - char tmppath[XBPS_MAXPATH] = {0}; - size_t len, nlines = 0; - ssize_t nread; - char *cfcwd, *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; - } - - xbps_dbg_printf(xhp, "Parsing configuration file: %s\n", path); - - while ((nread = 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, "architecture") == 0) { - xbps_dbg_printf(xhp, "%s: native architecture set to %s\n", - path, v); - snprintf(xhp->native_arch, sizeof(xhp->native_arch), "%s", v); - } else if (strcmp(k, "syslog") == 0) { - if (strcasecmp(v, "true") == 0) { - xhp->flags &= ~XBPS_FLAG_DISABLE_SYSLOG; - xbps_dbg_printf(xhp, "%s: syslog enabled\n", path); - } else { - xhp->flags |= XBPS_FLAG_DISABLE_SYSLOG; - xbps_dbg_printf(xhp, "%s: syslog disabled\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_vars(xhp, &xhp->vpkgd, k, path, nlines, v); - } else if (strcmp(k, "ignorepkg") == 0) { - store_ignored_pkg(xhp, v); - } else if (strcmp(k, "preserve") == 0) { - store_preserved_file(xhp, v); - } else if (strcmp(k, "bestmatching") == 0) { - if (strcasecmp(v, "true") == 0) { - xhp->flags |= XBPS_FLAG_BESTMATCH; - xbps_dbg_printf(xhp, "%s: pkg best matching enabled\n", path); - } else { - xhp->flags &= ~XBPS_FLAG_BESTMATCH; - xbps_dbg_printf(xhp, "%s: pkg best matching disabled\n", path); - } - xbps_dbg_printf(xhp, "%s: enabling pkg best matching\n", path); - } - /* Avoid double-nested parsing, only allow it once */ - if (nested) - continue; - - if (strcmp(k, "include")) - continue; - - /* cwd to the dir containing the config file */ - xbps_strlcpy(tmppath, path, sizeof(tmppath)); - cfcwd = dirname(tmppath); - if (chdir(cfcwd) == -1) { - rv = errno; - xbps_dbg_printf(xhp, "cannot chdir to %s: %s\n", cfcwd, strerror(rv)); - return rv; - } - if ((rv = parse_files_glob(xhp, cwd, v, true)) != 0) - break; - - } - free(line); - fclose(fp); - - return rv; -} - -static int -parse_dir(struct xbps_handle *xhp, const char *cwd, const char *confdir, const char *sysconfdir) -{ - struct dirent **namelist; - char *ext, conf[PATH_MAX]; - int i, n, rv = 0; - - if (confdir == NULL) - goto stage2; - /* - * Read all configuration files stored in the system - * foo.d directory. - */ - xbps_dbg_printf(xhp, "Processing configuration directory: %s\n", confdir); - - if ((n = scandir(confdir, &namelist, 0, alphasort)) < 0) - goto stage2; - - for (i = 0; i < n; i++) { - if ((strcmp(namelist[i]->d_name, "..") == 0) || - (strcmp(namelist[i]->d_name, ".") == 0)) { - free(namelist[i]); - continue; - } - /* only process .conf files, ignore something else */ - if ((ext = strrchr(namelist[i]->d_name, '.')) == NULL) { - free(namelist[i]); - continue; - } - if (strcmp(ext, ".conf")) { - xbps_dbg_printf(xhp, "%s: ignoring %s\n", confdir, namelist[i]->d_name); - free(namelist[i]); - continue; - } - /* parse conf file */ - snprintf(conf, sizeof(conf), "%s/%s", confdir, namelist[i]->d_name); - if ((rv = parse_file(xhp, cwd, conf, false)) != 0) { - free(namelist[i]); - break; - } - } - free(namelist); - if (rv != 0) - return rv; - -stage2: - if (sysconfdir == NULL) - return rv; - - /* - * Read all configuration files stored in the configuration foo.d directory. - */ - xbps_dbg_printf(xhp, "Processing system configuration directory: %s\n", sysconfdir); - - if ((n = scandir(sysconfdir, &namelist, 0, alphasort)) < 0) - return 0; - - for (i = 0; i < n; i++) { - if ((strcmp(namelist[i]->d_name, "..") == 0) || - (strcmp(namelist[i]->d_name, ".") == 0)) { - free(namelist[i]); - continue; - } - /* only process .conf files, ignore something else */ - if ((ext = strrchr(namelist[i]->d_name, '.')) == NULL) { - free(namelist[i]); - continue; - } - if (strcmp(ext, ".conf")) { - xbps_dbg_printf(xhp, "%s: ignoring %s\n", sysconfdir, namelist[i]->d_name); - free(namelist[i]); - continue; - } - /* if the same file exists in configuration directory, ignore it */ - snprintf(conf, sizeof(conf), "%s/%s", confdir, namelist[i]->d_name); - if (access(conf, R_OK) == 0) { - xbps_dbg_printf(xhp, "%s: ignoring %s (exists in confdir)\n", confdir, namelist[i]->d_name); - free(namelist[i]); - continue; - } - /* parse conf file */ - snprintf(conf, sizeof(conf), "%s/%s", sysconfdir, namelist[i]->d_name); - if ((rv = parse_file(xhp, cwd, conf, false)) != 0) { - free(namelist[i]); - break; - } - } - free(namelist); - - return rv; -} - int xbps_init(struct xbps_handle *xhp) { - struct utsname un; - char cwd[PATH_MAX-1], sysconfdir[XBPS_MAXPATH+sizeof(XBPS_SYSDEFCONF_PATH)], *buf; + char *buf; const char *repodir, *native_arch; int rv; size_t size; assert(xhp != NULL); - /* get cwd */ - if (getcwd(cwd, sizeof(cwd)) == NULL) - return ENOTSUP; - /* Set rootdir */ if (xhp->rootdir[0] == '\0') { xhp->rootdir[0] = '/'; xhp->rootdir[1] = '\0'; } else if (xhp->rootdir[0] != '/') { + char cwd[PATH_MAX-1]; + /* get cwd */ + if (getcwd(cwd, sizeof(cwd)) == NULL) + return ENOTSUP; buf = strdup(xhp->rootdir); if (!buf) return ENOMEM; @@ -436,7 +68,9 @@ xbps_init(struct xbps_handle *xhp) if (rv < 0 || (size_t)rv >= size) return 1; } + xbps_dbg_printf(xhp, "%s\n", XBPS_RELVER); + /* set confdir */ if (xhp->confdir[0] == '\0') { size = sizeof(xhp->confdir); @@ -457,27 +91,33 @@ xbps_init(struct xbps_handle *xhp) if (rv < 0 || (size_t)rv >= size) return 1; } - /* set sysconfdir */ - size = sizeof(sysconfdir); - rv = snprintf(sysconfdir, size, - "%s%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", - XBPS_SYSDEFCONF_PATH); - if (rv < 0 || (size_t)rv >= size) - return 1; + /* set sysconfdir */ + if (xhp->sysconfdir[0] == '\0') { + size = sizeof(xhp->sysconfdir); + snprintf(xhp->sysconfdir, size, + "%s%s", strcmp(xhp->rootdir, "/") ? xhp->rootdir : "", + XBPS_SYSDEFCONF_PATH); + if (rv < 0 || (size_t)rv >= size) + return 1; + } + + /* set architecture and target architecture */ xhp->target_arch = getenv("XBPS_TARGET_ARCH"); if ((native_arch = getenv("XBPS_ARCH")) != NULL) { - xbps_strlcpy(xhp->native_arch, native_arch, sizeof(xhp->native_arch)); + xbps_strlcpy(xhp->native_arch, native_arch, sizeof (xhp->native_arch)); } else { - uname(&un); - xbps_strlcpy(xhp->native_arch, un.machine, sizeof(xhp->native_arch)); + struct utsname un; + if (uname(&un) == -1) + return ENOTSUP; + xbps_strlcpy(xhp->native_arch, un.machine, sizeof (xhp->native_arch)); } assert(xhp->native_arch); xbps_fetch_set_cache_connection(XBPS_FETCH_CACHECONN, XBPS_FETCH_CACHECONN_HOST); - /* process xbps.d */ - if ((rv = parse_dir(xhp, cwd, xhp->confdir, sysconfdir)) != 0) + /* process xbps.d directories */ + if ((rv = xbps_conf_init(xhp)) != 0) return rv; /* Set cachedir */ @@ -525,7 +165,7 @@ xbps_init(struct xbps_handle *xhp) xbps_dbg_printf(xhp, "metadir=%s\n", xhp->metadir); xbps_dbg_printf(xhp, "cachedir=%s\n", xhp->cachedir); xbps_dbg_printf(xhp, "confdir=%s\n", xhp->confdir); - xbps_dbg_printf(xhp, "sysconfdir=%s\n", sysconfdir); + xbps_dbg_printf(xhp, "sysconfdir=%s\n", xhp->sysconfdir); xbps_dbg_printf(xhp, "syslog=%s\n", xhp->flags & XBPS_FLAG_DISABLE_SYSLOG ? "false" : "true"); xbps_dbg_printf(xhp, "bestmatching=%s\n", xhp->flags & XBPS_FLAG_BESTMATCH ? "true" : "false"); xbps_dbg_printf(xhp, "Architecture: %s\n", xhp->native_arch); @@ -537,11 +177,7 @@ xbps_init(struct xbps_handle *xhp) xbps_dbg_printf(xhp, "Repository[%u]=%s\n", i, repodir); } } - /* Going back to old working directory */ - if (chdir(cwd) == -1) { - xbps_dbg_printf(xhp, "%s: cannot chdir to %s: %s\n", - __func__, cwd, strerror(errno)); - } + return 0; } @@ -552,58 +188,3 @@ xbps_end(struct xbps_handle *xhp) xbps_pkgdb_release(xhp); } - -static void -common_printf(FILE *f, const char *msg, const char *fmt, va_list ap) -{ - if (msg != NULL) - fprintf(f, "%s", msg); - - vfprintf(f, fmt, ap); -} - -void -xbps_dbg_printf_append(struct xbps_handle *xhp, const char *fmt, ...) -{ - va_list ap; - - if ((xhp->flags & XBPS_FLAG_DEBUG) == 0) - return; - - va_start(ap, fmt); - common_printf(stderr, NULL, fmt, ap); - va_end(ap); -} - -void -xbps_dbg_printf(struct xbps_handle *xhp, const char *fmt, ...) -{ - va_list ap; - - if ((xhp->flags & XBPS_FLAG_DEBUG) == 0) - return; - - va_start(ap, fmt); - common_printf(stderr, "[DEBUG] ", fmt, ap); - va_end(ap); -} - -void -xbps_error_printf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - common_printf(stderr, "ERROR: ", fmt, ap); - va_end(ap); -} - -void -xbps_warn_printf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - common_printf(stderr, "WARNING: ", fmt, ap); - va_end(ap); -} diff --git a/lib/log.c b/lib/log.c new file mode 100644 index 00000000..82c967bc --- /dev/null +++ b/lib/log.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2011-2015 Juan Romero Pardines. + * Copyright (c) 2014 Enno Boland. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "xbps_api_impl.h" + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wformat-nonliteral" +#endif + +/** + * @file lib/log.c + * @brief Logging functions + * @defgroup log Logging functions + * + * Use these functions to log errors, warnings and debug messages. + */ + +static void +common_printf(FILE *f, const char *msg, const char *fmt, va_list ap) +{ + if (msg != NULL) + fprintf(f, "%s", msg); + + vfprintf(f, fmt, ap); +} + +void +xbps_dbg_printf_append(struct xbps_handle *xhp, const char *fmt, ...) +{ + va_list ap; + + if ((xhp->flags & XBPS_FLAG_DEBUG) == 0) + return; + + va_start(ap, fmt); + common_printf(stderr, NULL, fmt, ap); + va_end(ap); +} + +void +xbps_dbg_printf(struct xbps_handle *xhp, const char *fmt, ...) +{ + va_list ap; + + if ((xhp->flags & XBPS_FLAG_DEBUG) == 0) + return; + + va_start(ap, fmt); + common_printf(stderr, "[DEBUG] ", fmt, ap); + va_end(ap); +} + +void +xbps_error_printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + common_printf(stderr, "ERROR: ", fmt, ap); + va_end(ap); +} + +void +xbps_warn_printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + common_printf(stderr, "WARNING: ", fmt, ap); + va_end(ap); +} diff --git a/tests/xbps/libxbps/config/main.c b/tests/xbps/libxbps/config/main.c index 401a6896..495f6969 100644 --- a/tests/xbps/libxbps/config/main.c +++ b/tests/xbps/libxbps/config/main.c @@ -120,10 +120,65 @@ ATF_TC_BODY(config_include_nomatch_test, tc) ATF_REQUIRE_EQ(xbps_array_count(xh.repositories), 0); } +ATF_TC(config_masking); +ATF_TC_HEAD(config_masking, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test file masking"); +} + +ATF_TC_BODY(config_masking, tc) +{ + struct xbps_handle xh; + const char *tcsdir, *repo; + char *buf, *buf2, pwd[PATH_MAX]; + int ret; + + /* get test source dir */ + tcsdir = atf_tc_get_config_var(tc, "srcdir"); + + memset(&xh, 0, sizeof(xh)); + buf = getcwd(pwd, sizeof(pwd)); + + xbps_strlcpy(xh.rootdir, tcsdir, sizeof(xh.rootdir)); + xbps_strlcpy(xh.metadir, tcsdir, sizeof(xh.metadir)); + ret = snprintf(xh.confdir, sizeof(xh.confdir), "%s/xbps.d", pwd); + ATF_REQUIRE_EQ((ret >= 0), 1); + ATF_REQUIRE_EQ(((size_t)ret < sizeof(xh.confdir)), 1); + ret = snprintf(xh.sysconfdir, sizeof(xh.sysconfdir), "%s/sys-xbps.d", pwd); + ATF_REQUIRE_EQ((ret >= 0), 1); + ATF_REQUIRE_EQ(((size_t)ret < sizeof(xh.sysconfdir)), 1); + + ATF_REQUIRE_EQ(xbps_mkpath(xh.confdir, 0755), 0); + ATF_REQUIRE_EQ(xbps_mkpath(xh.sysconfdir, 0755), 0); + + buf = xbps_xasprintf("%s/1.include.cf", tcsdir); + buf2 = xbps_xasprintf("%s/xbps.d/repo.conf", pwd); + ATF_REQUIRE_EQ(symlink(buf, buf2), 0); + free(buf); + free(buf2); + + buf = xbps_xasprintf("%s/2.include.cf", tcsdir); + buf2 = xbps_xasprintf("%s/sys-xbps.d/repo.conf", pwd); + ATF_REQUIRE_EQ(symlink(buf, buf2), 0); + free(buf); + free(buf2); + + xh.flags = XBPS_FLAG_DEBUG; + ATF_REQUIRE_EQ(xbps_init(&xh), 0); + + /* should contain one repository */ + ATF_REQUIRE_EQ(xbps_array_count(xh.repositories), 1); + + /* should contain repository=1 */ + ATF_REQUIRE_EQ(xbps_array_get_cstring_nocopy(xh.repositories, 0, &repo), true); + ATF_REQUIRE_STREQ(repo, "1"); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, config_include_test); ATF_TP_ADD_TC(tp, config_include_nomatch_test); + ATF_TP_ADD_TC(tp, config_masking); return atf_no_error(); }