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 2003 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 /* 38 * patch /kernel/drv/md.conf file 39 */ 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <meta.h> 43 #include <sys/lvm/md_mddb.h> 44 45 /* 46 * magic strings in system 47 */ 48 #define BEGROOTSTR "* Begin MDD root info (do not edit)\n" 49 #define ENDROOTSTR "* End MDD root info (do not edit)\n" 50 #define BEGMDDBSTR "# Begin MDD database info (do not edit)\n" 51 #define ENDMDDBSTR "# End MDD database info (do not edit)\n" 52 53 /* 54 * copy system file, yank root and database lines 55 */ 56 int 57 meta_systemfile_copy( 58 char *sname, /* system file name */ 59 int doroot, /* remove mdd root stuff */ 60 int domddb, /* remove mdd database stuff */ 61 int doit, /* really copy file */ 62 int verbose, /* show what we're doing */ 63 char **tname, /* returned temp file name */ 64 FILE **tfp, /* returned open FILE */ 65 md_error_t *ep /* returned error */ 66 ) 67 { 68 FILE *fp; 69 struct stat sbuf; 70 char buf[MDDB_BOOTLIST_MAX_LEN]; 71 int delroot = 0; 72 int delmddb = 0; 73 74 /* check names */ 75 assert(sname != NULL); 76 assert(tname != NULL); 77 assert(tfp != NULL); 78 79 /* get temp name */ 80 *tfp = NULL; 81 *tname = Malloc(strlen(sname) + strlen(".tmp") + 1); 82 (void) strcpy(*tname, sname); 83 (void) strcat(*tname, ".tmp"); 84 85 /* copy system file, yank stuff */ 86 if (((fp = fopen(sname, "r")) == NULL) || 87 (fstat(fileno(fp), &sbuf) != 0)) { 88 if (errno != ENOENT) { 89 (void) mdsyserror(ep, errno, sname); 90 goto out; 91 } 92 } 93 if (doit) { 94 if ((*tfp = fopen(*tname, "w")) == NULL) { 95 /* 96 * If we are on the miniroot we need to create 97 * files in /var/tmp. Opening a writable file 98 * in the miniroot result is EROFS error. 99 */ 100 if (errno != EROFS) { 101 (void) mdsyserror(ep, errno, *tname); 102 goto out; 103 } 104 Free(*tname); 105 *tname = tempnam("/var/tmp", "svm_"); 106 if (*tname == NULL) { 107 (void) mdsyserror(ep, errno, NULL); 108 goto out; 109 } 110 if ((*tfp = fopen(*tname, "w")) == NULL) { 111 (void) mdsyserror(ep, errno, *tname); 112 goto out; 113 } 114 } 115 if (fp != NULL) { 116 if ((fchmod(fileno(*tfp), (sbuf.st_mode & 0777)) 117 != 0) || 118 (fchown(fileno(*tfp), sbuf.st_uid, sbuf.st_gid) 119 != 0)) { 120 (void) mdsyserror(ep, errno, *tname); 121 goto out; 122 } 123 } 124 } 125 if (verbose) { 126 (void) printf(dgettext(TEXT_DOMAIN, 127 "Delete the following lines from %s:\n\n"), sname); 128 } 129 while ((fp != NULL) && (fgets(buf, sizeof (buf), fp) != NULL)) { 130 if ((doroot) && (strcmp(buf, BEGROOTSTR) == 0)) { 131 delroot = 1; 132 if (verbose) 133 (void) printf("%s", buf); 134 continue; 135 } 136 if (delroot) { 137 if (strcmp(buf, ENDROOTSTR) == 0) 138 delroot = 0; 139 if (verbose) 140 (void) printf("%s", buf); 141 continue; 142 } 143 if ((domddb) && (strcmp(buf, BEGMDDBSTR) == 0)) { 144 delmddb = 1; 145 if (verbose) 146 (void) printf("%s", buf); 147 continue; 148 } 149 if (delmddb) { 150 if (strcmp(buf, ENDMDDBSTR) == 0) 151 delmddb = 0; 152 if (verbose) 153 (void) printf("%s", buf); 154 continue; 155 } 156 if (doit) { 157 if (fputs(buf, *tfp) == EOF) { 158 (void) mdsyserror(ep, errno, *tname); 159 goto out; 160 } 161 } 162 } 163 if (fp != NULL) { 164 if ((! feof(fp)) || 165 (fclose(fp) != 0)) { 166 (void) mdsyserror(ep, errno, sname); 167 goto out; 168 } 169 fp = NULL; 170 } 171 if (verbose) 172 (void) printf("\n"); 173 174 /* make sure we didn't stop mid-delete */ 175 if ((delroot) || (delmddb)) { 176 (void) mderror(ep, MDE_SYSTEM_FILE, sname); 177 goto out; 178 } 179 180 /* flush stuff */ 181 if (doit) { 182 if ((fflush(*tfp) != 0) || 183 (fsync(fileno(*tfp)) != 0)) { 184 (void) mdsyserror(ep, errno, *tname); 185 goto out; 186 } 187 } 188 189 /* return success */ 190 return (0); 191 192 /* cleanup, return error */ 193 out: 194 if (fp != NULL) 195 (void) fclose(fp); 196 if (*tname != NULL) { 197 (void) unlink(*tname); 198 Free(*tname); 199 } 200 if (*tfp != NULL) 201 (void) fclose(*tfp); 202 return (-1); 203 } 204 205 /* 206 * append root on MD lines to system 207 */ 208 int 209 meta_systemfile_append_mdroot( 210 mdname_t *rootnp, /* root device name */ 211 char *sname, /* system file name */ 212 char *tname, /* temp file name */ 213 FILE *tfp, /* temp FILE */ 214 int ismeta, /* is a metadevice */ 215 int doit, /* really patch file */ 216 int verbose, /* show what we're doing */ 217 md_error_t *ep 218 ) 219 { 220 char *longblkname; 221 222 /* check names */ 223 assert(sname != NULL); 224 assert(tname != NULL); 225 assert(!doit || tfp != NULL); 226 227 /* get root /devices name */ 228 if ((longblkname = metagetdevicesname(rootnp, ep)) == NULL) 229 return (-1); 230 231 /* add header */ 232 if (verbose) { 233 (void) printf(dgettext(TEXT_DOMAIN, 234 "Add the following lines to %s:\n\n"), sname); 235 (void) printf("%s", BEGROOTSTR); 236 } 237 if (doit) { 238 if (fprintf(tfp, "%s", BEGROOTSTR) == EOF) { 239 return (mdsyserror(ep, errno, tname)); 240 } 241 } 242 243 /* add rootdev */ 244 if (ismeta) { 245 if (verbose) 246 (void) printf("rootdev:%s\n", longblkname); 247 if (doit) { 248 if (fprintf(tfp, "rootdev:%s\n", longblkname) == EOF) { 249 return (mdsyserror(ep, errno, tname)); 250 } 251 } 252 } 253 254 /* add trailer */ 255 if (verbose) { 256 (void) printf("%s\n", ENDROOTSTR); 257 } 258 if (doit) { 259 if (fprintf(tfp, "%s", ENDROOTSTR) == EOF) { 260 return (mdsyserror(ep, errno, tname)); 261 } 262 } 263 264 /* flush stuff */ 265 if (doit) { 266 if ((fflush(tfp) != 0) || 267 (fsync(fileno(tfp)) != 0)) { 268 return (mdsyserror(ep, errno, tname)); 269 } 270 } 271 272 /* return success */ 273 return (0); 274 } 275 276 /* 277 * parse mddb.cf line 278 * 279 * Caller of this routine needs to free the device id string that 280 * is passed back during a successful return. 281 */ 282 static int 283 confline( 284 char *line, /* line in file */ 285 char **driver, /* returned driver name */ 286 minor_t *mnump, /* returned minor number */ 287 daddr_t *block, /* returned block offset */ 288 char **devid_char_pp /* returned device id string */ 289 ) 290 { 291 char *p = line; 292 int chksum = 0; 293 int i; 294 uint_t devid_size; 295 296 if (*p == '#') { 297 return (-1); 298 } 299 *driver = p; 300 while ((*p != ' ') && (*p != '\t')) 301 chksum += *p++; 302 if (*driver == p) { 303 return (-1); 304 } 305 *p++ = '\0'; 306 *mnump = strtoul(p, &p, 10); 307 chksum += *mnump; 308 *block = strtol(p, &p, 10); 309 chksum += *block; 310 311 /* parse out devid */ 312 while ((*p == ' ') || (*p == '\t')) { 313 p++; 314 } 315 i = strcspn(p, " \t"); 316 *devid_char_pp = Malloc(i+1); 317 (void) strncpy(*devid_char_pp, p, i); 318 (*devid_char_pp)[i] = '\0'; 319 devid_size = i; 320 p += devid_size; 321 for (i = 0; i < devid_size; i++) { 322 chksum += (*devid_char_pp)[i]; 323 } 324 325 chksum += strtol(p, &p, 10); 326 if (chksum != 42) { 327 Free (*devid_char_pp); 328 devid_char_pp = NULL; 329 return (-1); 330 } 331 return (0); 332 } 333 334 /* 335 * append MDDB lines to system 336 */ 337 int 338 meta_systemfile_append_mddb( 339 char *cname, /* mddb.cf file name */ 340 char *sname, /* system file name */ 341 char *tname, /* temp file name */ 342 FILE *tfp, /* temp FILE */ 343 int doit, /* really patch file */ 344 int verbose, /* show what we're doing */ 345 md_error_t *ep /* returned error */ 346 ) 347 { 348 FILE *cfp = NULL; 349 char buf[1024]; 350 char *p; 351 int i; 352 char *driver; 353 minor_t mnum; 354 daddr_t block; 355 char line[MDDB_BOOTLIST_MAX_LEN]; 356 char entry[MDDB_BOOTLIST_MAX_LEN]; 357 char *devid_char_p = NULL; 358 struct stat statbuf; 359 360 /* check names */ 361 assert(cname != NULL); 362 assert(sname != NULL); 363 assert(tname != NULL); 364 assert(!doit || tfp != NULL); 365 366 /* open database conf file */ 367 if ((cfp = fopen(cname, "r")) == NULL) { 368 (void) mdsyserror(ep, errno, cname); 369 goto out; 370 } 371 /* Check that it is an ordinary file */ 372 if (stat(cname, &statbuf) != 0) { 373 (void) mdsyserror(ep, errno, cname); 374 goto out; 375 } 376 if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 377 (void) mderror(ep, MDE_MDDB_FILE, cname); 378 goto out; 379 } 380 381 /* add header */ 382 if (verbose) { 383 (void) printf(dgettext(TEXT_DOMAIN, 384 "Add the following lines to %s:\n\n"), sname); 385 (void) printf("%s", BEGMDDBSTR); 386 } 387 if (doit) { 388 if (fprintf(tfp, "%s", BEGMDDBSTR) == EOF) { 389 (void) mdsyserror(ep, errno, tname); 390 goto out; 391 } 392 } 393 394 /* append database lines */ 395 while (((p = fgets(buf, sizeof (buf), cfp)) != NULL) && 396 (confline(buf, &driver, &mnum, &block, &devid_char_p) != 0)) 397 ; 398 for (i = 1; ((p != NULL) && (i <= MDDB_MAX_PATCH)); ++i) { 399 (void) snprintf(line, sizeof (line), 400 "mddb_bootlist%d=\"%s:%lu:%ld:%s", 401 i, driver, mnum, block, devid_char_p); 402 if (devid_char_p != NULL) { 403 free(devid_char_p); 404 devid_char_p = NULL; 405 } 406 407 while ((p = fgets(buf, sizeof (buf), cfp)) != NULL) { 408 if (confline(buf, &driver, &mnum, &block, 409 &devid_char_p) != 0) { 410 continue; 411 } 412 (void) snprintf(entry, sizeof (entry), " %s:%lu:%ld:%s", 413 driver, mnum, block, devid_char_p); 414 415 if ((strlen(line) + strlen(entry) + 4) > sizeof (line)) 416 break; 417 (void) strcat(line, entry); 418 if (devid_char_p != NULL) { 419 free(devid_char_p); 420 devid_char_p = NULL; 421 } 422 } 423 if (verbose) 424 /* CSTYLED */ 425 (void) printf("%s\";\n", line); 426 if (doit) { 427 /* CSTYLED */ 428 if (fprintf(tfp, "%s\";\n", line) <= 0) { 429 (void) mdsyserror(ep, errno, tname); 430 goto out; 431 } 432 } 433 } 434 435 if (devid_char_p != NULL) { 436 free(devid_char_p); 437 devid_char_p = NULL; 438 } 439 440 /* add trailer */ 441 if (verbose) 442 (void) printf("%s\n", ENDMDDBSTR); 443 if (doit) { 444 if (fprintf(tfp, "%s", ENDMDDBSTR) == EOF) { 445 (void) mdsyserror(ep, errno, tname); 446 goto out; 447 } 448 } 449 450 /* close database conf file */ 451 if (fclose(cfp) != 0) { 452 cfp = NULL; 453 (void) mdsyserror(ep, errno, cname); 454 goto out; 455 } 456 cfp = NULL; 457 458 /* flush stuff */ 459 if (doit) { 460 if ((fflush(tfp) != 0) || 461 (fsync(fileno(tfp)) != 0)) { 462 (void) mdsyserror(ep, errno, tname); 463 goto out; 464 } 465 } 466 467 /* return success */ 468 return (0); 469 470 /* cleanup, return error */ 471 out: 472 if (cfp != NULL) 473 (void) fclose(cfp); 474 return (-1); 475 } 476