libalpm
Arch Linux Package Manager Library
be_sync.c
Go to the documentation of this file.
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: */