home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / tar-1.11.8-src.tgz / tar.out / fsf / tar / intl / loadmsgcat.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  5KB  |  193 lines

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