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