libalpm
Arch Linux Package Manager Library
|
00001 /* 00002 * be_sync.c : backend for sync databases 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 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include <errno.h> 00022 #include <sys/types.h> 00023 #include <sys/stat.h> 00024 #include <fcntl.h> 00025 #include <unistd.h> 00026 00027 /* libarchive */ 00028 #include <archive.h> 00029 #include <archive_entry.h> 00030 00031 /* libalpm */ 00032 #include "util.h" 00033 #include "log.h" 00034 #include "alpm.h" 00035 #include "alpm_list.h" 00036 #include "package.h" 00037 #include "handle.h" 00038 #include "delta.h" 00039 #include "deps.h" 00040 #include "dload.h" 00041 00042 static char *get_sync_dir(alpm_handle_t *handle) 00043 { 00044 size_t len = strlen(handle->dbpath) + 6; 00045 char *syncpath; 00046 struct stat buf; 00047 00048 MALLOC(syncpath, len, RET_ERR(handle, ALPM_ERR_MEMORY, NULL)); 00049 sprintf(syncpath, "%s%s", handle->dbpath, "sync/"); 00050 00051 if(stat(syncpath, &buf) != 0) { 00052 _alpm_log(handle, ALPM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n", 00053 syncpath); 00054 if(_alpm_makepath(syncpath) != 0) { 00055 free(syncpath); 00056 RET_ERR(handle, ALPM_ERR_SYSTEM, NULL); 00057 } 00058 } else if(!S_ISDIR(buf.st_mode)) { 00059 _alpm_log(handle, ALPM_LOG_WARNING, _("removing invalid file: %s\n"), syncpath); 00060 if(unlink(syncpath) != 0 || _alpm_makepath(syncpath) != 0) { 00061 free(syncpath); 00062 RET_ERR(handle, ALPM_ERR_SYSTEM, NULL); 00063 } 00064 } 00065 00066 return syncpath; 00067 } 00068 00069 static int sync_db_validate(alpm_db_t *db) 00070 { 00071 alpm_siglevel_t level; 00072 const char *dbpath; 00073 00074 if(db->status & DB_STATUS_VALID || db->status & DB_STATUS_MISSING) { 00075 return 0; 00076 } 00077 if(db->status & DB_STATUS_INVALID) { 00078 db->handle->pm_errno = ALPM_ERR_DB_INVALID_SIG; 00079 return -1; 00080 } 00081 00082 dbpath = _alpm_db_path(db); 00083 if(!dbpath) { 00084 /* pm_errno set in _alpm_db_path() */ 00085 return -1; 00086 } 00087 00088 /* we can skip any validation if the database doesn't exist */ 00089 if(access(dbpath, R_OK) != 0 && errno == ENOENT) { 00090 db->status &= ~DB_STATUS_EXISTS; 00091 db->status |= DB_STATUS_MISSING; 00092 _alpm_log(db->handle, ALPM_LOG_WARNING, 00093 "database file for '%s' does not exist\n", db->treename); 00094 goto valid; 00095 } 00096 db->status |= DB_STATUS_EXISTS; 00097 db->status &= ~DB_STATUS_MISSING; 00098 00099 /* this takes into account the default verification level if UNKNOWN 00100 * was assigned to this db */ 00101 level = alpm_db_get_siglevel(db); 00102 00103 if(level & ALPM_SIG_DATABASE) { 00104 int retry, ret; 00105 do { 00106 retry = 0; 00107 alpm_siglist_t *siglist; 00108 ret = _alpm_check_pgp_helper(db->handle, dbpath, NULL, 00109 level & ALPM_SIG_DATABASE_OPTIONAL, level & ALPM_SIG_DATABASE_MARGINAL_OK, 00110 level & ALPM_SIG_DATABASE_UNKNOWN_OK, &siglist); 00111 if(ret) { 00112 retry = _alpm_process_siglist(db->handle, db->treename, siglist, 00113 level & ALPM_SIG_DATABASE_OPTIONAL, level & ALPM_SIG_DATABASE_MARGINAL_OK, 00114 level & ALPM_SIG_DATABASE_UNKNOWN_OK); 00115 } 00116 alpm_siglist_cleanup(siglist); 00117 free(siglist); 00118 } while(retry); 00119 00120 if(ret) { 00121 db->status &= ~DB_STATUS_VALID; 00122 db->status |= DB_STATUS_INVALID; 00123 db->handle->pm_errno = ALPM_ERR_DB_INVALID_SIG; 00124 return 1; 00125 } 00126 } 00127 00128 valid: 00129 db->status |= DB_STATUS_VALID; 00130 db->status &= ~DB_STATUS_INVALID; 00131 return 0; 00132 } 00133 00134 /** Update a package database 00135 * 00136 * An update of the package database \a db will be attempted. Unless 00137 * \a force is true, the update will only be performed if the remote 00138 * database was modified since the last update. 00139 * 00140 * This operation requires a database lock, and will return an applicable error 00141 * if the lock could not be obtained. 00142 * 00143 * Example: 00144 * @code 00145 * alpm_list_t *syncs = alpm_option_get_syncdbs(); 00146 * for(i = syncs; i; i = alpm_list_next(i)) { 00147 * alpm_db_t *db = alpm_list_getdata(i); 00148 * result = alpm_db_update(0, db); 00149 * 00150 * if(result < 0) { 00151 * printf("Unable to update database: %s\n", alpm_strerrorlast()); 00152 * } else if(result == 1) { 00153 * printf("Database already up to date\n"); 00154 * } else { 00155 * printf("Database updated\n"); 00156 * } 00157 * } 00158 * @endcode 00159 * 00160 * @ingroup alpm_databases 00161 * @note After a successful update, the \link alpm_db_get_pkgcache() 00162 * package cache \endlink will be invalidated 00163 * @param force if true, then forces the update, otherwise update only in case 00164 * the database isn't up to date 00165 * @param db pointer to the package database to update 00166 * @return 0 on success, -1 on error (pm_errno is set accordingly), 1 if up to 00167 * to date 00168 */ 00169 int SYMEXPORT alpm_db_update(int force, alpm_db_t *db) 00170 { 00171 char *syncpath; 00172 alpm_list_t *i; 00173 int ret = -1; 00174 mode_t oldmask; 00175 alpm_handle_t *handle; 00176 alpm_siglevel_t level; 00177 00178 /* Sanity checks */ 00179 ASSERT(db != NULL, return -1); 00180 handle = db->handle; 00181 handle->pm_errno = 0; 00182 ASSERT(db != handle->db_local, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1)); 00183 ASSERT(db->servers != NULL, RET_ERR(handle, ALPM_ERR_SERVER_NONE, -1)); 00184 00185 syncpath = get_sync_dir(handle); 00186 if(!syncpath) { 00187 return -1; 00188 } 00189 00190 /* make sure we have a sane umask */ 00191 oldmask = umask(0022); 00192 00193 level = alpm_db_get_siglevel(db); 00194 00195 /* attempt to grab a lock */ 00196 if(_alpm_handle_lock(handle)) { 00197 free(syncpath); 00198 umask(oldmask); 00199 RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1); 00200 } 00201 00202 for(i = db->servers; i; i = i->next) { 00203 const char *server = i->data; 00204 struct dload_payload payload; 00205 size_t len; 00206 int sig_ret = 0; 00207 00208 memset(&payload, 0, sizeof(struct dload_payload)); 00209 00210 /* set hard upper limit of 25MiB */ 00211 payload.max_size = 25 * 1024 * 1024; 00212 00213 /* print server + filename into a buffer */ 00214 len = strlen(server) + strlen(db->treename) + 5; 00215 /* TODO fix leak syncpath and umask unset */ 00216 MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); 00217 snprintf(payload.fileurl, len, "%s/%s.db", server, db->treename); 00218 payload.handle = handle; 00219 payload.force = force; 00220 payload.unlink_on_fail = 1; 00221 00222 ret = _alpm_download(&payload, syncpath, NULL); 00223 _alpm_dload_payload_reset(&payload); 00224 00225 if(ret == 0 && (level & ALPM_SIG_DATABASE)) { 00226 /* an existing sig file is no good at this point */ 00227 char *sigpath = _alpm_sigpath(handle, _alpm_db_path(db)); 00228 if(!sigpath) { 00229 ret = -1; 00230 break; 00231 } 00232 unlink(sigpath); 00233 free(sigpath); 00234 00235 /* if we downloaded a DB, we want the .sig from the same server */ 00236 /* print server + filename into a buffer (leave space for .sig) */ 00237 len = strlen(server) + strlen(db->treename) + 9; 00238 /* TODO fix leak syncpath and umask unset */ 00239 MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); 00240 snprintf(payload.fileurl, len, "%s/%s.db.sig", server, db->treename); 00241 payload.handle = handle; 00242 payload.force = 1; 00243 payload.errors_ok = (level & ALPM_SIG_DATABASE_OPTIONAL); 00244 00245 /* set hard upper limit of 16KiB */ 00246 payload.max_size = 16 * 1024; 00247 00248 sig_ret = _alpm_download(&payload, syncpath, NULL); 00249 /* errors_ok suppresses error messages, but not the return code */ 00250 sig_ret = payload.errors_ok ? 0 : sig_ret; 00251 _alpm_dload_payload_reset(&payload); 00252 } 00253 00254 if(ret != -1 && sig_ret != -1) { 00255 break; 00256 } 00257 } 00258 00259 if(ret == 1) { 00260 /* files match, do nothing */ 00261 handle->pm_errno = 0; 00262 goto cleanup; 00263 } else if(ret == -1) { 00264 /* pm_errno was set by the download code */ 00265 _alpm_log(handle, ALPM_LOG_DEBUG, "failed to sync db: %s\n", 00266 alpm_strerror(handle->pm_errno)); 00267 goto cleanup; 00268 } 00269 00270 /* Cache needs to be rebuilt */ 00271 _alpm_db_free_pkgcache(db); 00272 00273 /* clear all status flags regarding validity/existence */ 00274 db->status &= ~DB_STATUS_VALID; 00275 db->status &= ~DB_STATUS_INVALID; 00276 db->status &= ~DB_STATUS_EXISTS; 00277 db->status &= ~DB_STATUS_MISSING; 00278 00279 if(sync_db_validate(db)) { 00280 /* pm_errno should be set */ 00281 ret = -1; 00282 } 00283 00284 cleanup: 00285 00286 if(_alpm_handle_unlock(handle)) { 00287 _alpm_log(handle, ALPM_LOG_WARNING, _("could not remove lock file %s\n"), 00288 handle->lockfile); 00289 } 00290 free(syncpath); 00291 umask(oldmask); 00292 return ret; 00293 } 00294 00295 /* Forward decl so I don't reorganize the whole file right now */ 00296 static int sync_db_read(alpm_db_t *db, struct archive *archive, 00297 struct archive_entry *entry, alpm_pkg_t **likely_pkg); 00298 00299 static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname, 00300 const char **entry_filename, alpm_pkg_t *likely_pkg) 00301 { 00302 char *pkgname = NULL, *pkgver = NULL; 00303 unsigned long pkgname_hash; 00304 alpm_pkg_t *pkg; 00305 00306 /* get package and db file names */ 00307 if(entry_filename) { 00308 char *fname = strrchr(entryname, '/'); 00309 if(fname) { 00310 *entry_filename = fname + 1; 00311 } else { 00312 *entry_filename = NULL; 00313 } 00314 } 00315 if(_alpm_splitname(entryname, &pkgname, &pkgver, &pkgname_hash) != 0) { 00316 _alpm_log(db->handle, ALPM_LOG_ERROR, 00317 _("invalid name for database entry '%s'\n"), entryname); 00318 return NULL; 00319 } 00320 00321 if(likely_pkg && pkgname_hash == likely_pkg->name_hash 00322 && strcmp(likely_pkg->name, pkgname) == 0) { 00323 pkg = likely_pkg; 00324 } else { 00325 pkg = _alpm_pkghash_find(db->pkgcache, pkgname); 00326 } 00327 if(pkg == NULL) { 00328 pkg = _alpm_pkg_new(); 00329 if(pkg == NULL) { 00330 RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL); 00331 } 00332 00333 pkg->name = pkgname; 00334 pkg->version = pkgver; 00335 pkg->name_hash = pkgname_hash; 00336 00337 pkg->origin = PKG_FROM_SYNCDB; 00338 pkg->origin_data.db = db; 00339 pkg->ops = &default_pkg_ops; 00340 pkg->handle = db->handle; 00341 00342 /* add to the collection */ 00343 _alpm_log(db->handle, ALPM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n", 00344 pkg->name, db->treename); 00345 db->pkgcache = _alpm_pkghash_add(db->pkgcache, pkg); 00346 } else { 00347 free(pkgname); 00348 free(pkgver); 00349 } 00350 00351 return pkg; 00352 } 00353 00354 /* This function doesn't work as well as one might think, as size of database 00355 * entries varies considerably. Adding signatures nearly doubles the size of a 00356 * single entry; deltas also can make for large variations in size. These 00357 * current values are heavily influenced by Arch Linux; databases with no 00358 * deltas and a single signature per package. */ 00359 static size_t estimate_package_count(struct stat *st, struct archive *archive) 00360 { 00361 int per_package; 00362 00363 switch(archive_compression(archive)) { 00364 case ARCHIVE_COMPRESSION_NONE: 00365 per_package = 3015; 00366 break; 00367 case ARCHIVE_COMPRESSION_GZIP: 00368 case ARCHIVE_COMPRESSION_COMPRESS: 00369 per_package = 464; 00370 break; 00371 case ARCHIVE_COMPRESSION_BZIP2: 00372 per_package = 394; 00373 break; 00374 case ARCHIVE_COMPRESSION_LZMA: 00375 case ARCHIVE_COMPRESSION_XZ: 00376 per_package = 400; 00377 break; 00378 #ifdef ARCHIVE_COMPRESSION_UU 00379 case ARCHIVE_COMPRESSION_UU: 00380 per_package = 3015 * 4 / 3; 00381 break; 00382 #endif 00383 default: 00384 /* assume it is at least somewhat compressed */ 00385 per_package = 500; 00386 } 00387 return (size_t)((st->st_size / per_package) + 1); 00388 } 00389 00390 static int sync_db_populate(alpm_db_t *db) 00391 { 00392 const char *dbpath; 00393 size_t est_count; 00394 int count, fd; 00395 struct stat buf; 00396 struct archive *archive; 00397 struct archive_entry *entry; 00398 alpm_pkg_t *pkg = NULL; 00399 00400 if(db->status & DB_STATUS_INVALID) { 00401 RET_ERR(db->handle, ALPM_ERR_DB_INVALID, -1); 00402 } 00403 if(db->status & DB_STATUS_MISSING) { 00404 RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1); 00405 } 00406 dbpath = _alpm_db_path(db); 00407 if(!dbpath) { 00408 /* pm_errno set in _alpm_db_path() */ 00409 return -1; 00410 } 00411 00412 fd = _alpm_open_archive(db->handle, dbpath, &buf, 00413 &archive, ALPM_ERR_DB_OPEN); 00414 if(fd < 0) { 00415 return -1; 00416 } 00417 est_count = estimate_package_count(&buf, archive); 00418 00419 db->pkgcache = _alpm_pkghash_create(est_count); 00420 if(db->pkgcache == NULL) { 00421 db->handle->pm_errno = ALPM_ERR_MEMORY; 00422 count = -1; 00423 goto cleanup; 00424 } 00425 00426 while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { 00427 mode_t mode = archive_entry_mode(entry); 00428 if(S_ISDIR(mode)) { 00429 continue; 00430 } else { 00431 /* we have desc, depends or deltas - parse it */ 00432 if(sync_db_read(db, archive, entry, &pkg) != 0) { 00433 _alpm_log(db->handle, ALPM_LOG_ERROR, 00434 _("could not parse package description file '%s' from db '%s'\n"), 00435 archive_entry_pathname(entry), db->treename); 00436 continue; 00437 } 00438 } 00439 } 00440 00441 count = alpm_list_count(db->pkgcache->list); 00442 if(count > 0) { 00443 db->pkgcache->list = alpm_list_msort(db->pkgcache->list, 00444 (size_t)count, _alpm_pkg_cmp); 00445 } 00446 _alpm_log(db->handle, ALPM_LOG_DEBUG, 00447 "added %d packages to package cache for db '%s'\n", 00448 count, db->treename); 00449 00450 cleanup: 00451 archive_read_finish(archive); 00452 if(fd >= 0) { 00453 CLOSE(fd); 00454 } 00455 return count; 00456 } 00457 00458 #define READ_NEXT() do { \ 00459 if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ 00460 line = buf.line; \ 00461 _alpm_strip_newline(line); \ 00462 } while(0) 00463 00464 #define READ_AND_STORE(f) do { \ 00465 READ_NEXT(); \ 00466 STRDUP(f, line, goto error); \ 00467 } while(0) 00468 00469 #define READ_AND_STORE_ALL(f) do { \ 00470 char *linedup; \ 00471 if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ 00472 if(_alpm_strip_newline(buf.line) == 0) break; \ 00473 STRDUP(linedup, buf.line, goto error); \ 00474 f = alpm_list_add(f, linedup); \ 00475 } while(1) /* note the while(1) and not (0) */ 00476 00477 #define READ_AND_SPLITDEP(f) do { \ 00478 if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ 00479 if(_alpm_strip_newline(buf.line) == 0) break; \ 00480 f = alpm_list_add(f, _alpm_splitdep(line)); \ 00481 } while(1) /* note the while(1) and not (0) */ 00482 00483 static int sync_db_read(alpm_db_t *db, struct archive *archive, 00484 struct archive_entry *entry, alpm_pkg_t **likely_pkg) 00485 { 00486 const char *entryname, *filename; 00487 alpm_pkg_t *pkg; 00488 struct archive_read_buffer buf; 00489 00490 entryname = archive_entry_pathname(entry); 00491 if(entryname == NULL) { 00492 _alpm_log(db->handle, ALPM_LOG_DEBUG, 00493 "invalid archive entry provided to _alpm_sync_db_read, skipping\n"); 00494 return -1; 00495 } 00496 00497 _alpm_log(db->handle, ALPM_LOG_FUNCTION, "loading package data from archive entry %s\n", 00498 entryname); 00499 00500 memset(&buf, 0, sizeof(buf)); 00501 /* 512K for a line length seems reasonable */ 00502 buf.max_line_size = 512 * 1024; 00503 00504 pkg = load_pkg_for_entry(db, entryname, &filename, *likely_pkg); 00505 00506 if(pkg == NULL) { 00507 _alpm_log(db->handle, ALPM_LOG_DEBUG, 00508 "entry %s could not be loaded into %s sync database", 00509 entryname, db->treename); 00510 return -1; 00511 } 00512 00513 if(strcmp(filename, "desc") == 0 || strcmp(filename, "depends") == 0 00514 || strcmp(filename, "deltas") == 0) { 00515 int ret; 00516 while((ret = _alpm_archive_fgets(archive, &buf)) == ARCHIVE_OK) { 00517 char *line = buf.line; 00518 if(_alpm_strip_newline(line) == 0) { 00519 /* length of stripped line was zero */ 00520 continue; 00521 } 00522 00523 if(strcmp(line, "%NAME%") == 0) { 00524 READ_NEXT(); 00525 if(strcmp(line, pkg->name) != 0) { 00526 _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: name " 00527 "mismatch on package %s\n"), db->treename, pkg->name); 00528 } 00529 } else if(strcmp(line, "%VERSION%") == 0) { 00530 READ_NEXT(); 00531 if(strcmp(line, pkg->version) != 0) { 00532 _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: version " 00533 "mismatch on package %s\n"), db->treename, pkg->name); 00534 } 00535 } else if(strcmp(line, "%FILENAME%") == 0) { 00536 READ_AND_STORE(pkg->filename); 00537 } else if(strcmp(line, "%DESC%") == 0) { 00538 READ_AND_STORE(pkg->desc); 00539 } else if(strcmp(line, "%GROUPS%") == 0) { 00540 READ_AND_STORE_ALL(pkg->groups); 00541 } else if(strcmp(line, "%URL%") == 0) { 00542 READ_AND_STORE(pkg->url); 00543 } else if(strcmp(line, "%LICENSE%") == 0) { 00544 READ_AND_STORE_ALL(pkg->licenses); 00545 } else if(strcmp(line, "%ARCH%") == 0) { 00546 READ_AND_STORE(pkg->arch); 00547 } else if(strcmp(line, "%BUILDDATE%") == 0) { 00548 READ_NEXT(); 00549 pkg->builddate = _alpm_parsedate(line); 00550 } else if(strcmp(line, "%PACKAGER%") == 0) { 00551 READ_AND_STORE(pkg->packager); 00552 } else if(strcmp(line, "%CSIZE%") == 0) { 00553 READ_NEXT(); 00554 pkg->size = _alpm_strtoofft(line); 00555 } else if(strcmp(line, "%ISIZE%") == 0) { 00556 READ_NEXT(); 00557 pkg->isize = _alpm_strtoofft(line); 00558 } else if(strcmp(line, "%MD5SUM%") == 0) { 00559 READ_AND_STORE(pkg->md5sum); 00560 } else if(strcmp(line, "%SHA256SUM%") == 0) { 00561 READ_AND_STORE(pkg->sha256sum); 00562 } else if(strcmp(line, "%PGPSIG%") == 0) { 00563 READ_AND_STORE(pkg->base64_sig); 00564 } else if(strcmp(line, "%REPLACES%") == 0) { 00565 READ_AND_SPLITDEP(pkg->replaces); 00566 } else if(strcmp(line, "%DEPENDS%") == 0) { 00567 READ_AND_SPLITDEP(pkg->depends); 00568 } else if(strcmp(line, "%OPTDEPENDS%") == 0) { 00569 READ_AND_STORE_ALL(pkg->optdepends); 00570 } else if(strcmp(line, "%CONFLICTS%") == 0) { 00571 READ_AND_SPLITDEP(pkg->conflicts); 00572 } else if(strcmp(line, "%PROVIDES%") == 0) { 00573 READ_AND_SPLITDEP(pkg->provides); 00574 } else if(strcmp(line, "%DELTAS%") == 0) { 00575 /* Different than the rest because of the _alpm_delta_parse call. */ 00576 while(1) { 00577 READ_NEXT(); 00578 if(strlen(line) == 0) break; 00579 pkg->deltas = alpm_list_add(pkg->deltas, 00580 _alpm_delta_parse(db->handle, line)); 00581 } 00582 } 00583 } 00584 if(ret != ARCHIVE_EOF) { 00585 goto error; 00586 } 00587 *likely_pkg = pkg; 00588 } else if(strcmp(filename, "files") == 0) { 00589 /* currently do nothing with this file */ 00590 } else { 00591 /* unknown database file */ 00592 _alpm_log(db->handle, ALPM_LOG_DEBUG, "unknown database file: %s\n", filename); 00593 } 00594 00595 return 0; 00596 00597 error: 00598 _alpm_log(db->handle, ALPM_LOG_DEBUG, "error parsing database file: %s\n", filename); 00599 return -1; 00600 } 00601 00602 struct db_operations sync_db_ops = { 00603 .validate = sync_db_validate, 00604 .populate = sync_db_populate, 00605 .unregister = _alpm_db_unregister, 00606 }; 00607 00608 alpm_db_t *_alpm_db_register_sync(alpm_handle_t *handle, const char *treename, 00609 alpm_siglevel_t level) 00610 { 00611 alpm_db_t *db; 00612 00613 _alpm_log(handle, ALPM_LOG_DEBUG, "registering sync database '%s'\n", treename); 00614 00615 #ifndef HAVE_LIBGPGME 00616 if(level != 0 && level != ALPM_SIG_USE_DEFAULT) { 00617 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL); 00618 } 00619 #endif 00620 00621 db = _alpm_db_new(treename, 0); 00622 if(db == NULL) { 00623 RET_ERR(handle, ALPM_ERR_DB_CREATE, NULL); 00624 } 00625 db->ops = &sync_db_ops; 00626 db->handle = handle; 00627 db->siglevel = level; 00628 00629 sync_db_validate(db); 00630 00631 handle->dbs_sync = alpm_list_add(handle->dbs_sync, db); 00632 return db; 00633 } 00634 00635 /* vim: set ts=2 sw=2 noet: */