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__FBSDID("$FreeBSD: src/lib/libc/locale/ldpart.c,v 1.15 2004/04/25 19:56:50 ache Exp $"); 29 30#include "xlocale_private.h" 31 32#include "namespace.h" 33#include <sys/types.h> 34#include <sys/stat.h> 35 36#include <errno.h> 37#include <fcntl.h> 38#include <limits.h> 39#include <stdlib.h> 40#include <string.h> 41#include <unistd.h> 42#include "un-namespace.h" 43 44#include "ldpart.h" 45#include "setlocale.h" 46 47static int split_lines(char *, const char *); 48 49__private_extern__ int 50__part_load_locale(const char *name, 51 unsigned char *using_locale, 52 char **locale_buf, 53 const char *category_filename, 54 int locale_buf_size_max, 55 int locale_buf_size_min, 56 const char **dst_localebuf) 57{ 58 int saverr, fd, i, num_lines; 59 char *lbuf, *p; 60 const char *plim; 61 char filename[PATH_MAX]; 62 struct stat st; 63 size_t namesize, bufsize; 64 65 /* 66 * Slurp the locale file into the cache. 67 */ 68 namesize = strlen(name) + 1; 69 70 /* 'PathLocale' must be already set & checked. */ 71 72 /* Range checking not needed, 'name' size is limited */ 73 strcpy(filename, _PathLocale); 74 strcat(filename, "/"); 75 strcat(filename, name); 76 strcat(filename, "/"); 77 strcat(filename, category_filename); 78 if ((fd = _open(filename, O_RDONLY)) < 0) 79 return (_LDP_ERROR); 80 if (_fstat(fd, &st) != 0) 81 goto bad_locale; 82 if (st.st_size <= 0) { 83 errno = EFTYPE; 84 goto bad_locale; 85 } 86 bufsize = namesize + st.st_size; 87 if ((lbuf = malloc(bufsize)) == NULL) { 88 errno = ENOMEM; 89 goto bad_locale; 90 } 91 (void)strcpy(lbuf, name); 92 p = lbuf + namesize; 93 plim = p + st.st_size; 94 if (_read(fd, p, (size_t) st.st_size) != st.st_size) 95 goto bad_lbuf; 96 /* 97 * Parse the locale file into localebuf. 98 */ 99 if (plim[-1] != '\n') { 100 errno = EFTYPE; 101 goto bad_lbuf; 102 } 103 num_lines = split_lines(p, plim); 104 if (num_lines >= locale_buf_size_max) 105 num_lines = locale_buf_size_max; 106 else if (num_lines < locale_buf_size_min) { 107 errno = EFTYPE; 108 goto bad_lbuf; 109 } 110 (void)_close(fd); 111 /* 112 * Record the successful parse in the cache. 113 */ 114 if (*locale_buf != NULL) 115 free(*locale_buf); 116 *locale_buf = lbuf; 117 for (p = *locale_buf, i = 0; i < num_lines; i++) 118 dst_localebuf[i] = (p += strlen(p) + 1); 119 for (i = num_lines; i < locale_buf_size_max; i++) 120 dst_localebuf[i] = NULL; 121 *using_locale = 1; 122 123 return (_LDP_LOADED); 124 125bad_lbuf: 126 saverr = errno; 127 free(lbuf); 128 errno = saverr; 129bad_locale: 130 saverr = errno; 131 (void)_close(fd); 132 errno = saverr; 133 134 return (_LDP_ERROR); 135} 136 137static int 138split_lines(char *p, const char *plim) 139{ 140 int i; 141 142 i = 0; 143 while (p < plim) { 144 if (*p == '\n') { 145 *p = '\0'; 146 i++; 147 } 148 p++; 149 } 150 return (i); 151} 152 153__private_extern__ void 154__ldpart_free_extra(struct __xlocale_st_ldpart *lp) 155{ 156 if (lp) 157 free(lp->_locale_buf); 158} 159