Back to index

plt-scheme  4.2.1
loadmsgcat.c
Go to the documentation of this file.
00001 /* loadmsgcat.c -- load needed message catalogs
00002    Copyright (C) 1995, 1996 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
00016 Foundation, 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 _LIBC
00035 # include <sys/mman.h>
00036 #endif
00037 
00038 #include "gettext.h"
00039 #include "gettextP.h"
00040 
00041 /* @@ end of prolog @@ */
00042 
00043 #ifdef _LIBC
00044 /* Rename the non ANSI C functions.  This is required by the standard
00045    because some ANSI C functions will require linking with this object
00046    file and the name space must not be polluted.  */
00047 # define fstat  __fstat
00048 # define open   __open
00049 # define close  __close
00050 # define read   __read
00051 # define mmap   __mmap
00052 # define munmap __munmap
00053 #endif
00054 
00055 /* We need a sign, whether a new catalog was loaded, which can be associated
00056    with all translations.  This is important if the translations are
00057    cached by one of GCC's features.  */
00058 int _nl_msg_cat_cntr;
00059 
00060 
00061 /* Load the message catalogs specified by FILENAME.  If it is no valid
00062    message catalog do nothing.  */
00063 void
00064 _nl_load_domain (domain_file)
00065      struct loaded_l10nfile *domain_file;
00066 {
00067   int fd;
00068   struct stat st;
00069   struct mo_file_header *data = (struct mo_file_header *) -1;
00070 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
00071     || defined _LIBC
00072   int use_mmap = 0;
00073 #endif
00074   struct loaded_domain *domain;
00075 
00076   domain_file->decided = 1;
00077   domain_file->data = NULL;
00078 
00079   /* If the record does not represent a valid locale the FILENAME
00080      might be NULL.  This can happen when according to the given
00081      specification the locale file name is different for XPG and CEN
00082      syntax.  */
00083   if (domain_file->filename == NULL)
00084     return;
00085 
00086   /* Try to open the addressed file.  */
00087   fd = open (domain_file->filename, O_RDONLY);
00088   if (fd == -1)
00089     return;
00090 
00091   /* We must know about the size of the file.  */
00092   if (fstat (fd, &st) != 0
00093       && st.st_size < (off_t) sizeof (struct mo_file_header))
00094     {
00095       /* Something went wrong.  */
00096       close (fd);
00097       return;
00098     }
00099 
00100 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
00101     || defined _LIBC
00102   /* Now we are ready to load the file.  If mmap() is available we try
00103      this first.  If not available or it failed we try to load it.  */
00104   data = (struct mo_file_header *) mmap (NULL, st.st_size, PROT_READ,
00105                                     MAP_PRIVATE, fd, 0);
00106 
00107   if (data != (struct mo_file_header *) -1)
00108     {
00109       /* mmap() call was successful.  */
00110       close (fd);
00111       use_mmap = 1;
00112     }
00113 #endif
00114 
00115   /* If the data is not yet available (i.e. mmap'ed) we try to load
00116      it manually.  */
00117   if (data == (struct mo_file_header *) -1)
00118     {
00119       off_t to_read;
00120       char *read_ptr;
00121 
00122       data = (struct mo_file_header *) malloc (st.st_size);
00123       if (data == NULL)
00124        return;
00125 
00126       to_read = st.st_size;
00127       read_ptr = (char *) data;
00128       do
00129        {
00130          long int nb = (long int) read (fd, read_ptr, to_read);
00131          if (nb == -1)
00132            {
00133              close (fd);
00134              return;
00135            }
00136 
00137          read_ptr += nb;
00138          to_read -= nb;
00139        }
00140       while (to_read > 0);
00141 
00142       close (fd);
00143     }
00144 
00145   /* Using the magic number we can test whether it really is a message
00146      catalog file.  */
00147   if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
00148     {
00149       /* The magic number is wrong: not a message catalog file.  */
00150 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
00151     || defined _LIBC
00152       if (use_mmap)
00153        munmap ((caddr_t) data, st.st_size);
00154       else
00155 #endif
00156        free (data);
00157       return;
00158     }
00159 
00160   domain_file->data
00161     = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
00162   if (domain_file->data == NULL)
00163     return;
00164 
00165   domain = (struct loaded_domain *) domain_file->data;
00166   domain->data = (char *) data;
00167   domain->must_swap = data->magic != _MAGIC;
00168 
00169   /* Fill in the information about the available tables.  */
00170   switch (W (domain->must_swap, data->revision))
00171     {
00172     case 0:
00173       domain->nstrings = W (domain->must_swap, data->nstrings);
00174       domain->orig_tab = (struct string_desc *)
00175        ((char *) data + W (domain->must_swap, data->orig_tab_offset));
00176       domain->trans_tab = (struct string_desc *)
00177        ((char *) data + W (domain->must_swap, data->trans_tab_offset));
00178       domain->hash_size = W (domain->must_swap, data->hash_tab_size);
00179       domain->hash_tab = (nls_uint32 *)
00180        ((char *) data + W (domain->must_swap, data->hash_tab_offset));
00181       break;
00182     default:
00183       /* This is an illegal revision.  */
00184 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
00185     || defined _LIBC
00186       if (use_mmap)
00187        munmap ((caddr_t) data, st.st_size);
00188       else
00189 #endif
00190        free (data);
00191       free (domain);
00192       domain_file->data = NULL;
00193       return;
00194     }
00195 
00196   /* Show that one domain is changed.  This might make some cached
00197      translations invalid.  */
00198   ++_nl_msg_cat_cntr;
00199 }