Move important information up in -Si output
[pacman-ng.git] / lib / libalpm / handle.c
blob816162bd33fed895b2c2f0f31475890bdf11c65f
1 /*
2 * handle.c
4 * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
5 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
6 * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
7 * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <limits.h>
27 #include <sys/types.h>
28 #include <syslog.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
32 /* libalpm */
33 #include "handle.h"
34 #include "alpm_list.h"
35 #include "util.h"
36 #include "log.h"
37 #include "delta.h"
38 #include "trans.h"
39 #include "alpm.h"
41 alpm_handle_t *_alpm_handle_new(void)
43 alpm_handle_t *handle;
45 CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL);
46 handle->deltaratio = 0.0;
48 return handle;
51 void _alpm_handle_free(alpm_handle_t *handle)
53 if(handle == NULL) {
54 return;
57 /* close logfile */
58 if(handle->logstream) {
59 fclose(handle->logstream);
60 handle->logstream= NULL;
62 if(handle->usesyslog) {
63 handle->usesyslog = 0;
64 closelog();
67 #ifdef HAVE_LIBCURL
68 /* release curl handle */
69 curl_easy_cleanup(handle->curl);
70 #endif
72 regfree(&handle->delta_regex);
74 /* free memory */
75 _alpm_trans_free(handle->trans);
76 FREE(handle->root);
77 FREE(handle->dbpath);
78 FREELIST(handle->cachedirs);
79 FREE(handle->logfile);
80 FREE(handle->lockfile);
81 FREE(handle->arch);
82 FREE(handle->gpgdir);
83 FREELIST(handle->dbs_sync);
84 FREELIST(handle->noupgrade);
85 FREELIST(handle->noextract);
86 FREELIST(handle->ignorepkg);
87 FREELIST(handle->ignoregroup);
88 FREE(handle);
91 /** Lock the database */
92 int _alpm_handle_lock(alpm_handle_t *handle)
94 int fd;
95 char *dir, *ptr;
97 ASSERT(handle->lockfile != NULL, return -1);
98 ASSERT(handle->lckstream == NULL, return 0);
100 /* create the dir of the lockfile first */
101 dir = strdup(handle->lockfile);
102 ptr = strrchr(dir, '/');
103 if(ptr) {
104 *ptr = '\0';
106 if(_alpm_makepath(dir)) {
107 FREE(dir);
108 return -1;
110 FREE(dir);
112 do {
113 fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000);
114 } while(fd == -1 && errno == EINTR);
115 if(fd >= 0) {
116 FILE *f = fdopen(fd, "w");
117 fprintf(f, "%ld\n", (long)getpid());
118 fflush(f);
119 fsync(fd);
120 handle->lckstream = f;
121 return 0;
123 return -1;
126 /** Remove a lock file */
127 int _alpm_handle_unlock(alpm_handle_t *handle)
129 ASSERT(handle->lockfile != NULL, return -1);
130 ASSERT(handle->lckstream != NULL, return 0);
132 fclose(handle->lckstream);
133 handle->lckstream = NULL;
135 if(unlink(handle->lockfile) && errno != ENOENT) {
136 return -1;
138 return 0;
142 alpm_cb_log SYMEXPORT alpm_option_get_logcb(alpm_handle_t *handle)
144 CHECK_HANDLE(handle, return NULL);
145 return handle->logcb;
148 alpm_cb_download SYMEXPORT alpm_option_get_dlcb(alpm_handle_t *handle)
150 CHECK_HANDLE(handle, return NULL);
151 return handle->dlcb;
154 alpm_cb_fetch SYMEXPORT alpm_option_get_fetchcb(alpm_handle_t *handle)
156 CHECK_HANDLE(handle, return NULL);
157 return handle->fetchcb;
160 alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb(alpm_handle_t *handle)
162 CHECK_HANDLE(handle, return NULL);
163 return handle->totaldlcb;
166 alpm_cb_event SYMEXPORT alpm_option_get_eventcb(alpm_handle_t *handle)
168 CHECK_HANDLE(handle, return NULL);
169 return handle->eventcb;
172 alpm_cb_question SYMEXPORT alpm_option_get_questioncb(alpm_handle_t *handle)
174 CHECK_HANDLE(handle, return NULL);
175 return handle->questioncb;
178 alpm_cb_progress SYMEXPORT alpm_option_get_progresscb(alpm_handle_t *handle)
180 CHECK_HANDLE(handle, return NULL);
181 return handle->progresscb;
184 const char SYMEXPORT *alpm_option_get_root(alpm_handle_t *handle)
186 CHECK_HANDLE(handle, return NULL);
187 return handle->root;
190 const char SYMEXPORT *alpm_option_get_dbpath(alpm_handle_t *handle)
192 CHECK_HANDLE(handle, return NULL);
193 return handle->dbpath;
196 alpm_list_t SYMEXPORT *alpm_option_get_cachedirs(alpm_handle_t *handle)
198 CHECK_HANDLE(handle, return NULL);
199 return handle->cachedirs;
202 const char SYMEXPORT *alpm_option_get_logfile(alpm_handle_t *handle)
204 CHECK_HANDLE(handle, return NULL);
205 return handle->logfile;
208 const char SYMEXPORT *alpm_option_get_lockfile(alpm_handle_t *handle)
210 CHECK_HANDLE(handle, return NULL);
211 return handle->lockfile;
214 const char SYMEXPORT *alpm_option_get_gpgdir(alpm_handle_t *handle)
216 CHECK_HANDLE(handle, return NULL);
217 return handle->gpgdir;
220 int SYMEXPORT alpm_option_get_usesyslog(alpm_handle_t *handle)
222 CHECK_HANDLE(handle, return -1);
223 return handle->usesyslog;
226 alpm_list_t SYMEXPORT *alpm_option_get_noupgrades(alpm_handle_t *handle)
228 CHECK_HANDLE(handle, return NULL);
229 return handle->noupgrade;
232 alpm_list_t SYMEXPORT *alpm_option_get_noextracts(alpm_handle_t *handle)
234 CHECK_HANDLE(handle, return NULL);
235 return handle->noextract;
238 alpm_list_t SYMEXPORT *alpm_option_get_ignorepkgs(alpm_handle_t *handle)
240 CHECK_HANDLE(handle, return NULL);
241 return handle->ignorepkg;
244 alpm_list_t SYMEXPORT *alpm_option_get_ignoregroups(alpm_handle_t *handle)
246 CHECK_HANDLE(handle, return NULL);
247 return handle->ignoregroup;
250 const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle)
252 CHECK_HANDLE(handle, return NULL);
253 return handle->arch;
256 double SYMEXPORT alpm_option_get_deltaratio(alpm_handle_t *handle)
258 CHECK_HANDLE(handle, return -1);
259 return handle->deltaratio;
262 int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle)
264 CHECK_HANDLE(handle, return -1);
265 return handle->checkspace;
268 int SYMEXPORT alpm_option_set_logcb(alpm_handle_t *handle, alpm_cb_log cb)
270 CHECK_HANDLE(handle, return -1);
271 handle->logcb = cb;
272 return 0;
275 int SYMEXPORT alpm_option_set_dlcb(alpm_handle_t *handle, alpm_cb_download cb)
277 CHECK_HANDLE(handle, return -1);
278 handle->dlcb = cb;
279 return 0;
282 int SYMEXPORT alpm_option_set_fetchcb(alpm_handle_t *handle, alpm_cb_fetch cb)
284 CHECK_HANDLE(handle, return -1);
285 handle->fetchcb = cb;
286 return 0;
289 int SYMEXPORT alpm_option_set_totaldlcb(alpm_handle_t *handle, alpm_cb_totaldl cb)
291 CHECK_HANDLE(handle, return -1);
292 handle->totaldlcb = cb;
293 return 0;
296 int SYMEXPORT alpm_option_set_eventcb(alpm_handle_t *handle, alpm_cb_event cb)
298 CHECK_HANDLE(handle, return -1);
299 handle->eventcb = cb;
300 return 0;
303 int SYMEXPORT alpm_option_set_questioncb(alpm_handle_t *handle, alpm_cb_question cb)
305 CHECK_HANDLE(handle, return -1);
306 handle->questioncb = cb;
307 return 0;
310 int SYMEXPORT alpm_option_set_progresscb(alpm_handle_t *handle, alpm_cb_progress cb)
312 CHECK_HANDLE(handle, return -1);
313 handle->progresscb = cb;
314 return 0;
317 static char *canonicalize_path(const char *path) {
318 char *new_path;
319 size_t len;
321 /* verify path ends in a '/' */
322 len = strlen(path);
323 if(path[len - 1] != '/') {
324 len += 1;
326 CALLOC(new_path, len + 1, sizeof(char), return NULL);
327 strcpy(new_path, path);
328 new_path[len - 1] = '/';
329 return new_path;
332 alpm_errno_t _alpm_set_directory_option(const char *value,
333 char **storage, int must_exist)
335 struct stat st;
336 char real[PATH_MAX];
337 const char *path;
339 path = value;
340 if(!path) {
341 return ALPM_ERR_WRONG_ARGS;
343 if(must_exist) {
344 if(stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
345 return ALPM_ERR_NOT_A_DIR;
347 if(!realpath(path, real)) {
348 return ALPM_ERR_NOT_A_DIR;
350 path = real;
353 if(*storage) {
354 FREE(*storage);
356 *storage = canonicalize_path(path);
357 if(!*storage) {
358 return ALPM_ERR_MEMORY;
360 return 0;
363 int SYMEXPORT alpm_option_add_cachedir(alpm_handle_t *handle, const char *cachedir)
365 char *newcachedir;
367 CHECK_HANDLE(handle, return -1);
368 ASSERT(cachedir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
369 /* don't stat the cachedir yet, as it may not even be needed. we can
370 * fail later if it is needed and the path is invalid. */
372 newcachedir = canonicalize_path(cachedir);
373 if(!newcachedir) {
374 RET_ERR(handle, ALPM_ERR_MEMORY, -1);
376 handle->cachedirs = alpm_list_add(handle->cachedirs, newcachedir);
377 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'cachedir' = %s\n", newcachedir);
378 return 0;
381 int SYMEXPORT alpm_option_set_cachedirs(alpm_handle_t *handle, alpm_list_t *cachedirs)
383 alpm_list_t *i;
384 CHECK_HANDLE(handle, return -1);
385 if(handle->cachedirs) {
386 FREELIST(handle->cachedirs);
388 for(i = cachedirs; i; i = i->next) {
389 int ret = alpm_option_add_cachedir(handle, i->data);
390 if(ret) {
391 return ret;
394 return 0;
397 int SYMEXPORT alpm_option_remove_cachedir(alpm_handle_t *handle, const char *cachedir)
399 char *vdata = NULL;
400 char *newcachedir;
401 CHECK_HANDLE(handle, return -1);
402 ASSERT(cachedir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
404 newcachedir = canonicalize_path(cachedir);
405 if(!newcachedir) {
406 RET_ERR(handle, ALPM_ERR_MEMORY, -1);
408 handle->cachedirs = alpm_list_remove_str(handle->cachedirs, newcachedir, &vdata);
409 FREE(newcachedir);
410 if(vdata != NULL) {
411 FREE(vdata);
412 return 1;
414 return 0;
417 int SYMEXPORT alpm_option_set_logfile(alpm_handle_t *handle, const char *logfile)
419 char *oldlogfile = handle->logfile;
421 CHECK_HANDLE(handle, return -1);
422 if(!logfile) {
423 handle->pm_errno = ALPM_ERR_WRONG_ARGS;
424 return -1;
427 handle->logfile = strdup(logfile);
429 /* free the old logfile path string, and close the stream so logaction
430 * will reopen a new stream on the new logfile */
431 if(oldlogfile) {
432 FREE(oldlogfile);
434 if(handle->logstream) {
435 fclose(handle->logstream);
436 handle->logstream = NULL;
438 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'logfile' = %s\n", handle->logfile);
439 return 0;
442 int SYMEXPORT alpm_option_set_gpgdir(alpm_handle_t *handle, const char *gpgdir)
444 CHECK_HANDLE(handle, return -1);
445 if(!gpgdir) {
446 handle->pm_errno = ALPM_ERR_WRONG_ARGS;
447 return -1;
450 if(handle->gpgdir) {
451 FREE(handle->gpgdir);
453 handle->gpgdir = strdup(gpgdir);
455 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'gpgdir' = %s\n", handle->gpgdir);
456 return 0;
459 int SYMEXPORT alpm_option_set_usesyslog(alpm_handle_t *handle, int usesyslog)
461 CHECK_HANDLE(handle, return -1);
462 handle->usesyslog = usesyslog;
463 return 0;
466 int SYMEXPORT alpm_option_add_noupgrade(alpm_handle_t *handle, const char *pkg)
468 CHECK_HANDLE(handle, return -1);
469 handle->noupgrade = alpm_list_add(handle->noupgrade, strdup(pkg));
470 return 0;
473 int SYMEXPORT alpm_option_set_noupgrades(alpm_handle_t *handle, alpm_list_t *noupgrade)
475 CHECK_HANDLE(handle, return -1);
476 if(handle->noupgrade) FREELIST(handle->noupgrade);
477 handle->noupgrade = alpm_list_strdup(noupgrade);
478 return 0;
481 int SYMEXPORT alpm_option_remove_noupgrade(alpm_handle_t *handle, const char *pkg)
483 char *vdata = NULL;
484 CHECK_HANDLE(handle, return -1);
485 handle->noupgrade = alpm_list_remove_str(handle->noupgrade, pkg, &vdata);
486 if(vdata != NULL) {
487 FREE(vdata);
488 return 1;
490 return 0;
493 int SYMEXPORT alpm_option_add_noextract(alpm_handle_t *handle, const char *pkg)
495 CHECK_HANDLE(handle, return -1);
496 handle->noextract = alpm_list_add(handle->noextract, strdup(pkg));
497 return 0;
500 int SYMEXPORT alpm_option_set_noextracts(alpm_handle_t *handle, alpm_list_t *noextract)
502 CHECK_HANDLE(handle, return -1);
503 if(handle->noextract) FREELIST(handle->noextract);
504 handle->noextract = alpm_list_strdup(noextract);
505 return 0;
508 int SYMEXPORT alpm_option_remove_noextract(alpm_handle_t *handle, const char *pkg)
510 char *vdata = NULL;
511 CHECK_HANDLE(handle, return -1);
512 handle->noextract = alpm_list_remove_str(handle->noextract, pkg, &vdata);
513 if(vdata != NULL) {
514 FREE(vdata);
515 return 1;
517 return 0;
520 int SYMEXPORT alpm_option_add_ignorepkg(alpm_handle_t *handle, const char *pkg)
522 CHECK_HANDLE(handle, return -1);
523 handle->ignorepkg = alpm_list_add(handle->ignorepkg, strdup(pkg));
524 return 0;
527 int SYMEXPORT alpm_option_set_ignorepkgs(alpm_handle_t *handle, alpm_list_t *ignorepkgs)
529 CHECK_HANDLE(handle, return -1);
530 if(handle->ignorepkg) FREELIST(handle->ignorepkg);
531 handle->ignorepkg = alpm_list_strdup(ignorepkgs);
532 return 0;
535 int SYMEXPORT alpm_option_remove_ignorepkg(alpm_handle_t *handle, const char *pkg)
537 char *vdata = NULL;
538 CHECK_HANDLE(handle, return -1);
539 handle->ignorepkg = alpm_list_remove_str(handle->ignorepkg, pkg, &vdata);
540 if(vdata != NULL) {
541 FREE(vdata);
542 return 1;
544 return 0;
547 int SYMEXPORT alpm_option_add_ignoregroup(alpm_handle_t *handle, const char *grp)
549 CHECK_HANDLE(handle, return -1);
550 handle->ignoregroup = alpm_list_add(handle->ignoregroup, strdup(grp));
551 return 0;
554 int SYMEXPORT alpm_option_set_ignoregroups(alpm_handle_t *handle, alpm_list_t *ignoregrps)
556 CHECK_HANDLE(handle, return -1);
557 if(handle->ignoregroup) FREELIST(handle->ignoregroup);
558 handle->ignoregroup = alpm_list_strdup(ignoregrps);
559 return 0;
562 int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char *grp)
564 char *vdata = NULL;
565 CHECK_HANDLE(handle, return -1);
566 handle->ignoregroup = alpm_list_remove_str(handle->ignoregroup, grp, &vdata);
567 if(vdata != NULL) {
568 FREE(vdata);
569 return 1;
571 return 0;
574 int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch)
576 CHECK_HANDLE(handle, return -1);
577 if(handle->arch) FREE(handle->arch);
578 if(arch) {
579 handle->arch = strdup(arch);
580 } else {
581 handle->arch = NULL;
583 return 0;
586 int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio)
588 CHECK_HANDLE(handle, return -1);
589 if(ratio < 0.0 || ratio > 2.0) {
590 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
592 handle->deltaratio = ratio;
593 return 0;
596 int SYMEXPORT alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace)
598 CHECK_HANDLE(handle, return -1);
599 handle->checkspace = checkspace;
600 return 0;
603 int SYMEXPORT alpm_option_set_default_siglevel(alpm_handle_t *handle,
604 alpm_siglevel_t level)
606 CHECK_HANDLE(handle, return -1);
607 #ifdef HAVE_LIBGPGME
608 handle->siglevel = level;
609 #else
610 if(level != 0 && level != ALPM_SIG_USE_DEFAULT) {
611 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
613 #endif
614 return 0;
617 alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle)
619 CHECK_HANDLE(handle, return -1);
620 return handle->siglevel;
623 alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle)
625 CHECK_HANDLE(handle, return NULL);
626 return handle->db_local;
629 alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle)
631 CHECK_HANDLE(handle, return NULL);
632 return handle->dbs_sync;
635 /* vim: set ts=2 sw=2 noet: */