awful debugging hacking
[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 }