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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include "med_local.h" 27 #include "med_hash.h" 28 #include <sys/lvm/mdio.h> 29 #include <sys/lvm/md_mdiox.h> 30 #include <sys/lvm/md_crc.h> 31 32 static int med_db_is_inited = 0; 33 static Cache *med_db_cache = (Cache *) NULL; 34 static med_rec_t *med_db_medrp = NULL; 35 static int med_db_nma = 0; 36 static int med_db_nmu = 0; 37 static int rec_size = roundup(sizeof (med_rec_t), DEV_BSIZE); 38 static char *rec_buf = NULL; 39 static int dbfd = -1; 40 41 #define OP_FLAGS (O_RDWR | O_SYNC) 42 #define CR_FLAGS (OP_FLAGS | O_CREAT) 43 44 #define HASHSIZE 151 45 #define BSZ 4 46 47 #ifdef DEBUG 48 void 49 med_pr(void *keyp, int keyl, void *datap, int datal) 50 { 51 med_med_t *medp = (med_med_t *)keyp; 52 int medridx = *(int *)datap; 53 med_rec_t *medrp = &med_db_medrp[medridx]; 54 55 med_eprintf( 56 "key (%d)[keyp=0x%08x]: setno=%ld, setname=<%s>, caller=<%s>\n", 57 keyl, (unsigned)keyp, medp->med_setno, medp->med_setname, 58 medp->med_caller); 59 med_eprintf("data(%d)[datap=0x%x08][medrp=0x%x08]: medridx=%d\n", 60 datal, (unsigned)datap, (unsigned)medrp, medridx); 61 } 62 #endif /* DEBUG */ 63 64 static int 65 med_hash(void *datap, int datalen, int hsz) 66 { 67 med_med_t *medp = (med_med_t *)datap; 68 int i = datalen; 69 char *cp; 70 71 i = 0; 72 cp = medp->med_setname; 73 while (*cp != '\0') 74 i += *cp++; 75 76 cp = medp->med_caller; 77 while (*cp != '\0') 78 i += *cp++; 79 80 i *= medp->med_setno; 81 82 return (i % hsz); 83 } 84 85 /*ARGSUSED*/ 86 static int 87 med_comp(void *datap1, void *datap2, int datalen) 88 { 89 med_med_t *medp1 = (med_med_t *)datap1; 90 med_med_t *medp2 = (med_med_t *)datap2; 91 int ret; 92 93 94 ret = medp1->med_setno - medp2->med_setno; 95 96 if (ret != 0) 97 return (ret); 98 99 ret = strcmp(medp1->med_caller, medp2->med_caller); 100 101 if (ret != 0) 102 return (ret); 103 104 return (strcmp(medp1->med_setname, medp2->med_setname)); 105 } 106 107 static void 108 med_kfree(void *keyp) 109 { 110 med_med_t *medp = (med_med_t *)keyp; 111 112 (void) Free(medp->med_caller); 113 (void) Free(medp->med_setname); 114 (void) Free(keyp); 115 } 116 117 static int 118 add_key(med_med_t *medp, int medridx) 119 { 120 Item *itemp; 121 int len; 122 med_med_t *tmedp; 123 124 if (med_db_cache == (Cache *) NULL) { 125 len = init_cache(&med_db_cache, HASHSIZE, BSZ, med_hash, 126 med_comp, med_kfree, (void (*)())NULL); 127 if (len == -1) { 128 med_eprintf("add_key(): init_cache() failed.\n"); 129 return (-1); 130 } 131 } 132 133 len = sizeof (med_med_t); 134 135 if ((itemp = lookup_cache(med_db_cache, medp, len)) == Null_Item) { 136 if ((itemp = (Item *) Malloc(sizeof (*itemp))) == NULL) { 137 med_eprintf("add_key(): itemp = Malloc(%d)\n", 138 sizeof (*itemp)); 139 return (-1); 140 } 141 if ((tmedp = itemp->key = Malloc(len)) == NULL) { 142 med_eprintf("add_key(): itemp->key = Malloc(%d)\n", 143 len); 144 return (-1); 145 } 146 147 *tmedp = *medp; /* structure assignment */ 148 149 tmedp->med_caller = Malloc(strlen(medp->med_caller) + 1); 150 if (tmedp->med_caller == NULL) { 151 med_eprintf( 152 "add_key(): tmedp->med_caller = Malloc(%d)\n", 153 strlen(medp->med_caller) + 1); 154 return (-1); 155 } 156 (void) strcpy(tmedp->med_caller, medp->med_caller); 157 158 tmedp->med_setname = Malloc(strlen(medp->med_setname) + 1); 159 if (tmedp->med_setname == NULL) { 160 med_eprintf( 161 "add_key(): tmedp->med_setname = Malloc(%d)\n", 162 strlen(medp->med_setname) + 1); 163 return (-1); 164 } 165 (void) strcpy(tmedp->med_setname, medp->med_setname); 166 167 itemp->keyl = len; 168 169 if ((itemp->data = Malloc(sizeof (int))) == NULL) { 170 med_eprintf("add_key(): itemp->data = Malloc(%d)\n", 171 sizeof (med_rec_t *)); 172 return (-1); 173 } 174 175 *(int *)itemp->data = medridx; 176 177 itemp->datal = sizeof (int); 178 179 if (add_cache(med_db_cache, itemp) == -1) { 180 med_eprintf("add_key(): add_cache() failed.\n"); 181 return (-1); 182 } 183 return (0); 184 } 185 return (1); 186 } 187 188 static int 189 del_key(med_med_t *medp) 190 { 191 Item *itemp; 192 int len; 193 194 if (med_db_cache == (Cache *) NULL) 195 return (0); 196 197 len = sizeof (med_med_t); 198 199 if ((itemp = lookup_cache(med_db_cache, medp, len)) == Null_Item) 200 return (0); 201 202 (void) del_cache(med_db_cache, itemp); 203 204 return (0); 205 } 206 207 static int 208 find_key(med_med_t *medp) 209 { 210 Item *itemp; 211 int len; 212 213 if (med_db_cache == (Cache *) NULL) 214 return (-1); 215 216 len = sizeof (med_med_t); 217 218 if ((itemp = lookup_cache(med_db_cache, medp, len)) == Null_Item) 219 return (-1); 220 221 return (*(int *)itemp->data); 222 } 223 224 static int 225 add_db_keys(int medridx, med_err_t *medep) 226 { 227 med_med_t med; 228 med_rec_t *medrp; 229 int i; 230 231 medrp = &med_db_medrp[medridx]; 232 med.med_setno = medrp->med_rec_sn; 233 med.med_setname = medrp->med_rec_snm; 234 235 for (i = 0; i < MD_MAXSIDES; i++) { 236 if (medrp->med_rec_nodes[i][0] == '\0') 237 continue; 238 med.med_caller = medrp->med_rec_nodes[i]; 239 if (add_key(&med, medridx) == -1) 240 return (med_error(medep, MDE_MED_DBKEYADDFAIL, 241 medrp->med_rec_nodes[i])); 242 } 243 244 /* 245 * Looping through the actual list of mediator hosts 246 * because a mediator host may not actually be a host 247 * in the diskset and so access for such a host needs 248 * to be added. 249 */ 250 for (i = 0; i < MED_MAX_HOSTS; i++) { 251 if ((medrp->med_rec_meds.n_cnt > 0) && 252 (medrp->med_rec_meds.n_lst[i].a_cnt != 0)) { 253 med.med_caller = 254 medrp->med_rec_meds.n_lst[i].a_nm[0]; 255 if (add_key(&med, medridx) == -1) 256 return (med_error(medep, MDE_MED_DBKEYADDFAIL, 257 medrp->med_rec_meds.n_lst[i].a_nm[0])); 258 } 259 } 260 return (0); 261 } 262 263 static int 264 del_db_keys(int medridx, med_err_t *medep) 265 { 266 med_med_t med; 267 med_rec_t *medrp; 268 int i; 269 270 medrp = &med_db_medrp[medridx]; 271 med.med_setno = medrp->med_rec_sn; 272 med.med_setname = medrp->med_rec_snm; 273 274 for (i = 0; i < MD_MAXSIDES; i++) { 275 if (medrp->med_rec_nodes[i][0] == '\0') 276 continue; 277 med.med_caller = medrp->med_rec_nodes[i]; 278 if (del_key(&med) == -1) 279 return (med_error(medep, MDE_MED_DBKEYDELFAIL, 280 medrp->med_rec_nodes[i])); 281 } 282 283 for (i = 0; i < MED_MAX_HOSTS; i++) { 284 if ((medrp->med_rec_meds.n_cnt > 0) && 285 (medrp->med_rec_meds.n_lst[i].a_cnt != 0)) { 286 med.med_caller = 287 medrp->med_rec_meds.n_lst[i].a_nm[0]; 288 if (del_key(&med) == -1) 289 return (med_error(medep, MDE_MED_DBKEYDELFAIL, 290 medrp->med_rec_meds.n_lst[i].a_nm[0])); 291 } 292 } 293 return (0); 294 } 295 296 static int 297 alloc_rec_buf(med_err_t *medep) 298 { 299 if (rec_buf == NULL) { 300 if ((rec_buf = Malloc(rec_size)) == NULL) 301 return (med_error(medep, errno, 302 "alloc_rec_buf: Malloc()")); 303 } 304 305 (void) memset(rec_buf, '\0', rec_size); 306 return (0); 307 } 308 309 static void 310 free_rec_buf(void) 311 { 312 if (rec_buf == NULL) 313 return; 314 315 Free(rec_buf); 316 rec_buf = NULL; 317 } 318 319 static int 320 write_hdr( 321 int dbfd, 322 med_err_t *medep 323 ) 324 { 325 med_db_hdr_t dbh; 326 327 if (alloc_rec_buf(medep)) 328 return (-1); 329 330 (void) memset(&dbh, '\0', sizeof (med_db_hdr_t)); 331 332 /* Setup the new hdr record */ 333 dbh.med_dbh_mag = MED_DB_MAGIC; 334 dbh.med_dbh_rev = MED_DB_REV; 335 dbh.med_dbh_nm = med_db_nmu; 336 337 /* Checksum new header */ 338 crcgen(&dbh, &dbh.med_dbh_cks, sizeof (med_db_hdr_t), NULL); 339 340 /* Position to the beginning of the file */ 341 if (lseek(dbfd, 0, SEEK_SET) == -1) 342 return (med_error(medep, errno, "write_hdr: lseek()")); 343 344 /* Copy the header into the output buffer */ 345 (void) memmove(rec_buf, &dbh, sizeof (med_db_hdr_t)); 346 347 /* Write out the header */ 348 if (write(dbfd, rec_buf, rec_size) == -1) 349 return (med_error(medep, errno, "write_hdr: write()")); 350 351 return (0); 352 } 353 354 static int 355 write_rec( 356 int dbfd, 357 med_rec_t *medrp, 358 med_err_t *medep 359 ) 360 { 361 uint_t save_flags = 0; 362 uint_t save_cks = 0; 363 364 if (alloc_rec_buf(medep)) 365 return (-1); 366 367 if (medrp->med_rec_data.med_dat_fl) { 368 save_flags = medrp->med_rec_data.med_dat_fl; 369 save_cks = medrp->med_rec_data.med_dat_cks; 370 medrp->med_rec_data.med_dat_fl = 0; 371 /* Checksum the new data */ 372 crcgen(&medrp->med_rec_data, &medrp->med_rec_data.med_dat_cks, 373 sizeof (med_data_t), NULL); 374 } 375 376 /* Checksum record */ 377 crcgen(medrp, &medrp->med_rec_cks, sizeof (med_rec_t), NULL); 378 379 /* Load the record into the output buffer */ 380 (void) memmove(rec_buf, medrp, sizeof (med_rec_t)); 381 382 if (save_flags) { 383 medrp->med_rec_data.med_dat_fl = save_flags; 384 medrp->med_rec_data.med_dat_cks = save_cks; 385 /* Re-checksum the updated record */ 386 crcgen(medrp, &medrp->med_rec_cks, sizeof (med_rec_t), NULL); 387 } 388 389 /* Write out the record */ 390 if (write(dbfd, rec_buf, rec_size) == -1) 391 return (med_error(medep, errno, "write_rec: write()")); 392 393 return (0); 394 } 395 396 static int 397 open_dbfile(med_err_t *medep) 398 { 399 if (dbfd != -1) 400 return (0); 401 402 /* Open the database file */ 403 if ((dbfd = open(MED_DB_FILE, OP_FLAGS, 0644)) == -1) { 404 if (errno != ENOENT) 405 return (med_error(medep, errno, "open_dbfile: open()")); 406 407 if ((dbfd = open(MED_DB_FILE, CR_FLAGS, 0644)) == -1) 408 return (med_error(medep, errno, 409 "open_dbfile: open(create)")); 410 } 411 412 /* Try to take an advisory lock on the file */ 413 if (lockf(dbfd, F_TLOCK, (off_t)0) == -1) { 414 (void) med_error(medep, errno, "open_dbfile: lockf(F_TLOCK)"); 415 medde_perror(medep, ""); 416 med_exit(1); 417 } 418 419 return (0); 420 } 421 422 static int 423 close_dbfile(med_err_t *medep) 424 { 425 if (dbfd == -1) 426 return (0); 427 428 /* Make sure we are at the beginning of the file */ 429 if (lseek(dbfd, 0, SEEK_SET) == -1) 430 return (med_error(medep, errno, "close_dbfile: lseek()")); 431 432 /* Release the advisory lock on the file */ 433 if (lockf(dbfd, F_ULOCK, 0LL) == -1) { 434 (void) med_error(medep, errno, "close_dbfile: lockf(F_ULOCK)"); 435 medde_perror(medep, ""); 436 med_exit(1); 437 } 438 439 if (close(dbfd) == -1) 440 return (med_error(medep, errno, "close_dbfile: close()")); 441 442 dbfd = -1; 443 444 return (0); 445 } 446 447 static int 448 med_db_del_rec(med_med_t *medp, med_err_t *medep) 449 { 450 med_rec_t *medrp = NULL; 451 int i; 452 int medridx = -1; 453 454 455 if (! med_db_is_inited) 456 return (med_error(medep, MDE_MED_DBNOTINIT, "med_db_del_rec")); 457 458 if ((medridx = find_key(medp)) == -1) 459 return (0); 460 461 /* Delete the old keys */ 462 if (del_db_keys(medridx, medep)) 463 return (-1); 464 465 medrp = &med_db_medrp[medridx]; 466 467 /* Mark the record in core as deleted */ 468 medrp->med_rec_fl |= MED_RFL_DEL; 469 470 /* Decrement the used slot count */ 471 med_db_nmu--; 472 473 /* Get ready to re-write the file */ 474 if (ftruncate(dbfd, 0) == -1) 475 return (med_error(medep, errno, "med_db_del_rec: ftruncate()")); 476 477 if (write_hdr(dbfd, medep)) 478 return (-1); 479 480 for (i = 0; i < med_db_nma; i++) { 481 medrp = &med_db_medrp[i]; 482 483 if (medrp->med_rec_fl & MED_RFL_DEL) 484 continue; 485 486 /* Determine our location in the file */ 487 if ((medrp->med_rec_foff = lseek(dbfd, 0, SEEK_CUR)) == -1) 488 return (med_error(medep, errno, 489 "med_db_del_rec: lseek()")); 490 491 if (write_rec(dbfd, medrp, medep)) 492 return (-1); 493 } 494 return (0); 495 } 496 497 static int 498 cmp_medrec(med_rec_t *omedrp, med_rec_t *nmedrp) 499 { 500 int ret; 501 int i; 502 503 if (omedrp->med_rec_mag != nmedrp->med_rec_mag) 504 return (0); 505 506 if (omedrp->med_rec_rev != nmedrp->med_rec_rev) 507 return (0); 508 509 /* Can't compare checksums, since the new record has no data yet */ 510 511 /* Can't compare flags, since the in-core may have golden */ 512 513 if (omedrp->med_rec_sn != nmedrp->med_rec_sn) 514 return (0); 515 516 if (strcmp(omedrp->med_rec_snm, nmedrp->med_rec_snm) != 0) 517 return (0); 518 519 for (i = 0; i < MD_MAXSIDES; i++) { 520 if (omedrp->med_rec_nodes[i][0] == '\0' && 521 nmedrp->med_rec_nodes[i][0] == '\0') 522 continue; 523 524 ret = strcmp(omedrp->med_rec_nodes[i], 525 nmedrp->med_rec_nodes[i]); 526 if (ret != 0) 527 return (0); 528 } 529 530 ret = memcmp(&omedrp->med_rec_meds, &nmedrp->med_rec_meds, 531 sizeof (md_h_arr_t)); 532 if (ret != 0) 533 return (0); 534 535 return (1); 536 } 537 538 /* 539 * Exported routines 540 */ 541 542 int 543 med_db_init(med_err_t *medep) 544 { 545 int i; 546 int err = 0; 547 int ret; 548 struct stat statb; 549 med_db_hdr_t *dbhp; 550 med_rec_t *medrp; 551 int nm; 552 off_t cur_off; 553 554 if (med_db_is_inited) 555 return (0); 556 557 if (open_dbfile(medep)) 558 return (-1); 559 560 if (fstat(dbfd, &statb) == -1) 561 return (med_error(medep, errno, "med_db_init: fstat()")); 562 563 /* Empty file */ 564 if (statb.st_size == 0) 565 goto out; 566 567 /* File should be a multiple of the record size */ 568 if (((int)(statb.st_size % (off_t)rec_size)) != 0) 569 return (med_error(medep, MDE_MED_DBSZBAD, "med_db_init")); 570 571 if (alloc_rec_buf(medep)) 572 return (-1); 573 574 /* Read in the file header */ 575 if ((ret = read(dbfd, rec_buf, rec_size)) == -1) 576 return (med_error(medep, errno, "med_db_init: read(hdr)")); 577 578 if (ret != rec_size) 579 return (med_error(medep, MDE_MED_DBHDRSZBAD, "med_db_init")); 580 581 /*LINTED*/ 582 dbhp = (med_db_hdr_t *)rec_buf; 583 584 /* Header magic is not OK */ 585 if (dbhp->med_dbh_mag != MED_DB_MAGIC) 586 return (med_error(medep, MDE_MED_DBHDRMAGBAD, "med_db_init")); 587 588 /* Header revision is not OK */ 589 if (dbhp->med_dbh_rev != MED_DB_REV) 590 return (med_error(medep, MDE_MED_DBHDRREVBAD, "med_db_init")); 591 592 /* Header checksum is not OK */ 593 if (crcchk(dbhp, &dbhp->med_dbh_cks, sizeof (med_db_hdr_t), NULL)) 594 return (med_error(medep, MDE_MED_DBHDRCKSBAD, "med_db_init")); 595 596 /* File size does not add up */ 597 if (((off_t)((dbhp->med_dbh_nm * rec_size) + rec_size)) 598 != statb.st_size) 599 return (med_error(medep, MDE_MED_DBSZBAD, "med_db_init")); 600 601 if ((nm = dbhp->med_dbh_nm) > 0) { 602 /* Allocate space to hold the records to be read next */ 603 med_db_medrp = (med_rec_t *)Calloc(nm, sizeof (med_rec_t)); 604 if (med_db_medrp == NULL) 605 return (med_error(medep, errno, 606 "med_db_init: Calloc(med_db_medrp)")); 607 } 608 609 /* Read in all the records */ 610 for (i = 0; i < nm; i++) { 611 if ((cur_off = lseek(dbfd, 0, SEEK_CUR)) == -1) { 612 err = med_error(medep, errno, 613 "med_db_init: lseek()"); 614 goto out; 615 } 616 617 (void) memset(rec_buf, '\0', rec_size); 618 619 if ((ret = read(dbfd, rec_buf, rec_size)) == -1) { 620 err = med_error(medep, errno, 621 "med_db_init: read() rec"); 622 goto out; 623 } 624 625 if (ret != rec_size) { 626 err = med_error(medep, MDE_MED_DBRECSZBAD, 627 "med_db_init"); 628 goto out; 629 } 630 631 /*LINTED*/ 632 medrp = (med_rec_t *)rec_buf; 633 634 /* Record magic is not OK */ 635 if (medrp->med_rec_mag != MED_REC_MAGIC) { 636 err = med_error(medep, MDE_MED_DBRECMAGBAD, 637 "med_db_init"); 638 goto out; 639 } 640 641 /* Record revision is not OK */ 642 if (medrp->med_rec_rev != MED_REC_REV) { 643 err = med_error(medep, MDE_MED_DBRECREVBAD, 644 "med_db_init"); 645 goto out; 646 } 647 648 /* Record checksum is not OK */ 649 ret = crcchk(medrp, &medrp->med_rec_cks, sizeof (med_rec_t), 650 NULL); 651 if (ret) { 652 err = med_error(medep, MDE_MED_DBRECCKSBAD, 653 "med_db_init"); 654 goto out; 655 } 656 657 /* Record is not where it is supposed to be */ 658 if (medrp->med_rec_foff != cur_off) { 659 err = med_error(medep, MDE_MED_DBRECOFFBAD, 660 "med_db_init"); 661 goto out; 662 } 663 664 med_db_medrp[i] = *medrp; /* structure assignment */ 665 } 666 667 /* Add the keys to access this record */ 668 for (i = 0; i < nm; i++) 669 if ((err = add_db_keys(i, medep)) == -1) 670 goto out; 671 672 med_db_nma = nm; 673 med_db_nmu = nm; 674 675 out: 676 if (err && med_db_medrp != NULL) 677 Free(med_db_medrp); 678 679 if (!err) 680 med_db_is_inited = 1; 681 682 return (err); 683 } 684 685 med_rec_t * 686 med_db_get_rec(med_med_t *medp, med_err_t *medep) 687 { 688 int medridx = -1; 689 690 if ((medridx = find_key(medp)) == -1) { 691 (void) med_error(medep, MDE_MED_DBRECNOENT, "med_db_get_rec"); 692 return (NULL); 693 } 694 695 return (&med_db_medrp[medridx]); 696 } 697 698 med_data_t * 699 med_db_get_data(med_med_t *medp, med_err_t *medep) 700 { 701 int medridx = -1; 702 703 if ((medridx = find_key(medp)) == -1) { 704 (void) med_error(medep, MDE_MED_DBRECNOENT, "med_db_get_data"); 705 return (NULL); 706 } 707 708 return (&med_db_medrp[medridx].med_rec_data); 709 } 710 711 int 712 med_db_put_rec(med_med_t *medp, med_rec_t *nmedrp, med_err_t *medep) 713 { 714 med_rec_t *medrp = NULL; 715 med_rec_t *tmedrp = NULL; 716 int i; 717 int found = 0; 718 int medridx = -1; 719 720 721 if (! med_db_is_inited) 722 return (med_error(medep, MDE_MED_DBNOTINIT, "med_db_put_rec")); 723 724 if (medp->med_setno != nmedrp->med_rec_sn) 725 return (med_error(medep, MDE_MED_DBARGSMISMATCH, 726 "med_db_put_rec")); 727 728 /* See if we are still considered a mediator - is this a delete? */ 729 for (i = 0; i < MED_MAX_HOSTS; i++) { 730 if (nmedrp->med_rec_meds.n_lst[i].a_cnt == 0) 731 continue; 732 733 if (strcmp(nmedrp->med_rec_meds.n_lst[i].a_nm[0], 734 mynode()) == 0) { 735 found = 1; 736 break; 737 } 738 } 739 740 /* If it is a delete, make it happen */ 741 if (! found) 742 return (med_db_del_rec(medp, medep)); 743 744 /* See if there is an existing record */ 745 if ((medridx = find_key(medp)) != -1) { 746 747 medrp = &med_db_medrp[medridx]; 748 749 /* Delete the old keys */ 750 if (del_db_keys(medridx, medep)) 751 return (-1); 752 753 /* Decrement the used slot count */ 754 med_db_nmu--; 755 } else { 756 for (i = 0; i < MED_MAX_HOSTS; i++) { 757 med_med_t tmed; 758 759 if (nmedrp->med_rec_meds.n_lst[i].a_cnt == 0) 760 continue; 761 762 if (strcmp(nmedrp->med_rec_meds.n_lst[i].a_nm[0], 763 medp->med_caller) == 0) 764 continue; 765 766 tmed = *medp; /* structure assignment */ 767 768 tmed.med_caller = 769 Strdup(nmedrp->med_rec_meds.n_lst[i].a_nm[0]); 770 771 medridx = find_key(&tmed); 772 773 Free(tmed.med_caller); 774 775 if (medridx != -1) { 776 medrp = &med_db_medrp[medridx]; 777 778 if (cmp_medrec(medrp, nmedrp)) 779 return (0); 780 } 781 } 782 } 783 784 /* Allocate more space if needed */ 785 if ((med_db_nmu + 1) > med_db_nma) { 786 787 /* Allocate more space to hold the new record */ 788 tmedrp = (med_rec_t *)Calloc((med_db_nmu + 1), 789 sizeof (med_rec_t)); 790 if (tmedrp == NULL) 791 return (med_error(medep, errno, 792 "med_db_put_rec: Re-Calloc(tmedrp)")); 793 794 /* Copy the existing information into the new area */ 795 for (i = 0; i < med_db_nma; i++) 796 tmedrp[i] = med_db_medrp[i]; /* structure assignment */ 797 798 med_db_nmu++; 799 med_db_nma = med_db_nmu; 800 801 if (med_db_medrp) 802 Free(med_db_medrp); 803 804 med_db_medrp = tmedrp; 805 806 medridx = med_db_nma - 1; 807 808 /* Initialize */ 809 medrp = &med_db_medrp[medridx]; 810 medrp->med_rec_mag = MED_REC_MAGIC; 811 medrp->med_rec_rev = MED_REC_REV; 812 medrp->med_rec_sn = nmedrp->med_rec_sn; 813 (void) strcpy(medrp->med_rec_snm, nmedrp->med_rec_snm); 814 815 /* Calculate the record offset */ 816 medrp->med_rec_foff = (off_t)(((med_db_nma - 1) * rec_size) + 817 rec_size); 818 } else { 819 /* 820 * We did not find the record, but have space allocated. 821 * Find an empty slot. 822 */ 823 if (medrp == NULL) { 824 for (i = 0; i < med_db_nma; i++) { 825 medrp = &med_db_medrp[i]; 826 827 if (! (medrp->med_rec_fl & MED_RFL_DEL)) 828 continue; 829 830 medridx = i; 831 832 /* Mark as no longer deleted */ 833 medrp->med_rec_fl &= ~MED_RFL_DEL; 834 835 /* Initialize */ 836 medrp->med_rec_mag = MED_REC_MAGIC; 837 medrp->med_rec_rev = MED_REC_REV; 838 medrp->med_rec_sn = nmedrp->med_rec_sn; 839 (void) strcpy(medrp->med_rec_snm, 840 nmedrp->med_rec_snm); 841 842 /* Calculate the new offset of the record */ 843 medrp->med_rec_foff = (off_t) 844 ((med_db_nmu * rec_size) + rec_size); 845 846 /* Clear the old data */ 847 (void) memset(&medrp->med_rec_data, '\0', 848 sizeof (med_data_t)); 849 850 break; 851 } 852 } 853 med_db_nmu++; 854 } 855 856 assert(medridx != -1); 857 858 /* Update the record with the new information */ 859 medrp->med_rec_meds = nmedrp->med_rec_meds; /* structure assignment */ 860 861 for (i = 0; i < MD_MAXSIDES; i++) 862 (void) strcpy(medrp->med_rec_nodes[i], 863 nmedrp->med_rec_nodes[i]); 864 865 if (write_hdr(dbfd, medep)) 866 return (-1); 867 868 /* Position to record location */ 869 if (lseek(dbfd, medrp->med_rec_foff, SEEK_SET) == -1) 870 return (med_error(medep, errno, "med_db_put_rec: lseek(rec)")); 871 872 if (write_rec(dbfd, medrp, medep)) 873 return (-1); 874 875 /* Add the keys for this record */ 876 if (add_db_keys(medridx, medep)) 877 return (-1); 878 879 return (0); 880 } 881 882 int 883 med_db_put_data(med_med_t *medp, med_data_t *meddp, med_err_t *medep) 884 { 885 med_rec_t *medrp = NULL; 886 int medridx = -1; 887 888 889 if (! med_db_is_inited) 890 return (med_error(medep, MDE_MED_DBNOTINIT, "med_db_put_data")); 891 892 if (medp->med_setno != meddp->med_dat_sn) 893 return (med_error(medep, MDE_MED_DBARGSMISMATCH, 894 "med_db_put_data")); 895 896 if ((medridx = find_key(medp)) == -1) 897 return (med_error(medep, MDE_MED_DBRECNOENT, 898 "med_db_put_data")); 899 900 medrp = &med_db_medrp[medridx]; 901 902 medrp->med_rec_data = *meddp; /* structure assignment */ 903 904 /* Go to location of the record */ 905 if (lseek(dbfd, medrp->med_rec_foff, SEEK_SET) == -1) 906 return (med_error(medep, errno, "med_db_put_data: lseek()")); 907 908 if (write_rec(dbfd, medrp, medep)) 909 return (-1); 910 911 return (0); 912 } 913 914 int 915 med_db_finit(med_err_t *medep) 916 { 917 des_cache(&med_db_cache); 918 Free(med_db_medrp); 919 free_rec_buf(); 920 if (close_dbfile(medep)) 921 return (-1); 922 return (0); 923 } 924