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