chiark / gitweb /
dpkg (1.18.25) stretch; urgency=medium
[dpkg] / lib / dpkg / arch.c
1 /*
2  * libdpkg - Debian packaging suite library routines
3  * arch.c - architecture database functions
4  *
5  * Copyright © 2011 Linaro Limited
6  * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org>
7  * Copyright © 2011-2014 Guillem Jover <guillem@debian.org>
8  *
9  * This is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21  */
22
23 #include <config.h>
24 #include <compat.h>
25
26 #include <assert.h>
27 #include <limits.h>
28 #include <string.h>
29 #include <stdbool.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32
33 #include <dpkg/i18n.h>
34 #include <dpkg/c-ctype.h>
35 #include <dpkg/ehandle.h>
36 #include <dpkg/dpkg.h>
37 #include <dpkg/dpkg-db.h>
38 #include <dpkg/dir.h>
39 #include <dpkg/varbuf.h>
40 #include <dpkg/arch.h>
41
42 #define DPKG_DB_ARCH_FILE "arch"
43
44 /**
45  * Verify if the architecture name is valid.
46  *
47  * Returns NULL if the architecture name is valid. Otherwise it returns a
48  * string describing why it's not valid. Currently it ensures the name
49  * starts with an alphanumeric and is then composed of a combinations of
50  * hyphens and alphanumerics.
51  *
52  * The function will abort if you pass it a NULL pointer.
53  *
54  * @param name The architecture name to verify.
55  */
56 const char *
57 dpkg_arch_name_is_illegal(const char *name)
58 {
59         static char buf[150];
60         const char *p = name;
61
62         assert(name);
63         if (!*p)
64                 return _("may not be empty string");
65         if (!c_isalnum(*p))
66                 return _("must start with an alphanumeric");
67         while (*++p != '\0')
68                 if (!c_isalnum(*p) && *p != '-')
69                         break;
70         if (*p == '\0')
71                 return NULL;
72
73         snprintf(buf, sizeof(buf), _("character '%c' not allowed (only "
74                                      "letters, digits and characters '%s')"),
75                  *p, "-");
76         return buf;
77 }
78
79 /* This is a special architecture used to guarantee we always have a valid
80  * structure to handle. */
81 static struct dpkg_arch arch_item_none = {
82         .name = "",
83         .type = DPKG_ARCH_NONE,
84         .next = NULL,
85 };
86 static struct dpkg_arch arch_item_empty = {
87         .name = "",
88         .type = DPKG_ARCH_EMPTY,
89         .next = NULL,
90 };
91
92 static struct dpkg_arch arch_item_any = {
93         .name = "any",
94         .type = DPKG_ARCH_WILDCARD,
95         .next = NULL,
96 };
97 static struct dpkg_arch arch_item_all = {
98         .name = "all",
99         .type = DPKG_ARCH_ALL,
100         .next = &arch_item_any,
101 };
102 static struct dpkg_arch arch_item_native = {
103         .name = ARCHITECTURE,
104         .type = DPKG_ARCH_NATIVE,
105         .next = &arch_item_all,
106 };
107 static struct dpkg_arch *arch_head = &arch_item_native;
108 static struct dpkg_arch *arch_builtin_tail = &arch_item_any;
109 static bool arch_list_dirty;
110
111 static struct dpkg_arch *
112 dpkg_arch_new(const char *name, enum dpkg_arch_type type)
113 {
114         struct dpkg_arch *new;
115
116         new = nfmalloc(sizeof(*new));
117         new->next = NULL;
118         new->name = nfstrsave(name);
119         new->type = type;
120
121         return new;
122 }
123
124 /**
125  * Retrieve the struct dpkg_arch for the given architecture.
126  *
127  * Create a new structure for the architecture if it's not yet known from
128  * the system, in that case it will have arch->type == arch_unknown, if the
129  * architecture is illegal it will have arch->type == arch_illegal and if
130  * name is NULL or an empty string then it will have arch->type == arch_none.
131  *
132  * @param name The architecture name.
133  */
134 struct dpkg_arch *
135 dpkg_arch_find(const char *name)
136 {
137         struct dpkg_arch *arch, *last_arch = NULL;
138         enum dpkg_arch_type type;
139
140         if (name == NULL)
141                 return &arch_item_none;
142         if (name[0] == '\0')
143                 return &arch_item_empty;
144
145         for (arch = arch_head; arch; arch = arch->next) {
146                 if (strcmp(arch->name, name) == 0)
147                         return arch;
148                 last_arch = arch;
149         }
150
151         if (dpkg_arch_name_is_illegal(name))
152                 type = DPKG_ARCH_ILLEGAL;
153         else
154                 type = DPKG_ARCH_UNKNOWN;
155
156         arch = dpkg_arch_new(name, type);
157         last_arch->next = arch;
158
159         return arch;
160 }
161
162 /**
163  * Return the struct dpkg_arch corresponding to the architecture type.
164  *
165  * The function only returns instances for types which are unique. For
166  * forward-compatibility any unknown type will return NULL.
167  */
168 struct dpkg_arch *
169 dpkg_arch_get(enum dpkg_arch_type type)
170 {
171         switch (type) {
172         case DPKG_ARCH_NONE:
173                 return &arch_item_none;
174         case DPKG_ARCH_EMPTY:
175                 return &arch_item_empty;
176         case DPKG_ARCH_WILDCARD:
177                 return &arch_item_any;
178         case DPKG_ARCH_ALL:
179                 return &arch_item_all;
180         case DPKG_ARCH_NATIVE:
181                 return &arch_item_native;
182         case DPKG_ARCH_ILLEGAL:
183         case DPKG_ARCH_FOREIGN:
184         case DPKG_ARCH_UNKNOWN:
185                 internerr("architecture type %d is not unique", type);
186         default:
187                 /* Ignore unknown types for forward-compatibility. */
188                 return NULL;
189         }
190 }
191
192 /**
193  * Return the complete list of architectures.
194  *
195  * In fact it returns the first item of the linked list and you can
196  * traverse the list by following arch->next until it's NULL.
197  */
198 struct dpkg_arch *
199 dpkg_arch_get_list(void)
200 {
201         return arch_head;
202 }
203
204 /**
205  * Reset the list of architectures.
206  *
207  * Must be called before nffreeall() to ensure we don't point to
208  * unallocated memory.
209  */
210 void
211 dpkg_arch_reset_list(void)
212 {
213         arch_builtin_tail->next = NULL;
214         arch_list_dirty = false;
215 }
216
217 void
218 varbuf_add_archqual(struct varbuf *vb, const struct dpkg_arch *arch)
219 {
220         if (arch->type == DPKG_ARCH_NONE)
221                 return;
222         if (arch->type == DPKG_ARCH_EMPTY)
223                 return;
224
225         varbuf_add_char(vb, ':');
226         varbuf_add_str(vb, arch->name);
227 }
228
229 /**
230  * Return a descriptive architecture name.
231  */
232 const char *
233 dpkg_arch_describe(const struct dpkg_arch *arch)
234 {
235         if (arch->type == DPKG_ARCH_NONE)
236                 return C_("architecture", "<none>");
237         if (arch->type == DPKG_ARCH_EMPTY)
238                 return C_("architecture", "<empty>");
239
240         return arch->name;
241 }
242
243 /**
244  * Add a new foreign dpkg_arch architecture.
245  */
246 struct dpkg_arch *
247 dpkg_arch_add(const char *name)
248 {
249         struct dpkg_arch *arch;
250
251         arch = dpkg_arch_find(name);
252         if (arch->type == DPKG_ARCH_UNKNOWN) {
253                 arch->type = DPKG_ARCH_FOREIGN;
254                 arch_list_dirty = true;
255         }
256
257         return arch;
258 }
259
260 /**
261  * Unmark a foreign dpkg_arch architecture.
262  */
263 void
264 dpkg_arch_unmark(struct dpkg_arch *arch_remove)
265 {
266         struct dpkg_arch *arch;
267
268         for (arch = arch_builtin_tail->next; arch; arch = arch->next) {
269                 if (arch->type != DPKG_ARCH_FOREIGN)
270                         continue;
271
272                 if (arch == arch_remove) {
273                         arch->type = DPKG_ARCH_UNKNOWN;
274                         arch_list_dirty = true;
275                         return;
276                 }
277         }
278 }
279
280 /**
281  * Load the architecture database.
282  */
283 void
284 dpkg_arch_load_list(void)
285 {
286         FILE *fp;
287         char *archfile;
288         char archname[_POSIX2_LINE_MAX];
289
290         archfile = dpkg_db_get_path(DPKG_DB_ARCH_FILE);
291         fp = fopen(archfile, "r");
292         if (fp == NULL) {
293                 arch_list_dirty = true;
294                 free(archfile);
295                 return;
296         }
297
298         while (fgets_checked(archname, sizeof(archname), fp, archfile) >= 0)
299                 dpkg_arch_add(archname);
300
301         free(archfile);
302         fclose(fp);
303 }
304
305 /**
306  * Save the architecture database.
307  */
308 void
309 dpkg_arch_save_list(void)
310 {
311         struct atomic_file *file;
312         struct dpkg_arch *arch;
313         char *archfile;
314
315         if (!arch_list_dirty)
316                 return;
317
318         archfile = dpkg_db_get_path(DPKG_DB_ARCH_FILE);
319         file = atomic_file_new(archfile, 0);
320         atomic_file_open(file);
321
322         for (arch = arch_head; arch; arch = arch->next) {
323                 if (arch->type != DPKG_ARCH_FOREIGN &&
324                     arch->type != DPKG_ARCH_NATIVE)
325                         continue;
326
327                 if (fprintf(file->fp, "%s\n", arch->name) < 0)
328                         ohshite(_("error writing to architecture list"));
329         }
330
331         atomic_file_sync(file);
332         atomic_file_close(file);
333         atomic_file_commit(file);
334         atomic_file_free(file);
335
336         dir_sync_path(dpkg_db_get_dir());
337
338         arch_list_dirty = false;
339
340         free(archfile);
341 }