Fix locale.h/setlocale inclusion with --disable-nls
[pacman-ng.git] / lib / libalpm / be_local.c
blobc7110fafa8f25b061f0605e54a4a2705552c39b0
1 /*
2 * be_local.c
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/>.
21 #include "config.h"
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <stdint.h> /* intmax_t */
29 #include <sys/stat.h>
30 #include <dirent.h>
31 #include <time.h>
32 #include <limits.h> /* PATH_MAX */
34 /* libarchive */
35 #include <archive.h>
36 #include <archive_entry.h>
38 /* libalpm */
39 #include "db.h"
40 #include "alpm_list.h"
41 #include "log.h"
42 #include "util.h"
43 #include "alpm.h"
44 #include "handle.h"
45 #include "package.h"
46 #include "group.h"
47 #include "deps.h"
48 #include "dload.h"
51 #define LAZY_LOAD(info, errret) \
52 do { \
53 ALPM_LOG_FUNC; \
54 ASSERT(handle != NULL, return(errret)); \
55 ASSERT(pkg != NULL, return(errret)); \
56 if(pkg->origin != PKG_FROM_FILE && !(pkg->infolevel & info)) { \
57 _alpm_local_db_read(pkg->origin_data.db, pkg, info); \
58 } \
59 } while(0)
62 /* Cache-specific accessor functions. These implementations allow for lazy
63 * loading by the files backend when a data member is actually needed
64 * rather than loading all pieces of information when the package is first
65 * initialized.
68 static const char *_cache_get_filename(pmpkg_t *pkg)
70 LAZY_LOAD(INFRQ_DESC, NULL);
71 return pkg->filename;
74 static const char *_cache_get_name(pmpkg_t *pkg)
76 ASSERT(pkg != NULL, return(NULL));
77 return pkg->name;
80 static const char *_cache_get_version(pmpkg_t *pkg)
82 ASSERT(pkg != NULL, return(NULL));
83 return pkg->version;
86 static const char *_cache_get_desc(pmpkg_t *pkg)
88 LAZY_LOAD(INFRQ_DESC, NULL);
89 return pkg->desc;
92 static const char *_cache_get_url(pmpkg_t *pkg)
94 LAZY_LOAD(INFRQ_DESC, NULL);
95 return pkg->url;
98 static time_t _cache_get_builddate(pmpkg_t *pkg)
100 LAZY_LOAD(INFRQ_DESC, 0);
101 return pkg->builddate;
104 static time_t _cache_get_installdate(pmpkg_t *pkg)
106 LAZY_LOAD(INFRQ_DESC, 0);
107 return pkg->installdate;
110 static const char *_cache_get_packager(pmpkg_t *pkg)
112 LAZY_LOAD(INFRQ_DESC, NULL);
113 return pkg->packager;
116 static const char *_cache_get_md5sum(pmpkg_t *pkg)
118 LAZY_LOAD(INFRQ_DESC, NULL);
119 return pkg->md5sum;
122 static const char *_cache_get_arch(pmpkg_t *pkg)
124 LAZY_LOAD(INFRQ_DESC, NULL);
125 return pkg->arch;
128 static off_t _cache_get_size(pmpkg_t *pkg)
130 LAZY_LOAD(INFRQ_DESC, -1);
131 return pkg->size;
134 static off_t _cache_get_isize(pmpkg_t *pkg)
136 LAZY_LOAD(INFRQ_DESC, -1);
137 return pkg->isize;
140 static pmpkgreason_t _cache_get_reason(pmpkg_t *pkg)
142 LAZY_LOAD(INFRQ_DESC, -1);
143 return pkg->reason;
146 static alpm_list_t *_cache_get_licenses(pmpkg_t *pkg)
148 LAZY_LOAD(INFRQ_DESC, NULL);
149 return pkg->licenses;
152 static alpm_list_t *_cache_get_groups(pmpkg_t *pkg)
154 LAZY_LOAD(INFRQ_DESC, NULL);
155 return pkg->groups;
158 static int _cache_has_scriptlet(pmpkg_t *pkg)
160 ALPM_LOG_FUNC;
162 /* Sanity checks */
163 ASSERT(handle != NULL, return(-1));
164 ASSERT(pkg != NULL, return(-1));
166 if(!(pkg->infolevel & INFRQ_SCRIPTLET)) {
167 _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_SCRIPTLET);
169 return pkg->scriptlet;
172 static alpm_list_t *_cache_get_depends(pmpkg_t *pkg)
174 LAZY_LOAD(INFRQ_DESC, NULL);
175 return pkg->depends;
178 static alpm_list_t *_cache_get_optdepends(pmpkg_t *pkg)
180 LAZY_LOAD(INFRQ_DESC, NULL);
181 return pkg->optdepends;
184 static alpm_list_t *_cache_get_conflicts(pmpkg_t *pkg)
186 LAZY_LOAD(INFRQ_DESC, NULL);
187 return pkg->conflicts;
190 static alpm_list_t *_cache_get_provides(pmpkg_t *pkg)
192 LAZY_LOAD(INFRQ_DESC, NULL);
193 return pkg->provides;
196 static alpm_list_t *_cache_get_replaces(pmpkg_t *pkg)
198 LAZY_LOAD(INFRQ_DESC, NULL);
199 return pkg->replaces;
202 /* local packages can not have deltas */
203 static alpm_list_t *_cache_get_deltas(pmpkg_t *pkg)
205 return NULL;
208 static alpm_list_t *_cache_get_files(pmpkg_t *pkg)
210 ALPM_LOG_FUNC;
212 /* Sanity checks */
213 ASSERT(handle != NULL, return(NULL));
214 ASSERT(pkg != NULL, return(NULL));
216 if(pkg->origin == PKG_FROM_LOCALDB
217 && !(pkg->infolevel & INFRQ_FILES)) {
218 _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_FILES);
220 return pkg->files;
223 static alpm_list_t *_cache_get_backup(pmpkg_t *pkg)
225 ALPM_LOG_FUNC;
227 /* Sanity checks */
228 ASSERT(handle != NULL, return(NULL));
229 ASSERT(pkg != NULL, return(NULL));
231 if(pkg->origin == PKG_FROM_LOCALDB
232 && !(pkg->infolevel & INFRQ_FILES)) {
233 _alpm_local_db_read(pkg->origin_data.db, pkg, INFRQ_FILES);
235 return pkg->backup;
239 * Open a package changelog for reading. Similar to fopen in functionality,
240 * except that the returned 'file stream' is from the database.
241 * @param pkg the package (from db) to read the changelog
242 * @return a 'file stream' to the package changelog
244 static void *_cache_changelog_open(pmpkg_t *pkg)
246 ALPM_LOG_FUNC;
248 /* Sanity checks */
249 ASSERT(handle != NULL, return(NULL));
250 ASSERT(pkg != NULL, return(NULL));
252 char clfile[PATH_MAX];
253 snprintf(clfile, PATH_MAX, "%s/%s/%s-%s/changelog",
254 alpm_option_get_dbpath(),
255 alpm_db_get_name(alpm_pkg_get_db(pkg)),
256 alpm_pkg_get_name(pkg),
257 alpm_pkg_get_version(pkg));
258 return fopen(clfile, "r");
262 * Read data from an open changelog 'file stream'. Similar to fread in
263 * functionality, this function takes a buffer and amount of data to read.
264 * @param ptr a buffer to fill with raw changelog data
265 * @param size the size of the buffer
266 * @param pkg the package that the changelog is being read from
267 * @param fp a 'file stream' to the package changelog
268 * @return the number of characters read, or 0 if there is no more data
270 static size_t _cache_changelog_read(void *ptr, size_t size,
271 const pmpkg_t *pkg, const void *fp)
273 return ( fread(ptr, 1, size, (FILE*)fp) );
277 static int _cache_changelog_feof(const pmpkg_t *pkg, void *fp)
279 return( feof((FILE*)fp) );
284 * Close a package changelog for reading. Similar to fclose in functionality,
285 * except that the 'file stream' is from the database.
286 * @param pkg the package that the changelog was read from
287 * @param fp a 'file stream' to the package changelog
288 * @return whether closing the package changelog stream was successful
290 static int _cache_changelog_close(const pmpkg_t *pkg, void *fp)
292 return( fclose((FILE*)fp) );
296 /** The local database operations struct. Get package fields through
297 * lazy accessor methods that handle any backend loading and caching
298 * logic.
300 static struct pkg_operations local_pkg_ops = {
301 .get_filename = _cache_get_filename,
302 .get_name = _cache_get_name,
303 .get_version = _cache_get_version,
304 .get_desc = _cache_get_desc,
305 .get_url = _cache_get_url,
306 .get_builddate = _cache_get_builddate,
307 .get_installdate = _cache_get_installdate,
308 .get_packager = _cache_get_packager,
309 .get_md5sum = _cache_get_md5sum,
310 .get_arch = _cache_get_arch,
311 .get_size = _cache_get_size,
312 .get_isize = _cache_get_isize,
313 .get_reason = _cache_get_reason,
314 .has_scriptlet = _cache_has_scriptlet,
315 .get_licenses = _cache_get_licenses,
316 .get_groups = _cache_get_groups,
317 .get_depends = _cache_get_depends,
318 .get_optdepends = _cache_get_optdepends,
319 .get_conflicts = _cache_get_conflicts,
320 .get_provides = _cache_get_provides,
321 .get_replaces = _cache_get_replaces,
322 .get_deltas = _cache_get_deltas,
323 .get_files = _cache_get_files,
324 .get_backup = _cache_get_backup,
326 .changelog_open = _cache_changelog_open,
327 .changelog_read = _cache_changelog_read,
328 .changelog_close = _cache_changelog_close,
331 static int checkdbdir(pmdb_t *db)
333 struct stat buf;
334 const char *path = _alpm_db_path(db);
336 if(stat(path, &buf) != 0) {
337 _alpm_log(PM_LOG_DEBUG, "database dir '%s' does not exist, creating it\n",
338 path);
339 if(_alpm_makepath(path) != 0) {
340 RET_ERR(PM_ERR_SYSTEM, -1);
342 } else if(!S_ISDIR(buf.st_mode)) {
343 _alpm_log(PM_LOG_WARNING, _("removing invalid database: %s\n"), path);
344 if(unlink(path) != 0 || _alpm_makepath(path) != 0) {
345 RET_ERR(PM_ERR_SYSTEM, -1);
348 return(0);
351 static int is_dir(const char *path, struct dirent *entry)
353 #ifdef HAVE_STRUCT_DIRENT_D_TYPE
354 return(entry->d_type == DT_DIR);
355 #else
356 char buffer[PATH_MAX];
357 snprintf(buffer, PATH_MAX, "%s/%s", path, entry->d_name);
359 struct stat sbuf;
360 if (!stat(buffer, &sbuf)) {
361 return(S_ISDIR(sbuf.st_mode));
364 return(0);
365 #endif
368 static int local_db_populate(pmdb_t *db)
370 int count = 0;
371 struct dirent *ent = NULL;
372 const char *dbpath;
373 DIR *dbdir;
375 ALPM_LOG_FUNC;
377 ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
379 dbpath = _alpm_db_path(db);
380 if(dbpath == NULL) {
381 return(-1);
383 dbdir = opendir(dbpath);
384 if(dbdir == NULL) {
385 return(0);
387 while((ent = readdir(dbdir)) != NULL) {
388 const char *name = ent->d_name;
390 pmpkg_t *pkg;
392 if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
393 continue;
395 if(!is_dir(dbpath, ent)) {
396 continue;
399 pkg = _alpm_pkg_new();
400 if(pkg == NULL) {
401 closedir(dbdir);
402 RET_ERR(PM_ERR_MEMORY, -1);
404 /* split the db entry name */
405 if(_alpm_splitname(name, pkg) != 0) {
406 _alpm_log(PM_LOG_ERROR, _("invalid name for database entry '%s'\n"),
407 name);
408 _alpm_pkg_free(pkg);
409 continue;
412 /* duplicated database entries are not allowed */
413 if(_alpm_pkg_find(db->pkgcache, pkg->name)) {
414 _alpm_log(PM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name);
415 _alpm_pkg_free(pkg);
416 continue;
419 pkg->origin = PKG_FROM_LOCALDB;
420 pkg->origin_data.db = db;
421 pkg->ops = &local_pkg_ops;
423 /* explicitly read with only 'BASE' data, accessors will handle the rest */
424 if(_alpm_local_db_read(db, pkg, INFRQ_BASE) == -1) {
425 _alpm_log(PM_LOG_ERROR, _("corrupted database entry '%s'\n"), name);
426 _alpm_pkg_free(pkg);
427 continue;
430 /* add to the collection */
431 _alpm_log(PM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n",
432 pkg->name, db->treename);
433 db->pkgcache = alpm_list_add(db->pkgcache, pkg);
434 count++;
437 closedir(dbdir);
438 db->pkgcache = alpm_list_msort(db->pkgcache, (size_t)count, _alpm_pkg_cmp);
439 return(count);
442 /* Note: the return value must be freed by the caller */
443 static char *get_pkgpath(pmdb_t *db, pmpkg_t *info)
445 size_t len;
446 char *pkgpath;
447 const char *dbpath;
449 dbpath = _alpm_db_path(db);
450 len = strlen(dbpath) + strlen(info->name) + strlen(info->version) + 3;
451 MALLOC(pkgpath, len, RET_ERR(PM_ERR_MEMORY, NULL));
452 sprintf(pkgpath, "%s%s-%s/", dbpath, info->name, info->version);
453 return(pkgpath);
457 int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
459 FILE *fp = NULL;
460 char path[PATH_MAX];
461 char line[1024];
462 char *pkgpath = NULL;
464 ALPM_LOG_FUNC;
466 if(db == NULL) {
467 RET_ERR(PM_ERR_DB_NULL, -1);
470 if(info == NULL || info->name == NULL || info->version == NULL) {
471 _alpm_log(PM_LOG_DEBUG, "invalid package entry provided to _alpm_local_db_read, skipping\n");
472 return(-1);
475 if(info->origin != PKG_FROM_LOCALDB) {
476 _alpm_log(PM_LOG_DEBUG,
477 "request to read info for a non-local package '%s', skipping...\n",
478 info->name);
479 return(-1);
482 /* bitmask logic here:
483 * infolevel: 00001111
484 * inforeq: 00010100
485 * & result: 00000100
486 * == to inforeq? nope, we need to load more info. */
487 if((info->infolevel & inforeq) == inforeq) {
488 /* already loaded all of this info, do nothing */
489 return(0);
491 _alpm_log(PM_LOG_FUNCTION, "loading package data for %s : level=0x%x\n",
492 info->name, inforeq);
494 /* clear out 'line', to be certain - and to make valgrind happy */
495 memset(line, 0, sizeof(line));
497 pkgpath = get_pkgpath(db, info);
499 if(access(pkgpath, F_OK)) {
500 /* directory doesn't exist or can't be opened */
501 _alpm_log(PM_LOG_DEBUG, "cannot find '%s-%s' in db '%s'\n",
502 info->name, info->version, db->treename);
503 goto error;
506 /* DESC */
507 if(inforeq & INFRQ_DESC && !(info->infolevel & INFRQ_DESC)) {
508 snprintf(path, PATH_MAX, "%sdesc", pkgpath);
509 if((fp = fopen(path, "r")) == NULL) {
510 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
511 goto error;
513 while(!feof(fp)) {
514 if(fgets(line, sizeof(line), fp) == NULL) {
515 break;
517 _alpm_strtrim(line);
518 if(strcmp(line, "%NAME%") == 0) {
519 if(fgets(line, sizeof(line), fp) == NULL) {
520 goto error;
522 if(strcmp(_alpm_strtrim(line), info->name) != 0) {
523 _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: name "
524 "mismatch on package %s\n"), db->treename, info->name);
526 } else if(strcmp(line, "%VERSION%") == 0) {
527 if(fgets(line, sizeof(line), fp) == NULL) {
528 goto error;
530 if(strcmp(_alpm_strtrim(line), info->version) != 0) {
531 _alpm_log(PM_LOG_ERROR, _("%s database is inconsistent: version "
532 "mismatch on package %s\n"), db->treename, info->name);
534 } else if(strcmp(line, "%DESC%") == 0) {
535 if(fgets(line, sizeof(line), fp) == NULL) {
536 goto error;
538 STRDUP(info->desc, _alpm_strtrim(line), goto error);
539 } else if(strcmp(line, "%GROUPS%") == 0) {
540 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
541 char *linedup;
542 STRDUP(linedup, _alpm_strtrim(line), goto error);
543 info->groups = alpm_list_add(info->groups, linedup);
545 } else if(strcmp(line, "%URL%") == 0) {
546 if(fgets(line, sizeof(line), fp) == NULL) {
547 goto error;
549 STRDUP(info->url, _alpm_strtrim(line), goto error);
550 } else if(strcmp(line, "%LICENSE%") == 0) {
551 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
552 char *linedup;
553 STRDUP(linedup, _alpm_strtrim(line), goto error);
554 info->licenses = alpm_list_add(info->licenses, linedup);
556 } else if(strcmp(line, "%ARCH%") == 0) {
557 if(fgets(line, sizeof(line), fp) == NULL) {
558 goto error;
560 STRDUP(info->arch, _alpm_strtrim(line), goto error);
561 } else if(strcmp(line, "%BUILDDATE%") == 0) {
562 if(fgets(line, sizeof(line), fp) == NULL) {
563 goto error;
565 _alpm_strtrim(line);
566 info->builddate = _alpm_parsedate(line);
567 } else if(strcmp(line, "%INSTALLDATE%") == 0) {
568 if(fgets(line, sizeof(line), fp) == NULL) {
569 goto error;
571 _alpm_strtrim(line);
572 info->installdate = _alpm_parsedate(line);
573 } else if(strcmp(line, "%PACKAGER%") == 0) {
574 if(fgets(line, sizeof(line), fp) == NULL) {
575 goto error;
577 STRDUP(info->packager, _alpm_strtrim(line), goto error);
578 } else if(strcmp(line, "%REASON%") == 0) {
579 if(fgets(line, sizeof(line), fp) == NULL) {
580 goto error;
582 info->reason = (pmpkgreason_t)atol(_alpm_strtrim(line));
583 } else if(strcmp(line, "%SIZE%") == 0) {
584 /* NOTE: the CSIZE and SIZE fields both share the "size" field
585 * in the pkginfo_t struct. This can be done b/c CSIZE
586 * is currently only used in sync databases, and SIZE is
587 * only used in local databases.
589 if(fgets(line, sizeof(line), fp) == NULL) {
590 goto error;
592 info->size = atol(_alpm_strtrim(line));
593 /* also store this value to isize */
594 info->isize = info->size;
595 } else if(strcmp(line, "%REPLACES%") == 0) {
596 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
597 char *linedup;
598 STRDUP(linedup, _alpm_strtrim(line), goto error);
599 info->replaces = alpm_list_add(info->replaces, linedup);
601 } else if(strcmp(line, "%DEPENDS%") == 0) {
602 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
603 pmdepend_t *dep = _alpm_splitdep(_alpm_strtrim(line));
604 info->depends = alpm_list_add(info->depends, dep);
606 } else if(strcmp(line, "%OPTDEPENDS%") == 0) {
607 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
608 char *linedup;
609 STRDUP(linedup, _alpm_strtrim(line), goto error);
610 info->optdepends = alpm_list_add(info->optdepends, linedup);
612 } else if(strcmp(line, "%CONFLICTS%") == 0) {
613 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
614 char *linedup;
615 STRDUP(linedup, _alpm_strtrim(line), goto error);
616 info->conflicts = alpm_list_add(info->conflicts, linedup);
618 } else if(strcmp(line, "%PROVIDES%") == 0) {
619 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
620 char *linedup;
621 STRDUP(linedup, _alpm_strtrim(line), goto error);
622 info->provides = alpm_list_add(info->provides, linedup);
626 fclose(fp);
627 fp = NULL;
630 /* FILES */
631 if(inforeq & INFRQ_FILES && !(info->infolevel & INFRQ_FILES)) {
632 snprintf(path, PATH_MAX, "%sfiles", pkgpath);
633 if((fp = fopen(path, "r")) == NULL) {
634 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
635 goto error;
637 while(fgets(line, sizeof(line), fp)) {
638 _alpm_strtrim(line);
639 if(strcmp(line, "%FILES%") == 0) {
640 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
641 char *linedup;
642 STRDUP(linedup, _alpm_strtrim(line), goto error);
643 info->files = alpm_list_add(info->files, linedup);
645 } else if(strcmp(line, "%BACKUP%") == 0) {
646 while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) {
647 char *linedup;
648 STRDUP(linedup, _alpm_strtrim(line), goto error);
649 info->backup = alpm_list_add(info->backup, linedup);
653 fclose(fp);
654 fp = NULL;
657 /* INSTALL */
658 if(inforeq & INFRQ_SCRIPTLET && !(info->infolevel & INFRQ_SCRIPTLET)) {
659 snprintf(path, PATH_MAX, "%sinstall", pkgpath);
660 if(access(path, F_OK) == 0) {
661 info->scriptlet = 1;
665 /* internal */
666 info->infolevel |= inforeq;
668 free(pkgpath);
669 return(0);
671 error:
672 free(pkgpath);
673 if(fp) {
674 fclose(fp);
676 return(-1);
679 int _alpm_local_db_prepare(pmdb_t *db, pmpkg_t *info)
681 mode_t oldmask;
682 int retval = 0;
683 char *pkgpath = NULL;
685 if(checkdbdir(db) != 0) {
686 return(-1);
689 oldmask = umask(0000);
690 pkgpath = get_pkgpath(db, info);
692 if((retval = mkdir(pkgpath, 0755)) != 0) {
693 _alpm_log(PM_LOG_ERROR, _("could not create directory %s: %s\n"),
694 pkgpath, strerror(errno));
697 free(pkgpath);
698 umask(oldmask);
700 return(retval);
703 int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq)
705 FILE *fp = NULL;
706 char path[PATH_MAX];
707 mode_t oldmask;
708 alpm_list_t *lp = NULL;
709 int retval = 0;
710 char *pkgpath = NULL;
712 ALPM_LOG_FUNC;
714 if(db == NULL || info == NULL) {
715 return(-1);
718 pkgpath = get_pkgpath(db, info);
720 /* make sure we have a sane umask */
721 oldmask = umask(0022);
723 if(strcmp(db->treename, "local") != 0) {
724 return(-1);
727 /* DESC */
728 if(inforeq & INFRQ_DESC) {
729 _alpm_log(PM_LOG_DEBUG, "writing %s-%s DESC information back to db\n",
730 info->name, info->version);
731 snprintf(path, PATH_MAX, "%sdesc", pkgpath);
732 if((fp = fopen(path, "w")) == NULL) {
733 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
734 retval = -1;
735 goto cleanup;
737 fprintf(fp, "%%NAME%%\n%s\n\n"
738 "%%VERSION%%\n%s\n\n", info->name, info->version);
739 if(info->desc) {
740 fprintf(fp, "%%DESC%%\n"
741 "%s\n\n", info->desc);
743 if(info->groups) {
744 fputs("%GROUPS%\n", fp);
745 for(lp = info->groups; lp; lp = lp->next) {
746 fprintf(fp, "%s\n", (char *)lp->data);
748 fprintf(fp, "\n");
750 if(info->replaces) {
751 fputs("%REPLACES%\n", fp);
752 for(lp = info->replaces; lp; lp = lp->next) {
753 fprintf(fp, "%s\n", (char *)lp->data);
755 fprintf(fp, "\n");
757 if(info->url) {
758 fprintf(fp, "%%URL%%\n"
759 "%s\n\n", info->url);
761 if(info->licenses) {
762 fputs("%LICENSE%\n", fp);
763 for(lp = info->licenses; lp; lp = lp->next) {
764 fprintf(fp, "%s\n", (char *)lp->data);
766 fprintf(fp, "\n");
768 if(info->arch) {
769 fprintf(fp, "%%ARCH%%\n"
770 "%s\n\n", info->arch);
772 if(info->builddate) {
773 fprintf(fp, "%%BUILDDATE%%\n"
774 "%ld\n\n", info->builddate);
776 if(info->installdate) {
777 fprintf(fp, "%%INSTALLDATE%%\n"
778 "%ld\n\n", info->installdate);
780 if(info->packager) {
781 fprintf(fp, "%%PACKAGER%%\n"
782 "%s\n\n", info->packager);
784 if(info->isize) {
785 /* only write installed size, csize is irrelevant once installed */
786 fprintf(fp, "%%SIZE%%\n"
787 "%jd\n\n", (intmax_t)info->isize);
789 if(info->reason) {
790 fprintf(fp, "%%REASON%%\n"
791 "%u\n\n", info->reason);
793 if(info->depends) {
794 fputs("%DEPENDS%\n", fp);
795 for(lp = info->depends; lp; lp = lp->next) {
796 char *depstring = alpm_dep_compute_string(lp->data);
797 fprintf(fp, "%s\n", depstring);
798 free(depstring);
800 fprintf(fp, "\n");
802 if(info->optdepends) {
803 fputs("%OPTDEPENDS%\n", fp);
804 for(lp = info->optdepends; lp; lp = lp->next) {
805 fprintf(fp, "%s\n", (char *)lp->data);
807 fprintf(fp, "\n");
809 if(info->conflicts) {
810 fputs("%CONFLICTS%\n", fp);
811 for(lp = info->conflicts; lp; lp = lp->next) {
812 fprintf(fp, "%s\n", (char *)lp->data);
814 fprintf(fp, "\n");
816 if(info->provides) {
817 fputs("%PROVIDES%\n", fp);
818 for(lp = info->provides; lp; lp = lp->next) {
819 fprintf(fp, "%s\n", (char *)lp->data);
821 fprintf(fp, "\n");
824 fclose(fp);
825 fp = NULL;
828 /* FILES */
829 if(inforeq & INFRQ_FILES) {
830 _alpm_log(PM_LOG_DEBUG, "writing %s-%s FILES information back to db\n",
831 info->name, info->version);
832 snprintf(path, PATH_MAX, "%sfiles", pkgpath);
833 if((fp = fopen(path, "w")) == NULL) {
834 _alpm_log(PM_LOG_ERROR, _("could not open file %s: %s\n"), path, strerror(errno));
835 retval = -1;
836 goto cleanup;
838 if(info->files) {
839 fprintf(fp, "%%FILES%%\n");
840 for(lp = info->files; lp; lp = lp->next) {
841 fprintf(fp, "%s\n", (char *)lp->data);
843 fprintf(fp, "\n");
845 if(info->backup) {
846 fprintf(fp, "%%BACKUP%%\n");
847 for(lp = info->backup; lp; lp = lp->next) {
848 fprintf(fp, "%s\n", (char *)lp->data);
850 fprintf(fp, "\n");
852 fclose(fp);
853 fp = NULL;
856 /* INSTALL */
857 /* nothing needed here (script is automatically extracted) */
859 cleanup:
860 umask(oldmask);
861 free(pkgpath);
863 if(fp) {
864 fclose(fp);
867 return(retval);
870 int _alpm_local_db_remove(pmdb_t *db, pmpkg_t *info)
872 int ret = 0;
873 char *pkgpath = NULL;
875 ALPM_LOG_FUNC;
877 if(db == NULL || info == NULL) {
878 RET_ERR(PM_ERR_DB_NULL, -1);
881 pkgpath = get_pkgpath(db, info);
883 ret = _alpm_rmrf(pkgpath);
884 free(pkgpath);
885 if(ret != 0) {
886 ret = -1;
888 return(ret);
891 struct db_operations local_db_ops = {
892 .populate = local_db_populate,
893 .unregister = _alpm_db_unregister,
896 pmdb_t *_alpm_db_register_local(void)
898 pmdb_t *db;
900 ALPM_LOG_FUNC;
902 _alpm_log(PM_LOG_DEBUG, "registering local database\n");
904 db = _alpm_db_new("local", 1);
905 db->ops = &local_db_ops;
906 if(db == NULL) {
907 RET_ERR(PM_ERR_DB_CREATE, NULL);
910 handle->db_local = db;
911 return(db);
914 /* vim: set ts=2 sw=2 noet: */