locale-util.c revision a34286684ebb78dd3db0d7f34feb2c121c9d00cc
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack This file is part of systemd.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack Copyright 2014 Lennart Poettering
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack systemd is free software; you can redistribute it and/or modify it
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack under the terms of the GNU Lesser General Public License as published by
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack the Free Software Foundation; either version 2.1 of the License, or
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack (at your option) any later version.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack systemd is distributed in the hope that it will be useful, but
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack WITHOUT ANY WARRANTY; without even the implied warranty of
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack Lesser General Public License for more details.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack You should have received a copy of the GNU Lesser General Public License
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack along with systemd; If not, see <http://www.gnu.org/licenses/>.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringstatic int add_locales_from_archive(Set *locales) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* Stolen from glibc... */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Serial number. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* Name hash table. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* String table. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* Table with locale records. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* MD5 sum hash table. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* Hash value of the name. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* Offset of the name in the string table. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack /* Offset of the locale record. */
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack const struct locarhead *h;
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack const struct namehashent *e;
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack const void *p = MAP_FAILED;
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (st.st_size < (off_t) sizeof(struct locarhead))
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack h = (const struct locarhead *) p;
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack h->namehash_offset + h->namehash_size > st.st_size ||
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack h->string_offset + h->string_size > st.st_size ||
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack h->locrectab_offset + h->locrectab_size > st.st_size ||
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack h->sumhash_offset + h->sumhash_size > st.st_size) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack for (i = 0; i < h->namehash_size; i++) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (e[i].locrec_offset == 0)
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (!utf8_is_valid((char*) p + e[i].name_offset))
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int add_locales_from_libdir (Set *locales) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (r < 0 && r != -EEXIST)
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack if (r < 0 && r != -ENOENT)