chiark / gitweb /
lib/dpkg/tarfn.c: Kludge `tar_header_decode' to handle spurious `errno'.
[dpkg] / src / infodb-format.c
1 /*
2  * dpkg - main program for package management
3  * infodb-format.c - package control information database format
4  *
5  * Copyright © 2011-2014 Guillem Jover <guillem@debian.org>
6  *
7  * This 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 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
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <compat.h>
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30
31 #include <dpkg/i18n.h>
32 #include <dpkg/dpkg.h>
33 #include <dpkg/dpkg-db.h>
34 #include <dpkg/varbuf.h>
35
36 #include "infodb.h"
37
38 static enum pkg_infodb_format db_format = PKG_INFODB_FORMAT_UNKNOWN;
39 static bool db_upgrading;
40
41 static enum pkg_infodb_format
42 pkg_infodb_parse_format(const char *file)
43 {
44         FILE *fp;
45         int format;
46
47         fp = fopen(file, "r");
48         if (fp == NULL) {
49                 /* A missing format file means legacy format (0). */
50                 if (errno == ENOENT)
51                         return PKG_INFODB_FORMAT_LEGACY;
52                 ohshite(_("error trying to open %.250s"), file);
53         }
54
55         if (fscanf(fp, "%u", &format) != 1)
56                 ohshit(_("corrupt info database format file '%s'"), file);
57
58         fclose(fp);
59
60         return format;
61 }
62
63 static enum pkg_infodb_format
64 pkg_infodb_read_format(void)
65 {
66         struct atomic_file *file;
67         struct stat st;
68         char *filename;
69
70         filename = dpkg_db_get_path(INFODIR "/format");
71         file = atomic_file_new(filename, 0);
72
73         db_format = pkg_infodb_parse_format(file->name);
74
75         /* Check if a previous upgrade got interrupted. Because we are only
76          * supposed to upgrade the db layout one format at a time, if the
77          * new file exists that means the new format is just one ahead,
78          * we don't try to read it because it contains unreliable data. */
79         if (stat(file->name_new, &st) == 0) {
80                 db_format++;
81                 db_upgrading = true;
82         }
83
84         atomic_file_free(file);
85         free(filename);
86
87         if (db_format < 0 || db_format >= PKG_INFODB_FORMAT_LAST)
88                 ohshit(_("info database format (%d) is bogus or too new; "
89                          "try getting a newer dpkg"), db_format);
90
91         return db_format;
92 }
93
94 enum pkg_infodb_format
95 pkg_infodb_get_format(void)
96 {
97         if (db_format > PKG_INFODB_FORMAT_UNKNOWN)
98                 return db_format;
99         else
100                 return pkg_infodb_read_format();
101 }
102
103 void
104 pkg_infodb_set_format(enum pkg_infodb_format version)
105 {
106         db_format = version;
107 }
108
109 bool
110 pkg_infodb_is_upgrading(void)
111 {
112         if (db_format < 0)
113                 pkg_infodb_read_format();
114
115         return db_upgrading;
116 }
117
118 const char *
119 pkg_infodb_get_dir(void)
120 {
121         static char *infodir;
122
123         if (infodir == NULL)
124                 infodir = dpkg_db_get_path(INFODIR);
125
126         return infodir;
127 }
128
129 const char *
130 pkg_infodb_get_file(struct pkginfo *pkg, struct pkgbin *pkgbin,
131                     const char *filetype)
132 {
133         static struct varbuf vb;
134         enum pkg_infodb_format format;
135
136         /* Make sure to always read and verify the format version. */
137         format = pkg_infodb_get_format();
138
139         varbuf_reset(&vb);
140         varbuf_add_str(&vb, pkg_infodb_get_dir());
141         varbuf_add_char(&vb, '/');
142         varbuf_add_str(&vb, pkg->set->name);
143         if (pkgbin->multiarch == PKG_MULTIARCH_SAME &&
144             format == PKG_INFODB_FORMAT_MULTIARCH)
145                 varbuf_add_archqual(&vb, pkgbin->arch);
146         varbuf_add_char(&vb, '.');
147         varbuf_add_str(&vb, filetype);
148         varbuf_end_str(&vb);
149
150         return vb.buf;
151 }