libalpm
Arch Linux Package Manager Library
|
00001 /* 00002 * db.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 by Christian Hamar <krics@linuxforum.hu> 00008 * Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org> 00009 * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org> 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00023 */ 00024 00025 #include <stdio.h> 00026 #include <stdlib.h> 00027 #include <string.h> 00028 #include <regex.h> 00029 00030 /* libalpm */ 00031 #include "db.h" 00032 #include "alpm_list.h" 00033 #include "log.h" 00034 #include "util.h" 00035 #include "handle.h" 00036 #include "alpm.h" 00037 #include "package.h" 00038 #include "group.h" 00039 00040 /** \addtogroup alpm_databases Database Functions 00041 * @brief Functions to query and manipulate the database of libalpm 00042 * @{ 00043 */ 00044 00045 /** Register a sync database of packages. */ 00046 alpm_db_t SYMEXPORT *alpm_db_register_sync(alpm_handle_t *handle, 00047 const char *treename, alpm_siglevel_t level) 00048 { 00049 /* Sanity checks */ 00050 CHECK_HANDLE(handle, return NULL); 00051 ASSERT(treename != NULL && strlen(treename) != 0, 00052 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL)); 00053 /* Do not register a database if a transaction is on-going */ 00054 ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, NULL)); 00055 00056 return _alpm_db_register_sync(handle, treename, level); 00057 } 00058 00059 /* Helper function for alpm_db_unregister{_all} */ 00060 void _alpm_db_unregister(alpm_db_t *db) 00061 { 00062 if(db == NULL) { 00063 return; 00064 } 00065 00066 _alpm_log(db->handle, ALPM_LOG_DEBUG, "unregistering database '%s'\n", db->treename); 00067 _alpm_db_free(db); 00068 } 00069 00070 /** Unregister all package databases. */ 00071 int SYMEXPORT alpm_db_unregister_all(alpm_handle_t *handle) 00072 { 00073 alpm_list_t *i; 00074 alpm_db_t *db; 00075 00076 /* Sanity checks */ 00077 CHECK_HANDLE(handle, return -1); 00078 /* Do not unregister a database if a transaction is on-going */ 00079 ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, -1)); 00080 00081 /* unregister all sync dbs */ 00082 for(i = handle->dbs_sync; i; i = i->next) { 00083 db = i->data; 00084 db->ops->unregister(db); 00085 i->data = NULL; 00086 } 00087 FREELIST(handle->dbs_sync); 00088 return 0; 00089 } 00090 00091 /** Unregister a package database. */ 00092 int SYMEXPORT alpm_db_unregister(alpm_db_t *db) 00093 { 00094 int found = 0; 00095 alpm_handle_t *handle; 00096 00097 /* Sanity checks */ 00098 ASSERT(db != NULL, return -1); 00099 /* Do not unregister a database if a transaction is on-going */ 00100 handle = db->handle; 00101 handle->pm_errno = 0; 00102 ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, -1)); 00103 00104 if(db == handle->db_local) { 00105 handle->db_local = NULL; 00106 found = 1; 00107 } else { 00108 /* Warning : this function shouldn't be used to unregister all sync 00109 * databases by walking through the list returned by 00110 * alpm_option_get_syncdbs, because the db is removed from that list here. 00111 */ 00112 void *data; 00113 handle->dbs_sync = alpm_list_remove(handle->dbs_sync, 00114 db, _alpm_db_cmp, &data); 00115 if(data) { 00116 found = 1; 00117 } 00118 } 00119 00120 if(!found) { 00121 RET_ERR(handle, ALPM_ERR_DB_NOT_FOUND, -1); 00122 } 00123 00124 db->ops->unregister(db); 00125 return 0; 00126 } 00127 00128 /** Get the serverlist of a database. */ 00129 alpm_list_t SYMEXPORT *alpm_db_get_servers(const alpm_db_t *db) 00130 { 00131 ASSERT(db != NULL, return NULL); 00132 return db->servers; 00133 } 00134 00135 /** Set the serverlist of a database. */ 00136 int SYMEXPORT alpm_db_set_servers(alpm_db_t *db, alpm_list_t *servers) 00137 { 00138 ASSERT(db != NULL, return -1); 00139 if(db->servers) FREELIST(db->servers); 00140 db->servers = servers; 00141 return 0; 00142 } 00143 00144 static char *sanitize_url(const char *url) 00145 { 00146 char *newurl; 00147 size_t len = strlen(url); 00148 00149 STRDUP(newurl, url, return NULL); 00150 /* strip the trailing slash if one exists */ 00151 if(newurl[len - 1] == '/') { 00152 newurl[len - 1] = '\0'; 00153 } 00154 return newurl; 00155 } 00156 00157 /** Add a download server to a database. 00158 * @param db database pointer 00159 * @param url url of the server 00160 * @return 0 on success, -1 on error (pm_errno is set accordingly) 00161 */ 00162 int SYMEXPORT alpm_db_add_server(alpm_db_t *db, const char *url) 00163 { 00164 char *newurl; 00165 00166 /* Sanity checks */ 00167 ASSERT(db != NULL, return -1); 00168 db->handle->pm_errno = 0; 00169 ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1)); 00170 00171 newurl = sanitize_url(url); 00172 if(!newurl) { 00173 return -1; 00174 } 00175 db->servers = alpm_list_add(db->servers, newurl); 00176 _alpm_log(db->handle, ALPM_LOG_DEBUG, "adding new server URL to database '%s': %s\n", 00177 db->treename, newurl); 00178 00179 return 0; 00180 } 00181 00182 /** Remove a download server from a database. 00183 * @param db database pointer 00184 * @param url url of the server 00185 * @return 0 on success, 1 on server not present, 00186 * -1 on error (pm_errno is set accordingly) 00187 */ 00188 int SYMEXPORT alpm_db_remove_server(alpm_db_t *db, const char *url) 00189 { 00190 char *newurl, *vdata = NULL; 00191 00192 /* Sanity checks */ 00193 ASSERT(db != NULL, return -1); 00194 db->handle->pm_errno = 0; 00195 ASSERT(url != NULL && strlen(url) != 0, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1)); 00196 00197 newurl = sanitize_url(url); 00198 if(!newurl) { 00199 return -1; 00200 } 00201 db->servers = alpm_list_remove_str(db->servers, newurl, &vdata); 00202 free(newurl); 00203 if(vdata) { 00204 _alpm_log(db->handle, ALPM_LOG_DEBUG, "removed server URL from database '%s': %s\n", 00205 db->treename, newurl); 00206 free(vdata); 00207 return 0; 00208 } 00209 00210 return 1; 00211 } 00212 00213 /** Get the name of a package database. */ 00214 const char SYMEXPORT *alpm_db_get_name(const alpm_db_t *db) 00215 { 00216 ASSERT(db != NULL, return NULL); 00217 return db->treename; 00218 } 00219 00220 /** Get the signature verification level for a database. */ 00221 alpm_siglevel_t SYMEXPORT alpm_db_get_siglevel(alpm_db_t *db) 00222 { 00223 ASSERT(db != NULL, return -1); 00224 if(db->siglevel & ALPM_SIG_USE_DEFAULT) { 00225 return db->handle->siglevel; 00226 } else { 00227 return db->siglevel; 00228 } 00229 } 00230 00231 /** Check the validity of a database. */ 00232 int SYMEXPORT alpm_db_get_valid(alpm_db_t *db) 00233 { 00234 ASSERT(db != NULL, return -1); 00235 db->handle->pm_errno = 0; 00236 return db->ops->validate(db); 00237 } 00238 00239 /** Get a package entry from a package database. */ 00240 alpm_pkg_t SYMEXPORT *alpm_db_get_pkg(alpm_db_t *db, const char *name) 00241 { 00242 alpm_pkg_t *pkg; 00243 ASSERT(db != NULL, return NULL); 00244 db->handle->pm_errno = 0; 00245 ASSERT(name != NULL && strlen(name) != 0, 00246 RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, NULL)); 00247 00248 pkg = _alpm_db_get_pkgfromcache(db, name); 00249 if(!pkg) { 00250 RET_ERR(db->handle, ALPM_ERR_PKG_NOT_FOUND, NULL); 00251 } 00252 return pkg; 00253 } 00254 00255 /** Get the package cache of a package database. */ 00256 alpm_list_t SYMEXPORT *alpm_db_get_pkgcache(alpm_db_t *db) 00257 { 00258 ASSERT(db != NULL, return NULL); 00259 db->handle->pm_errno = 0; 00260 return _alpm_db_get_pkgcache(db); 00261 } 00262 00263 /** Get a group entry from a package database. */ 00264 alpm_group_t SYMEXPORT *alpm_db_readgroup(alpm_db_t *db, const char *name) 00265 { 00266 ASSERT(db != NULL, return NULL); 00267 db->handle->pm_errno = 0; 00268 ASSERT(name != NULL && strlen(name) != 0, 00269 RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, NULL)); 00270 00271 return _alpm_db_get_groupfromcache(db, name); 00272 } 00273 00274 /** Get the group cache of a package database. */ 00275 alpm_list_t SYMEXPORT *alpm_db_get_groupcache(alpm_db_t *db) 00276 { 00277 ASSERT(db != NULL, return NULL); 00278 db->handle->pm_errno = 0; 00279 00280 return _alpm_db_get_groupcache(db); 00281 } 00282 00283 /** Searches a database. */ 00284 alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles) 00285 { 00286 ASSERT(db != NULL, return NULL); 00287 db->handle->pm_errno = 0; 00288 00289 return _alpm_db_search(db, needles); 00290 } 00291 00292 /** Set install reason for a package in db. */ 00293 int SYMEXPORT alpm_db_set_pkgreason(alpm_handle_t *handle, alpm_pkg_t *pkg, 00294 alpm_pkgreason_t reason) 00295 { 00296 CHECK_HANDLE(handle, return -1); 00297 ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); 00298 ASSERT(pkg->origin == PKG_FROM_LOCALDB, 00299 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); 00300 ASSERT(pkg->origin_data.db == handle->db_local, 00301 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); 00302 00303 _alpm_log(handle, ALPM_LOG_DEBUG, 00304 "setting install reason %u for %s\n", reason, pkg->name); 00305 if(alpm_pkg_get_reason(pkg) == reason) { 00306 /* we are done */ 00307 return 0; 00308 } 00309 /* set reason (in pkgcache) */ 00310 pkg->reason = reason; 00311 /* write DESC */ 00312 if(_alpm_local_db_write(handle->db_local, pkg, INFRQ_DESC)) { 00313 RET_ERR(handle, ALPM_ERR_DB_WRITE, -1); 00314 } 00315 00316 return 0; 00317 } 00318 00319 /** @} */ 00320 00321 alpm_db_t *_alpm_db_new(const char *treename, int is_local) 00322 { 00323 alpm_db_t *db; 00324 00325 CALLOC(db, 1, sizeof(alpm_db_t), return NULL); 00326 STRDUP(db->treename, treename, return NULL); 00327 if(is_local) { 00328 db->status |= DB_STATUS_LOCAL; 00329 } else { 00330 db->status &= ~DB_STATUS_LOCAL; 00331 } 00332 00333 return db; 00334 } 00335 00336 void _alpm_db_free(alpm_db_t *db) 00337 { 00338 /* cleanup pkgcache */ 00339 _alpm_db_free_pkgcache(db); 00340 /* cleanup server list */ 00341 FREELIST(db->servers); 00342 FREE(db->_path); 00343 FREE(db->treename); 00344 FREE(db); 00345 00346 return; 00347 } 00348 00349 const char *_alpm_db_path(alpm_db_t *db) 00350 { 00351 if(!db) { 00352 return NULL; 00353 } 00354 if(!db->_path) { 00355 const char *dbpath; 00356 size_t pathsize; 00357 00358 dbpath = db->handle->dbpath; 00359 if(!dbpath) { 00360 _alpm_log(db->handle, ALPM_LOG_ERROR, _("database path is undefined\n")); 00361 RET_ERR(db->handle, ALPM_ERR_DB_OPEN, NULL); 00362 } 00363 00364 if(db->status & DB_STATUS_LOCAL) { 00365 pathsize = strlen(dbpath) + strlen(db->treename) + 2; 00366 CALLOC(db->_path, 1, pathsize, RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL)); 00367 sprintf(db->_path, "%s%s/", dbpath, db->treename); 00368 } else { 00369 pathsize = strlen(dbpath) + 5 + strlen(db->treename) + 4; 00370 CALLOC(db->_path, 1, pathsize, RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL)); 00371 /* all sync DBs now reside in the sync/ subdir of the dbpath */ 00372 sprintf(db->_path, "%ssync/%s.db", dbpath, db->treename); 00373 } 00374 _alpm_log(db->handle, ALPM_LOG_DEBUG, "database path for tree %s set to %s\n", 00375 db->treename, db->_path); 00376 } 00377 return db->_path; 00378 } 00379 00380 int _alpm_db_cmp(const void *d1, const void *d2) 00381 { 00382 const alpm_db_t *db1 = d1; 00383 const alpm_db_t *db2 = d2; 00384 return strcmp(db1->treename, db2->treename); 00385 } 00386 00387 alpm_list_t *_alpm_db_search(alpm_db_t *db, const alpm_list_t *needles) 00388 { 00389 const alpm_list_t *i, *j, *k; 00390 alpm_list_t *ret = NULL; 00391 /* copy the pkgcache- we will free the list var after each needle */ 00392 alpm_list_t *list = alpm_list_copy(_alpm_db_get_pkgcache(db)); 00393 00394 for(i = needles; i; i = i->next) { 00395 char *targ; 00396 regex_t reg; 00397 00398 if(i->data == NULL) { 00399 continue; 00400 } 00401 ret = NULL; 00402 targ = i->data; 00403 _alpm_log(db->handle, ALPM_LOG_DEBUG, "searching for target '%s'\n", targ); 00404 00405 if(regcomp(®, targ, REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE) != 0) { 00406 RET_ERR(db->handle, ALPM_ERR_INVALID_REGEX, NULL); 00407 } 00408 00409 for(j = list; j; j = j->next) { 00410 alpm_pkg_t *pkg = j->data; 00411 const char *matched = NULL; 00412 const char *name = pkg->name; 00413 const char *desc = alpm_pkg_get_desc(pkg); 00414 00415 /* check name as regex AND as plain text */ 00416 if(name && (regexec(®, name, 0, 0, 0) == 0 || strstr(name, targ))) { 00417 matched = name; 00418 } 00419 /* check desc */ 00420 else if(desc && regexec(®, desc, 0, 0, 0) == 0) { 00421 matched = desc; 00422 } 00423 /* TODO: should we be doing this, and should we print something 00424 * differently when we do match it since it isn't currently printed? */ 00425 if(!matched) { 00426 /* check provides */ 00427 for(k = alpm_pkg_get_provides(pkg); k; k = k->next) { 00428 alpm_depend_t *provide = k->data; 00429 if(regexec(®, provide->name, 0, 0, 0) == 0) { 00430 matched = provide->name; 00431 break; 00432 } 00433 } 00434 } 00435 if(!matched) { 00436 /* check groups */ 00437 for(k = alpm_pkg_get_groups(pkg); k; k = k->next) { 00438 if(regexec(®, k->data, 0, 0, 0) == 0) { 00439 matched = k->data; 00440 break; 00441 } 00442 } 00443 } 00444 00445 if(matched != NULL) { 00446 _alpm_log(db->handle, ALPM_LOG_DEBUG, 00447 "search target '%s' matched '%s'\n", targ, matched); 00448 ret = alpm_list_add(ret, pkg); 00449 } 00450 } 00451 00452 /* Free the existing search list, and use the returned list for the 00453 * next needle. This allows for AND-based package searching. */ 00454 alpm_list_free(list); 00455 list = ret; 00456 regfree(®); 00457 } 00458 00459 return ret; 00460 } 00461 00462 /* Returns a new package cache from db. 00463 * It frees the cache if it already exists. 00464 */ 00465 static int load_pkgcache(alpm_db_t *db) 00466 { 00467 _alpm_db_free_pkgcache(db); 00468 00469 _alpm_log(db->handle, ALPM_LOG_DEBUG, "loading package cache for repository '%s'\n", 00470 db->treename); 00471 if(db->ops->populate(db) == -1) { 00472 _alpm_log(db->handle, ALPM_LOG_DEBUG, 00473 "failed to load package cache for repository '%s'\n", db->treename); 00474 return -1; 00475 } 00476 00477 db->status |= DB_STATUS_PKGCACHE; 00478 return 0; 00479 } 00480 00481 static void free_groupcache(alpm_db_t *db) 00482 { 00483 alpm_list_t *lg; 00484 00485 if(db == NULL || !(db->status & DB_STATUS_GRPCACHE)) { 00486 return; 00487 } 00488 00489 _alpm_log(db->handle, ALPM_LOG_DEBUG, 00490 "freeing group cache for repository '%s'\n", db->treename); 00491 00492 for(lg = db->grpcache; lg; lg = lg->next) { 00493 _alpm_group_free(lg->data); 00494 lg->data = NULL; 00495 } 00496 FREELIST(db->grpcache); 00497 db->status &= ~DB_STATUS_GRPCACHE; 00498 } 00499 00500 void _alpm_db_free_pkgcache(alpm_db_t *db) 00501 { 00502 if(db == NULL || !(db->status & DB_STATUS_PKGCACHE)) { 00503 return; 00504 } 00505 00506 _alpm_log(db->handle, ALPM_LOG_DEBUG, 00507 "freeing package cache for repository '%s'\n", db->treename); 00508 00509 if(db->pkgcache) { 00510 alpm_list_free_inner(db->pkgcache->list, 00511 (alpm_list_fn_free)_alpm_pkg_free); 00512 _alpm_pkghash_free(db->pkgcache); 00513 } 00514 db->status &= ~DB_STATUS_PKGCACHE; 00515 00516 free_groupcache(db); 00517 } 00518 00519 alpm_pkghash_t *_alpm_db_get_pkgcache_hash(alpm_db_t *db) 00520 { 00521 if(db == NULL) { 00522 return NULL; 00523 } 00524 00525 if(!(db->status & DB_STATUS_VALID)) { 00526 RET_ERR(db->handle, ALPM_ERR_DB_INVALID, NULL); 00527 } 00528 00529 if(!(db->status & DB_STATUS_PKGCACHE)) { 00530 load_pkgcache(db); 00531 } 00532 00533 return db->pkgcache; 00534 } 00535 00536 alpm_list_t *_alpm_db_get_pkgcache(alpm_db_t *db) 00537 { 00538 alpm_pkghash_t *hash = _alpm_db_get_pkgcache_hash(db); 00539 00540 if(hash == NULL) { 00541 return NULL; 00542 } 00543 00544 return hash->list; 00545 } 00546 00547 /* "duplicate" pkg then add it to pkgcache */ 00548 int _alpm_db_add_pkgincache(alpm_db_t *db, alpm_pkg_t *pkg) 00549 { 00550 alpm_pkg_t *newpkg; 00551 00552 if(db == NULL || pkg == NULL || !(db->status & DB_STATUS_PKGCACHE)) { 00553 return -1; 00554 } 00555 00556 if(_alpm_pkg_dup(pkg, &newpkg)) { 00557 return -1; 00558 } 00559 00560 _alpm_log(db->handle, ALPM_LOG_DEBUG, "adding entry '%s' in '%s' cache\n", 00561 newpkg->name, db->treename); 00562 db->pkgcache = _alpm_pkghash_add_sorted(db->pkgcache, newpkg); 00563 00564 free_groupcache(db); 00565 00566 return 0; 00567 } 00568 00569 int _alpm_db_remove_pkgfromcache(alpm_db_t *db, alpm_pkg_t *pkg) 00570 { 00571 alpm_pkg_t *data = NULL; 00572 00573 if(db == NULL || pkg == NULL || !(db->status & DB_STATUS_PKGCACHE)) { 00574 return -1; 00575 } 00576 00577 _alpm_log(db->handle, ALPM_LOG_DEBUG, "removing entry '%s' from '%s' cache\n", 00578 pkg->name, db->treename); 00579 00580 db->pkgcache = _alpm_pkghash_remove(db->pkgcache, pkg, &data); 00581 if(data == NULL) { 00582 /* package not found */ 00583 _alpm_log(db->handle, ALPM_LOG_DEBUG, "cannot remove entry '%s' from '%s' cache: not found\n", 00584 pkg->name, db->treename); 00585 return -1; 00586 } 00587 00588 _alpm_pkg_free(data); 00589 00590 free_groupcache(db); 00591 00592 return 0; 00593 } 00594 00595 alpm_pkg_t *_alpm_db_get_pkgfromcache(alpm_db_t *db, const char *target) 00596 { 00597 if(db == NULL) { 00598 return NULL; 00599 } 00600 00601 alpm_pkghash_t *pkgcache = _alpm_db_get_pkgcache_hash(db); 00602 if(!pkgcache) { 00603 return NULL; 00604 } 00605 00606 return _alpm_pkghash_find(pkgcache, target); 00607 } 00608 00609 /* Returns a new group cache from db. 00610 */ 00611 static int load_grpcache(alpm_db_t *db) 00612 { 00613 alpm_list_t *lp; 00614 00615 if(db == NULL) { 00616 return -1; 00617 } 00618 00619 _alpm_log(db->handle, ALPM_LOG_DEBUG, "loading group cache for repository '%s'\n", 00620 db->treename); 00621 00622 for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) { 00623 const alpm_list_t *i; 00624 alpm_pkg_t *pkg = lp->data; 00625 00626 for(i = alpm_pkg_get_groups(pkg); i; i = i->next) { 00627 const char *grpname = i->data; 00628 alpm_list_t *j; 00629 alpm_group_t *grp = NULL; 00630 int found = 0; 00631 00632 /* first look through the group cache for a group with this name */ 00633 for(j = db->grpcache; j; j = j->next) { 00634 grp = j->data; 00635 00636 if(strcmp(grp->name, grpname) == 0 00637 && !alpm_list_find_ptr(grp->packages, pkg)) { 00638 grp->packages = alpm_list_add(grp->packages, pkg); 00639 found = 1; 00640 break; 00641 } 00642 } 00643 if(found) { 00644 continue; 00645 } 00646 /* we didn't find the group, so create a new one with this name */ 00647 grp = _alpm_group_new(grpname); 00648 if(!grp) { 00649 free_groupcache(db); 00650 return -1; 00651 } 00652 grp->packages = alpm_list_add(grp->packages, pkg); 00653 db->grpcache = alpm_list_add(db->grpcache, grp); 00654 } 00655 } 00656 00657 db->status |= DB_STATUS_GRPCACHE; 00658 return 0; 00659 } 00660 00661 alpm_list_t *_alpm_db_get_groupcache(alpm_db_t *db) 00662 { 00663 if(db == NULL) { 00664 return NULL; 00665 } 00666 00667 if(!(db->status & DB_STATUS_VALID)) { 00668 RET_ERR(db->handle, ALPM_ERR_DB_INVALID, NULL); 00669 } 00670 00671 if(!(db->status & DB_STATUS_GRPCACHE)) { 00672 load_grpcache(db); 00673 } 00674 00675 return db->grpcache; 00676 } 00677 00678 alpm_group_t *_alpm_db_get_groupfromcache(alpm_db_t *db, const char *target) 00679 { 00680 alpm_list_t *i; 00681 00682 if(db == NULL || target == NULL || strlen(target) == 0) { 00683 return NULL; 00684 } 00685 00686 for(i = _alpm_db_get_groupcache(db); i; i = i->next) { 00687 alpm_group_t *info = i->data; 00688 00689 if(strcmp(info->name, target) == 0) { 00690 return info; 00691 } 00692 } 00693 00694 return NULL; 00695 } 00696 00697 /* vim: set ts=2 sw=2 noet: */