Rename pmdb_t to alpm_db_t
[pacman-ng.git] / lib / libalpm / handle.c
blob48b674c0e6a57b5b18351f493ec863fe2f0190e7
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 "config.h"
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <limits.h>
29 #include <sys/types.h>
30 #include <syslog.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
34 /* libalpm */
35 #include "handle.h"
36 #include "alpm_list.h"
37 #include "util.h"
38 #include "log.h"
39 #include "trans.h"
40 #include "alpm.h"
42 alpm_handle_t *_alpm_handle_new()
44 alpm_handle_t *handle;
46 CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL);
48 handle->sigverify = PM_PGP_VERIFY_OPTIONAL;
50 return handle;
53 void _alpm_handle_free(alpm_handle_t *handle)
55 if(handle == NULL) {
56 return;
59 /* close logfile */
60 if(handle->logstream) {
61 fclose(handle->logstream);
62 handle->logstream= NULL;
64 if(handle->usesyslog) {
65 handle->usesyslog = 0;
66 closelog();
69 #ifdef HAVE_LIBCURL
70 /* release curl handle */
71 curl_easy_cleanup(handle->curl);
72 #endif
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->ignoregrp);
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 if(handle->lckstream != NULL) {
133 fclose(handle->lckstream);
134 handle->lckstream = NULL;
136 if(unlink(handle->lockfile) && errno != ENOENT) {
137 return -1;
139 return 0;
143 alpm_cb_log SYMEXPORT alpm_option_get_logcb(alpm_handle_t *handle)
145 CHECK_HANDLE(handle, return NULL);
146 return handle->logcb;
149 alpm_cb_download SYMEXPORT alpm_option_get_dlcb(alpm_handle_t *handle)
151 CHECK_HANDLE(handle, return NULL);
152 return handle->dlcb;
155 alpm_cb_fetch SYMEXPORT alpm_option_get_fetchcb(alpm_handle_t *handle)
157 CHECK_HANDLE(handle, return NULL);
158 return handle->fetchcb;
161 alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb(alpm_handle_t *handle)
163 CHECK_HANDLE(handle, return NULL);
164 return handle->totaldlcb;
167 const char SYMEXPORT *alpm_option_get_root(alpm_handle_t *handle)
169 CHECK_HANDLE(handle, return NULL);
170 return handle->root;
173 const char SYMEXPORT *alpm_option_get_dbpath(alpm_handle_t *handle)
175 CHECK_HANDLE(handle, return NULL);
176 return handle->dbpath;
179 alpm_list_t SYMEXPORT *alpm_option_get_cachedirs(alpm_handle_t *handle)
181 CHECK_HANDLE(handle, return NULL);
182 return handle->cachedirs;
185 const char SYMEXPORT *alpm_option_get_logfile(alpm_handle_t *handle)
187 CHECK_HANDLE(handle, return NULL);
188 return handle->logfile;
191 const char SYMEXPORT *alpm_option_get_lockfile(alpm_handle_t *handle)
193 CHECK_HANDLE(handle, return NULL);
194 return handle->lockfile;
197 const char SYMEXPORT *alpm_option_get_gpgdir(alpm_handle_t *handle)
199 CHECK_HANDLE(handle, return NULL);
200 return handle->gpgdir;
203 int SYMEXPORT alpm_option_get_usesyslog(alpm_handle_t *handle)
205 CHECK_HANDLE(handle, return -1);
206 return handle->usesyslog;
209 alpm_list_t SYMEXPORT *alpm_option_get_noupgrades(alpm_handle_t *handle)
211 CHECK_HANDLE(handle, return NULL);
212 return handle->noupgrade;
215 alpm_list_t SYMEXPORT *alpm_option_get_noextracts(alpm_handle_t *handle)
217 CHECK_HANDLE(handle, return NULL);
218 return handle->noextract;
221 alpm_list_t SYMEXPORT *alpm_option_get_ignorepkgs(alpm_handle_t *handle)
223 CHECK_HANDLE(handle, return NULL);
224 return handle->ignorepkg;
227 alpm_list_t SYMEXPORT *alpm_option_get_ignoregrps(alpm_handle_t *handle)
229 CHECK_HANDLE(handle, return NULL);
230 return handle->ignoregrp;
233 const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle)
235 CHECK_HANDLE(handle, return NULL);
236 return handle->arch;
239 int SYMEXPORT alpm_option_get_usedelta(alpm_handle_t *handle)
241 CHECK_HANDLE(handle, return -1);
242 return handle->usedelta;
245 int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle)
247 CHECK_HANDLE(handle, return -1);
248 return handle->checkspace;
251 alpm_db_t SYMEXPORT *alpm_option_get_localdb(alpm_handle_t *handle)
253 CHECK_HANDLE(handle, return NULL);
254 return handle->db_local;
257 alpm_list_t SYMEXPORT *alpm_option_get_syncdbs(alpm_handle_t *handle)
259 CHECK_HANDLE(handle, return NULL);
260 return handle->dbs_sync;
263 int SYMEXPORT alpm_option_set_logcb(alpm_handle_t *handle, alpm_cb_log cb)
265 CHECK_HANDLE(handle, return -1);
266 handle->logcb = cb;
267 return 0;
270 int SYMEXPORT alpm_option_set_dlcb(alpm_handle_t *handle, alpm_cb_download cb)
272 CHECK_HANDLE(handle, return -1);
273 handle->dlcb = cb;
274 return 0;
277 int SYMEXPORT alpm_option_set_fetchcb(alpm_handle_t *handle, alpm_cb_fetch cb)
279 CHECK_HANDLE(handle, return -1);
280 handle->fetchcb = cb;
281 return 0;
284 int SYMEXPORT alpm_option_set_totaldlcb(alpm_handle_t *handle, alpm_cb_totaldl cb)
286 CHECK_HANDLE(handle, return -1);
287 handle->totaldlcb = cb;
288 return 0;
291 static char *canonicalize_path(const char *path) {
292 char *new_path;
293 size_t len;
295 /* verify path ends in a '/' */
296 len = strlen(path);
297 if(path[len - 1] != '/') {
298 len += 1;
300 CALLOC(new_path, len + 1, sizeof(char), return NULL);
301 strncpy(new_path, path, len);
302 new_path[len - 1] = '/';
303 return new_path;
306 enum _pmerrno_t _alpm_set_directory_option(const char *value,
307 char **storage, int must_exist)
309 struct stat st;
310 char *real = NULL;
311 const char *path;
313 path = value;
314 if(!path) {
315 return PM_ERR_WRONG_ARGS;
317 if(must_exist) {
318 if(stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
319 return PM_ERR_NOT_A_DIR;
321 CALLOC(real, PATH_MAX, sizeof(char), return PM_ERR_MEMORY);
322 if(!realpath(path, real)) {
323 free(real);
324 return PM_ERR_NOT_A_DIR;
326 path = real;
329 if(*storage) {
330 FREE(*storage);
332 *storage = canonicalize_path(path);
333 if(!*storage) {
334 return PM_ERR_MEMORY;
336 free(real);
337 return 0;
340 int SYMEXPORT alpm_option_add_cachedir(alpm_handle_t *handle, const char *cachedir)
342 char *newcachedir;
344 CHECK_HANDLE(handle, return -1);
345 ASSERT(cachedir != NULL, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1));
346 /* don't stat the cachedir yet, as it may not even be needed. we can
347 * fail later if it is needed and the path is invalid. */
349 newcachedir = canonicalize_path(cachedir);
350 if(!newcachedir) {
351 RET_ERR(handle, PM_ERR_MEMORY, -1);
353 handle->cachedirs = alpm_list_add(handle->cachedirs, newcachedir);
354 _alpm_log(handle, PM_LOG_DEBUG, "option 'cachedir' = %s\n", newcachedir);
355 return 0;
358 int SYMEXPORT alpm_option_set_cachedirs(alpm_handle_t *handle, alpm_list_t *cachedirs)
360 alpm_list_t *i;
361 CHECK_HANDLE(handle, return -1);
362 if(handle->cachedirs) {
363 FREELIST(handle->cachedirs);
365 for(i = cachedirs; i; i = i->next) {
366 int ret = alpm_option_add_cachedir(handle, i->data);
367 if(ret) {
368 return ret;
371 return 0;
374 int SYMEXPORT alpm_option_remove_cachedir(alpm_handle_t *handle, const char *cachedir)
376 char *vdata = NULL;
377 char *newcachedir;
378 CHECK_HANDLE(handle, return -1);
379 ASSERT(cachedir != NULL, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1));
381 newcachedir = canonicalize_path(cachedir);
382 if(!newcachedir) {
383 RET_ERR(handle, PM_ERR_MEMORY, -1);
385 handle->cachedirs = alpm_list_remove_str(handle->cachedirs, newcachedir, &vdata);
386 FREE(newcachedir);
387 if(vdata != NULL) {
388 FREE(vdata);
389 return 1;
391 return 0;
394 int SYMEXPORT alpm_option_set_logfile(alpm_handle_t *handle, const char *logfile)
396 char *oldlogfile = handle->logfile;
398 CHECK_HANDLE(handle, return -1);
399 if(!logfile) {
400 handle->pm_errno = PM_ERR_WRONG_ARGS;
401 return -1;
404 handle->logfile = strdup(logfile);
406 /* free the old logfile path string, and close the stream so logaction
407 * will reopen a new stream on the new logfile */
408 if(oldlogfile) {
409 FREE(oldlogfile);
411 if(handle->logstream) {
412 fclose(handle->logstream);
413 handle->logstream = NULL;
415 _alpm_log(handle, PM_LOG_DEBUG, "option 'logfile' = %s\n", handle->logfile);
416 return 0;
419 int SYMEXPORT alpm_option_set_gpgdir(alpm_handle_t *handle, const char *gpgdir)
421 CHECK_HANDLE(handle, return -1);
422 if(!gpgdir) {
423 handle->pm_errno = PM_ERR_WRONG_ARGS;
424 return -1;
427 if(handle->gpgdir) {
428 FREE(handle->gpgdir);
430 handle->gpgdir = strdup(gpgdir);
432 _alpm_log(handle, PM_LOG_DEBUG, "option 'gpgdir' = %s\n", handle->gpgdir);
433 return 0;
436 int SYMEXPORT alpm_option_set_usesyslog(alpm_handle_t *handle, int usesyslog)
438 CHECK_HANDLE(handle, return -1);
439 handle->usesyslog = usesyslog;
440 return 0;
443 int SYMEXPORT alpm_option_add_noupgrade(alpm_handle_t *handle, const char *pkg)
445 CHECK_HANDLE(handle, return -1);
446 handle->noupgrade = alpm_list_add(handle->noupgrade, strdup(pkg));
447 return 0;
450 int SYMEXPORT alpm_option_set_noupgrades(alpm_handle_t *handle, alpm_list_t *noupgrade)
452 CHECK_HANDLE(handle, return -1);
453 if(handle->noupgrade) FREELIST(handle->noupgrade);
454 handle->noupgrade = alpm_list_strdup(noupgrade);
455 return 0;
458 int SYMEXPORT alpm_option_remove_noupgrade(alpm_handle_t *handle, const char *pkg)
460 char *vdata = NULL;
461 CHECK_HANDLE(handle, return -1);
462 handle->noupgrade = alpm_list_remove_str(handle->noupgrade, pkg, &vdata);
463 if(vdata != NULL) {
464 FREE(vdata);
465 return 1;
467 return 0;
470 int SYMEXPORT alpm_option_add_noextract(alpm_handle_t *handle, const char *pkg)
472 CHECK_HANDLE(handle, return -1);
473 handle->noextract = alpm_list_add(handle->noextract, strdup(pkg));
474 return 0;
477 int SYMEXPORT alpm_option_set_noextracts(alpm_handle_t *handle, alpm_list_t *noextract)
479 CHECK_HANDLE(handle, return -1);
480 if(handle->noextract) FREELIST(handle->noextract);
481 handle->noextract = alpm_list_strdup(noextract);
482 return 0;
485 int SYMEXPORT alpm_option_remove_noextract(alpm_handle_t *handle, const char *pkg)
487 char *vdata = NULL;
488 CHECK_HANDLE(handle, return -1);
489 handle->noextract = alpm_list_remove_str(handle->noextract, pkg, &vdata);
490 if(vdata != NULL) {
491 FREE(vdata);
492 return 1;
494 return 0;
497 int SYMEXPORT alpm_option_add_ignorepkg(alpm_handle_t *handle, const char *pkg)
499 CHECK_HANDLE(handle, return -1);
500 handle->ignorepkg = alpm_list_add(handle->ignorepkg, strdup(pkg));
501 return 0;
504 int SYMEXPORT alpm_option_set_ignorepkgs(alpm_handle_t *handle, alpm_list_t *ignorepkgs)
506 CHECK_HANDLE(handle, return -1);
507 if(handle->ignorepkg) FREELIST(handle->ignorepkg);
508 handle->ignorepkg = alpm_list_strdup(ignorepkgs);
509 return 0;
512 int SYMEXPORT alpm_option_remove_ignorepkg(alpm_handle_t *handle, const char *pkg)
514 char *vdata = NULL;
515 CHECK_HANDLE(handle, return -1);
516 handle->ignorepkg = alpm_list_remove_str(handle->ignorepkg, pkg, &vdata);
517 if(vdata != NULL) {
518 FREE(vdata);
519 return 1;
521 return 0;
524 int SYMEXPORT alpm_option_add_ignoregrp(alpm_handle_t *handle, const char *grp)
526 CHECK_HANDLE(handle, return -1);
527 handle->ignoregrp = alpm_list_add(handle->ignoregrp, strdup(grp));
528 return 0;
531 int SYMEXPORT alpm_option_set_ignoregrps(alpm_handle_t *handle, alpm_list_t *ignoregrps)
533 CHECK_HANDLE(handle, return -1);
534 if(handle->ignoregrp) FREELIST(handle->ignoregrp);
535 handle->ignoregrp = alpm_list_strdup(ignoregrps);
536 return 0;
539 int SYMEXPORT alpm_option_remove_ignoregrp(alpm_handle_t *handle, const char *grp)
541 char *vdata = NULL;
542 CHECK_HANDLE(handle, return -1);
543 handle->ignoregrp = alpm_list_remove_str(handle->ignoregrp, grp, &vdata);
544 if(vdata != NULL) {
545 FREE(vdata);
546 return 1;
548 return 0;
551 int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch)
553 CHECK_HANDLE(handle, return -1);
554 if(handle->arch) FREE(handle->arch);
555 if(arch) {
556 handle->arch = strdup(arch);
557 } else {
558 handle->arch = NULL;
560 return 0;
563 int SYMEXPORT alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta)
565 CHECK_HANDLE(handle, return -1);
566 handle->usedelta = usedelta;
567 return 0;
570 int SYMEXPORT alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace)
572 CHECK_HANDLE(handle, return -1);
573 handle->checkspace = checkspace;
574 return 0;
577 int SYMEXPORT alpm_option_set_default_sigverify(alpm_handle_t *handle, pgp_verify_t level)
579 CHECK_HANDLE(handle, return -1);
580 ASSERT(level != PM_PGP_VERIFY_UNKNOWN, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1));
581 handle->sigverify = level;
582 return 0;
585 pgp_verify_t SYMEXPORT alpm_option_get_default_sigverify(alpm_handle_t *handle)
587 CHECK_HANDLE(handle, return PM_PGP_VERIFY_UNKNOWN);
588 return handle->sigverify;
591 /* vim: set ts=2 sw=2 noet: */