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