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