po: Update German man pages translation
[dpkg.git] / lib / dpkg / arch.c
blob9409f5a5e0f14439dd1594cf63216dbe727bcb73
1 /*
2 * libdpkg - Debian packaging suite library routines
3 * arch.c - architecture database functions
5 * Copyright © 2011 Linaro Limited
6 * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org>
7 * Copyright © 2011-2014 Guillem Jover <guillem@debian.org>
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.
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.
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/>.
23 #include <config.h>
24 #include <compat.h>
26 #include <limits.h>
27 #include <string.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <stdio.h>
32 #include <dpkg/i18n.h>
33 #include <dpkg/c-ctype.h>
34 #include <dpkg/ehandle.h>
35 #include <dpkg/dpkg.h>
36 #include <dpkg/dpkg-db.h>
37 #include <dpkg/dir.h>
38 #include <dpkg/varbuf.h>
39 #include <dpkg/arch.h>
41 #define DPKG_DB_ARCH_FILE "arch"
43 /**
44 * Verify if the architecture name is valid.
46 * Returns NULL if the architecture name is valid. Otherwise it returns a
47 * string describing why it's not valid. Currently it ensures the name
48 * starts with an alphanumeric and is then composed of a combinations of
49 * hyphens and alphanumerics.
51 * The function will abort if you pass it a NULL pointer.
53 * @param name The architecture name to verify.
55 const char *
56 dpkg_arch_name_is_illegal(const char *name)
58 static char buf[150];
59 const char *p = name;
61 if (p == NULL)
62 internerr("arch name argument is NULL");
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;
73 snprintf(buf, sizeof(buf), _("character '%c' not allowed (only "
74 "letters, digits and characters '%s')"),
75 *p, "-");
76 return buf;
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,
86 static struct dpkg_arch arch_item_empty = {
87 .name = "",
88 .type = DPKG_ARCH_EMPTY,
89 .next = NULL,
92 static struct dpkg_arch arch_item_any = {
93 .name = "any",
94 .type = DPKG_ARCH_WILDCARD,
95 .next = NULL,
97 static struct dpkg_arch arch_item_all = {
98 .name = "all",
99 .type = DPKG_ARCH_ALL,
100 .next = &arch_item_any,
102 static struct dpkg_arch arch_item_native = {
103 .name = ARCHITECTURE,
104 .type = DPKG_ARCH_NATIVE,
105 .next = &arch_item_all,
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;
111 static struct dpkg_arch *
112 dpkg_arch_new(const char *name, enum dpkg_arch_type type)
114 struct dpkg_arch *new;
116 new = nfmalloc(sizeof(*new));
117 new->next = NULL;
118 new->name = nfstrsave(name);
119 new->type = type;
121 return new;
125 * Retrieve the struct dpkg_arch for the given architecture.
127 * Create a new structure for the architecture if it is not yet known from
128 * the system, in that case it will have type == DPKG_ARCH_UNKNOWN, if the
129 * architecture is illegal it will have type == DPKG_ARCH_ILLEGAL, if name
130 * is an empty string it will have type == DPKG_ARCH_EMPTY, and if it is
131 * NULL then it will have type == DPKG_ARCH_NONE.
133 * @param name The architecture name.
135 struct dpkg_arch *
136 dpkg_arch_find(const char *name)
138 struct dpkg_arch *arch, *last_arch = NULL;
139 enum dpkg_arch_type type;
141 if (name == NULL)
142 return &arch_item_none;
143 if (name[0] == '\0')
144 return &arch_item_empty;
146 for (arch = arch_head; arch; arch = arch->next) {
147 if (strcmp(arch->name, name) == 0)
148 return arch;
149 last_arch = arch;
152 if (dpkg_arch_name_is_illegal(name))
153 type = DPKG_ARCH_ILLEGAL;
154 else
155 type = DPKG_ARCH_UNKNOWN;
157 arch = dpkg_arch_new(name, type);
158 last_arch->next = arch;
160 return arch;
164 * Return the struct dpkg_arch corresponding to the architecture type.
166 * The function only returns instances for types which are unique. For
167 * forward-compatibility any unknown type will return NULL.
169 struct dpkg_arch *
170 dpkg_arch_get(enum dpkg_arch_type type)
172 switch (type) {
173 case DPKG_ARCH_NONE:
174 return &arch_item_none;
175 case DPKG_ARCH_EMPTY:
176 return &arch_item_empty;
177 case DPKG_ARCH_WILDCARD:
178 return &arch_item_any;
179 case DPKG_ARCH_ALL:
180 return &arch_item_all;
181 case DPKG_ARCH_NATIVE:
182 return &arch_item_native;
183 case DPKG_ARCH_ILLEGAL:
184 case DPKG_ARCH_FOREIGN:
185 case DPKG_ARCH_UNKNOWN:
186 internerr("architecture type %d is not unique", type);
187 default:
188 /* Ignore unknown types for forward-compatibility. */
189 return NULL;
194 * Return the complete list of architectures.
196 * In fact it returns the first item of the linked list and you can
197 * traverse the list by following arch->next until it's NULL.
199 struct dpkg_arch *
200 dpkg_arch_get_list(void)
202 return arch_head;
206 * Reset the list of architectures.
208 * Must be called before nffreeall() to ensure we don't point to
209 * unallocated memory.
211 void
212 dpkg_arch_reset_list(void)
214 arch_builtin_tail->next = NULL;
215 arch_list_dirty = false;
218 void
219 varbuf_add_archqual(struct varbuf *vb, const struct dpkg_arch *arch)
221 if (arch->type == DPKG_ARCH_NONE)
222 return;
223 if (arch->type == DPKG_ARCH_EMPTY)
224 return;
226 varbuf_add_char(vb, ':');
227 varbuf_add_str(vb, arch->name);
231 * Return a descriptive architecture name.
233 const char *
234 dpkg_arch_describe(const struct dpkg_arch *arch)
236 if (arch->type == DPKG_ARCH_NONE)
237 return C_("architecture", "<none>");
238 if (arch->type == DPKG_ARCH_EMPTY)
239 return C_("architecture", "<empty>");
241 return arch->name;
245 * Add a new foreign dpkg_arch architecture.
247 struct dpkg_arch *
248 dpkg_arch_add(const char *name)
250 struct dpkg_arch *arch;
252 arch = dpkg_arch_find(name);
253 if (arch->type == DPKG_ARCH_UNKNOWN) {
254 arch->type = DPKG_ARCH_FOREIGN;
255 arch_list_dirty = true;
258 return arch;
262 * Unmark a foreign dpkg_arch architecture.
264 void
265 dpkg_arch_unmark(const struct dpkg_arch *arch_remove)
267 struct dpkg_arch *arch;
269 for (arch = arch_builtin_tail->next; arch; arch = arch->next) {
270 if (arch->type != DPKG_ARCH_FOREIGN)
271 continue;
273 if (arch == arch_remove) {
274 arch->type = DPKG_ARCH_UNKNOWN;
275 arch_list_dirty = true;
276 return;
282 * Load the architecture database.
284 void
285 dpkg_arch_load_list(void)
287 FILE *fp;
288 char *archfile;
289 char archname[_POSIX2_LINE_MAX];
291 archfile = dpkg_db_get_path(DPKG_DB_ARCH_FILE);
292 fp = fopen(archfile, "r");
293 if (fp == NULL) {
294 arch_list_dirty = true;
295 free(archfile);
296 return;
299 while (fgets_checked(archname, sizeof(archname), fp, archfile) >= 0)
300 dpkg_arch_add(archname);
302 free(archfile);
303 fclose(fp);
307 * Save the architecture database.
309 void
310 dpkg_arch_save_list(void)
312 struct atomic_file *file;
313 struct dpkg_arch *arch;
314 char *archfile;
316 if (!arch_list_dirty)
317 return;
319 archfile = dpkg_db_get_path(DPKG_DB_ARCH_FILE);
320 file = atomic_file_new(archfile, ATOMIC_FILE_MKPATH);
321 atomic_file_open(file);
323 for (arch = arch_head; arch; arch = arch->next) {
324 if (arch->type != DPKG_ARCH_FOREIGN &&
325 arch->type != DPKG_ARCH_NATIVE)
326 continue;
328 if (fprintf(file->fp, "%s\n", arch->name) < 0)
329 ohshite(_("error writing to architecture list"));
332 atomic_file_sync(file);
333 atomic_file_close(file);
334 atomic_file_commit(file);
335 atomic_file_free(file);
337 dir_sync_path(dpkg_db_get_dir());
339 arch_list_dirty = false;
341 free(archfile);