2 * be_sync.c : backend for sync databases
4 * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
5 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #include <archive_entry.h>
35 #include "alpm_list.h"
42 static char *get_sync_dir(alpm_handle_t
*handle
)
44 const char *dbpath
= alpm_option_get_dbpath(handle
);
45 size_t len
= strlen(dbpath
) + 6;
49 MALLOC(syncpath
, len
, RET_ERR(handle
, PM_ERR_MEMORY
, NULL
));
50 sprintf(syncpath
, "%s%s", dbpath
, "sync/");
52 if(stat(syncpath
, &buf
) != 0) {
53 _alpm_log(handle
, PM_LOG_DEBUG
, "database dir '%s' does not exist, creating it\n",
55 if(_alpm_makepath(syncpath
) != 0) {
57 RET_ERR(handle
, PM_ERR_SYSTEM
, NULL
);
59 } else if(!S_ISDIR(buf
.st_mode
)) {
60 _alpm_log(handle
, PM_LOG_WARNING
, _("removing invalid file: %s\n"), syncpath
);
61 if(unlink(syncpath
) != 0 || _alpm_makepath(syncpath
) != 0) {
63 RET_ERR(handle
, PM_ERR_SYSTEM
, NULL
);
70 static int sync_db_validate(pmdb_t
*db
)
72 pgp_verify_t check_sig
;
74 if(db
->status
& DB_STATUS_VALID
) {
78 /* this takes into account the default verification level if UNKNOWN
79 * was assigned to this db */
80 check_sig
= _alpm_db_get_sigverify_level(db
);
82 if(check_sig
!= PM_PGP_VERIFY_NEVER
) {
84 const char *dbpath
= _alpm_db_path(db
);
86 /* pm_errno set in _alpm_db_path() */
90 /* we can skip any validation if the database doesn't exist */
91 if(access(dbpath
, R_OK
) != 0 && errno
== ENOENT
) {
96 _alpm_log(db
->handle
, PM_LOG_DEBUG
, "checking signature for %s\n",
98 ret
= _alpm_gpgme_checksig(db
->handle
, dbpath
, NULL
);
99 if((check_sig
== PM_PGP_VERIFY_ALWAYS
&& ret
!= 0) ||
100 (check_sig
== PM_PGP_VERIFY_OPTIONAL
&& ret
== 1)) {
101 RET_ERR(db
->handle
, PM_ERR_SIG_INVALID
, -1);
106 db
->status
|= DB_STATUS_VALID
;
110 /** Update a package database
112 * An update of the package database \a db will be attempted. Unless
113 * \a force is true, the update will only be performed if the remote
114 * database was modified since the last update.
116 * This operation requires a database lock, and will return an applicable error
117 * if the lock could not be obtained.
121 * alpm_list_t *syncs = alpm_option_get_syncdbs();
122 * for(i = syncs; i; i = alpm_list_next(i)) {
123 * pmdb_t *db = alpm_list_getdata(i);
124 * result = alpm_db_update(0, db);
127 * printf("Unable to update database: %s\n", alpm_strerrorlast());
128 * } else if(result == 1) {
129 * printf("Database already up to date\n");
131 * printf("Database updated\n");
136 * @ingroup alpm_databases
137 * @note After a successful update, the \link alpm_db_get_pkgcache()
138 * package cache \endlink will be invalidated
139 * @param force if true, then forces the update, otherwise update only in case
140 * the database isn't up to date
141 * @param db pointer to the package database to update
142 * @return 0 on success, -1 on error (pm_errno is set accordingly), 1 if up to
145 int SYMEXPORT
alpm_db_update(int force
, pmdb_t
*db
)
151 alpm_handle_t
*handle
;
152 pgp_verify_t check_sig
;
155 ASSERT(db
!= NULL
, return -1);
157 handle
->pm_errno
= 0;
158 ASSERT(db
!= handle
->db_local
, RET_ERR(handle
, PM_ERR_WRONG_ARGS
, -1));
159 ASSERT(db
->servers
!= NULL
, RET_ERR(handle
, PM_ERR_SERVER_NONE
, -1));
161 syncpath
= get_sync_dir(handle
);
166 /* make sure we have a sane umask */
167 oldmask
= umask(0022);
169 check_sig
= _alpm_db_get_sigverify_level(db
);
171 /* attempt to grab a lock */
172 if(_alpm_handle_lock(handle
)) {
173 RET_ERR(handle
, PM_ERR_HANDLE_LOCK
, -1);
176 for(i
= db
->servers
; i
; i
= i
->next
) {
177 const char *server
= i
->data
;
182 /* print server + filename into a buffer (leave space for .sig) */
183 len
= strlen(server
) + strlen(db
->treename
) + 9;
184 CALLOC(fileurl
, len
, sizeof(char), RET_ERR(handle
, PM_ERR_MEMORY
, -1));
185 snprintf(fileurl
, len
, "%s/%s.db", server
, db
->treename
);
187 ret
= _alpm_download(handle
, fileurl
, syncpath
, force
, 0, 0);
189 if(ret
== 0 && (check_sig
== PM_PGP_VERIFY_ALWAYS
||
190 check_sig
== PM_PGP_VERIFY_OPTIONAL
)) {
191 /* an existing sig file is no good at this point */
192 char *sigpath
= _alpm_db_sig_path(db
);
200 int errors_ok
= (check_sig
== PM_PGP_VERIFY_OPTIONAL
);
201 /* if we downloaded a DB, we want the .sig from the same server */
202 snprintf(fileurl
, len
, "%s/%s.db.sig", server
, db
->treename
);
204 sig_ret
= _alpm_download(handle
, fileurl
, syncpath
, 1, 0, errors_ok
);
205 /* errors_ok suppresses error messages, but not the return code */
206 sig_ret
= errors_ok
? 0 : sig_ret
;
210 if(ret
!= -1 && sig_ret
!= -1) {
216 /* files match, do nothing */
217 handle
->pm_errno
= 0;
219 } else if(ret
== -1) {
220 /* pm_errno was set by the download code */
221 _alpm_log(handle
, PM_LOG_DEBUG
, "failed to sync db: %s\n",
222 alpm_strerror(handle
->pm_errno
));
226 /* Cache needs to be rebuilt */
227 _alpm_db_free_pkgcache(db
);
229 db
->status
&= ~DB_STATUS_VALID
;
230 if(sync_db_validate(db
)) {
231 /* pm_errno should be set */
237 if(_alpm_handle_unlock(handle
)) {
238 _alpm_log(handle
, PM_LOG_WARNING
, _("could not remove lock file %s\n"),
239 alpm_option_get_lockfile(handle
));
246 /* Forward decl so I don't reorganize the whole file right now */
247 static int sync_db_read(pmdb_t
*db
, struct archive
*archive
,
248 struct archive_entry
*entry
, pmpkg_t
**likely_pkg
);
250 static pmpkg_t
*load_pkg_for_entry(pmdb_t
*db
, const char *entryname
,
251 const char **entry_filename
, pmpkg_t
*likely_pkg
)
253 char *pkgname
= NULL
, *pkgver
= NULL
;
254 unsigned long pkgname_hash
;
257 /* get package and db file names */
259 char *fname
= strrchr(entryname
, '/');
261 *entry_filename
= fname
+ 1;
263 *entry_filename
= NULL
;
266 if(_alpm_splitname(entryname
, &pkgname
, &pkgver
, &pkgname_hash
) != 0) {
267 _alpm_log(db
->handle
, PM_LOG_ERROR
,
268 _("invalid name for database entry '%s'\n"), entryname
);
272 if(likely_pkg
&& strcmp(likely_pkg
->name
, pkgname
) == 0) {
275 pkg
= _alpm_pkghash_find(db
->pkgcache
, pkgname
);
278 pkg
= _alpm_pkg_new();
280 RET_ERR(db
->handle
, PM_ERR_MEMORY
, NULL
);
284 pkg
->version
= pkgver
;
285 pkg
->name_hash
= pkgname_hash
;
287 pkg
->origin
= PKG_FROM_SYNCDB
;
288 pkg
->origin_data
.db
= db
;
289 pkg
->ops
= &default_pkg_ops
;
290 pkg
->handle
= db
->handle
;
292 /* add to the collection */
293 _alpm_log(db
->handle
, PM_LOG_FUNCTION
, "adding '%s' to package cache for db '%s'\n",
294 pkg
->name
, db
->treename
);
295 db
->pkgcache
= _alpm_pkghash_add(db
->pkgcache
, pkg
);
305 * This is the data table used to generate the estimating function below.
306 * "Weighted Avg" means averaging the bottom table values; thus each repo, big
307 * or small, will have equal influence. "Unweighted Avg" means averaging the
308 * sums of the top table columns, thus each package has equal influence. The
309 * final values are calculated by (surprise) averaging the averages, because
312 * Database Pkgs tar bz2 gz xz
313 * community 2096 5294080 256391 421227 301296
314 * core 180 460800 25257 36850 29356
315 * extra 2606 6635520 294647 470818 339392
316 * multilib 126 327680 16120 23261 18732
317 * testing 76 204800 10902 14348 12100
320 * community 2096 2525.80 122.32 200.97 143.75
321 * core 180 2560.00 140.32 204.72 163.09
322 * extra 2606 2546.25 113.06 180.67 130.23
323 * multilib 126 2600.63 127.94 184.61 148.67
324 * testing 76 2694.74 143.45 188.79 159.21
326 * Weighted Avg 2585.48 129.42 191.95 148.99
327 * Unweighted Avg 2543.39 118.74 190.16 137.93
328 * Average of Avgs 2564.44 124.08 191.06 143.46
330 static size_t estimate_package_count(struct stat
*st
, struct archive
*archive
)
332 unsigned int per_package
;
334 switch(archive_compression(archive
)) {
335 case ARCHIVE_COMPRESSION_NONE
:
338 case ARCHIVE_COMPRESSION_GZIP
:
341 case ARCHIVE_COMPRESSION_BZIP2
:
344 case ARCHIVE_COMPRESSION_COMPRESS
:
347 case ARCHIVE_COMPRESSION_LZMA
:
348 case ARCHIVE_COMPRESSION_XZ
:
351 #ifdef ARCHIVE_COMPRESSION_UU
352 case ARCHIVE_COMPRESSION_UU
:
357 /* assume it is at least somewhat compressed */
360 return (size_t)((st
->st_size
/ per_package
) + 1);
363 static int sync_db_populate(pmdb_t
*db
)
369 struct archive
*archive
;
370 struct archive_entry
*entry
;
373 if((archive
= archive_read_new()) == NULL
) {
374 RET_ERR(db
->handle
, PM_ERR_LIBARCHIVE
, -1);
377 archive_read_support_compression_all(archive
);
378 archive_read_support_format_all(archive
);
380 dbpath
= _alpm_db_path(db
);
382 /* pm_errno set in _alpm_db_path() */
386 _alpm_log(db
->handle
, PM_LOG_DEBUG
, "opening database archive %s\n", dbpath
);
388 if(archive_read_open_filename(archive
, dbpath
,
389 ARCHIVE_DEFAULT_BYTES_PER_BLOCK
) != ARCHIVE_OK
) {
390 _alpm_log(db
->handle
, PM_LOG_ERROR
, _("could not open file %s: %s\n"), dbpath
,
391 archive_error_string(archive
));
392 archive_read_finish(archive
);
393 RET_ERR(db
->handle
, PM_ERR_DB_OPEN
, -1);
395 if(stat(dbpath
, &buf
) != 0) {
396 RET_ERR(db
->handle
, PM_ERR_DB_OPEN
, -1);
398 est_count
= estimate_package_count(&buf
, archive
);
400 /* initialize hash at 66% full */
401 db
->pkgcache
= _alpm_pkghash_create(est_count
* 3 / 2);
402 if(db
->pkgcache
== NULL
) {
403 RET_ERR(db
->handle
, PM_ERR_MEMORY
, -1);
406 while(archive_read_next_header(archive
, &entry
) == ARCHIVE_OK
) {
407 const struct stat
*st
;
409 st
= archive_entry_stat(entry
);
411 if(S_ISDIR(st
->st_mode
)) {
414 /* we have desc, depends or deltas - parse it */
415 if(sync_db_read(db
, archive
, entry
, &pkg
) != 0) {
416 _alpm_log(db
->handle
, PM_LOG_ERROR
,
417 _("could not parse package description file '%s' from db '%s'\n"),
418 archive_entry_pathname(entry
), db
->treename
);
424 count
= alpm_list_count(db
->pkgcache
->list
);
427 db
->pkgcache
->list
= alpm_list_msort(db
->pkgcache
->list
, (size_t)count
, _alpm_pkg_cmp
);
429 archive_read_finish(archive
);
430 _alpm_log(db
->handle
, PM_LOG_DEBUG
, "added %d packages to package cache for db '%s'\n",
431 count
, db
->treename
);
436 #define READ_NEXT(s) do { \
437 if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \
438 s = _alpm_strtrim(buf.line); \
441 #define READ_AND_STORE(f) do { \
443 STRDUP(f, line, goto error); \
446 #define READ_AND_STORE_ALL(f) do { \
449 if(strlen(line) == 0) break; \
450 STRDUP(linedup, line, goto error); \
451 f = alpm_list_add(f, linedup); \
452 } while(1) /* note the while(1) and not (0) */
454 static int sync_db_read(pmdb_t
*db
, struct archive
*archive
,
455 struct archive_entry
*entry
, pmpkg_t
**likely_pkg
)
457 const char *entryname
, *filename
;
459 struct archive_read_buffer buf
;
461 entryname
= archive_entry_pathname(entry
);
462 if(entryname
== NULL
) {
463 _alpm_log(db
->handle
, PM_LOG_DEBUG
,
464 "invalid archive entry provided to _alpm_sync_db_read, skipping\n");
468 _alpm_log(db
->handle
, PM_LOG_FUNCTION
, "loading package data from archive entry %s\n",
471 memset(&buf
, 0, sizeof(buf
));
472 /* 512K for a line length seems reasonable */
473 buf
.max_line_size
= 512 * 1024;
475 pkg
= load_pkg_for_entry(db
, entryname
, &filename
, *likely_pkg
);
478 _alpm_log(db
->handle
, PM_LOG_DEBUG
,
479 "entry %s could not be loaded into %s sync database",
480 entryname
, db
->treename
);
484 if(strcmp(filename
, "desc") == 0 || strcmp(filename
, "depends") == 0
485 || strcmp(filename
, "deltas") == 0) {
487 while((ret
= _alpm_archive_fgets(archive
, &buf
)) == ARCHIVE_OK
) {
488 char *line
= _alpm_strtrim(buf
.line
);
490 if(strcmp(line
, "%NAME%") == 0) {
492 if(strcmp(line
, pkg
->name
) != 0) {
493 _alpm_log(db
->handle
, PM_LOG_ERROR
, _("%s database is inconsistent: name "
494 "mismatch on package %s\n"), db
->treename
, pkg
->name
);
496 } else if(strcmp(line
, "%VERSION%") == 0) {
498 if(strcmp(line
, pkg
->version
) != 0) {
499 _alpm_log(db
->handle
, PM_LOG_ERROR
, _("%s database is inconsistent: version "
500 "mismatch on package %s\n"), db
->treename
, pkg
->name
);
502 } else if(strcmp(line
, "%FILENAME%") == 0) {
503 READ_AND_STORE(pkg
->filename
);
504 } else if(strcmp(line
, "%DESC%") == 0) {
505 READ_AND_STORE(pkg
->desc
);
506 } else if(strcmp(line
, "%GROUPS%") == 0) {
507 READ_AND_STORE_ALL(pkg
->groups
);
508 } else if(strcmp(line
, "%URL%") == 0) {
509 READ_AND_STORE(pkg
->url
);
510 } else if(strcmp(line
, "%LICENSE%") == 0) {
511 READ_AND_STORE_ALL(pkg
->licenses
);
512 } else if(strcmp(line
, "%ARCH%") == 0) {
513 READ_AND_STORE(pkg
->arch
);
514 } else if(strcmp(line
, "%BUILDDATE%") == 0) {
516 pkg
->builddate
= _alpm_parsedate(line
);
517 } else if(strcmp(line
, "%PACKAGER%") == 0) {
518 READ_AND_STORE(pkg
->packager
);
519 } else if(strcmp(line
, "%CSIZE%") == 0) {
520 /* Note: the CSIZE and SIZE fields both share the "size" field in the
521 * pkginfo_t struct. This can be done b/c CSIZE is currently only used
522 * in sync databases, and SIZE is only used in local databases.
525 pkg
->size
= atol(line
);
526 /* also store this value to isize if isize is unset */
527 if(pkg
->isize
== 0) {
528 pkg
->isize
= pkg
->size
;
530 } else if(strcmp(line
, "%ISIZE%") == 0) {
532 pkg
->isize
= atol(line
);
533 } else if(strcmp(line
, "%MD5SUM%") == 0) {
534 READ_AND_STORE(pkg
->md5sum
);
535 } else if(strcmp(line
, "%SHA256SUM%") == 0) {
536 /* we don't do anything with this value right now */
538 } else if(strcmp(line
, "%PGPSIG%") == 0) {
539 READ_AND_STORE(pkg
->base64_sig
);
540 } else if(strcmp(line
, "%REPLACES%") == 0) {
541 READ_AND_STORE_ALL(pkg
->replaces
);
542 } else if(strcmp(line
, "%DEPENDS%") == 0) {
543 /* Different than the rest because of the _alpm_splitdep call. */
546 if(strlen(line
) == 0) break;
547 pkg
->depends
= alpm_list_add(pkg
->depends
, _alpm_splitdep(line
));
549 } else if(strcmp(line
, "%OPTDEPENDS%") == 0) {
550 READ_AND_STORE_ALL(pkg
->optdepends
);
551 } else if(strcmp(line
, "%CONFLICTS%") == 0) {
552 READ_AND_STORE_ALL(pkg
->conflicts
);
553 } else if(strcmp(line
, "%PROVIDES%") == 0) {
554 READ_AND_STORE_ALL(pkg
->provides
);
555 } else if(strcmp(line
, "%DELTAS%") == 0) {
556 /* Different than the rest because of the _alpm_delta_parse call. */
559 if(strlen(line
) == 0) break;
560 pkg
->deltas
= alpm_list_add(pkg
->deltas
, _alpm_delta_parse(line
));
564 if(ret
!= ARCHIVE_EOF
) {
568 } else if(strcmp(filename
, "files") == 0) {
569 /* currently do nothing with this file */
571 /* unknown database file */
572 _alpm_log(db
->handle
, PM_LOG_DEBUG
, "unknown database file: %s\n", filename
);
578 _alpm_log(db
->handle
, PM_LOG_DEBUG
, "error parsing database file: %s\n", filename
);
582 struct db_operations sync_db_ops
= {
583 .populate
= sync_db_populate
,
584 .unregister
= _alpm_db_unregister
,
587 pmdb_t
*_alpm_db_register_sync(alpm_handle_t
*handle
, const char *treename
,
592 _alpm_log(handle
, PM_LOG_DEBUG
, "registering sync database '%s'\n", treename
);
594 db
= _alpm_db_new(treename
, 0);
596 RET_ERR(handle
, PM_ERR_DB_CREATE
, NULL
);
598 db
->ops
= &sync_db_ops
;
600 db
->pgp_verify
= level
;
602 if(sync_db_validate(db
)) {
607 handle
->dbs_sync
= alpm_list_add(handle
->dbs_sync
, db
);
612 /* vim: set ts=2 sw=2 noet: */