diff options
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/filesdb.c | 4 | ||||
-rw-r--r-- | src/infodb-access.c | 11 | ||||
-rw-r--r-- | src/infodb-format.c | 111 | ||||
-rw-r--r-- | src/infodb.h | 10 |
6 files changed, 139 insertions, 2 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in index 275eaeede..35f967167 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -52,6 +52,7 @@ src/errors.c src/filesdb.c src/help.c src/infodb-access.c +src/infodb-format.c src/main.c src/packages.c src/processarc.c diff --git a/src/Makefile.am b/src/Makefile.am index de1b706a6..caf614030 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,6 +40,7 @@ dpkg_SOURCES = \ file-match.c file-match.h \ filters.c filters.h \ infodb-access.c \ + infodb-format.c \ divertdb.c \ statdb.c \ help.c \ @@ -57,17 +58,20 @@ dpkg_LDADD = \ dpkg_divert_SOURCES = \ filesdb.c \ + infodb-format.c \ divertdb.c \ divertcmd.c dpkg_query_SOURCES = \ filesdb.c \ infodb-access.c \ + infodb-format.c \ divertdb.c \ querycmd.c dpkg_statoverride_SOURCES = \ filesdb.c \ + infodb-format.c \ statdb.c \ statcmd.c diff --git a/src/filesdb.c b/src/filesdb.c index 1fa291c2c..c55bf1e65 100644 --- a/src/filesdb.c +++ b/src/filesdb.c @@ -50,6 +50,7 @@ #include <dpkg/progress.h> #include "filesdb.h" +#include "infodb.h" #include "main.h" /*** Package control information database directory routines. ***/ @@ -85,6 +86,9 @@ pkgadminfile(struct pkginfo *pkg, struct pkgbin *pkgbin, const char *filetype) varbuf_add_str(&vb, infodir); varbuf_add_char(&vb, '/'); varbuf_add_str(&vb, pkg->set->name); + if (pkgbin->multiarch == multiarch_same && + pkg_infodb_get_format() == pkg_infodb_format_multiarch) + varbuf_add_archqual(&vb, pkgbin->arch); varbuf_add_char(&vb, '.'); varbuf_add_str(&vb, filetype); varbuf_end_str(&vb); diff --git a/src/infodb-access.c b/src/infodb-access.c index 31dcbf181..451da2dfe 100644 --- a/src/infodb-access.c +++ b/src/infodb-access.c @@ -60,8 +60,15 @@ pkg_infodb_foreach(struct pkginfo *pkg, struct pkgbin *pkgbin, DIR *db_dir; struct dirent *db_de; struct varbuf db_path = VARBUF_INIT; + const char *pkgname; size_t db_path_len; + if (pkgbin->multiarch == multiarch_same && + pkg_infodb_get_format() == pkg_infodb_format_multiarch) + pkgname = pkgbin_name(pkg, pkgbin, pnaw_always); + else + pkgname = pkgbin_name(pkg, pkgbin, pnaw_never); + varbuf_add_str(&db_path, pkgadmindir()); varbuf_add_char(&db_path, '/'); db_path_len = db_path.used; @@ -88,8 +95,8 @@ pkg_infodb_foreach(struct pkginfo *pkg, struct pkgbin *pkgbin, continue; /* Ignore files from other packages. */ - if (strlen(pkg->set->name) != (size_t)(dot - db_de->d_name) || - strncmp(db_de->d_name, pkg->set->name, dot - db_de->d_name)) + if (strlen(pkgname) != (size_t)(dot - db_de->d_name) || + strncmp(db_de->d_name, pkgname, dot - db_de->d_name)) continue; debug(dbg_stupidlyverbose, "infodb foreach file this pkg"); diff --git a/src/infodb-format.c b/src/infodb-format.c new file mode 100644 index 000000000..488767fbb --- /dev/null +++ b/src/infodb-format.c @@ -0,0 +1,111 @@ +/* + * dpkg - main program for package management + * infodb-format.c - package control information database format + * + * Copyright © 2011 Guillem Jover <guillem@debian.org> + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <compat.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> + +#include <dpkg/i18n.h> +#include <dpkg/dpkg.h> +#include <dpkg/dpkg-db.h> + +#include "infodb.h" + +static enum pkg_infodb_format db_format = pkg_infodb_format_unknown; +static bool db_upgrading; + +static enum pkg_infodb_format +pkg_infodb_parse_format(const char *file) +{ + FILE *fp; + int format; + + fp = fopen(file, "r"); + if (fp == NULL) { + /* A missing format file means legacy format (0). */ + if (errno == ENOENT) + return pkg_infodb_format_legacy; + ohshite(_("error trying to open %.250s"), file); + } + + if (fscanf(fp, "%u", &format) != 1) + ohshit(_("corrupt info database format file '%s'"), file); + + fclose(fp); + + return format; +} + +static enum pkg_infodb_format +pkg_infodb_read_format(void) +{ + struct atomic_file *file; + struct stat st; + char *filename; + + filename = dpkg_db_get_path(INFODIR "/format"); + file = atomic_file_new(filename, 0); + + db_format = pkg_infodb_parse_format(file->name); + + /* Check if a previous upgrade got interrupted. Because we are only + * supposed to upgrade the db layout one format at a time, if the + * new file exists that means the new format is just one ahead, + * we don't try to read it because it contains unreliable data. */ + if (stat(file->name_new, &st) == 0) { + db_format++; + db_upgrading = true; + } + + atomic_file_free(file); + free(filename); + + return db_format; +} + +enum pkg_infodb_format +pkg_infodb_get_format(void) +{ + if (db_format > pkg_infodb_format_unknown) + return db_format; + else + return pkg_infodb_read_format(); +} + +void +pkg_infodb_set_format(enum pkg_infodb_format version) +{ + db_format = version; +} + +bool +pkg_infodb_is_upgrading(void) +{ + if (db_format < 0) + pkg_infodb_read_format(); + + return db_upgrading; +} diff --git a/src/infodb.h b/src/infodb.h index 338b5bccd..fbba824f7 100644 --- a/src/infodb.h +++ b/src/infodb.h @@ -25,6 +25,16 @@ #include <dpkg/dpkg-db.h> +enum pkg_infodb_format { + pkg_infodb_format_unknown = -1, + pkg_infodb_format_legacy = 0, + pkg_infodb_format_multiarch = 1, +}; + +enum pkg_infodb_format pkg_infodb_get_format(void); +void pkg_infodb_set_format(enum pkg_infodb_format format); +bool pkg_infodb_is_upgrading(void); + bool pkg_infodb_has_file(struct pkginfo *pkg, struct pkgbin *pkgbin, const char *name); |