xref: /onnv-gate/usr/src/cmd/fm/eversholt/common/eftread.c (revision 6277:1ae6f93f8c0a)
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