Back to Evolution Project page
00001 /* Load needed message catalogs. 00002 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2, or (at your option) 00007 any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software Foundation, 00016 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 00017 00018 #ifdef HAVE_CONFIG_H 00019 # include <config.h> 00020 #endif 00021 00022 #include <fcntl.h> 00023 #include <sys/types.h> 00024 #include <sys/stat.h> 00025 00026 #if defined STDC_HEADERS || defined _LIBC 00027 # include <stdlib.h> 00028 #endif 00029 00030 #if defined HAVE_UNISTD_H || defined _LIBC 00031 # include <unistd.h> 00032 #endif 00033 00034 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ 00035 || (defined _LIBC && defined _POSIX_MAPPED_FILES) 00036 # include <sys/mman.h> 00037 # undef HAVE_MMAP 00038 # define HAVE_MMAP 1 00039 #else 00040 # undef HAVE_MMAP 00041 #endif 00042 00043 #include "gettext.h" 00044 #include "gettextP.h" 00045 00046 /* @@ end of prolog @@ */ 00047 00048 #ifdef _LIBC 00049 /* Rename the non ISO C functions. This is required by the standard 00050 because some ISO C functions will require linking with this object 00051 file and the name space must not be polluted. */ 00052 # define open __open 00053 # define close __close 00054 # define read __read 00055 # define mmap __mmap 00056 # define munmap __munmap 00057 #endif 00058 00059 /* We need a sign, whether a new catalog was loaded, which can be associated 00060 with all translations. This is important if the translations are 00061 cached by one of GCC's features. */ 00062 int _nl_msg_cat_cntr = 0; 00063 00064 00065 /* Load the message catalogs specified by FILENAME. If it is no valid 00066 message catalog do nothing. */ 00067 void 00068 internal_function 00069 _nl_load_domain (domain_file) 00070 struct loaded_l10nfile *domain_file; 00071 { 00072 int fd; 00073 size_t size; 00074 struct stat st; 00075 struct mo_file_header *data = (struct mo_file_header *) -1; 00076 int use_mmap = 0; 00077 struct loaded_domain *domain; 00078 00079 domain_file->decided = 1; 00080 domain_file->data = NULL; 00081 00082 /* If the record does not represent a valid locale the FILENAME 00083 might be NULL. This can happen when according to the given 00084 specification the locale file name is different for XPG and CEN 00085 syntax. */ 00086 if (domain_file->filename == NULL) 00087 return; 00088 00089 /* Try to open the addressed file. */ 00090 fd = open (domain_file->filename, O_RDONLY); 00091 if (fd == -1) 00092 return; 00093 00094 /* We must know about the size of the file. */ 00095 if (fstat (fd, &st) != 0 00096 || (size = (size_t) st.st_size) != st.st_size 00097 || size < sizeof (struct mo_file_header)) 00098 { 00099 /* Something went wrong. */ 00100 close (fd); 00101 return; 00102 } 00103 00104 #ifdef HAVE_MMAP 00105 /* Now we are ready to load the file. If mmap() is available we try 00106 this first. If not available or it failed we try to load it. */ 00107 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, 00108 MAP_PRIVATE, fd, 0); 00109 00110 if (data != (struct mo_file_header *) -1) 00111 { 00112 /* mmap() call was successful. */ 00113 close (fd); 00114 use_mmap = 1; 00115 } 00116 #endif 00117 00118 /* If the data is not yet available (i.e. mmap'ed) we try to load 00119 it manually. */ 00120 if (data == (struct mo_file_header *) -1) 00121 { 00122 size_t to_read; 00123 char *read_ptr; 00124 00125 data = (struct mo_file_header *) malloc (size); 00126 if (data == NULL) 00127 return; 00128 00129 to_read = size; 00130 read_ptr = (char *) data; 00131 do 00132 { 00133 long int nb = (long int) read (fd, read_ptr, to_read); 00134 if (nb == -1) 00135 { 00136 close (fd); 00137 return; 00138 } 00139 00140 read_ptr += nb; 00141 to_read -= nb; 00142 } 00143 while (to_read > 0); 00144 00145 close (fd); 00146 } 00147 00148 /* Using the magic number we can test whether it really is a message 00149 catalog file. */ 00150 if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED) 00151 { 00152 /* The magic number is wrong: not a message catalog file. */ 00153 #ifdef HAVE_MMAP 00154 if (use_mmap) 00155 munmap ((caddr_t) data, size); 00156 else 00157 #endif 00158 free (data); 00159 return; 00160 } 00161 00162 domain_file->data 00163 = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); 00164 if (domain_file->data == NULL) 00165 return; 00166 00167 domain = (struct loaded_domain *) domain_file->data; 00168 domain->data = (char *) data; 00169 domain->use_mmap = use_mmap; 00170 domain->mmap_size = size; 00171 domain->must_swap = data->magic != _MAGIC; 00172 00173 /* Fill in the information about the available tables. */ 00174 switch (W (domain->must_swap, data->revision)) 00175 { 00176 case 0: 00177 domain->nstrings = W (domain->must_swap, data->nstrings); 00178 domain->orig_tab = (struct string_desc *) 00179 ((char *) data + W (domain->must_swap, data->orig_tab_offset)); 00180 domain->trans_tab = (struct string_desc *) 00181 ((char *) data + W (domain->must_swap, data->trans_tab_offset)); 00182 domain->hash_size = W (domain->must_swap, data->hash_tab_size); 00183 domain->hash_tab = (nls_uint32 *) 00184 ((char *) data + W (domain->must_swap, data->hash_tab_offset)); 00185 break; 00186 default: 00187 /* This is an invalid revision. */ 00188 #ifdef HAVE_MMAP 00189 if (use_mmap) 00190 munmap ((caddr_t) data, size); 00191 else 00192 #endif 00193 free (data); 00194 free (domain); 00195 domain_file->data = NULL; 00196 return; 00197 } 00198 00199 /* Show that one domain is changed. This might make some cached 00200 translations invalid. */ 00201 ++_nl_msg_cat_cntr; 00202 } 00203 00204 00205 #ifdef _LIBC 00206 void 00207 internal_function 00208 _nl_unload_domain (domain) 00209 struct loaded_domain *domain; 00210 { 00211 #ifdef _POSIX_MAPPED_FILES 00212 if (domain->use_mmap) 00213 munmap ((caddr_t) domain->data, domain->mmap_size); 00214 else 00215 #endif /* _POSIX_MAPPED_FILES */ 00216 free ((void *) domain->data); 00217 00218 free (domain); 00219 } 00220 #endif