ALPM API adjustments for sanity and consistency
[pacman-ng.git] / lib / libalpm / handle.c
blobec4cc56b0e9ca54f47b242f31d355e2152e01268
1 /*
2 * handle.c
4 * Copyright (c) 2006-2011 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 = NULL;
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 CALLOC(real, PATH_MAX, sizeof(char), return ALPM_ERR_MEMORY);
348 if(!realpath(path, real)) {
349 free(real);
350 return ALPM_ERR_NOT_A_DIR;
352 path = real;
355 if(*storage) {
356 FREE(*storage);
358 *storage = canonicalize_path(path);
359 if(!*storage) {
360 return ALPM_ERR_MEMORY;
362 free(real);
363 return 0;
366 int SYMEXPORT alpm_option_add_cachedir(alpm_handle_t *handle, const char *cachedir)
368 char *newcachedir;
370 CHECK_HANDLE(handle, return -1);
371 ASSERT(cachedir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
372 /* don't stat the cachedir yet, as it may not even be needed. we can
373 * fail later if it is needed and the path is invalid. */
375 newcachedir = canonicalize_path(cachedir);
376 if(!newcachedir) {
377 RET_ERR(handle, ALPM_ERR_MEMORY, -1);
379 handle->cachedirs = alpm_list_add(handle->cachedirs, newcachedir);
380 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'cachedir' = %s\n", newcachedir);
381 return 0;
384 int SYMEXPORT alpm_option_set_cachedirs(alpm_handle_t *handle, alpm_list_t *cachedirs)
386 alpm_list_t *i;
387 CHECK_HANDLE(handle, return -1);
388 if(handle->cachedirs) {
389 FREELIST(handle->cachedirs);
391 for(i = cachedirs; i; i = i->next) {
392 int ret = alpm_option_add_cachedir(handle, i->data);
393 if(ret) {
394 return ret;
397 return 0;
400 int SYMEXPORT alpm_option_remove_cachedir(alpm_handle_t *handle, const char *cachedir)
402 char *vdata = NULL;
403 char *newcachedir;
404 CHECK_HANDLE(handle, return -1);
405 ASSERT(cachedir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
407 newcachedir = canonicalize_path(cachedir);
408 if(!newcachedir) {
409 RET_ERR(handle, ALPM_ERR_MEMORY, -1);
411 handle->cachedirs = alpm_list_remove_str(handle->cachedirs, newcachedir, &vdata);
412 FREE(newcachedir);
413 if(vdata != NULL) {
414 FREE(vdata);
415 return 1;
417 return 0;
420 int SYMEXPORT alpm_option_set_logfile(alpm_handle_t *handle, const char *logfile)
422 char *oldlogfile = handle->logfile;
424 CHECK_HANDLE(handle, return -1);
425 if(!logfile) {
426 handle->pm_errno = ALPM_ERR_WRONG_ARGS;
427 return -1;
430 handle->logfile = strdup(logfile);
432 /* free the old logfile path string, and close the stream so logaction
433 * will reopen a new stream on the new logfile */
434 if(oldlogfile) {
435 FREE(oldlogfile);
437 if(handle->logstream) {
438 fclose(handle->logstream);
439 handle->logstream = NULL;
441 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'logfile' = %s\n", handle->logfile);
442 return 0;
445 int SYMEXPORT alpm_option_set_gpgdir(alpm_handle_t *handle, const char *gpgdir)
447 CHECK_HANDLE(handle, return -1);
448 if(!gpgdir) {
449 handle->pm_errno = ALPM_ERR_WRONG_ARGS;
450 return -1;
453 if(handle->gpgdir) {
454 FREE(handle->gpgdir);
456 handle->gpgdir = strdup(gpgdir);
458 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'gpgdir' = %s\n", handle->gpgdir);
459 return 0;
462 int SYMEXPORT alpm_option_set_usesyslog(alpm_handle_t *handle, int usesyslog)
464 CHECK_HANDLE(handle, return -1);
465 handle->usesyslog = usesyslog;
466 return 0;
469 int SYMEXPORT alpm_option_add_noupgrade(alpm_handle_t *handle, const char *pkg)
471 CHECK_HANDLE(handle, return -1);
472 handle->noupgrade = alpm_list_add(handle->noupgrade, strdup(pkg));
473 return 0;
476 int SYMEXPORT alpm_option_set_noupgrades(alpm_handle_t *handle, alpm_list_t *noupgrade)
478 CHECK_HANDLE(handle, return -1);
479 if(handle->noupgrade) FREELIST(handle->noupgrade);
480 handle->noupgrade = alpm_list_strdup(noupgrade);
481 return 0;
484 int SYMEXPORT alpm_option_remove_noupgrade(alpm_handle_t *handle, const char *pkg)
486 char *vdata = NULL;
487 CHECK_HANDLE(handle, return -1);
488 handle->noupgrade = alpm_list_remove_str(handle->noupgrade, pkg, &vdata);
489 if(vdata != NULL) {
490 FREE(vdata);
491 return 1;
493 return 0;
496 int SYMEXPORT alpm_option_add_noextract(alpm_handle_t *handle, const char *pkg)
498 CHECK_HANDLE(handle, return -1);
499 handle->noextract = alpm_list_add(handle->noextract, strdup(pkg));
500 return 0;
503 int SYMEXPORT alpm_option_set_noextracts(alpm_handle_t *handle, alpm_list_t *noextract)
505 CHECK_HANDLE(handle, return -1);
506 if(handle->noextract) FREELIST(handle->noextract);
507 handle->noextract = alpm_list_strdup(noextract);
508 return 0;
511 int SYMEXPORT alpm_option_remove_noextract(alpm_handle_t *handle, const char *pkg)
513 char *vdata = NULL;
514 CHECK_HANDLE(handle, return -1);
515 handle->noextract = alpm_list_remove_str(handle->noextract, pkg, &vdata);
516 if(vdata != NULL) {
517 FREE(vdata);
518 return 1;
520 return 0;
523 int SYMEXPORT alpm_option_add_ignorepkg(alpm_handle_t *handle, const char *pkg)
525 CHECK_HANDLE(handle, return -1);
526 handle->ignorepkg = alpm_list_add(handle->ignorepkg, strdup(pkg));
527 return 0;
530 int SYMEXPORT alpm_option_set_ignorepkgs(alpm_handle_t *handle, alpm_list_t *ignorepkgs)
532 CHECK_HANDLE(handle, return -1);
533 if(handle->ignorepkg) FREELIST(handle->ignorepkg);
534 handle->ignorepkg = alpm_list_strdup(ignorepkgs);
535 return 0;
538 int SYMEXPORT alpm_option_remove_ignorepkg(alpm_handle_t *handle, const char *pkg)
540 char *vdata = NULL;
541 CHECK_HANDLE(handle, return -1);
542 handle->ignorepkg = alpm_list_remove_str(handle->ignorepkg, pkg, &vdata);
543 if(vdata != NULL) {
544 FREE(vdata);
545 return 1;
547 return 0;
550 int SYMEXPORT alpm_option_add_ignoregroup(alpm_handle_t *handle, const char *grp)
552 CHECK_HANDLE(handle, return -1);
553 handle->ignoregroup = alpm_list_add(handle->ignoregroup, strdup(grp));
554 return 0;
557 int SYMEXPORT alpm_option_set_ignoregroups(alpm_handle_t *handle, alpm_list_t *ignoregrps)
559 CHECK_HANDLE(handle, return -1);
560 if(handle->ignoregroup) FREELIST(handle->ignoregroup);
561 handle->ignoregroup = alpm_list_strdup(ignoregrps);
562 return 0;
565 int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char *grp)
567 char *vdata = NULL;
568 CHECK_HANDLE(handle, return -1);
569 handle->ignoregroup = alpm_list_remove_str(handle->ignoregroup, grp, &vdata);
570 if(vdata != NULL) {
571 FREE(vdata);
572 return 1;
574 return 0;
577 int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch)
579 CHECK_HANDLE(handle, return -1);
580 if(handle->arch) FREE(handle->arch);
581 if(arch) {
582 handle->arch = strdup(arch);
583 } else {
584 handle->arch = NULL;
586 return 0;
589 int SYMEXPORT alpm_option_set_deltaratio(alpm_handle_t *handle, double ratio)
591 CHECK_HANDLE(handle, return -1);
592 if(ratio < 0.0 || ratio > 2.0) {
593 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
595 handle->deltaratio = ratio;
596 return 0;
599 int SYMEXPORT alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace)
601 CHECK_HANDLE(handle, return -1);
602 handle->checkspace = checkspace;
603 return 0;
606 int SYMEXPORT alpm_option_set_default_siglevel(alpm_handle_t *handle,
607 alpm_siglevel_t level)
609 CHECK_HANDLE(handle, return -1);
610 #ifdef HAVE_LIBGPGME
611 handle->siglevel = level;
612 #else
613 if(level != 0 && level != ALPM_SIG_USE_DEFAULT) {
614 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
616 #endif
617 return 0;
620 alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle)
622 CHECK_HANDLE(handle, return -1);
623 return handle->siglevel;
626 alpm_db_t SYMEXPORT *alpm_get_localdb(alpm_handle_t *handle)
628 CHECK_HANDLE(handle, return NULL);
629 return handle->db_local;
632 alpm_list_t SYMEXPORT *alpm_get_syncdbs(alpm_handle_t *handle)
634 CHECK_HANDLE(handle, return NULL);
635 return handle->dbs_sync;
638 /* vim: set ts=2 sw=2 noet: */