00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025
00026 #include <unistd.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <errno.h>
00030 #include <string.h>
00031 #include <stdint.h>
00032 #include <sys/stat.h>
00033 #include <dirent.h>
00034 #include <regex.h>
00035 #include <time.h>
00036
00037
00038 #include "db.h"
00039 #include "alpm_list.h"
00040 #include "log.h"
00041 #include "util.h"
00042 #include "error.h"
00043 #include "server.h"
00044 #include "handle.h"
00045 #include "cache.h"
00046 #include "alpm.h"
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 pmdb_t SYMEXPORT *alpm_db_register_sync(const char *treename)
00058 {
00059 ALPM_LOG_FUNC;
00060
00061
00062 ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, NULL));
00063 ASSERT(treename != NULL && strlen(treename) != 0, RET_ERR(PM_ERR_WRONG_ARGS, NULL));
00064
00065 ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, NULL));
00066
00067 return(_alpm_db_register_sync(treename));
00068 }
00069
00070
00071
00072
00073 pmdb_t SYMEXPORT *alpm_db_register_local(void)
00074 {
00075 ALPM_LOG_FUNC;
00076
00077
00078 ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, NULL));
00079
00080 ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, NULL));
00081
00082 return(_alpm_db_register_local());
00083 }
00084
00085
00086 static void _alpm_db_unregister(pmdb_t *db)
00087 {
00088 if(db == NULL) {
00089 return;
00090 }
00091
00092 _alpm_log(PM_LOG_DEBUG, "closing database '%s'\n", db->treename);
00093 _alpm_db_close(db);
00094
00095 _alpm_log(PM_LOG_DEBUG, "unregistering database '%s'\n", db->treename);
00096 _alpm_db_free(db);
00097 }
00098
00099
00100
00101
00102 int SYMEXPORT alpm_db_unregister_all(void)
00103 {
00104 alpm_list_t *i;
00105
00106 ALPM_LOG_FUNC;
00107
00108
00109 ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
00110
00111 ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1));
00112
00113
00114 _alpm_db_unregister(handle->db_local);
00115 handle->db_local = NULL;
00116
00117
00118 for(i = handle->dbs_sync; i; i = i->next) {
00119 pmdb_t *db = i->data;
00120 _alpm_db_unregister(db);
00121 i->data = NULL;
00122 }
00123 FREELIST(handle->dbs_sync);
00124 return(0);
00125 }
00126
00127
00128
00129
00130
00131 int SYMEXPORT alpm_db_unregister(pmdb_t *db)
00132 {
00133 int found = 0;
00134
00135 ALPM_LOG_FUNC;
00136
00137
00138 ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
00139 ASSERT(db != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
00140
00141 ASSERT(handle->trans == NULL, RET_ERR(PM_ERR_TRANS_NOT_NULL, -1));
00142
00143 if(db == handle->db_local) {
00144 handle->db_local = NULL;
00145 found = 1;
00146 } else {
00147
00148
00149
00150
00151 void *data;
00152 handle->dbs_sync = alpm_list_remove(handle->dbs_sync,
00153 db, _alpm_db_cmp, &data);
00154 if(data) {
00155 found = 1;
00156 }
00157 }
00158
00159 if(!found) {
00160 RET_ERR(PM_ERR_DB_NOT_FOUND, -1);
00161 }
00162
00163 _alpm_db_unregister(db);
00164 return(0);
00165 }
00166
00167
00168
00169
00170
00171
00172 int SYMEXPORT alpm_db_setserver(pmdb_t *db, const char *url)
00173 {
00174 alpm_list_t *i;
00175 int found = 0;
00176
00177 ALPM_LOG_FUNC;
00178
00179
00180 ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
00181
00182 for(i = handle->dbs_sync; i && !found; i = i->next) {
00183 pmdb_t *sdb = i->data;
00184 if(strcmp(db->treename, sdb->treename) == 0) {
00185 found = 1;
00186 }
00187 }
00188 if(!found) {
00189 RET_ERR(PM_ERR_DB_NOT_FOUND, -1);
00190 }
00191
00192 if(url && strlen(url)) {
00193 pmserver_t *server;
00194 if((server = _alpm_server_new(url)) == NULL) {
00195
00196 return(-1);
00197 }
00198 db->servers = alpm_list_add(db->servers, server);
00199 _alpm_log(PM_LOG_DEBUG, "adding new server to database '%s': protocol '%s', server '%s', path '%s'\n",
00200 db->treename, server->s_url->scheme, server->s_url->host, server->s_url->doc);
00201 } else {
00202 FREELIST(db->servers);
00203 _alpm_log(PM_LOG_DEBUG, "serverlist flushed for '%s'\n", db->treename);
00204 }
00205
00206 return(0);
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216 int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
00217 {
00218 alpm_list_t *lp;
00219 char path[PATH_MAX];
00220 alpm_list_t *files = NULL;
00221 time_t newmtime = 0, lastupdate = 0;
00222 const char *dbpath;
00223 int ret;
00224
00225 ALPM_LOG_FUNC;
00226
00227
00228 ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
00229 ASSERT(db != NULL && db != handle->db_local, RET_ERR(PM_ERR_WRONG_ARGS, -1));
00230
00231
00232
00233
00234 ASSERT(handle->trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
00235 ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED, -1));
00236 ASSERT(handle->trans->type == PM_TRANS_TYPE_SYNC, RET_ERR(PM_ERR_TRANS_TYPE, -1));
00237
00238 if(!alpm_list_find_ptr(handle->dbs_sync, db)) {
00239 RET_ERR(PM_ERR_DB_NOT_FOUND, -1);
00240 }
00241
00242 if(!force) {
00243
00244 lastupdate = _alpm_db_getlastupdate(db);
00245 if(lastupdate == 0) {
00246 _alpm_log(PM_LOG_DEBUG, "failed to get lastupdate time for %s\n",
00247 db->treename);
00248 }
00249 }
00250
00251
00252 snprintf(path, PATH_MAX, "%s" DBEXT, db->treename);
00253 files = alpm_list_add(files, strdup(path));
00254
00255 dbpath = alpm_option_get_dbpath();
00256
00257 ret = _alpm_downloadfiles_forreal(db->servers, dbpath, files, lastupdate,
00258 &newmtime, NULL, 0);
00259 FREELIST(files);
00260 if(ret == 1) {
00261
00262 pm_errno = 0;
00263 return(1);
00264 } else if(ret == -1) {
00265
00266
00267 _alpm_log(PM_LOG_DEBUG, "failed to sync db: %s [%d]\n",
00268 downloadLastErrString, downloadLastErrCode);
00269 RET_ERR(PM_ERR_DB_SYNC, -1);
00270 } else {
00271 if(newmtime != 0) {
00272 _alpm_log(PM_LOG_DEBUG, "sync: new mtime for %s: %ju\n",
00273 db->treename, (uintmax_t)newmtime);
00274 _alpm_db_setlastupdate(db, newmtime);
00275 }
00276 snprintf(path, PATH_MAX, "%s%s" DBEXT, dbpath, db->treename);
00277
00278
00279 _alpm_log(PM_LOG_DEBUG, "flushing database %s\n", db->path);
00280 for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) {
00281 pmpkg_t *pkg = lp->data;
00282 if(pkg && _alpm_db_remove(db, pkg) == -1) {
00283 _alpm_log(PM_LOG_ERROR, _("could not remove database entry %s%s\n"), db->treename,
00284 alpm_pkg_get_name(pkg));
00285 RET_ERR(PM_ERR_DB_REMOVE, -1);
00286 }
00287 }
00288
00289
00290 _alpm_db_free_pkgcache(db);
00291
00292
00293 if(_alpm_db_install(db, path) == -1) {
00294 return -1;
00295 }
00296 }
00297
00298 return(0);
00299 }
00300
00301
00302
00303
00304
00305 const char SYMEXPORT *alpm_db_get_name(const pmdb_t *db)
00306 {
00307 ALPM_LOG_FUNC;
00308
00309
00310 ASSERT(handle != NULL, return(NULL));
00311 ASSERT(db != NULL, return(NULL));
00312
00313 return db->treename;
00314 }
00315
00316
00317
00318
00319
00320 const char SYMEXPORT *alpm_db_get_url(const pmdb_t *db)
00321 {
00322 char path[PATH_MAX];
00323 pmserver_t *s;
00324
00325 ALPM_LOG_FUNC;
00326
00327
00328 ASSERT(handle != NULL, return(NULL));
00329 ASSERT(db != NULL, return(NULL));
00330
00331 s = (pmserver_t*)db->servers->data;
00332
00333 snprintf(path, PATH_MAX, "%s://%s%s", s->s_url->scheme, s->s_url->host, s->s_url->doc);
00334 return strdup(path);
00335 }
00336
00337
00338
00339
00340
00341
00342
00343 pmpkg_t SYMEXPORT *alpm_db_get_pkg(pmdb_t *db, const char *name)
00344 {
00345 ALPM_LOG_FUNC;
00346
00347
00348 ASSERT(handle != NULL, return(NULL));
00349 ASSERT(db != NULL, return(NULL));
00350 ASSERT(name != NULL && strlen(name) != 0, return(NULL));
00351
00352 return(_alpm_db_get_pkgfromcache(db, name));
00353 }
00354
00355
00356
00357
00358
00359 alpm_list_t SYMEXPORT *alpm_db_getpkgcache(pmdb_t *db)
00360 {
00361 ALPM_LOG_FUNC;
00362
00363
00364 ASSERT(handle != NULL, return(NULL));
00365 ASSERT(db != NULL, return(NULL));
00366
00367 return(_alpm_db_get_pkgcache(db));
00368 }
00369
00370
00371
00372
00373
00374
00375 alpm_list_t SYMEXPORT *alpm_db_whatprovides(pmdb_t *db, const char *name)
00376 {
00377 ALPM_LOG_FUNC;
00378
00379
00380 ASSERT(handle != NULL, return(NULL));
00381 ASSERT(db != NULL, return(NULL));
00382 ASSERT(name != NULL && strlen(name) != 0, return(NULL));
00383
00384 return(_alpm_db_whatprovides(db, name));
00385 }
00386
00387
00388
00389
00390
00391
00392 pmgrp_t SYMEXPORT *alpm_db_readgrp(pmdb_t *db, const char *name)
00393 {
00394 ALPM_LOG_FUNC;
00395
00396
00397 ASSERT(handle != NULL, return(NULL));
00398 ASSERT(db != NULL, return(NULL));
00399 ASSERT(name != NULL && strlen(name) != 0, return(NULL));
00400
00401 return(_alpm_db_get_grpfromcache(db, name));
00402 }
00403
00404
00405
00406
00407
00408 alpm_list_t SYMEXPORT *alpm_db_getgrpcache(pmdb_t *db)
00409 {
00410 ALPM_LOG_FUNC;
00411
00412
00413 ASSERT(handle != NULL, return(NULL));
00414 ASSERT(db != NULL, return(NULL));
00415
00416 return(_alpm_db_get_grpcache(db));
00417 }
00418
00419
00420
00421
00422
00423
00424 alpm_list_t SYMEXPORT *alpm_db_search(pmdb_t *db, const alpm_list_t* needles)
00425 {
00426 ALPM_LOG_FUNC;
00427
00428
00429 ASSERT(handle != NULL, return(NULL));
00430 ASSERT(db != NULL, return(NULL));
00431
00432 return(_alpm_db_search(db, needles));
00433 }
00434
00435
00436
00437 pmdb_t *_alpm_db_new(const char *dbpath, const char *treename)
00438 {
00439 pmdb_t *db;
00440 const size_t pathsize = strlen(dbpath) + strlen(treename) + 2;
00441
00442 ALPM_LOG_FUNC;
00443
00444 CALLOC(db, 1, sizeof(pmdb_t), RET_ERR(PM_ERR_MEMORY, NULL));
00445 CALLOC(db->path, 1, pathsize, RET_ERR(PM_ERR_MEMORY, NULL));
00446
00447 sprintf(db->path, "%s%s/", dbpath, treename);
00448
00449 strncpy(db->treename, treename, PATH_MAX);
00450
00451 return(db);
00452 }
00453
00454 void _alpm_db_free(pmdb_t *db)
00455 {
00456 alpm_list_t *tmp;
00457
00458 ALPM_LOG_FUNC;
00459
00460
00461 _alpm_db_free_pkgcache(db);
00462
00463 for(tmp = db->servers; tmp; tmp = alpm_list_next(tmp)) {
00464 _alpm_server_free(tmp->data);
00465 }
00466 alpm_list_free(db->servers);
00467 FREE(db->path);
00468 FREE(db);
00469
00470 return;
00471 }
00472
00473 int _alpm_db_cmp(const void *db1, const void *db2)
00474 {
00475 ALPM_LOG_FUNC;
00476 return(strcmp(((pmdb_t *)db1)->treename, ((pmdb_t *)db2)->treename));
00477 }
00478
00479 alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles)
00480 {
00481 const alpm_list_t *i, *j, *k;
00482 alpm_list_t *ret = NULL;
00483
00484 ALPM_LOG_FUNC;
00485
00486 for(i = needles; i; i = i->next) {
00487 char *targ;
00488 regex_t reg;
00489
00490 if(i->data == NULL) {
00491 continue;
00492 }
00493 targ = i->data;
00494 _alpm_log(PM_LOG_DEBUG, "searching for target '%s'\n", targ);
00495
00496 if(regcomp(®, targ, REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE) != 0) {
00497 RET_ERR(PM_ERR_INVALID_REGEX, NULL);
00498 }
00499
00500 for(j = _alpm_db_get_pkgcache(db); j; j = j->next) {
00501 pmpkg_t *pkg = j->data;
00502 const char *matched = NULL;
00503 const char *name = alpm_pkg_get_name(pkg);
00504 const char *desc = alpm_pkg_get_desc(pkg);
00505
00506
00507 if(name && (regexec(®, name, 0, 0, 0) == 0 || strstr(name, targ))) {
00508 matched = name;
00509 }
00510
00511 else if (desc && regexec(®, desc, 0, 0, 0) == 0) {
00512 matched = desc;
00513 }
00514
00515
00516
00517 else {
00518 for(k = alpm_pkg_get_provides(pkg); k; k = k->next) {
00519 if (regexec(®, k->data, 0, 0, 0) == 0) {
00520 matched = k->data;
00521 break;
00522 }
00523 }
00524 }
00525
00526 if(matched != NULL) {
00527 _alpm_log(PM_LOG_DEBUG, " search target '%s' matched '%s'\n",
00528 targ, matched);
00529 ret = alpm_list_add(ret, pkg);
00530 }
00531 }
00532
00533 regfree(®);
00534 }
00535
00536 return(ret);
00537 }
00538
00539 pmdb_t *_alpm_db_register_local(void)
00540 {
00541 struct stat buf;
00542 pmdb_t *db;
00543 const char *dbpath;
00544 char path[PATH_MAX];
00545
00546 ALPM_LOG_FUNC;
00547
00548 if(handle->db_local != NULL) {
00549 _alpm_log(PM_LOG_WARNING, _("attempt to re-register the 'local' DB\n"));
00550 RET_ERR(PM_ERR_DB_NOT_NULL, NULL);
00551 }
00552
00553 _alpm_log(PM_LOG_DEBUG, "registering local database\n");
00554
00555
00556 dbpath = alpm_option_get_dbpath();
00557 if(!dbpath) {
00558 _alpm_log(PM_LOG_ERROR, _("database path is undefined\n"));
00559 RET_ERR(PM_ERR_DB_OPEN, NULL);
00560 }
00561 snprintf(path, PATH_MAX, "%slocal", dbpath);
00562
00563 if(stat(path, &buf) != 0 || !S_ISDIR(buf.st_mode)) {
00564 _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n",
00565 path);
00566 if(_alpm_makepath(path) != 0) {
00567 RET_ERR(PM_ERR_SYSTEM, NULL);
00568 }
00569 }
00570
00571 db = _alpm_db_new(dbpath, "local");
00572 if(db == NULL) {
00573 RET_ERR(PM_ERR_DB_CREATE, NULL);
00574 }
00575
00576 _alpm_log(PM_LOG_DEBUG, "opening database '%s'\n", db->treename);
00577 if(_alpm_db_open(db) == -1) {
00578 _alpm_db_free(db);
00579 RET_ERR(PM_ERR_DB_OPEN, NULL);
00580 }
00581
00582 handle->db_local = db;
00583 return(db);
00584 }
00585
00586 pmdb_t *_alpm_db_register_sync(const char *treename)
00587 {
00588 struct stat buf;
00589 pmdb_t *db;
00590 const char *dbpath;
00591 char path[PATH_MAX];
00592 alpm_list_t *i;
00593
00594 ALPM_LOG_FUNC;
00595
00596 for(i = handle->dbs_sync; i; i = i->next) {
00597 pmdb_t *sdb = i->data;
00598 if(strcmp(treename, sdb->treename) == 0) {
00599 _alpm_log(PM_LOG_DEBUG, "attempt to re-register the '%s' database, using existing\n", sdb->treename);
00600 return sdb;
00601 }
00602 }
00603
00604 _alpm_log(PM_LOG_DEBUG, "registering sync database '%s'\n", treename);
00605
00606
00607 dbpath = alpm_option_get_dbpath();
00608 if(!dbpath) {
00609 _alpm_log(PM_LOG_ERROR, _("database path is undefined\n"));
00610 RET_ERR(PM_ERR_DB_OPEN, NULL);
00611 }
00612
00613 snprintf(path, PATH_MAX, "%ssync/%s", dbpath, treename);
00614
00615 if(stat(path, &buf) != 0 || !S_ISDIR(buf.st_mode)) {
00616 _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n",
00617 path);
00618 if(_alpm_makepath(path) != 0) {
00619 RET_ERR(PM_ERR_SYSTEM, NULL);
00620 }
00621 }
00622
00623
00624 path[0] = '\0';
00625 snprintf(path, PATH_MAX, "%ssync/", dbpath);
00626
00627 db = _alpm_db_new(path, treename);
00628 if(db == NULL) {
00629 RET_ERR(PM_ERR_DB_CREATE, NULL);
00630 }
00631
00632 _alpm_log(PM_LOG_DEBUG, "opening database '%s'\n", db->treename);
00633 if(_alpm_db_open(db) == -1) {
00634 _alpm_db_free(db);
00635 RET_ERR(PM_ERR_DB_OPEN, NULL);
00636 }
00637
00638 handle->dbs_sync = alpm_list_add(handle->dbs_sync, db);
00639 return(db);
00640 }
00641
00642
00643
00644
00645
00646 int _alpm_prov_cmp(const void *provision, const void *needle)
00647 {
00648 char *tmpptr;
00649 char *provname = strdup(provision);
00650 int retval = 0;
00651 tmpptr = strchr(provname, '=');
00652
00653 if(tmpptr != NULL) {
00654 *tmpptr='\0';
00655 }
00656 retval = strcmp(provname, needle);
00657 free(provname);
00658 return(retval);
00659 }
00660
00661
00662
00663 alpm_list_t *_alpm_db_whatprovides(pmdb_t *db, const char *package)
00664 {
00665 alpm_list_t *pkgs = NULL;
00666 alpm_list_t *lp;
00667
00668 ALPM_LOG_FUNC;
00669
00670 if(db == NULL || package == NULL || strlen(package) == 0) {
00671 return(NULL);
00672 }
00673
00674 for(lp = _alpm_db_get_pkgcache(db); lp; lp = lp->next) {
00675 pmpkg_t *info = lp->data;
00676
00677 if(alpm_list_find(alpm_pkg_get_provides(info), (const void *)package, _alpm_prov_cmp)) {
00678 pkgs = alpm_list_add(pkgs, info);
00679 }
00680 }
00681
00682 return(pkgs);
00683 }
00684
00685