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/>.
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>
38 #include <dpkg/varbuf.h>
39 #include <dpkg/arch.h>
41 #define DPKG_DB_ARCH_FILE "arch"
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.
56 dpkg_arch_name_is_illegal(const char *name
)
62 internerr("arch name argument is NULL");
64 return _("may not be empty string");
66 return _("must start with an alphanumeric");
68 if (!c_isalnum(*p
) && *p
!= '-')
73 snprintf(buf
, sizeof(buf
), _("character '%c' not allowed (only "
74 "letters, digits and characters '%s')"),
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
= {
83 .type
= DPKG_ARCH_NONE
,
86 static struct dpkg_arch arch_item_empty
= {
88 .type
= DPKG_ARCH_EMPTY
,
92 static struct dpkg_arch arch_item_any
= {
94 .type
= DPKG_ARCH_WILDCARD
,
97 static struct dpkg_arch arch_item_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));
118 new->name
= nfstrsave(name
);
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.
136 dpkg_arch_find(const char *name
)
138 struct dpkg_arch
*arch
, *last_arch
= NULL
;
139 enum dpkg_arch_type type
;
142 return &arch_item_none
;
144 return &arch_item_empty
;
146 for (arch
= arch_head
; arch
; arch
= arch
->next
) {
147 if (strcmp(arch
->name
, name
) == 0)
152 if (dpkg_arch_name_is_illegal(name
))
153 type
= DPKG_ARCH_ILLEGAL
;
155 type
= DPKG_ARCH_UNKNOWN
;
157 arch
= dpkg_arch_new(name
, type
);
158 last_arch
->next
= 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.
170 dpkg_arch_get(enum dpkg_arch_type type
)
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
;
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
);
188 /* Ignore unknown types for forward-compatibility. */
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.
200 dpkg_arch_get_list(void)
206 * Reset the list of architectures.
208 * Must be called before nffreeall() to ensure we don't point to
209 * unallocated memory.
212 dpkg_arch_reset_list(void)
214 arch_builtin_tail
->next
= NULL
;
215 arch_list_dirty
= false;
219 varbuf_add_archqual(struct varbuf
*vb
, const struct dpkg_arch
*arch
)
221 if (arch
->type
== DPKG_ARCH_NONE
)
223 if (arch
->type
== DPKG_ARCH_EMPTY
)
226 varbuf_add_char(vb
, ':');
227 varbuf_add_str(vb
, arch
->name
);
231 * Return a descriptive architecture name.
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>");
245 * Add a new foreign dpkg_arch architecture.
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;
262 * Unmark a foreign dpkg_arch architecture.
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
)
273 if (arch
== arch_remove
) {
274 arch
->type
= DPKG_ARCH_UNKNOWN
;
275 arch_list_dirty
= true;
282 * Load the architecture database.
285 dpkg_arch_load_list(void)
289 char archname
[_POSIX2_LINE_MAX
];
291 archfile
= dpkg_db_get_path(DPKG_DB_ARCH_FILE
);
292 fp
= fopen(archfile
, "r");
294 arch_list_dirty
= true;
299 while (fgets_checked(archname
, sizeof(archname
), fp
, archfile
) >= 0)
300 dpkg_arch_add(archname
);
307 * Save the architecture database.
310 dpkg_arch_save_list(void)
312 struct atomic_file
*file
;
313 struct dpkg_arch
*arch
;
316 if (!arch_list_dirty
)
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
)
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;