]> wolfpit.net Git - tool/Arch-pacman/.git/blame - lib/libalpm/be_sync.c
libalpm: introduce a usage level for repos
[tool/Arch-pacman/.git] / lib / libalpm / be_sync.c
CommitLineData
e2faeb46 1/*
d980bd40 2 * be_sync.c : backend for sync databases
23229097 3 *
1dd34058 4 * Copyright (c) 2006-2013 Pacman Development Team <pacman-dev@archlinux.org>
6cebd4e6 5 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
23229097 6 *
e2faeb46
AF
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.
11 *
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.
16 *
17 * You should have received a copy of the GNU General Public License
9781d0d6 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
e2faeb46
AF
19 */
20
db3b86e7 21#include <errno.h>
6df55817 22#include <sys/types.h>
791928dc 23#include <sys/stat.h>
6df55817 24#include <fcntl.h>
5cc099a8 25#include <limits.h>
db3b86e7 26#include <unistd.h>
869e81e1 27
2f4ee434
XC
28/* libarchive */
29#include <archive.h>
30#include <archive_entry.h>
31
869e81e1 32/* libalpm */
e2faeb46 33#include "util.h"
5b2de3d8 34#include "log.h"
e1e4bbb7 35#include "libarchive-compat.h"
e2faeb46 36#include "alpm.h"
5b2de3d8 37#include "alpm_list.h"
aa1c0ba9 38#include "package.h"
5b2de3d8 39#include "handle.h"
0c2cc108 40#include "delta.h"
c244cfec 41#include "deps.h"
04600384 42#include "dload.h"
d37ad048 43
64c1cf79 44static char *get_sync_dir(alpm_handle_t *handle)
f6700d5c 45{
d9e5dab6 46 size_t len = strlen(handle->dbpath) + 6;
f6700d5c
DM
47 char *syncpath;
48 struct stat buf;
49
afc96f2a 50 MALLOC(syncpath, len, RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
d9e5dab6 51 sprintf(syncpath, "%s%s", handle->dbpath, "sync/");
f6700d5c
DM
52
53 if(stat(syncpath, &buf) != 0) {
ca43fdd9 54 _alpm_log(handle, ALPM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n",
f6700d5c
DM
55 syncpath);
56 if(_alpm_makepath(syncpath) != 0) {
57 free(syncpath);
afc96f2a 58 RET_ERR(handle, ALPM_ERR_SYSTEM, NULL);
f6700d5c
DM
59 }
60 } else if(!S_ISDIR(buf.st_mode)) {
ca43fdd9 61 _alpm_log(handle, ALPM_LOG_WARNING, _("removing invalid file: %s\n"), syncpath);
f6700d5c
DM
62 if(unlink(syncpath) != 0 || _alpm_makepath(syncpath) != 0) {
63 free(syncpath);
afc96f2a 64 RET_ERR(handle, ALPM_ERR_SYSTEM, NULL);
f6700d5c
DM
65 }
66 }
67
68 return syncpath;
69}
70
939d5a95 71static int sync_db_validate(alpm_db_t *db)
db3b86e7 72{
7af0ab1c 73 alpm_siglevel_t level;
c885a953 74 const char *dbpath;
79e98316 75
c885a953 76 if(db->status & DB_STATUS_VALID || db->status & DB_STATUS_MISSING) {
79e98316
DM
77 return 0;
78 }
c885a953 79 if(db->status & DB_STATUS_INVALID) {
c4069492 80 db->handle->pm_errno = ALPM_ERR_DB_INVALID_SIG;
c885a953
DM
81 return -1;
82 }
83
84 dbpath = _alpm_db_path(db);
85 if(!dbpath) {
86 /* pm_errno set in _alpm_db_path() */
87 return -1;
88 }
89
90 /* we can skip any validation if the database doesn't exist */
20a16f55 91 if(_alpm_access(db->handle, NULL, dbpath, R_OK) != 0 && errno == ENOENT) {
c885a953
DM
92 db->status &= ~DB_STATUS_EXISTS;
93 db->status |= DB_STATUS_MISSING;
f5d904d9 94 EVENT(db->handle, ALPM_EVENT_DATABASE_MISSING, db->treename, NULL);
c885a953
DM
95 goto valid;
96 }
97 db->status |= DB_STATUS_EXISTS;
98 db->status &= ~DB_STATUS_MISSING;
79e98316 99
db3b86e7
DM
100 /* this takes into account the default verification level if UNKNOWN
101 * was assigned to this db */
7af0ab1c 102 level = alpm_db_get_siglevel(db);
db3b86e7 103
7af0ab1c 104 if(level & ALPM_SIG_DATABASE) {
ec790ced
DM
105 int retry, ret;
106 do {
107 retry = 0;
108 alpm_siglist_t *siglist;
109 ret = _alpm_check_pgp_helper(db->handle, dbpath, NULL,
7af0ab1c 110 level & ALPM_SIG_DATABASE_OPTIONAL, level & ALPM_SIG_DATABASE_MARGINAL_OK,
ec790ced
DM
111 level & ALPM_SIG_DATABASE_UNKNOWN_OK, &siglist);
112 if(ret) {
113 retry = _alpm_process_siglist(db->handle, db->treename, siglist,
114 level & ALPM_SIG_DATABASE_OPTIONAL, level & ALPM_SIG_DATABASE_MARGINAL_OK,
115 level & ALPM_SIG_DATABASE_UNKNOWN_OK);
116 }
994cb4da
DM
117 alpm_siglist_cleanup(siglist);
118 free(siglist);
ec790ced
DM
119 } while(retry);
120
121 if(ret) {
c4069492
DM
122 db->status &= ~DB_STATUS_VALID;
123 db->status |= DB_STATUS_INVALID;
ec790ced 124 db->handle->pm_errno = ALPM_ERR_DB_INVALID_SIG;
7af0ab1c 125 return 1;
db3b86e7
DM
126 }
127 }
128
79e98316
DM
129valid:
130 db->status |= DB_STATUS_VALID;
c885a953 131 db->status &= ~DB_STATUS_INVALID;
db3b86e7
DM
132 return 0;
133}
134
04600384 135/** Update a package database
63fc9360
SN
136 *
137 * An update of the package database \a db will be attempted. Unless
138 * \a force is true, the update will only be performed if the remote
139 * database was modified since the last update.
140 *
4f8ae2ba
DM
141 * This operation requires a database lock, and will return an applicable error
142 * if the lock could not be obtained.
63fc9360
SN
143 *
144 * Example:
145 * @code
e0daaea3 146 * alpm_list_t *syncs = alpm_get_syncdbs();
4f8ae2ba 147 * for(i = syncs; i; i = alpm_list_next(i)) {
939d5a95 148 * alpm_db_t *db = alpm_list_getdata(i);
4f8ae2ba 149 * result = alpm_db_update(0, db);
63fc9360 150 *
4f8ae2ba
DM
151 * if(result < 0) {
152 * printf("Unable to update database: %s\n", alpm_strerrorlast());
153 * } else if(result == 1) {
154 * printf("Database already up to date\n");
155 * } else {
156 * printf("Database updated\n");
63fc9360
SN
157 * }
158 * }
159 * @endcode
160 *
161 * @ingroup alpm_databases
162 * @note After a successful update, the \link alpm_db_get_pkgcache()
163 * package cache \endlink will be invalidated
04600384
DM
164 * @param force if true, then forces the update, otherwise update only in case
165 * the database isn't up to date
166 * @param db pointer to the package database to update
ed1aef7b 167 * @return 0 on success, -1 on error (pm_errno is set accordingly), 1 if up to
04600384 168 * to date
e8275fa9 169 */
939d5a95 170int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
e8275fa9 171{
9579879b 172 char *syncpath;
9579879b 173 alpm_list_t *i;
9579879b 174 int ret = -1;
f6716ae9 175 mode_t oldmask;
64c1cf79 176 alpm_handle_t *handle;
7af0ab1c 177 alpm_siglevel_t level;
04600384 178
04600384 179 /* Sanity checks */
e2aa9526
DM
180 ASSERT(db != NULL, return -1);
181 handle = db->handle;
ee015f08 182 handle->pm_errno = 0;
afc96f2a
AM
183 ASSERT(db != handle->db_local, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
184 ASSERT(db->servers != NULL, RET_ERR(handle, ALPM_ERR_SERVER_NONE, -1));
0966c33a 185
106d0fc5
DR
186 if(!(db->usage & ALPM_DB_USAGE_SYNC)) {
187 return 0;
188 }
189
f6700d5c
DM
190 syncpath = get_sync_dir(handle);
191 if(!syncpath) {
192 return -1;
1ff81182 193 }
4f8ae2ba
DM
194
195 /* make sure we have a sane umask */
196 oldmask = umask(0022);
197
7af0ab1c 198 level = alpm_db_get_siglevel(db);
9579879b 199
4f8ae2ba
DM
200 /* attempt to grab a lock */
201 if(_alpm_handle_lock(handle)) {
455ca55f
LF
202 free(syncpath);
203 umask(oldmask);
afc96f2a 204 RET_ERR(handle, ALPM_ERR_HANDLE_LOCK, -1);
4f8ae2ba
DM
205 }
206
9579879b
DM
207 for(i = db->servers; i; i = i->next) {
208 const char *server = i->data;
e0acf2f1 209 struct dload_payload payload;
9579879b
DM
210 size_t len;
211 int sig_ret = 0;
212
e0acf2f1 213 memset(&payload, 0, sizeof(struct dload_payload));
6dc71926
DR
214
215 /* set hard upper limit of 25MiB */
e0acf2f1 216 payload.max_size = 25 * 1024 * 1024;
6dc71926 217
e0acf2f1
DM
218 /* print server + filename into a buffer */
219 len = strlen(server) + strlen(db->treename) + 5;
6df55817 220 /* TODO fix leak syncpath and umask unset */
e0acf2f1
DM
221 MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
222 snprintf(payload.fileurl, len, "%s/%s.db", server, db->treename);
223 payload.handle = handle;
224 payload.force = force;
225 payload.unlink_on_fail = 1;
9579879b 226
27067b13 227 ret = _alpm_download(&payload, syncpath, NULL, NULL);
e0acf2f1 228 _alpm_dload_payload_reset(&payload);
9579879b 229
7af0ab1c 230 if(ret == 0 && (level & ALPM_SIG_DATABASE)) {
db3b86e7 231 /* an existing sig file is no good at this point */
11f4a7a4 232 char *sigpath = _alpm_sigpath(handle, _alpm_db_path(db));
db3b86e7
DM
233 if(!sigpath) {
234 ret = -1;
235 break;
236 }
237 unlink(sigpath);
238 free(sigpath);
239
9579879b 240 /* if we downloaded a DB, we want the .sig from the same server */
e0acf2f1
DM
241 /* print server + filename into a buffer (leave space for .sig) */
242 len = strlen(server) + strlen(db->treename) + 9;
6df55817 243 /* TODO fix leak syncpath and umask unset */
e0acf2f1
DM
244 MALLOC(payload.fileurl, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
245 snprintf(payload.fileurl, len, "%s/%s.db.sig", server, db->treename);
246 payload.handle = handle;
247 payload.force = 1;
248 payload.errors_ok = (level & ALPM_SIG_DATABASE_OPTIONAL);
6dc71926
DR
249
250 /* set hard upper limit of 16KiB */
e0acf2f1 251 payload.max_size = 16 * 1024;
9579879b 252
27067b13 253 sig_ret = _alpm_download(&payload, syncpath, NULL, NULL);
9579879b 254 /* errors_ok suppresses error messages, but not the return code */
e0acf2f1
DM
255 sig_ret = payload.errors_ok ? 0 : sig_ret;
256 _alpm_dload_payload_reset(&payload);
9579879b
DM
257 }
258
9579879b
DM
259 if(ret != -1 && sig_ret != -1) {
260 break;
261 }
262 }
04600384
DM
263
264 if(ret == 1) {
d2dbb04a 265 /* files match, do nothing */
e2aa9526 266 handle->pm_errno = 0;
38da050f 267 goto cleanup;
04600384
DM
268 } else if(ret == -1) {
269 /* pm_errno was set by the download code */
ca43fdd9 270 _alpm_log(handle, ALPM_LOG_DEBUG, "failed to sync db: %s\n",
52bffd24 271 alpm_strerror(handle->pm_errno));
38da050f
AM
272 goto cleanup;
273 }
274
2f4ee434
XC
275 /* Cache needs to be rebuilt */
276 _alpm_db_free_pkgcache(db);
277
c885a953 278 /* clear all status flags regarding validity/existence */
79e98316 279 db->status &= ~DB_STATUS_VALID;
c885a953
DM
280 db->status &= ~DB_STATUS_INVALID;
281 db->status &= ~DB_STATUS_EXISTS;
282 db->status &= ~DB_STATUS_MISSING;
283
db3b86e7
DM
284 if(sync_db_validate(db)) {
285 /* pm_errno should be set */
286 ret = -1;
287 }
288
38da050f
AM
289cleanup:
290
4f8ae2ba 291 if(_alpm_handle_unlock(handle)) {
ca43fdd9 292 _alpm_log(handle, ALPM_LOG_WARNING, _("could not remove lock file %s\n"),
d9e5dab6 293 handle->lockfile);
4f8ae2ba 294 }
38da050f
AM
295 free(syncpath);
296 umask(oldmask);
297 return ret;
e8275fa9
AG
298}
299
94d3d665 300/* Forward decl so I don't reorganize the whole file right now */
939d5a95 301static int sync_db_read(alpm_db_t *db, struct archive *archive,
8a04bc25 302 struct archive_entry *entry, alpm_pkg_t **likely_pkg);
777bdc6c 303
f34864cc
AM
304static alpm_pkgvalidation_t _sync_get_validation(alpm_pkg_t *pkg)
305{
306 if(pkg->validation) {
307 return pkg->validation;
308 }
309
310 if(pkg->md5sum) {
311 pkg->validation |= ALPM_PKG_VALIDATION_MD5SUM;
312 }
313 if(pkg->sha256sum) {
314 pkg->validation |= ALPM_PKG_VALIDATION_SHA256SUM;
315 }
316 if(pkg->base64_sig) {
317 pkg->validation |= ALPM_PKG_VALIDATION_SIGNATURE;
318 }
319
320 if(!pkg->validation) {
321 pkg->validation |= ALPM_PKG_VALIDATION_NONE;
322 }
323
324 return pkg->validation;
325}
326
8a04bc25
AM
327static alpm_pkg_t *load_pkg_for_entry(alpm_db_t *db, const char *entryname,
328 const char **entry_filename, alpm_pkg_t *likely_pkg)
777bdc6c
DM
329{
330 char *pkgname = NULL, *pkgver = NULL;
331 unsigned long pkgname_hash;
8a04bc25 332 alpm_pkg_t *pkg;
777bdc6c
DM
333
334 /* get package and db file names */
335 if(entry_filename) {
336 char *fname = strrchr(entryname, '/');
337 if(fname) {
338 *entry_filename = fname + 1;
339 } else {
340 *entry_filename = NULL;
341 }
342 }
343 if(_alpm_splitname(entryname, &pkgname, &pkgver, &pkgname_hash) != 0) {
ca43fdd9 344 _alpm_log(db->handle, ALPM_LOG_ERROR,
777bdc6c
DM
345 _("invalid name for database entry '%s'\n"), entryname);
346 return NULL;
347 }
348
177beb91
DM
349 if(likely_pkg && pkgname_hash == likely_pkg->name_hash
350 && strcmp(likely_pkg->name, pkgname) == 0) {
777bdc6c
DM
351 pkg = likely_pkg;
352 } else {
353 pkg = _alpm_pkghash_find(db->pkgcache, pkgname);
354 }
355 if(pkg == NULL) {
356 pkg = _alpm_pkg_new();
357 if(pkg == NULL) {
afc96f2a 358 RET_ERR(db->handle, ALPM_ERR_MEMORY, NULL);
777bdc6c
DM
359 }
360
361 pkg->name = pkgname;
362 pkg->version = pkgver;
363 pkg->name_hash = pkgname_hash;
364
3be02aa2 365 pkg->origin = ALPM_PKG_FROM_SYNCDB;
777bdc6c
DM
366 pkg->origin_data.db = db;
367 pkg->ops = &default_pkg_ops;
f34864cc 368 pkg->ops->get_validation = _sync_get_validation;
777bdc6c
DM
369 pkg->handle = db->handle;
370
371 /* add to the collection */
ca43fdd9 372 _alpm_log(db->handle, ALPM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n",
777bdc6c
DM
373 pkg->name, db->treename);
374 db->pkgcache = _alpm_pkghash_add(db->pkgcache, pkg);
375 } else {
376 free(pkgname);
377 free(pkgver);
378 }
379
380 return pkg;
381}
94d3d665 382
2d794cc0
DM
383/* This function doesn't work as well as one might think, as size of database
384 * entries varies considerably. Adding signatures nearly doubles the size of a
385 * single entry; deltas also can make for large variations in size. These
386 * current values are heavily influenced by Arch Linux; databases with no
387 * deltas and a single signature per package. */
d1cc1ef6 388static size_t estimate_package_count(struct stat *st, struct archive *archive)
5dae577a 389{
2d794cc0 390 int per_package;
5dae577a 391
e1e4bbb7 392 switch(_alpm_archive_filter_code(archive)) {
5dae577a 393 case ARCHIVE_COMPRESSION_NONE:
2d794cc0 394 per_package = 3015;
5dae577a
DM
395 break;
396 case ARCHIVE_COMPRESSION_GZIP:
2d794cc0
DM
397 case ARCHIVE_COMPRESSION_COMPRESS:
398 per_package = 464;
5dae577a
DM
399 break;
400 case ARCHIVE_COMPRESSION_BZIP2:
2d794cc0 401 per_package = 394;
5dae577a
DM
402 break;
403 case ARCHIVE_COMPRESSION_LZMA:
404 case ARCHIVE_COMPRESSION_XZ:
2d794cc0 405 per_package = 400;
5dae577a 406 break;
c3771073 407#ifdef ARCHIVE_COMPRESSION_UU
5dae577a 408 case ARCHIVE_COMPRESSION_UU:
2d794cc0 409 per_package = 3015 * 4 / 3;
5dae577a 410 break;
c3771073 411#endif
5dae577a
DM
412 default:
413 /* assume it is at least somewhat compressed */
2d794cc0 414 per_package = 500;
5dae577a 415 }
0303b26b 416 return (size_t)((st->st_size / per_package) + 1);
5dae577a
DM
417}
418
939d5a95 419static int sync_db_populate(alpm_db_t *db)
e2faeb46 420{
39fd8bc3 421 const char *dbpath;
d1cc1ef6 422 size_t est_count;
7f51ba99 423 int count, fd;
5dae577a 424 struct stat buf;
5e61f077
AM
425 struct archive *archive;
426 struct archive_entry *entry;
8a04bc25 427 alpm_pkg_t *pkg = NULL;
e2faeb46 428
c885a953
DM
429 if(db->status & DB_STATUS_INVALID) {
430 RET_ERR(db->handle, ALPM_ERR_DB_INVALID, -1);
431 }
432 if(db->status & DB_STATUS_MISSING) {
433 RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1);
434 }
6df55817
DM
435 dbpath = _alpm_db_path(db);
436 if(!dbpath) {
437 /* pm_errno set in _alpm_db_path() */
438 return -1;
439 }
c885a953 440
dee8144c
DM
441 fd = _alpm_open_archive(db->handle, dbpath, &buf,
442 &archive, ALPM_ERR_DB_OPEN);
443 if(fd < 0) {
7f51ba99 444 return -1;
5dae577a
DM
445 }
446 est_count = estimate_package_count(&buf, archive);
5e61f077 447
0b9cd944 448 db->pkgcache = _alpm_pkghash_create(est_count);
be9a60a3 449 if(db->pkgcache == NULL) {
6df55817 450 db->handle->pm_errno = ALPM_ERR_MEMORY;
7f51ba99 451 count = -1;
6df55817 452 goto cleanup;
be9a60a3 453 }
f8fdce6c 454
5e61f077 455 while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
d8fab9b4
DM
456 mode_t mode = archive_entry_mode(entry);
457 if(S_ISDIR(mode)) {
777bdc6c 458 continue;
4a8e396a
AM
459 } else {
460 /* we have desc, depends or deltas - parse it */
777bdc6c 461 if(sync_db_read(db, archive, entry, &pkg) != 0) {
ca43fdd9 462 _alpm_log(db->handle, ALPM_LOG_ERROR,
d589a7b5
DM
463 _("could not parse package description file '%s' from db '%s'\n"),
464 archive_entry_pathname(entry), db->treename);
cc25576f
DM
465 continue;
466 }
4a8e396a 467 }
e2faeb46
AF
468 }
469
777bdc6c 470 count = alpm_list_count(db->pkgcache->list);
f8fdce6c 471 if(count > 0) {
6df55817
DM
472 db->pkgcache->list = alpm_list_msort(db->pkgcache->list,
473 (size_t)count, _alpm_pkg_cmp);
f8fdce6c 474 }
6df55817
DM
475 _alpm_log(db->handle, ALPM_LOG_DEBUG,
476 "added %d packages to package cache for db '%s'\n",
3045f09e 477 count, db->treename);
5e61f077 478
6df55817 479cleanup:
e1e4bbb7 480 _alpm_archive_read_free(archive);
6df55817 481 if(fd >= 0) {
eb19d41d 482 close(fd);
6df55817 483 }
0303b26b 484 return count;
e2faeb46
AF
485}
486
dd62fde5
SG
487/* This function validates %FILENAME%. filename must be between 3 and
488 * PATH_MAX characters and cannot be contain a path */
489static int _alpm_validate_filename(alpm_db_t *db, const char *pkgname,
490 const char *filename)
491{
492 size_t len = strlen(filename);
493
494 if(filename[0] == '.') {
495 errno = EINVAL;
496 _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: filename "
497 "of package %s is illegal\n"), db->treename, pkgname);
498 return -1;
499 } else if(memchr(filename, '/', len) != NULL) {
500 errno = EINVAL;
501 _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: filename "
502 "of package %s is illegal\n"), db->treename, pkgname);
503 return -1;
504 } else if(len > PATH_MAX) {
505 errno = EINVAL;
506 _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: filename "
507 "of package %s is too long\n"), db->treename, pkgname);
508 return -1;
509 }
510
511 return 0;
512}
513
de8b9a85 514#define READ_NEXT() do { \
f2dff086 515 if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \
cbaff216 516 line = buf.line; \
f556fe8b 517 _alpm_strip_newline(line, buf.real_line_size); \
8ac7f7e6
DM
518} while(0)
519
520#define READ_AND_STORE(f) do { \
de8b9a85 521 READ_NEXT(); \
8ac7f7e6
DM
522 STRDUP(f, line, goto error); \
523} while(0)
524
525#define READ_AND_STORE_ALL(f) do { \
526 char *linedup; \
cbaff216 527 if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \
f556fe8b 528 if(_alpm_strip_newline(buf.line, buf.real_line_size) == 0) break; \
cbaff216 529 STRDUP(linedup, buf.line, goto error); \
8ac7f7e6
DM
530 f = alpm_list_add(f, linedup); \
531} while(1) /* note the while(1) and not (0) */
532
a628feee
DM
533#define READ_AND_SPLITDEP(f) do { \
534 if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \
f556fe8b 535 if(_alpm_strip_newline(buf.line, buf.real_line_size) == 0) break; \
a628feee
DM
536 f = alpm_list_add(f, _alpm_splitdep(line)); \
537} while(1) /* note the while(1) and not (0) */
538
939d5a95 539static int sync_db_read(alpm_db_t *db, struct archive *archive,
8a04bc25 540 struct archive_entry *entry, alpm_pkg_t **likely_pkg)
e2faeb46 541{
e2aa9526 542 const char *entryname, *filename;
8a04bc25 543 alpm_pkg_t *pkg;
f2dff086 544 struct archive_read_buffer buf;
e2faeb46 545
e2aa9526 546 entryname = archive_entry_pathname(entry);
c2cce1f4 547 if(entryname == NULL) {
ca43fdd9 548 _alpm_log(db->handle, ALPM_LOG_DEBUG,
52bffd24 549 "invalid archive entry provided to _alpm_sync_db_read, skipping\n");
0303b26b 550 return -1;
e2faeb46
AF
551 }
552
ca43fdd9 553 _alpm_log(db->handle, ALPM_LOG_FUNCTION, "loading package data from archive entry %s\n",
4a8e396a
AM
554 entryname);
555
f2dff086
DM
556 memset(&buf, 0, sizeof(buf));
557 /* 512K for a line length seems reasonable */
558 buf.max_line_size = 512 * 1024;
559
777bdc6c
DM
560 pkg = load_pkg_for_entry(db, entryname, &filename, *likely_pkg);
561
4a8e396a 562 if(pkg == NULL) {
ca43fdd9 563 _alpm_log(db->handle, ALPM_LOG_DEBUG,
777bdc6c
DM
564 "entry %s could not be loaded into %s sync database",
565 entryname, db->treename);
0303b26b 566 return -1;
3bf918dc
AG
567 }
568
24abcddc
DR
569 if(filename == NULL) {
570 /* A file exists outside of a subdirectory. This isn't a read error, so return
571 * success and try to continue on. */
572 _alpm_log(db->handle, ALPM_LOG_WARNING, _("unknown database file: %s\n"),
573 filename);
574 return 0;
575 }
576
3030542d 577 if(strcmp(filename, "desc") == 0 || strcmp(filename, "depends") == 0
17d4ec5e 578 || (strcmp(filename, "deltas") == 0 && db->handle->deltaratio > 0.0) ) {
cc25576f
DM
579 int ret;
580 while((ret = _alpm_archive_fgets(archive, &buf)) == ARCHIVE_OK) {
cbaff216 581 char *line = buf.line;
f556fe8b 582 if(_alpm_strip_newline(line, buf.real_line_size) == 0) {
b221af66
DM
583 /* length of stripped line was zero */
584 continue;
585 }
f2dff086 586
da1c11cc 587 if(strcmp(line, "%NAME%") == 0) {
de8b9a85 588 READ_NEXT();
8ac7f7e6 589 if(strcmp(line, pkg->name) != 0) {
ca43fdd9 590 _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: name "
4a8e396a 591 "mismatch on package %s\n"), db->treename, pkg->name);
da1c11cc
NG
592 }
593 } else if(strcmp(line, "%VERSION%") == 0) {
de8b9a85 594 READ_NEXT();
8ac7f7e6 595 if(strcmp(line, pkg->version) != 0) {
ca43fdd9 596 _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: version "
4a8e396a 597 "mismatch on package %s\n"), db->treename, pkg->name);
da1c11cc
NG
598 }
599 } else if(strcmp(line, "%FILENAME%") == 0) {
8ac7f7e6 600 READ_AND_STORE(pkg->filename);
dd62fde5
SG
601 if(_alpm_validate_filename(db, pkg->name, pkg->filename) < 0) {
602 return -1;
603 }
da1c11cc 604 } else if(strcmp(line, "%DESC%") == 0) {
8ac7f7e6 605 READ_AND_STORE(pkg->desc);
ccc1c731 606 } else if(strcmp(line, "%GROUPS%") == 0) {
8ac7f7e6 607 READ_AND_STORE_ALL(pkg->groups);
ccc1c731 608 } else if(strcmp(line, "%URL%") == 0) {
8ac7f7e6 609 READ_AND_STORE(pkg->url);
ccc1c731 610 } else if(strcmp(line, "%LICENSE%") == 0) {
8ac7f7e6 611 READ_AND_STORE_ALL(pkg->licenses);
ccc1c731 612 } else if(strcmp(line, "%ARCH%") == 0) {
8ac7f7e6 613 READ_AND_STORE(pkg->arch);
ccc1c731 614 } else if(strcmp(line, "%BUILDDATE%") == 0) {
de8b9a85 615 READ_NEXT();
4bc6ed56 616 pkg->builddate = _alpm_parsedate(line);
ccc1c731 617 } else if(strcmp(line, "%PACKAGER%") == 0) {
8ac7f7e6 618 READ_AND_STORE(pkg->packager);
5b17d8f2 619 } else if(strcmp(line, "%CSIZE%") == 0) {
de8b9a85 620 READ_NEXT();
234b6ffc 621 pkg->size = _alpm_strtoofft(line);
ccc1c731 622 } else if(strcmp(line, "%ISIZE%") == 0) {
de8b9a85 623 READ_NEXT();
234b6ffc 624 pkg->isize = _alpm_strtoofft(line);
ccc1c731 625 } else if(strcmp(line, "%MD5SUM%") == 0) {
8ac7f7e6 626 READ_AND_STORE(pkg->md5sum);
a31d091f 627 } else if(strcmp(line, "%SHA256SUM%") == 0) {
ebb2e36c 628 READ_AND_STORE(pkg->sha256sum);
39ce9b3a 629 } else if(strcmp(line, "%PGPSIG%") == 0) {
225acbbf 630 READ_AND_STORE(pkg->base64_sig);
ccc1c731 631 } else if(strcmp(line, "%REPLACES%") == 0) {
a628feee 632 READ_AND_SPLITDEP(pkg->replaces);
a44c7b89 633 } else if(strcmp(line, "%DEPENDS%") == 0) {
a628feee 634 READ_AND_SPLITDEP(pkg->depends);
ccc1c731 635 } else if(strcmp(line, "%OPTDEPENDS%") == 0) {
e85e77e6 636 READ_AND_SPLITDEP(pkg->optdepends);
81bc390d
AM
637 } else if(strcmp(line, "%MAKEDEPENDS%") == 0) {
638 /* currently unused */
639 while(1) {
640 READ_NEXT();
641 if(strlen(line) == 0) break;
642 }
e253968b
AM
643 } else if(strcmp(line, "%CHECKDEPENDS%") == 0) {
644 /* currently unused */
645 while(1) {
646 READ_NEXT();
647 if(strlen(line) == 0) break;
648 }
ccc1c731 649 } else if(strcmp(line, "%CONFLICTS%") == 0) {
a628feee 650 READ_AND_SPLITDEP(pkg->conflicts);
ccc1c731 651 } else if(strcmp(line, "%PROVIDES%") == 0) {
a628feee 652 READ_AND_SPLITDEP(pkg->provides);
3030542d 653 } else if(strcmp(line, "%DELTAS%") == 0) {
b48f7184 654 /* Different than the rest because of the _alpm_delta_parse call. */
655 while(1) {
de8b9a85 656 READ_NEXT();
b48f7184 657 if(strlen(line) == 0) break;
819c28bf
DM
658 pkg->deltas = alpm_list_add(pkg->deltas,
659 _alpm_delta_parse(db->handle, line));
b48f7184 660 }
3030542d 661 }
e2faeb46 662 }
cc25576f
DM
663 if(ret != ARCHIVE_EOF) {
664 goto error;
665 }
777bdc6c 666 *likely_pkg = pkg;
17d4ec5e
AM
667 } else if(strcmp(filename, "deltas") == 0) {
668 /* skip reading delta files if UseDelta is unset */
f2023176
AM
669 } else if(strcmp(filename, "files") == 0) {
670 /* currently do nothing with this file */
4a8e396a 671 } else {
f2023176 672 /* unknown database file */
ca43fdd9 673 _alpm_log(db->handle, ALPM_LOG_DEBUG, "unknown database file: %s\n", filename);
e2faeb46
AF
674 }
675
cc25576f
DM
676 return 0;
677
e2faeb46 678error:
ca43fdd9 679 _alpm_log(db->handle, ALPM_LOG_DEBUG, "error parsing database file: %s\n", filename);
cc25576f 680 return -1;
e2faeb46
AF
681}
682
fc32faaa 683struct db_operations sync_db_ops = {
68284da0 684 .validate = sync_db_validate,
c00e0599 685 .populate = sync_db_populate,
fc32faaa
AM
686 .unregister = _alpm_db_unregister,
687};
688
939d5a95 689alpm_db_t *_alpm_db_register_sync(alpm_handle_t *handle, const char *treename,
7af0ab1c 690 alpm_siglevel_t level)
fc32faaa 691{
939d5a95 692 alpm_db_t *db;
fc32faaa 693
ca43fdd9 694 _alpm_log(handle, ALPM_LOG_DEBUG, "registering sync database '%s'\n", treename);
fc32faaa 695
05f7c028 696#ifndef HAVE_LIBGPGME
8fe8233d 697 if((level &= ~ALPM_SIG_PACKAGE_SET) != 0 && level != ALPM_SIG_USE_DEFAULT) {
05f7c028
DM
698 RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL);
699 }
700#endif
701
fc32faaa 702 db = _alpm_db_new(treename, 0);
fc32faaa 703 if(db == NULL) {
afc96f2a 704 RET_ERR(handle, ALPM_ERR_DB_CREATE, NULL);
fc32faaa 705 }
be9a60a3 706 db->ops = &sync_db_ops;
c47d25d7 707 db->handle = handle;
7af0ab1c 708 db->siglevel = level;
db3b86e7 709
c748eadc 710 sync_db_validate(db);
fc32faaa
AM
711
712 handle->dbs_sync = alpm_list_add(handle->dbs_sync, db);
0303b26b 713 return db;
fc32faaa
AM
714}
715
e2faeb46 716/* vim: set ts=2 sw=2 noet: */