1/* loadmsgcat.c -- load needed message catalogs 2 Copyright (C) 1995 Software Foundation, Inc. 3 4This program is free software; you can redistribute it and/or modify 5it under the terms of the GNU General Public License as published by 6the Free Software Foundation; either version 2, or (at your option) 7any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12GNU General Public License for more details. 13 14You should have received a copy of the GNU General Public License 15along with this program; if not, write to the Free Software 16Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18#ifdef HAVE_CONFIG_H 19# include <config.h> 20#endif 21 22#include <fcntl.h> 23#include <sys/types.h> 24#include <sys/stat.h> 25 26#if defined STDC_HEADERS || defined _LIBC 27# include <stdlib.h> 28#endif 29 30#if defined HAVE_UNISTD_H || defined _LIBC 31# include <unistd.h> 32#endif 33 34#if (defined HAVE_MMAP && defined HAVE_MUNMAP) || defined _LIBC 35# include <sys/mman.h> 36#endif 37 38#include "gettext.h" 39#include "gettextP.h" 40 41/* @@ end of prolog @@ */ 42 43#ifdef _LIBC 44/* Rename the non ANSI C functions. This is required by the standard 45 because some ANSI C functions will require linking with this object 46 file and the name space must not be polluted. */ 47# define fstat __fstat 48# define open __open 49# define close __close 50# define read __read 51# define mmap __mmap 52# define munmap __munmap 53#endif 54 55/* We need a sign, whether a new catalog was loaded, which can be associated 56 with all translations. This is important if the translations are 57 cached by one of GCC's features. */ 58int _nl_msg_cat_cntr; 59 60 61/* Load the message catalogs specified by FILENAME. If it is no valid 62 message catalog do nothing. */ 63void 64_nl_load_domain (domain) 65 struct loaded_domain *domain; 66{ 67 int fd; 68 struct stat st; 69 struct mo_file_header *data = (struct mo_file_header *) -1; 70#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ 71 || defined _LIBC 72 int use_mmap = 0; 73#endif 74 75 domain->decided = 1; 76 domain->data = NULL; 77 78 /* If the record does not represent a valid locale the FILENAME 79 might be NULL. This can happen when according to the given 80 specification the locale file name is different for XPG and CEN 81 syntax. */ 82 if (domain->filename == NULL) 83 return; 84 85 /* Try to open the addressed file. */ 86 fd = open (domain->filename, O_RDONLY); 87 if (fd == -1) 88 return; 89 90 /* We must know about the size of the file. */ 91 if (fstat (fd, &st) != 0 92 && st.st_size < (off_t) sizeof (struct mo_file_header)) 93 { 94 /* Something went wrong. */ 95 close (fd); 96 return; 97 } 98 99#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ 100 || defined _LIBC 101 /* Now we are ready to load the file. If mmap() is available we try 102 this first. If not available or it failed we try to load it. */ 103 data = (struct mo_file_header *) mmap (NULL, st.st_size, PROT_READ, 104 MAP_PRIVATE, fd, 0); 105 106 if (data != (struct mo_file_header *) -1) 107 { 108 /* mmap() call was successful. */ 109 close (fd); 110 use_mmap = 1; 111 } 112#endif 113 114 /* If the data is not yet available (i.e. mmap'ed) we try to load 115 it manually. */ 116 if (data == (struct mo_file_header *) -1) 117 { 118 off_t to_read; 119 char *read_ptr; 120 121 data = (struct mo_file_header *) malloc (st.st_size); 122 if (data == NULL) 123 return; 124 125 to_read = st.st_size; 126 read_ptr = (char *) data; 127 do 128 { 129 long int nb = (long int) read (fd, read_ptr, to_read); 130 if (nb == -1) 131 { 132 close (fd); 133 return; 134 } 135 136 read_ptr += nb; 137 to_read -= nb; 138 } 139 while (to_read > 0); 140 141 close (fd); 142 } 143 144 /* Using the magic number we can test whether it really is a message 145 catalog file. */ 146 if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED) 147 { 148 /* The magic number is wrong: not a message catalog file. */ 149#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ 150 || defined _LIBC 151 if (use_mmap) 152 munmap ((caddr_t) data, st.st_size); 153 else 154#endif 155 free (data); 156 return; 157 } 158 159 domain->data = (char *) data; 160 domain->must_swap = data->magic != _MAGIC; 161 162 /* Fill in the information about the available tables. */ 163 switch (W (domain->must_swap, data->revision)) 164 { 165 case 0: 166 domain->nstrings = W (domain->must_swap, data->nstrings); 167 domain->orig_tab = (struct string_desc *) 168 ((char *) data + W (domain->must_swap, data->orig_tab_offset)); 169 domain->trans_tab = (struct string_desc *) 170 ((char *) data + W (domain->must_swap, data->trans_tab_offset)); 171 domain->hash_size = W (domain->must_swap, data->hash_tab_size); 172 domain->hash_tab = (nls_uint32 *) 173 ((char *) data + W (domain->must_swap, data->hash_tab_offset)); 174 break; 175 default: 176 /* This is an illegal revision. */ 177#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ 178 || defined _LIBC 179 if (use_mmap) 180 munmap ((caddr_t) data, st.st_size); 181 else 182#endif 183 free (data); 184 domain->data = NULL; 185 return; 186 } 187 188 /* Show that one domain is changed. This might make some cached 189 translation invalid. */ 190 ++_nl_msg_cat_cntr; 191} 192