libalpm
Arch Linux Package Manager Library
|
00001 /* 00002 * handle.c 00003 * 00004 * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> 00005 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> 00006 * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> 00007 * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00021 */ 00022 00023 #include <errno.h> 00024 #include <stdlib.h> 00025 #include <string.h> 00026 #include <limits.h> 00027 #include <sys/types.h> 00028 #include <syslog.h> 00029 #include <sys/stat.h> 00030 #include <fcntl.h> 00031 00032 /* libalpm */ 00033 #include "handle.h" 00034 #include "alpm_list.h" 00035 #include "util.h" 00036 #include "log.h" 00037 #include "delta.h" 00038 #include "trans.h" 00039 #include "alpm.h" 00040 00041 alpm_handle_t *_alpm_handle_new(void) 00042 { 00043 alpm_handle_t *handle; 00044 00045 CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL); 00046 00047 return handle; 00048 } 00049 00050 void _alpm_handle_free(alpm_handle_t *handle) 00051 { 00052 if(handle == NULL) { 00053 return; 00054 } 00055 00056 /* close logfile */ 00057 if(handle->logstream) { 00058 fclose(handle->logstream); 00059 handle->logstream= NULL; 00060 } 00061 if(handle->usesyslog) { 00062 handle->usesyslog = 0; 00063 closelog(); 00064 } 00065 00066 #ifdef HAVE_LIBCURL 00067 /* release curl handle */ 00068 curl_easy_cleanup(handle->curl); 00069 #endif 00070 00071 regfree(&handle->delta_regex); 00072 00073 /* free memory */ 00074 _alpm_trans_free(handle->trans); 00075 FREE(handle->root); 00076 FREE(handle->dbpath); 00077 FREELIST(handle->cachedirs); 00078 FREE(handle->logfile); 00079 FREE(handle->lockfile); 00080 FREE(handle->arch); 00081 FREE(handle->gpgdir); 00082 FREELIST(handle->dbs_sync); 00083 FREELIST(handle->noupgrade); 00084 FREELIST(handle->noextract); 00085 FREELIST(handle->ignorepkg); 00086 FREELIST(handle->ignoregroup); 00087 FREE(handle); 00088 } 00089 00090 /** Lock the database */ 00091 int _alpm_handle_lock(alpm_handle_t *handle) 00092 { 00093 int fd; 00094 char *dir, *ptr; 00095 00096 ASSERT(handle->lockfile != NULL, return -1); 00097 ASSERT(handle->lckstream == NULL, return 0); 00098 00099 /* create the dir of the lockfile first */ 00100 dir = strdup(handle->lockfile); 00101 ptr = strrchr(dir, '/'); 00102 if(ptr) { 00103 *ptr = '\0'; 00104 } 00105 if(_alpm_makepath(dir)) { 00106 FREE(dir); 00107 return -1; 00108 } 00109 FREE(dir); 00110 00111 do { 00112 fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000); 00113 } while(fd == -1 && errno == EINTR); 00114 if(fd >= 0) { 00115 FILE *f = fdopen(fd, "w"); 00116 fprintf(f, "%ld\n", (long)getpid()); 00117 fflush(f); 00118 fsync(fd); 00119 handle->lckstream = f; 00120 return 0; 00121 } 00122 return -1; 00123 } 00124 00125 /** Remove a lock file */ 00126 int _alpm_handle_unlock(alpm_handle_t *handle) 00127 { 00128 ASSERT(handle->lockfile != NULL, return -1); 00129 ASSERT(handle->lckstream != NULL, return 0); 00130 00131 fclose(handle->lckstream); 00132 handle->lckstream = NULL; 00133 00134 if(unlink(handle->lockfile) && errno != ENOENT) { 00135 return -1; 00136 } 00137 return 0; 00138 } 00139 00140 00141 alpm_cb_log SYMEXPORT alpm_option_get_logcb(alpm_handle_t *handle) 00142 { 00143 CHECK_HANDLE(handle, return NULL); 00144 return handle->logcb; 00145 } 00146 00147 alpm_cb_download SYMEXPORT alpm_option_get_dlcb(alpm_handle_t *handle) 00148 { 00149 CHECK_HANDLE(handle, return NULL); 00150 return handle->dlcb; 00151 } 00152 00153 alpm_cb_fetch SYMEXPORT alpm_option_get_fetchcb(alpm_handle_t *handle) 00154 { 00155 CHECK_HANDLE(handle, return NULL); 00156 return handle->fetchcb; 00157 } 00158 00159 alpm_cb_totaldl SYMEXPORT alpm_option_get_totaldlcb(alpm_handle_t *handle) 00160 { 00161 CHECK_HANDLE(handle, return NULL); 00162 return handle->totaldlcb; 00163 } 00164 00165 alpm_cb_event SYMEXPORT alpm_option_get_eventcb(alpm_handle_t *handle) 00166 { 00167 CHECK_HANDLE(handle, return NULL); 00168 return handle->eventcb; 00169 } 00170 00171 alpm_cb_question SYMEXPORT alpm_option_get_questioncb(alpm_handle_t *handle) 00172 { 00173 CHECK_HANDLE(handle, return NULL); 00174 return handle->questioncb; 00175 } 00176 00177 alpm_cb_progress SYMEXPORT alpm_option_get_progresscb(alpm_handle_t *handle) 00178 { 00179 CHECK_HANDLE(handle, return NULL); 00180 return handle->progresscb; 00181 } 00182 00183 const char SYMEXPORT *alpm_option_get_root(alpm_handle_t *handle) 00184 { 00185 CHECK_HANDLE(handle, return NULL); 00186 return handle->root; 00187 } 00188 00189 const char SYMEXPORT *alpm_option_get_dbpath(alpm_handle_t *handle) 00190 { 00191 CHECK_HANDLE(handle, return NULL); 00192 return handle->dbpath; 00193 } 00194 00195 alpm_list_t SYMEXPORT *alpm_option_get_cachedirs(alpm_handle_t *handle) 00196 { 00197 CHECK_HANDLE(handle, return NULL); 00198 return handle->cachedirs; 00199 } 00200 00201 const char SYMEXPORT *alpm_option_get_logfile(alpm_handle_t *handle) 00202 { 00203 CHECK_HANDLE(handle, return NULL); 00204 return handle->logfile; 00205 } 00206 00207 const char SYMEXPORT *alpm_option_get_lockfile(alpm_handle_t *handle) 00208 { 00209 CHECK_HANDLE(handle, return NULL); 00210 return handle->lockfile; 00211 } 00212 00213 const char SYMEXPORT *alpm_option_get_gpgdir(alpm_handle_t *handle) 00214 { 00215 CHECK_HANDLE(handle, return NULL); 00216 return handle->gpgdir; 00217 } 00218 00219 int SYMEXPORT alpm_option_get_usesyslog(alpm_handle_t *handle) 00220 { 00221 CHECK_HANDLE(handle, return -1); 00222 return handle->usesyslog; 00223 } 00224 00225 alpm_list_t SYMEXPORT *alpm_option_get_noupgrades(alpm_handle_t *handle) 00226 { 00227 CHECK_HANDLE(handle, return NULL); 00228 return handle->noupgrade; 00229 } 00230 00231 alpm_list_t SYMEXPORT *alpm_option_get_noextracts(alpm_handle_t *handle) 00232 { 00233 CHECK_HANDLE(handle, return NULL); 00234 return handle->noextract; 00235 } 00236 00237 alpm_list_t SYMEXPORT *alpm_option_get_ignorepkgs(alpm_handle_t *handle) 00238 { 00239 CHECK_HANDLE(handle, return NULL); 00240 return handle->ignorepkg; 00241 } 00242 00243 alpm_list_t SYMEXPORT *alpm_option_get_ignoregroups(alpm_handle_t *handle) 00244 { 00245 CHECK_HANDLE(handle, return NULL); 00246 return handle->ignoregroup; 00247 } 00248 00249 const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle) 00250 { 00251 CHECK_HANDLE(handle, return NULL); 00252 return handle->arch; 00253 } 00254 00255 int SYMEXPORT alpm_option_get_usedelta(alpm_handle_t *handle) 00256 { 00257 CHECK_HANDLE(handle, return -1); 00258 return handle->usedelta; 00259 } 00260 00261 int SYMEXPORT alpm_option_get_checkspace(alpm_handle_t *handle) 00262 { 00263 CHECK_HANDLE(handle, return -1); 00264 return handle->checkspace; 00265 } 00266 00267 alpm_db_t SYMEXPORT *alpm_option_get_localdb(alpm_handle_t *handle) 00268 { 00269 CHECK_HANDLE(handle, return NULL); 00270 return handle->db_local; 00271 } 00272 00273 alpm_list_t SYMEXPORT *alpm_option_get_syncdbs(alpm_handle_t *handle) 00274 { 00275 CHECK_HANDLE(handle, return NULL); 00276 return handle->dbs_sync; 00277 } 00278 00279 int SYMEXPORT alpm_option_set_logcb(alpm_handle_t *handle, alpm_cb_log cb) 00280 { 00281 CHECK_HANDLE(handle, return -1); 00282 handle->logcb = cb; 00283 return 0; 00284 } 00285 00286 int SYMEXPORT alpm_option_set_dlcb(alpm_handle_t *handle, alpm_cb_download cb) 00287 { 00288 CHECK_HANDLE(handle, return -1); 00289 handle->dlcb = cb; 00290 return 0; 00291 } 00292 00293 int SYMEXPORT alpm_option_set_fetchcb(alpm_handle_t *handle, alpm_cb_fetch cb) 00294 { 00295 CHECK_HANDLE(handle, return -1); 00296 handle->fetchcb = cb; 00297 return 0; 00298 } 00299 00300 int SYMEXPORT alpm_option_set_totaldlcb(alpm_handle_t *handle, alpm_cb_totaldl cb) 00301 { 00302 CHECK_HANDLE(handle, return -1); 00303 handle->totaldlcb = cb; 00304 return 0; 00305 } 00306 00307 int SYMEXPORT alpm_option_set_eventcb(alpm_handle_t *handle, alpm_cb_event cb) 00308 { 00309 CHECK_HANDLE(handle, return -1); 00310 handle->eventcb = cb; 00311 return 0; 00312 } 00313 00314 int SYMEXPORT alpm_option_set_questioncb(alpm_handle_t *handle, alpm_cb_question cb) 00315 { 00316 CHECK_HANDLE(handle, return -1); 00317 handle->questioncb = cb; 00318 return 0; 00319 } 00320 00321 int SYMEXPORT alpm_option_set_progresscb(alpm_handle_t *handle, alpm_cb_progress cb) 00322 { 00323 CHECK_HANDLE(handle, return -1); 00324 handle->progresscb = cb; 00325 return 0; 00326 } 00327 00328 static char *canonicalize_path(const char *path) { 00329 char *new_path; 00330 size_t len; 00331 00332 /* verify path ends in a '/' */ 00333 len = strlen(path); 00334 if(path[len - 1] != '/') { 00335 len += 1; 00336 } 00337 CALLOC(new_path, len + 1, sizeof(char), return NULL); 00338 strcpy(new_path, path); 00339 new_path[len - 1] = '/'; 00340 return new_path; 00341 } 00342 00343 alpm_errno_t _alpm_set_directory_option(const char *value, 00344 char **storage, int must_exist) 00345 { 00346 struct stat st; 00347 char *real = NULL; 00348 const char *path; 00349 00350 path = value; 00351 if(!path) { 00352 return ALPM_ERR_WRONG_ARGS; 00353 } 00354 if(must_exist) { 00355 if(stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { 00356 return ALPM_ERR_NOT_A_DIR; 00357 } 00358 CALLOC(real, PATH_MAX, sizeof(char), return ALPM_ERR_MEMORY); 00359 if(!realpath(path, real)) { 00360 free(real); 00361 return ALPM_ERR_NOT_A_DIR; 00362 } 00363 path = real; 00364 } 00365 00366 if(*storage) { 00367 FREE(*storage); 00368 } 00369 *storage = canonicalize_path(path); 00370 if(!*storage) { 00371 return ALPM_ERR_MEMORY; 00372 } 00373 free(real); 00374 return 0; 00375 } 00376 00377 int SYMEXPORT alpm_option_add_cachedir(alpm_handle_t *handle, const char *cachedir) 00378 { 00379 char *newcachedir; 00380 00381 CHECK_HANDLE(handle, return -1); 00382 ASSERT(cachedir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); 00383 /* don't stat the cachedir yet, as it may not even be needed. we can 00384 * fail later if it is needed and the path is invalid. */ 00385 00386 newcachedir = canonicalize_path(cachedir); 00387 if(!newcachedir) { 00388 RET_ERR(handle, ALPM_ERR_MEMORY, -1); 00389 } 00390 handle->cachedirs = alpm_list_add(handle->cachedirs, newcachedir); 00391 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'cachedir' = %s\n", newcachedir); 00392 return 0; 00393 } 00394 00395 int SYMEXPORT alpm_option_set_cachedirs(alpm_handle_t *handle, alpm_list_t *cachedirs) 00396 { 00397 alpm_list_t *i; 00398 CHECK_HANDLE(handle, return -1); 00399 if(handle->cachedirs) { 00400 FREELIST(handle->cachedirs); 00401 } 00402 for(i = cachedirs; i; i = i->next) { 00403 int ret = alpm_option_add_cachedir(handle, i->data); 00404 if(ret) { 00405 return ret; 00406 } 00407 } 00408 return 0; 00409 } 00410 00411 int SYMEXPORT alpm_option_remove_cachedir(alpm_handle_t *handle, const char *cachedir) 00412 { 00413 char *vdata = NULL; 00414 char *newcachedir; 00415 CHECK_HANDLE(handle, return -1); 00416 ASSERT(cachedir != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); 00417 00418 newcachedir = canonicalize_path(cachedir); 00419 if(!newcachedir) { 00420 RET_ERR(handle, ALPM_ERR_MEMORY, -1); 00421 } 00422 handle->cachedirs = alpm_list_remove_str(handle->cachedirs, newcachedir, &vdata); 00423 FREE(newcachedir); 00424 if(vdata != NULL) { 00425 FREE(vdata); 00426 return 1; 00427 } 00428 return 0; 00429 } 00430 00431 int SYMEXPORT alpm_option_set_logfile(alpm_handle_t *handle, const char *logfile) 00432 { 00433 char *oldlogfile = handle->logfile; 00434 00435 CHECK_HANDLE(handle, return -1); 00436 if(!logfile) { 00437 handle->pm_errno = ALPM_ERR_WRONG_ARGS; 00438 return -1; 00439 } 00440 00441 handle->logfile = strdup(logfile); 00442 00443 /* free the old logfile path string, and close the stream so logaction 00444 * will reopen a new stream on the new logfile */ 00445 if(oldlogfile) { 00446 FREE(oldlogfile); 00447 } 00448 if(handle->logstream) { 00449 fclose(handle->logstream); 00450 handle->logstream = NULL; 00451 } 00452 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'logfile' = %s\n", handle->logfile); 00453 return 0; 00454 } 00455 00456 int SYMEXPORT alpm_option_set_gpgdir(alpm_handle_t *handle, const char *gpgdir) 00457 { 00458 CHECK_HANDLE(handle, return -1); 00459 if(!gpgdir) { 00460 handle->pm_errno = ALPM_ERR_WRONG_ARGS; 00461 return -1; 00462 } 00463 00464 if(handle->gpgdir) { 00465 FREE(handle->gpgdir); 00466 } 00467 handle->gpgdir = strdup(gpgdir); 00468 00469 _alpm_log(handle, ALPM_LOG_DEBUG, "option 'gpgdir' = %s\n", handle->gpgdir); 00470 return 0; 00471 } 00472 00473 int SYMEXPORT alpm_option_set_usesyslog(alpm_handle_t *handle, int usesyslog) 00474 { 00475 CHECK_HANDLE(handle, return -1); 00476 handle->usesyslog = usesyslog; 00477 return 0; 00478 } 00479 00480 int SYMEXPORT alpm_option_add_noupgrade(alpm_handle_t *handle, const char *pkg) 00481 { 00482 CHECK_HANDLE(handle, return -1); 00483 handle->noupgrade = alpm_list_add(handle->noupgrade, strdup(pkg)); 00484 return 0; 00485 } 00486 00487 int SYMEXPORT alpm_option_set_noupgrades(alpm_handle_t *handle, alpm_list_t *noupgrade) 00488 { 00489 CHECK_HANDLE(handle, return -1); 00490 if(handle->noupgrade) FREELIST(handle->noupgrade); 00491 handle->noupgrade = alpm_list_strdup(noupgrade); 00492 return 0; 00493 } 00494 00495 int SYMEXPORT alpm_option_remove_noupgrade(alpm_handle_t *handle, const char *pkg) 00496 { 00497 char *vdata = NULL; 00498 CHECK_HANDLE(handle, return -1); 00499 handle->noupgrade = alpm_list_remove_str(handle->noupgrade, pkg, &vdata); 00500 if(vdata != NULL) { 00501 FREE(vdata); 00502 return 1; 00503 } 00504 return 0; 00505 } 00506 00507 int SYMEXPORT alpm_option_add_noextract(alpm_handle_t *handle, const char *pkg) 00508 { 00509 CHECK_HANDLE(handle, return -1); 00510 handle->noextract = alpm_list_add(handle->noextract, strdup(pkg)); 00511 return 0; 00512 } 00513 00514 int SYMEXPORT alpm_option_set_noextracts(alpm_handle_t *handle, alpm_list_t *noextract) 00515 { 00516 CHECK_HANDLE(handle, return -1); 00517 if(handle->noextract) FREELIST(handle->noextract); 00518 handle->noextract = alpm_list_strdup(noextract); 00519 return 0; 00520 } 00521 00522 int SYMEXPORT alpm_option_remove_noextract(alpm_handle_t *handle, const char *pkg) 00523 { 00524 char *vdata = NULL; 00525 CHECK_HANDLE(handle, return -1); 00526 handle->noextract = alpm_list_remove_str(handle->noextract, pkg, &vdata); 00527 if(vdata != NULL) { 00528 FREE(vdata); 00529 return 1; 00530 } 00531 return 0; 00532 } 00533 00534 int SYMEXPORT alpm_option_add_ignorepkg(alpm_handle_t *handle, const char *pkg) 00535 { 00536 CHECK_HANDLE(handle, return -1); 00537 handle->ignorepkg = alpm_list_add(handle->ignorepkg, strdup(pkg)); 00538 return 0; 00539 } 00540 00541 int SYMEXPORT alpm_option_set_ignorepkgs(alpm_handle_t *handle, alpm_list_t *ignorepkgs) 00542 { 00543 CHECK_HANDLE(handle, return -1); 00544 if(handle->ignorepkg) FREELIST(handle->ignorepkg); 00545 handle->ignorepkg = alpm_list_strdup(ignorepkgs); 00546 return 0; 00547 } 00548 00549 int SYMEXPORT alpm_option_remove_ignorepkg(alpm_handle_t *handle, const char *pkg) 00550 { 00551 char *vdata = NULL; 00552 CHECK_HANDLE(handle, return -1); 00553 handle->ignorepkg = alpm_list_remove_str(handle->ignorepkg, pkg, &vdata); 00554 if(vdata != NULL) { 00555 FREE(vdata); 00556 return 1; 00557 } 00558 return 0; 00559 } 00560 00561 int SYMEXPORT alpm_option_add_ignoregroup(alpm_handle_t *handle, const char *grp) 00562 { 00563 CHECK_HANDLE(handle, return -1); 00564 handle->ignoregroup = alpm_list_add(handle->ignoregroup, strdup(grp)); 00565 return 0; 00566 } 00567 00568 int SYMEXPORT alpm_option_set_ignoregroups(alpm_handle_t *handle, alpm_list_t *ignoregrps) 00569 { 00570 CHECK_HANDLE(handle, return -1); 00571 if(handle->ignoregroup) FREELIST(handle->ignoregroup); 00572 handle->ignoregroup = alpm_list_strdup(ignoregrps); 00573 return 0; 00574 } 00575 00576 int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char *grp) 00577 { 00578 char *vdata = NULL; 00579 CHECK_HANDLE(handle, return -1); 00580 handle->ignoregroup = alpm_list_remove_str(handle->ignoregroup, grp, &vdata); 00581 if(vdata != NULL) { 00582 FREE(vdata); 00583 return 1; 00584 } 00585 return 0; 00586 } 00587 00588 int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch) 00589 { 00590 CHECK_HANDLE(handle, return -1); 00591 if(handle->arch) FREE(handle->arch); 00592 if(arch) { 00593 handle->arch = strdup(arch); 00594 } else { 00595 handle->arch = NULL; 00596 } 00597 return 0; 00598 } 00599 00600 int SYMEXPORT alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta) 00601 { 00602 CHECK_HANDLE(handle, return -1); 00603 handle->usedelta = usedelta; 00604 return 0; 00605 } 00606 00607 int SYMEXPORT alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace) 00608 { 00609 CHECK_HANDLE(handle, return -1); 00610 handle->checkspace = checkspace; 00611 return 0; 00612 } 00613 00614 int SYMEXPORT alpm_option_set_default_siglevel(alpm_handle_t *handle, 00615 alpm_siglevel_t level) 00616 { 00617 CHECK_HANDLE(handle, return -1); 00618 #ifdef HAVE_LIBGPGME 00619 handle->siglevel = level; 00620 #else 00621 if(level != 0 && level != ALPM_SIG_USE_DEFAULT) { 00622 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); 00623 } 00624 #endif 00625 return 0; 00626 } 00627 00628 alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle) 00629 { 00630 CHECK_HANDLE(handle, return -1); 00631 return handle->siglevel; 00632 } 00633 00634 /* vim: set ts=2 sw=2 noet: */