xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_tab.c (revision 70025d765b044c6d8594bb965a2247a61e991a99)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Just in case we're not in a build environment, make sure that
31  * TEXT_DOMAIN gets set to something.
32  */
33 #if !defined(TEXT_DOMAIN)
34 #define	TEXT_DOMAIN "SYS_TEST"
35 #endif
36 
37 #include <meta.h>
38 
39 #include <ctype.h>
40 
41 /*
42  * free md.tab struct
43  */
44 void
45 meta_tab_free(
46 	md_tab_t	*tabp
47 )
48 {
49 	size_t		line;
50 
51 	Free(tabp->filename);
52 	Free(tabp->data);
53 	if (tabp->lines != NULL) {
54 		assert(tabp->alloc > 0);
55 		for (line = 0; (line < tabp->nlines); ++line) {
56 			md_tab_line_t	*linep = &tabp->lines[line];
57 
58 			if (linep->context != NULL)
59 				Free(linep->context);
60 			if (linep->cname != NULL)
61 				Free(linep->cname);
62 			if (linep->argv != NULL) {
63 				assert(linep->alloc > 0);
64 				Free(linep->argv);
65 			}
66 		}
67 		Free(tabp->lines);
68 	}
69 	Free(tabp);
70 }
71 
72 /*
73  * (re)allocate argv array
74  */
75 static void
76 realloc_argv(
77 	md_tab_line_t	*linep,
78 	size_t		argc
79 )
80 {
81 	/* allocate in chunks */
82 	argc = roundup(argc, TAB_ARG_ALLOC);
83 	if (argc < linep->alloc)
84 		return;
85 
86 	/* (re)allocate */
87 	if (linep->alloc == 0) {
88 		linep->argv = Malloc(argc * sizeof (*linep->argv));
89 	} else {
90 		assert(linep->argv != NULL);
91 		linep->argv =
92 		    Realloc(linep->argv, (argc * sizeof (*linep->argv)));
93 	}
94 
95 	/* zero out new stuff */
96 	(void) memset(&linep->argv[linep->alloc], 0,
97 	    ((argc - linep->alloc) * sizeof (*linep->argv)));
98 
99 	/* adjust for new size */
100 	linep->alloc = argc;
101 }
102 
103 /*
104  * (re)allocate line array
105  */
106 static void
107 realloc_lines(
108 	md_tab_t	*tabp,
109 	size_t		nlines
110 )
111 {
112 	/* allocate in chunks */
113 	nlines = roundup(nlines, TAB_LINE_ALLOC);
114 	if (nlines < tabp->alloc)
115 		return;
116 
117 	/* (re)allocate */
118 	if (tabp->alloc == 0) {
119 		assert(tabp->lines == NULL);
120 		tabp->lines = Malloc(nlines * sizeof (*tabp->lines));
121 	} else {
122 		assert(tabp->lines != NULL);
123 		tabp->lines =
124 		    Realloc(tabp->lines, (nlines * sizeof (*tabp->lines)));
125 	}
126 
127 	/* zero out new stuff */
128 	(void) memset(&tabp->lines[tabp->alloc], 0,
129 	    ((nlines - tabp->alloc) * sizeof (*tabp->lines)));
130 
131 	/* adjust for new size */
132 	tabp->alloc = nlines;
133 }
134 
135 /*
136  * parse up md.tab struct
137  */
138 static void
139 parse_tab(
140 	md_tab_t	*tabp
141 )
142 {
143 	uint_t		lineno = 1;
144 	char		*p = tabp->data;
145 	char		*e = tabp->data + tabp->total - 1;
146 	char		*context;
147 	size_t		len;
148 
149 	/* we can count on '\n\0' as the last characters */
150 	assert(tabp->total >= 2);
151 	assert(tabp->data[tabp->total - 2] == '\n');
152 	assert(tabp->data[tabp->total - 1] == '\0');
153 
154 	/* allocate context buffer "file line XXX" */
155 	assert(tabp->filename != NULL);
156 	len = strlen(tabp->filename) +
157 	    strlen(dgettext(TEXT_DOMAIN, "%s line %u")) + 20 + 1;
158 	context = Malloc(len);
159 
160 	/* parse lines */
161 	while (p < e) {
162 		md_tab_line_t	*linep;
163 		char		*t;
164 
165 		/* allocate new line */
166 		realloc_lines(tabp, (tabp->nlines + 1));
167 		linep = &tabp->lines[tabp->nlines];
168 		(void) snprintf(context, len,
169 		    dgettext(TEXT_DOMAIN, "%s line %u"), tabp->filename,
170 		    lineno);
171 
172 		/* comments */
173 		if (*p == '#') {
174 			while (*p != '\n')
175 				++p;
176 		}
177 
178 		/* coalesce \ continuations */
179 		t = p;
180 		while (*t != '\n') {
181 			if ((*t == '\\') && (*(t + 1) == '\n')) {
182 				*t++ = ' ';
183 				*t = ' ';
184 				++lineno;
185 			}
186 			++t;
187 		}
188 
189 		/* leading whitespace */
190 		while ((*p != '\n') && (isspace(*p)))
191 			++p;
192 
193 		/* count lines */
194 		if (*p == '\n') {
195 			++p;
196 			++lineno;
197 			continue;
198 		}
199 
200 		/* tokenize line */
201 		while ((p < e) && (*p != '\n')) {
202 			char	**argvp;
203 
204 			/* allocate new token */
205 			realloc_argv(linep, (linep->argc + 1));
206 			argvp = &linep->argv[linep->argc++];
207 
208 			/* find end of token */
209 			*argvp = p;
210 			while ((*p != '\n') && (! isspace(*p)))
211 				++p;
212 
213 			/* terminate */
214 			if (*p == '\n') {
215 				*p++ = '\0';
216 				++lineno;
217 				break;
218 			}
219 
220 			/* eat white space */
221 			*p++ = '\0';
222 			while ((p < e) && (*p != '\n') && (isspace(*p)))
223 				++p;
224 		}
225 		tabp->nlines++;
226 
227 		/* fill in the rest */
228 		assert((linep->argc > 0) && (linep->argv != NULL) &&
229 		    (linep->argv[0][0] != '\0') &&
230 		    (! isspace(linep->argv[0][0])));
231 		linep->context = Strdup(context);
232 		linep->type = meta_get_init_type(linep->argc, linep->argv);
233 		linep->cname = Strdup(meta_canonicalize(NULL, linep->argv[0]));
234 		assert(linep->cname != NULL);
235 	}
236 
237 	/* cleanup */
238 	Free(context);
239 }
240 
241 /*
242  * read in md.tab file and return struct
243  */
244 md_tab_t *
245 meta_tab_parse(
246 	char		*filename,
247 	md_error_t	*ep
248 )
249 {
250 	md_tab_t	*tabp = NULL;
251 	int		fd = -1;
252 	struct stat	statbuf;
253 	size_t		sofar;
254 	char		*p;
255 
256 	/* open tab file */
257 	if (filename == NULL)
258 		filename = METATAB;
259 	if ((fd = open(filename, O_RDONLY, 0)) < 0) {
260 		(void) mdsyserror(ep, errno, filename);
261 		goto out;
262 	}
263 	if (fstat(fd, &statbuf) != 0) {
264 		(void) mdsyserror(ep, errno, filename);
265 		goto out;
266 	}
267 
268 	/* allocate table */
269 	tabp = Zalloc(sizeof (*tabp));
270 	tabp->filename = Strdup(filename);
271 	tabp->total = statbuf.st_size + 2;	/* terminating "\n\0" */
272 	tabp->data = Malloc(tabp->total);
273 
274 	/* read in data */
275 	sofar = 0;
276 	p = tabp->data;
277 	while (sofar < statbuf.st_size) {
278 		int	cnt;
279 
280 		if ((cnt = read(fd, p, 8192)) < 0) {
281 			(void) mdsyserror(ep, errno, filename);
282 			goto out;
283 		} else if (cnt == 0) {
284 			(void) mderror(ep, MDE_SYNTAX, filename);
285 			goto out;
286 		}
287 		sofar += cnt;
288 		p += cnt;
289 	}
290 	tabp->data[tabp->total - 2] = '\n';
291 	tabp->data[tabp->total - 1] = '\0';
292 
293 	/* close file */
294 	if (close(fd) != 0) {
295 		(void) mdsyserror(ep, errno, filename);
296 		fd = -1;
297 		goto out;
298 	}
299 	fd = -1;
300 
301 	/* parse it up */
302 	parse_tab(tabp);
303 
304 	/* return success */
305 	return (tabp);
306 
307 	/* cleanup, return error */
308 out:
309 	if (fd >= 0)
310 		(void) close(fd);
311 	if (tabp != NULL)
312 		meta_tab_free(tabp);
313 	return (NULL);
314 }
315 
316 /*
317  * find line in md.tab
318  */
319 md_tab_line_t *
320 meta_tab_find(
321 	mdsetname_t	*sp,
322 	md_tab_t	*tabp,
323 	char		*name,
324 	mdinittypes_t	type
325 )
326 {
327 	char		*cname = meta_canonicalize(sp, name);
328 	size_t		line;
329 
330 	for (line = 0; (line < tabp->nlines); ++line) {
331 		md_tab_line_t	*linep = &tabp->lines[line];
332 
333 		assert((linep->argc > 0) && (linep->argv[0] != NULL));
334 		if (((linep->type & type) != 0) &&
335 		    (strcmp(linep->cname, cname) == 0)) {
336 			Free(cname);
337 			return (linep);
338 		}
339 	}
340 	Free(cname);
341 	return (NULL);
342 }
343