10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52869Sgavinm * Common Development and Distribution License (the "License").
62869Sgavinm * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*6277Scy152378 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate *
250Sstevel@tonic-gate * eftread.c -- routines for reading .eft files
260Sstevel@tonic-gate *
270Sstevel@tonic-gate */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <strings.h>
340Sstevel@tonic-gate #include <time.h>
350Sstevel@tonic-gate #include <unistd.h>
360Sstevel@tonic-gate #include <errno.h>
370Sstevel@tonic-gate #include <stdlib.h>
380Sstevel@tonic-gate #include <alloca.h>
390Sstevel@tonic-gate #include "out.h"
400Sstevel@tonic-gate #include "stable.h"
410Sstevel@tonic-gate #include "lut.h"
420Sstevel@tonic-gate #include "tree.h"
430Sstevel@tonic-gate #include "eft.h"
440Sstevel@tonic-gate #include "eftread.h"
450Sstevel@tonic-gate #include "esclex.h"
460Sstevel@tonic-gate #include "version.h"
470Sstevel@tonic-gate #include "ptree.h"
480Sstevel@tonic-gate
490Sstevel@tonic-gate /* for uintX_t, htonl(), etc */
500Sstevel@tonic-gate #include <sys/types.h>
510Sstevel@tonic-gate #include <netinet/in.h>
520Sstevel@tonic-gate #include <inttypes.h>
530Sstevel@tonic-gate
54*6277Scy152378 #ifndef MIN
552869Sgavinm #define MIN(x, y) ((x) <= (y) ? (x) : (y))
56*6277Scy152378 #endif
572869Sgavinm
580Sstevel@tonic-gate static int Showheader;
590Sstevel@tonic-gate
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate * eftread_showheader -- set showheader flag
620Sstevel@tonic-gate *
630Sstevel@tonic-gate */
640Sstevel@tonic-gate void
eftread_showheader(int newval)650Sstevel@tonic-gate eftread_showheader(int newval)
660Sstevel@tonic-gate {
670Sstevel@tonic-gate Showheader = newval;
680Sstevel@tonic-gate }
690Sstevel@tonic-gate
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate * eftread_fopen -- fopen an EFT file for reading
720Sstevel@tonic-gate *
730Sstevel@tonic-gate */
740Sstevel@tonic-gate
750Sstevel@tonic-gate FILE *
eftread_fopen(const char * fname,char * idbuf,size_t idbufsz)762869Sgavinm eftread_fopen(const char *fname, char *idbuf, size_t idbufsz)
770Sstevel@tonic-gate {
780Sstevel@tonic-gate FILE *fp;
790Sstevel@tonic-gate FILE *tfp;
800Sstevel@tonic-gate struct eftheader hdr;
810Sstevel@tonic-gate #define BUFLEN 8192
820Sstevel@tonic-gate char buf[BUFLEN];
830Sstevel@tonic-gate int cc;
840Sstevel@tonic-gate uint32_t csum = 0;
850Sstevel@tonic-gate char *ptr;
860Sstevel@tonic-gate
870Sstevel@tonic-gate if ((ptr = strrchr(fname, '.')) == NULL || strcmp(ptr, ".eft") != 0) {
880Sstevel@tonic-gate out(O_ERR, "%s: not a valid EFT (bad extension)", fname);
890Sstevel@tonic-gate return (NULL);
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
920Sstevel@tonic-gate if ((fp = fopen(fname, "r")) == NULL) {
930Sstevel@tonic-gate out(O_ERR|O_SYS, "%s", fname);
940Sstevel@tonic-gate return (NULL);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate
970Sstevel@tonic-gate if (fread(&hdr, 1, sizeof (hdr), fp) < sizeof (hdr)) {
980Sstevel@tonic-gate (void) fclose(fp);
990Sstevel@tonic-gate out(O_ERR, "%s: not a valid EFT (too short)", fname);
1000Sstevel@tonic-gate return (NULL);
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate hdr.magic = ntohl(hdr.magic);
1030Sstevel@tonic-gate hdr.major = ntohs(hdr.major);
1040Sstevel@tonic-gate hdr.minor = ntohs(hdr.minor);
1050Sstevel@tonic-gate hdr.cmajor = ntohs(hdr.cmajor);
1060Sstevel@tonic-gate hdr.cminor = ntohs(hdr.cminor);
1070Sstevel@tonic-gate hdr.identlen = ntohl(hdr.identlen);
1080Sstevel@tonic-gate hdr.dictlen = ntohl(hdr.dictlen);
1090Sstevel@tonic-gate hdr.csum = ntohl(hdr.csum);
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate if (Showheader)
1120Sstevel@tonic-gate out(O_VERB, "%s: magic %x EFT version %d.%d esc version %d.%d",
1130Sstevel@tonic-gate fname, hdr.magic, hdr.major, hdr.minor,
1140Sstevel@tonic-gate hdr.cmajor, hdr.cminor);
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate if (hdr.magic != EFT_HDR_MAGIC) {
1170Sstevel@tonic-gate (void) fclose(fp);
1180Sstevel@tonic-gate out(O_ERR, "%s: not a valid EFT (bad magic)", fname);
1190Sstevel@tonic-gate return (NULL);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate if (hdr.major != EFT_HDR_MAJOR || hdr.minor > EFT_HDR_MINOR) {
1230Sstevel@tonic-gate (void) fclose(fp);
1240Sstevel@tonic-gate out(O_ERR, "%s is version %d.%d, "
1250Sstevel@tonic-gate "this program supports up to %d.%d", fname,
1260Sstevel@tonic-gate hdr.major, hdr.minor, EFT_HDR_MAJOR, EFT_HDR_MINOR);
1270Sstevel@tonic-gate return (NULL);
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate
1302869Sgavinm bzero(idbuf, idbufsz);
1312869Sgavinm if (hdr.identlen != 0) {
1322869Sgavinm long npos = ftell(fp) + (long)hdr.identlen; /* after ident */
1332869Sgavinm size_t rsz = MIN(hdr.identlen, idbufsz - 1);
1342869Sgavinm
1352869Sgavinm if (fread(idbuf, 1, rsz, fp) != rsz)
1362869Sgavinm out(O_DIE|O_SYS, "%s: fread", fname);
1372869Sgavinm if (fseek(fp, npos, SEEK_SET) == -1)
1382869Sgavinm out(O_DIE|O_SYS, "%s: fseek", fname);
1392869Sgavinm }
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate if (hdr.dictlen && (hdr.dictlen < 2 || hdr.dictlen > 1000)) {
1420Sstevel@tonic-gate (void) fclose(fp);
1430Sstevel@tonic-gate out(O_ERR, "%s: bad dictlen: %d", fname, hdr.dictlen);
1440Sstevel@tonic-gate return (NULL);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate /* read in dict strings */
1480Sstevel@tonic-gate if (hdr.dictlen) {
1490Sstevel@tonic-gate char *dbuf = alloca(hdr.dictlen);
1500Sstevel@tonic-gate char *dptr;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate if ((cc = fread(dbuf, 1, hdr.dictlen, fp)) != hdr.dictlen)
1530Sstevel@tonic-gate out(O_DIE|O_SYS, "short fread on %s (dictlen %d)",
1540Sstevel@tonic-gate fname, hdr.dictlen);
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate /* work from end of string array backwards, finding names */
1570Sstevel@tonic-gate for (dptr = &dbuf[hdr.dictlen - 2]; dptr > dbuf; dptr--)
1580Sstevel@tonic-gate if (*dptr == '\0') {
1590Sstevel@tonic-gate /* found separator, record string */
1600Sstevel@tonic-gate Dicts = lut_add(Dicts,
1610Sstevel@tonic-gate (void *)stable(dptr + 1), (void *)0, NULL);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate /* record the first string */
1640Sstevel@tonic-gate Dicts = lut_add(Dicts,
1650Sstevel@tonic-gate (void *)stable(dptr), (void *)0, NULL);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate if ((tfp = tmpfile()) == NULL)
1690Sstevel@tonic-gate out(O_DIE|O_SYS, "cannot create temporary file");
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate while ((cc = fread(buf, 1, BUFLEN, fp)) > 0) {
1720Sstevel@tonic-gate char *ptr;
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate for (ptr = buf; ptr < &buf[cc]; ptr++) {
1750Sstevel@tonic-gate *ptr = ~((unsigned char)*ptr);
1760Sstevel@tonic-gate csum += (uint32_t)*ptr;
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate if (cc != fwrite(buf, 1, cc, tfp) || ferror(tfp))
1790Sstevel@tonic-gate out(O_DIE|O_SYS, "fwrite on tmpfile");
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate if (ferror(fp))
1820Sstevel@tonic-gate out(O_DIE|O_SYS, "fread on %s", fname);
1830Sstevel@tonic-gate (void) fclose(fp);
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate if (hdr.csum != csum) {
1860Sstevel@tonic-gate out(O_ERR, "%s: bad checksum (%x != %x)", fname,
1870Sstevel@tonic-gate hdr.csum, csum);
1880Sstevel@tonic-gate (void) fclose(tfp);
1890Sstevel@tonic-gate return (NULL);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate if (Showheader) {
1930Sstevel@tonic-gate int len = strlen(hdr.comment);
1940Sstevel@tonic-gate if (len > 0 && hdr.comment[len - 1] == '\n')
1950Sstevel@tonic-gate hdr.comment[len - 1] = '\0';
1960Sstevel@tonic-gate out(O_OK, "%s:\n\t%s", fname, hdr.comment);
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate rewind(tfp);
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate return (tfp);
2020Sstevel@tonic-gate }
203