xref: /titanic_52/usr/src/cmd/fm/eversholt/common/eftwrite.c (revision fb3fb4f3d76d55b64440afd0af72775dfad3bd1d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * eftwrite.c -- routines for writing .eft files
27  *
28  * this module emits the table resulting from compilation of the
29  * source files.  this code done nothing unless the -o option
30  * was given on the command line.
31  */
32 
33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
34 
35 #include <stdio.h>
36 #include <string.h>
37 #include <strings.h>
38 #include <time.h>
39 #include <unistd.h>
40 #include <errno.h>
41 #include "out.h"
42 #include "stats.h"
43 #include "stable.h"
44 #include "lut.h"
45 #include "tree.h"
46 #include "eft.h"
47 #include "eftwrite.h"
48 #include "esclex.h"
49 #include "version.h"
50 #include "ptree.h"
51 
52 /* for uintX_t, htonl(), etc */
53 #include <sys/types.h>
54 #include <netinet/in.h>
55 #include <inttypes.h>
56 
57 extern char Args[];
58 
59 static struct stats *Outbytes;
60 
61 static int Identlen;
62 static int Dictlen;
63 
64 void
65 eftwrite_init(void)
66 {
67 	Outbytes = stats_new_counter("eftwrite.total", "bytes written", 1);
68 }
69 
70 static const char *
71 mygetlogin(void)
72 {
73 	const char *result = getlogin();
74 	static char id[100];
75 
76 	if (result != NULL)
77 		return (result);
78 
79 	(void) snprintf(id, 100, "uid:%ld", getuid());
80 	return (id);
81 }
82 
83 /*ARGSUSED*/
84 static void
85 ident_lencalc(const char *s, void *rhs, void *arg)
86 {
87 	Identlen += strlen(s) + 1;
88 }
89 
90 /*ARGSUSED*/
91 static void
92 dict_lencalc(const char *s, void *rhs, void *arg)
93 {
94 	Dictlen += strlen(s) + 1;
95 }
96 
97 /*ARGSUSED*/
98 static void
99 ident_printer(const char *s, void *rhs, void *arg)
100 {
101 	FILE *fp = (FILE *)arg;
102 
103 	fwrite(s, strlen(s) + 1, 1, fp);
104 }
105 
106 /*ARGSUSED*/
107 static void
108 dict_printer(const char *s, void *rhs, void *arg)
109 {
110 	FILE *fp = (FILE *)arg;
111 
112 	fwrite(s, strlen(s) + 1, 1, fp);
113 }
114 
115 void
116 eftwrite(const char *fname)
117 {
118 	FILE *fp;
119 	FILE *tfp;
120 	struct eftheader hdr;
121 #define	BUFLEN	8192
122 	char buf[BUFLEN];
123 	int cc;
124 	time_t clock;
125 
126 	if ((tfp = tmpfile()) == NULL)
127 		out(O_DIE|O_SYS, "cannot create temporary file");
128 
129 	/* XXX switch stdout to tfp temporarily */
130 	/* XXX for now */
131 	out_altfp(tfp);
132 	ptree(O_ALTFP, tree_root(NULL), 0, 1);
133 
134 	rewind(tfp);
135 
136 	lut_walk(Ident, (lut_cb)ident_lencalc, (void *)0);
137 	lut_walk(Dicts, (lut_cb)dict_lencalc, (void *)0);
138 
139 	bzero(&hdr, sizeof (hdr));
140 	hdr.magic = EFT_HDR_MAGIC;
141 	hdr.major = EFT_HDR_MAJOR;
142 	hdr.minor = EFT_HDR_MINOR;
143 	hdr.cmajor = VERSION_MAJOR;
144 	hdr.cminor = VERSION_MINOR;
145 	hdr.identlen = Identlen;
146 	hdr.dictlen = Dictlen;
147 	(void) time(&clock);
148 	if (gethostname(buf, BUFLEN) < 0)
149 		out(O_DIE|O_SYS, "gethostname");
150 	buf[BUFLEN - 1] = '\0';
151 	(void) snprintf(hdr.comment, EFT_HDR_MAXCOMMENT,
152 	    "Built using esc-%d.%d by %s on %s at %s\tArgs: \"%s\"\n",
153 	    VERSION_MAJOR, VERSION_MINOR, mygetlogin(), buf, ctime(&clock),
154 	    Args);
155 
156 	if ((fp = fopen(fname, "w")) == NULL)
157 		out(O_DIE|O_SYS, "can't open output file: %s", fname);
158 
159 	while ((cc = fread(buf, 1, BUFLEN, tfp)) > 0) {
160 		char *ptr;
161 
162 		for (ptr = buf; ptr < &buf[cc]; ptr++)
163 			hdr.csum += (uint32_t)*ptr;
164 	}
165 	if (ferror(tfp))
166 		out(O_DIE|O_SYS, "fread on tmpfile");
167 	rewind(tfp);
168 
169 	hdr.magic = htonl(hdr.magic);
170 	hdr.major = htons(hdr.major);
171 	hdr.minor = htons(hdr.minor);
172 	hdr.cmajor = htons(hdr.cmajor);
173 	hdr.cminor = htons(hdr.cminor);
174 	hdr.identlen = htonl(hdr.identlen);
175 	hdr.dictlen = htonl(hdr.dictlen);
176 	hdr.csum = htonl(hdr.csum);
177 
178 	fwrite(&hdr, sizeof (hdr), 1, fp);
179 	if (ferror(fp))
180 		out(O_DIE|O_SYS, "%s: can't write header", fname);
181 	stats_counter_add(Outbytes, sizeof (hdr));
182 
183 	lut_walk(Ident, (lut_cb)ident_printer, (void *)fp);
184 	stats_counter_add(Outbytes, Identlen);
185 	lut_walk(Dicts, (lut_cb)dict_printer, (void *)fp);
186 	stats_counter_add(Outbytes, Dictlen);
187 
188 	while ((cc = fread(buf, 1, BUFLEN, tfp)) > 0) {
189 		char *ptr;
190 
191 		for (ptr = buf; ptr < &buf[cc]; ptr++)
192 			*ptr = ~((unsigned char)*ptr);
193 		if (cc != fwrite(buf, 1, cc, fp) || ferror(fp))
194 			out(O_DIE|O_SYS, "fwrite on %s", fname);
195 		stats_counter_add(Outbytes, cc);
196 	}
197 	if (ferror(tfp))
198 		out(O_DIE|O_SYS, "fread on tmpfile");
199 	fclose(tfp);
200 	fclose(fp);
201 }
202