XBPS Library API  0.19
The X Binary Package System
initend.c
1 /*-
2  * Copyright (c) 2011-2012 Juan Romero Pardines.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <sys/utsname.h>
27 #include <sys/types.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <stdarg.h>
33 #include <dirent.h>
34 
35 #include "xbps_api_impl.h"
36 
37 /**
38  * @file lib/initend.c
39  * @brief Initialization and finalization routines
40  * @defgroup initend Initialization and finalization functions
41  *
42  * Use these functions to initialize some parameters before start
43  * using libxbps and finalize usage to release resources at the end.
44  */
45 static char *
46 set_cachedir(struct xbps_handle *xh)
47 {
48  if (xh->cachedir[0] == '/') {
49  /* full path */
50  return strdup(xh->cachedir);
51  } else {
52  /* relative to rootdir */
53  if (strcmp(xh->rootdir, "/") == 0)
54  return xbps_xasprintf("/%s", xh->cachedir);
55  else
56  return xbps_xasprintf("%s/%s", xh->rootdir,
57  xh->cachedir);
58  }
59 }
60 
61 static char *
62 set_metadir(struct xbps_handle *xh)
63 {
64  if (xh->metadir == NULL) {
65  if (strcmp(xh->rootdir, "/") == 0)
66  return xbps_xasprintf("/%s", XBPS_META_PATH);
67  else
68  return xbps_xasprintf("%s/%s", xh->rootdir, XBPS_META_PATH);
69  } else {
70  return strdup(xh->metadir);
71  }
72 }
73 
74 static void
75 config_inject_vpkgs(struct xbps_handle *xh)
76 {
77  DIR *dirp;
78  struct dirent *dp;
79  char *ext, *vpkgdir;
80  FILE *fp;
81 
82  if (strcmp(xh->rootdir, "/"))
83  vpkgdir = xbps_xasprintf("%s/etc/xbps/virtualpkg.d",
84  xh->rootdir);
85  else
86  vpkgdir = strdup("/etc/xbps/virtualpkg.d");
87 
88  if ((dirp = opendir(vpkgdir)) == NULL) {
89  xbps_dbg_printf(xh, "config: failed to open %s: %s\n",
90  vpkgdir, strerror(errno));
91  return;
92  }
93 
94  while ((dp = readdir(dirp)) != NULL) {
95  if ((strcmp(dp->d_name, "..") == 0) ||
96  (strcmp(dp->d_name, ".") == 0))
97  continue;
98  /* only process .conf files, ignore something else */
99  if ((ext = strrchr(dp->d_name, '.')) == NULL)
100  continue;
101  if (strcmp(ext, ".conf") == 0) {
102  char *path;
103 
104  path = xbps_xasprintf("%s/%s", vpkgdir, dp->d_name);
105  fp = fopen(path, "r");
106  assert(fp);
107  free(path);
108  if (cfg_parse_fp(xh->cfg, fp) != 0) {
109  xbps_error_printf("Failed to parse "
110  "vpkg conf file %s:\n", dp->d_name);
111  }
112  fclose(fp);
113  }
114  }
115  closedir(dirp);
116  free(vpkgdir);
117 }
118 
119 static int
120 cb_validate_virtual(cfg_t *cfg, cfg_opt_t *opt)
121 {
122  unsigned int i;
123 
124  for (i = 0; i < cfg_size(cfg, "virtual-package"); i++) {
125  cfg_t *sec = cfg_opt_getnsec(opt, i);
126  if (cfg_getstr(sec, "targets") == 0) {
127  cfg_error(cfg, "targets must be set for "
128  "virtual-package %s", cfg_title(sec));
129  return -1;
130  }
131  }
132  return 0;
133 }
134 
135 int
136 xbps_init(struct xbps_handle *xhp)
137 {
138  cfg_opt_t vpkg_opts[] = {
139  CFG_STR_LIST(__UNCONST("targets"), NULL, CFGF_NONE),
140  CFG_END()
141  };
142  cfg_opt_t opts[] = {
143  /* Defaults if not set in configuration file */
144  CFG_STR(__UNCONST("rootdir"), __UNCONST("/"), CFGF_NONE),
145  CFG_STR(__UNCONST("cachedir"),
146  __UNCONST(XBPS_CACHE_PATH), CFGF_NONE),
147  CFG_INT(__UNCONST("FetchCacheConnections"),
148  XBPS_FETCH_CACHECONN, CFGF_NONE),
149  CFG_INT(__UNCONST("FetchCacheConnectionsPerHost"),
150  XBPS_FETCH_CACHECONN_HOST, CFGF_NONE),
151  CFG_INT(__UNCONST("FetchTimeoutConnection"),
152  XBPS_FETCH_TIMEOUT, CFGF_NONE),
153  CFG_BOOL(__UNCONST("syslog"), true, CFGF_NONE),
154  CFG_STR_LIST(__UNCONST("repositories"), NULL, CFGF_MULTI),
155  CFG_STR_LIST(__UNCONST("PackagesOnHold"), NULL, CFGF_MULTI),
156  CFG_SEC(__UNCONST("virtual-package"),
157  vpkg_opts, CFGF_MULTI|CFGF_TITLE),
158  CFG_FUNC(__UNCONST("include"), &cfg_include),
159  CFG_END()
160  };
161  struct utsname un;
162  int rv, cc, cch;
163  bool syslog_enabled = false;
164 
165  assert(xhp != NULL);
166 
167  if (xhp->initialized)
168  return 0;
169 
170  if (xhp->conffile == NULL)
171  xhp->conffile = XBPS_CONF_DEF;
172 
173  /* parse configuration file */
174  xhp->cfg = cfg_init(opts, CFGF_NOCASE);
175  cfg_set_validate_func(xhp->cfg, "virtual-package", &cb_validate_virtual);
176 
177  if ((rv = cfg_parse(xhp->cfg, xhp->conffile)) != CFG_SUCCESS) {
178  if (rv == CFG_FILE_ERROR) {
179  /*
180  * Don't error out if config file not found.
181  * If a default repository is set, use it; otherwise
182  * use defaults (no repos and no virtual packages).
183  */
184  if (errno != ENOENT)
185  return rv;
186 
187  xhp->conffile = NULL;
188  if (xhp->repository) {
189  char *buf;
190 
191  buf = xbps_xasprintf("repositories = { %s }",
192  xhp->repository);
193  if ((rv = cfg_parse_buf(xhp->cfg, buf)) != 0)
194  return rv;
195  free(buf);
196  }
197  } else if (rv == CFG_PARSE_ERROR) {
198  /*
199  * Parser error from configuration file.
200  */
201  return ENOTSUP;
202  }
203  }
204 
205  xbps_dbg_printf(xhp, "Configuration file: %s\n",
206  xhp->conffile ? xhp->conffile : "not found");
207  /*
208  * Respect client setting in struct xbps_handle for {root,cache}dir;
209  * otherwise use values from configuration file or defaults if unset.
210  */
211  if (xhp->rootdir == NULL) {
212  if (xhp->cfg == NULL)
213  xhp->rootdir = "/";
214  else
215  xhp->rootdir = cfg_getstr(xhp->cfg, "rootdir");
216  } else {
217  if (xhp->rootdir[0] != '/') {
218  /* relative path */
219  char *buf, path[PATH_MAX-1];
220 
221  if (getcwd(path, sizeof(path)) == NULL)
222  return ENOTSUP;
223 
224  buf = xbps_xasprintf("%s/%s", path, xhp->rootdir);
225  xhp->rootdir = buf;
226  }
227  }
228 
229  if (xhp->cachedir == NULL) {
230  if (xhp->cfg == NULL)
231  xhp->cachedir = XBPS_CACHE_PATH;
232  else
233  xhp->cachedir = cfg_getstr(xhp->cfg, "cachedir");
234  }
235  if ((xhp->cachedir_priv = set_cachedir(xhp)) == NULL)
236  return ENOMEM;
237  xhp->cachedir = xhp->cachedir_priv;
238 
239  if ((xhp->metadir_priv = set_metadir(xhp)) == NULL)
240  return ENOMEM;
241  xhp->metadir = xhp->metadir_priv;
242 
243  uname(&un);
244  xhp->un_machine = strdup(un.machine);
245  assert(xhp->un_machine);
246 
247  if (xhp->cfg == NULL) {
248  xhp->flags |= XBPS_FLAG_SYSLOG;
249  xhp->fetch_timeout = XBPS_FETCH_TIMEOUT;
250  cc = XBPS_FETCH_CACHECONN;
251  cch = XBPS_FETCH_CACHECONN_HOST;
252  } else {
253  if (cfg_getbool(xhp->cfg, "syslog"))
254  xhp->flags |= XBPS_FLAG_SYSLOG;
255  xhp->fetch_timeout = cfg_getint(xhp->cfg, "FetchTimeoutConnection");
256  cc = cfg_getint(xhp->cfg, "FetchCacheConnections");
257  cch = cfg_getint(xhp->cfg, "FetchCacheConnectionsPerHost");
258  }
259  if (xhp->flags & XBPS_FLAG_SYSLOG)
260  syslog_enabled = true;
261 
262  /* Inject virtual packages from virtualpkg.d files */
263  config_inject_vpkgs(xhp);
264 
265  xbps_fetch_set_cache_connection(cc, cch);
266 
267  xbps_dbg_printf(xhp, "Rootdir=%s\n", xhp->rootdir);
268  xbps_dbg_printf(xhp, "Metadir=%s\n", xhp->metadir);
269  xbps_dbg_printf(xhp, "Cachedir=%s\n", xhp->cachedir);
270  xbps_dbg_printf(xhp, "FetchTimeout=%u\n", xhp->fetch_timeout);
271  xbps_dbg_printf(xhp, "FetchCacheconn=%u\n", cc);
272  xbps_dbg_printf(xhp, "FetchCacheconnHost=%u\n", cch);
273  xbps_dbg_printf(xhp, "Syslog=%u\n", syslog_enabled);
274  xbps_dbg_printf(xhp, "Architecture: %s\n", xhp->un_machine);
275 
276  xhp->initialized = true;
277 
278  return 0;
279 }
280 
281 void
282 xbps_end(struct xbps_handle *xhp)
283 {
284  assert(xhp);
285 
286  if (!xhp->initialized)
287  return;
288 
289  xbps_pkgdb_release(xhp);
290  xbps_rpool_release(xhp);
291  xbps_fetch_unset_cache_connection();
292  if (xhp->pkgdb_revdeps != NULL)
293  prop_object_release(xhp->pkgdb_revdeps);
294 
295  cfg_free(xhp->cfg);
296  free(xhp->cachedir_priv);
297  free(xhp->metadir_priv);
298  free(xhp->un_machine);
299 
300  xhp->initialized = false;
301  xhp = NULL;
302 }
303 
304 static void
305 common_printf(FILE *f, const char *msg, const char *fmt, va_list ap)
306 {
307  if (msg != NULL)
308  fprintf(f, "%s", msg);
309 
310  vfprintf(f, fmt, ap);
311 }
312 
313 void
314 xbps_dbg_printf_append(struct xbps_handle *xhp, const char *fmt, ...)
315 {
316  va_list ap;
317 
318  if ((xhp->flags & XBPS_FLAG_DEBUG) == 0)
319  return;
320 
321  va_start(ap, fmt);
322  common_printf(stderr, NULL, fmt, ap);
323  va_end(ap);
324 }
325 
326 void
327 xbps_dbg_printf(struct xbps_handle *xhp, const char *fmt, ...)
328 {
329  va_list ap;
330 
331  if ((xhp->flags & XBPS_FLAG_DEBUG) == 0)
332  return;
333 
334  va_start(ap, fmt);
335  common_printf(stderr, "[DEBUG] ", fmt, ap);
336  va_end(ap);
337 }
338 
339 void
340 xbps_error_printf(const char *fmt, ...)
341 {
342  va_list ap;
343 
344  va_start(ap, fmt);
345  common_printf(stderr, "ERROR: ", fmt, ap);
346  va_end(ap);
347 }
348 
349 void
350 xbps_warn_printf(const char *fmt, ...)
351 {
352  va_list ap;
353 
354  va_start(ap, fmt);
355  common_printf(stderr, "WARNING: ", fmt, ap);
356  va_end(ap);
357 }