14297a3b0SGarrett D'Amore /* 2*2d08521bSGarrett D'Amore * Copyright 2013 Garrett D'Amore <garrett@damore.org> 36b5e5868SGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 44297a3b0SGarrett D'Amore * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org> 54297a3b0SGarrett D'Amore * All rights reserved. 64297a3b0SGarrett D'Amore * 74297a3b0SGarrett D'Amore * Redistribution and use in source and binary forms, with or without 84297a3b0SGarrett D'Amore * modification, are permitted provided that the following conditions 94297a3b0SGarrett D'Amore * are met: 104297a3b0SGarrett D'Amore * 1. Redistributions of source code must retain the above copyright 114297a3b0SGarrett D'Amore * notice, this list of conditions and the following disclaimer. 124297a3b0SGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright 134297a3b0SGarrett D'Amore * notice, this list of conditions and the following disclaimer in the 144297a3b0SGarrett D'Amore * documentation and/or other materials provided with the distribution. 154297a3b0SGarrett D'Amore * 164297a3b0SGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 174297a3b0SGarrett D'Amore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 184297a3b0SGarrett D'Amore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 194297a3b0SGarrett D'Amore * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 204297a3b0SGarrett D'Amore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 214297a3b0SGarrett D'Amore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 224297a3b0SGarrett D'Amore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 234297a3b0SGarrett D'Amore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 244297a3b0SGarrett D'Amore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 254297a3b0SGarrett D'Amore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 264297a3b0SGarrett D'Amore * SUCH DAMAGE. 274297a3b0SGarrett D'Amore */ 284297a3b0SGarrett D'Amore 294297a3b0SGarrett D'Amore #include "lint.h" 30eda71b4aSGarrett D'Amore #include "file64.h" 314297a3b0SGarrett D'Amore #include <sys/types.h> 324297a3b0SGarrett D'Amore #include <sys/stat.h> 334297a3b0SGarrett D'Amore #include <errno.h> 344297a3b0SGarrett D'Amore #include <fcntl.h> 354297a3b0SGarrett D'Amore #include <limits.h> 364297a3b0SGarrett D'Amore #include <stdlib.h> 374297a3b0SGarrett D'Amore #include <string.h> 384297a3b0SGarrett D'Amore #include <unistd.h> 396da5aa94SGarrett D'Amore #include <stdio.h> 404297a3b0SGarrett D'Amore 41*2d08521bSGarrett D'Amore #include "libc.h" 424297a3b0SGarrett D'Amore #include "ldpart.h" 434297a3b0SGarrett D'Amore #include "setlocale.h" 444297a3b0SGarrett D'Amore 454297a3b0SGarrett D'Amore static int split_lines(char *, const char *); 464297a3b0SGarrett D'Amore 474297a3b0SGarrett D'Amore int 48*2d08521bSGarrett D'Amore __part_load_locale(const char *name, 494297a3b0SGarrett D'Amore char **locale_buf, const char *category_filename, 504297a3b0SGarrett D'Amore int locale_buf_size_max, int locale_buf_size_min, 514297a3b0SGarrett D'Amore const char **dst_localebuf) 524297a3b0SGarrett D'Amore { 534297a3b0SGarrett D'Amore int saverr, fd, i, num_lines; 544297a3b0SGarrett D'Amore char *lbuf, *p; 554297a3b0SGarrett D'Amore const char *plim; 564297a3b0SGarrett D'Amore char filename[PATH_MAX]; 574297a3b0SGarrett D'Amore struct stat st; 584297a3b0SGarrett D'Amore size_t namesize, bufsize; 594297a3b0SGarrett D'Amore 604297a3b0SGarrett D'Amore /* 614297a3b0SGarrett D'Amore * Slurp the locale file into the cache. 624297a3b0SGarrett D'Amore */ 634297a3b0SGarrett D'Amore namesize = strlen(name) + 1; 644297a3b0SGarrett D'Amore 654297a3b0SGarrett D'Amore /* 'PathLocale' must be already set & checked. */ 664297a3b0SGarrett D'Amore 676da5aa94SGarrett D'Amore (void) snprintf(filename, sizeof (filename), "%s/%s/%s/LCL_DATA", 686da5aa94SGarrett D'Amore _PathLocale, name, category_filename); 696da5aa94SGarrett D'Amore 704297a3b0SGarrett D'Amore if ((fd = open(filename, O_RDONLY)) < 0) 714297a3b0SGarrett D'Amore return (_LDP_ERROR); 724297a3b0SGarrett D'Amore if (fstat(fd, &st) != 0) 734297a3b0SGarrett D'Amore goto bad_locale; 744297a3b0SGarrett D'Amore if (st.st_size <= 0) { 754297a3b0SGarrett D'Amore errno = EINVAL; 764297a3b0SGarrett D'Amore goto bad_locale; 774297a3b0SGarrett D'Amore } 784297a3b0SGarrett D'Amore bufsize = namesize + st.st_size; 79*2d08521bSGarrett D'Amore if ((lbuf = libc_malloc(bufsize)) == NULL) { 804297a3b0SGarrett D'Amore errno = ENOMEM; 814297a3b0SGarrett D'Amore goto bad_locale; 824297a3b0SGarrett D'Amore } 834297a3b0SGarrett D'Amore (void) strcpy(lbuf, name); 844297a3b0SGarrett D'Amore p = lbuf + namesize; 854297a3b0SGarrett D'Amore plim = p + st.st_size; 864297a3b0SGarrett D'Amore if (read(fd, p, (size_t)st.st_size) != st.st_size) 874297a3b0SGarrett D'Amore goto bad_lbuf; 884297a3b0SGarrett D'Amore /* 894297a3b0SGarrett D'Amore * Parse the locale file into localebuf. 904297a3b0SGarrett D'Amore */ 914297a3b0SGarrett D'Amore if (plim[-1] != '\n') { 924297a3b0SGarrett D'Amore errno = EINVAL; 934297a3b0SGarrett D'Amore goto bad_lbuf; 944297a3b0SGarrett D'Amore } 954297a3b0SGarrett D'Amore num_lines = split_lines(p, plim); 964297a3b0SGarrett D'Amore if (num_lines >= locale_buf_size_max) 974297a3b0SGarrett D'Amore num_lines = locale_buf_size_max; 984297a3b0SGarrett D'Amore else if (num_lines >= locale_buf_size_min) 994297a3b0SGarrett D'Amore num_lines = locale_buf_size_min; 1004297a3b0SGarrett D'Amore else { 1014297a3b0SGarrett D'Amore errno = EINVAL; 1024297a3b0SGarrett D'Amore goto bad_lbuf; 1034297a3b0SGarrett D'Amore } 1044297a3b0SGarrett D'Amore (void) close(fd); 1054297a3b0SGarrett D'Amore /* 1064297a3b0SGarrett D'Amore * Record the successful parse in the cache. 1074297a3b0SGarrett D'Amore */ 1084297a3b0SGarrett D'Amore *locale_buf = lbuf; 1094297a3b0SGarrett D'Amore for (p = *locale_buf, i = 0; i < num_lines; i++) 1104297a3b0SGarrett D'Amore dst_localebuf[i] = (p += strlen(p) + 1); 1114297a3b0SGarrett D'Amore for (i = num_lines; i < locale_buf_size_max; i++) 1124297a3b0SGarrett D'Amore dst_localebuf[i] = NULL; 1134297a3b0SGarrett D'Amore 1144297a3b0SGarrett D'Amore return (_LDP_LOADED); 1154297a3b0SGarrett D'Amore 1164297a3b0SGarrett D'Amore bad_lbuf: 1174297a3b0SGarrett D'Amore saverr = errno; 1184297a3b0SGarrett D'Amore free(lbuf); 1194297a3b0SGarrett D'Amore errno = saverr; 1204297a3b0SGarrett D'Amore bad_locale: 1214297a3b0SGarrett D'Amore saverr = errno; 1224297a3b0SGarrett D'Amore (void) close(fd); 1234297a3b0SGarrett D'Amore errno = saverr; 1244297a3b0SGarrett D'Amore 1254297a3b0SGarrett D'Amore return (_LDP_ERROR); 1264297a3b0SGarrett D'Amore } 1274297a3b0SGarrett D'Amore 1284297a3b0SGarrett D'Amore static int 1294297a3b0SGarrett D'Amore split_lines(char *p, const char *plim) 1304297a3b0SGarrett D'Amore { 1314297a3b0SGarrett D'Amore int i; 1324297a3b0SGarrett D'Amore 1334297a3b0SGarrett D'Amore i = 0; 1344297a3b0SGarrett D'Amore while (p < plim) { 1354297a3b0SGarrett D'Amore if (*p == '\n') { 1364297a3b0SGarrett D'Amore *p = '\0'; 1374297a3b0SGarrett D'Amore i++; 1384297a3b0SGarrett D'Amore } 1394297a3b0SGarrett D'Amore p++; 1404297a3b0SGarrett D'Amore } 1414297a3b0SGarrett D'Amore return (i); 1424297a3b0SGarrett D'Amore } 143