Subversion Repositories Kolibri OS

Rev

Rev 6099 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24.  * SUCH DAMAGE.
  25.  */
  26.  
  27. #include <sys/cdefs.h>
  28.  
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <sys/syslimits.h>
  32. #include <fcntl.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <unistd.h>
  36.  
  37. #include "setlocale.h"
  38. #include "ldpart.h"
  39.  
  40. static int split_lines(char *, const char *);
  41. static void set_from_buf(const char *, int, const char **);
  42.  
  43. int
  44. __part_load_locale(const char *name,
  45.                 int *using_locale,
  46.                 char *locale_buf,
  47.                 const char *category_filename,
  48.                 int locale_buf_size_max,
  49.                 int locale_buf_size_min,
  50.                 const char **dst_localebuf) {
  51.  
  52.         static char             locale_buf_C[] = "C";
  53.         static int              num_lines;
  54.  
  55.         int                      fd;
  56.         char                    *lbuf;
  57.         char                    *p;
  58.         const char              *plim;
  59.         char                     filename[PATH_MAX];
  60. #ifdef __USE_INTERNAL_STAT64
  61.         struct stat64            st;
  62. #else
  63.         struct stat              st;
  64. #endif
  65.         size_t                   namesize;
  66.         size_t                   bufsize;
  67.         int                      save_using_locale;
  68.         char *nptr;
  69.  
  70.         save_using_locale = *using_locale;
  71.         *using_locale = 0;
  72.  
  73.         if (name == NULL)
  74.                 goto no_locale;
  75.  
  76.         if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
  77.                 return 0;
  78.  
  79.         /*
  80.          * If the locale name is the same as our cache, use the cache.
  81.          */
  82.         lbuf = locale_buf;
  83.         if (lbuf != NULL && strcmp(name, lbuf) == 0) {
  84.                 set_from_buf(lbuf, num_lines, dst_localebuf);
  85.                 *using_locale = 1;
  86.                 return 0;
  87.         }
  88.  
  89.         /*
  90.          * Slurp the locale file into the cache.
  91.          */
  92.         namesize = strlen(name) + 1;
  93.  
  94.         if (!_PathLocale)
  95.                 goto no_locale;
  96.         /* Range checking not needed, 'name' size is limited */
  97.         strcpy(filename, _PathLocale);
  98.         strcat(filename, "/");
  99.         strcat(filename, name);
  100.         strcat(filename, "/");
  101.         strcat(filename, category_filename);
  102.         fd = open(filename, O_RDONLY);
  103.         if (fd < 0)
  104.                 goto no_locale;
  105. #ifdef __USE_INTERNAL_STAT64
  106.         if (fstat64(fd, &st) != 0)
  107. #else
  108.         if (fstat(fd, &st) != 0)
  109. #endif
  110.                 goto bad_locale;
  111.         if (st.st_size <= 0)
  112.                 goto bad_locale;
  113.         bufsize = namesize + st.st_size;
  114.         locale_buf = NULL;
  115.  
  116.         if (lbuf == NULL || lbuf == locale_buf_C)
  117.           {
  118.             lbuf = malloc(bufsize);
  119.           }
  120.         else
  121.           {
  122.             nptr = realloc(lbuf, bufsize);
  123.             if (!nptr && lbuf)
  124.               free (lbuf);
  125.             lbuf = nptr;
  126.           }
  127.  
  128.         if (lbuf == NULL)
  129.                 goto bad_locale;
  130.         (void) strcpy(lbuf, name);
  131.         p = lbuf + namesize;
  132.         plim = p + st.st_size;
  133.         if (read(fd, p, (size_t) st.st_size) != st.st_size)
  134.                 goto bad_lbuf;
  135.         if (close(fd) != 0)
  136.                 goto bad_lbuf;
  137.         /*
  138.          * Parse the locale file into localebuf.
  139.          */
  140.         if (plim[-1] != '\n')
  141.                 goto bad_lbuf;
  142.         num_lines = split_lines(p, plim);
  143.         if (num_lines >= locale_buf_size_max)
  144.                 num_lines = locale_buf_size_max;
  145.         else if (num_lines >= locale_buf_size_min)
  146.                 num_lines = locale_buf_size_min;
  147.         else
  148.                 goto reset_locale;
  149.         set_from_buf(lbuf, num_lines, dst_localebuf);
  150.         /*
  151.          * Record the successful parse in the cache.
  152.          */
  153.         locale_buf = lbuf;
  154.  
  155.         *using_locale = 1;
  156.         return 0;
  157.  
  158. reset_locale:
  159.         locale_buf = locale_buf_C;
  160.         save_using_locale = 0;
  161. bad_lbuf:
  162.         free(lbuf);
  163. bad_locale:
  164.         (void)close(fd);
  165. no_locale:
  166.         *using_locale = save_using_locale;
  167.         return -1;
  168. }
  169.  
  170. static int
  171. split_lines(char *p, const char *plim) {
  172.  
  173.         int i;
  174.  
  175.         for (i = 0; p < plim; i++) {
  176.                 p = strchr(p, '\n');
  177.                 *p++ = '\0';
  178.         }
  179.         return i;
  180. }
  181.  
  182. static void
  183. set_from_buf(const char *p, int num_lines, const char **dst_localebuf) {
  184.  
  185.         const char **ap;
  186.         int i;
  187.  
  188.         for (ap = dst_localebuf, i = 0; i < num_lines; ++ap, ++i)
  189.                 *ap = p += strlen(p) + 1;
  190. }
  191.  
  192.