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 #include <stdio.h> 28 #include <stdlib.h> 29 #include <errno.h> 30 #include <sys/types.h> 31 #include <ctype.h> 32 #include <string.h> 33 #include <strings.h> 34 #include <thread.h> 35 #include <synch.h> 36 #include "libfsmgt.h" 37 38 /* 39 * Private datastructures. 40 */ 41 typedef struct dfstab_entry { 42 struct dfstab_entry *next; 43 char *path; 44 char *resource; 45 char *fstype; 46 char *options; 47 char *description; 48 } dfstab_entry_t; 49 50 static const char *whitespace = " \t"; 51 static mutex_t dfstab_lock = DEFAULTMUTEX; 52 53 /* 54 * Private functions 55 */ 56 static dfstab_entry_t *get_dfstab_ents(int *); 57 static void free_dfstab_list(dfstab_entry_t *); 58 static dfstab_entry_t *dfstab_line_to_dfstab_entry(char *, int *); 59 static char *create_share_cmd(dfstab_entry_t *, char *, int *); 60 static dfstab_entry_t *change_dfstab_ent(dfstab_entry_t *, 61 dfstab_entry_t *, int *); 62 static void add_entry_to_dfstab(dfstab_entry_t *, int *); 63 64 65 static dfstab_entry_t * 66 get_dfstab_ents(int *err) 67 { 68 dfstab_entry_t *dfstablist, *headptr, *tailptr = NULL; 69 FILE *dfp; /* fp for dfs list */ 70 static char cmd[BUFSIZE]; 71 *err = 0; 72 73 if ((dfp = fopen(DFSTAB, "r")) != NULL) { 74 char *share_cmd; 75 (void) mutex_lock(&dfstab_lock); 76 while ((share_cmd = 77 fileutil_getline(dfp, cmd, BUFSIZE)) != NULL) { 78 if ((dfstablist = 79 dfstab_line_to_dfstab_entry(share_cmd, err)) != 80 NULL) { 81 if (tailptr == NULL) { 82 headptr = dfstablist; 83 tailptr = dfstablist; 84 } else { 85 tailptr->next = dfstablist; 86 tailptr = dfstablist; 87 } 88 dfstablist = dfstablist->next; 89 } else { 90 free(share_cmd); 91 break; 92 } 93 free(share_cmd); 94 } 95 if (tailptr == NULL) { 96 headptr = tailptr; 97 } 98 (void) mutex_unlock(&dfstab_lock); 99 fclose(dfp); 100 } else { 101 *err = errno; 102 (void) fprintf(stderr, "%s: cannot open %s\n", cmd, DFSTAB); 103 headptr = NULL; 104 } 105 return (headptr); 106 } /* get_dfstab_ents */ 107 108 static void 109 add_entry_to_dfstab(dfstab_entry_t *list, int *err) 110 { 111 FILE *dfp; /* fp for dfs list */ 112 113 if ((dfp = fopen(DFSTAB, "a")) != NULL) { 114 char *share_cmd; 115 if ((share_cmd = create_share_cmd(list, NULL, err)) != NULL) { 116 (void) mutex_lock(&dfstab_lock); 117 fprintf(dfp, "%s", share_cmd); 118 fclose(dfp); 119 (void) mutex_unlock(&dfstab_lock); 120 free(share_cmd); 121 } else { 122 *err = errno; 123 } 124 } else { 125 *err = errno; 126 } 127 128 } /* add_entry_to_dfstab */ 129 130 static void 131 free_dfstab_list(dfstab_entry_t *headp) 132 { 133 dfstab_entry_t *tmp = headp; 134 135 while (headp != NULL) { 136 tmp = headp->next; 137 if (headp->path != NULL) { 138 free(headp->path); 139 } 140 if (headp->resource != NULL) { 141 free(headp->resource); 142 } 143 if (headp->fstype != NULL) { 144 free(headp->fstype); 145 } 146 if (headp->options != NULL) { 147 free(headp->options); 148 } 149 if (headp->description != NULL) { 150 free(headp->description); 151 } 152 headp->next = NULL; 153 free(headp); 154 headp = tmp; 155 } 156 } /* free_dfstab_list */ 157 158 static char * 159 create_share_cmd(dfstab_entry_t *new_entry, char *temp_line, int *err) 160 { 161 char tempstr[BUFSIZE]; 162 char *cmd, *ret_val; 163 164 cmd = (char *)calloc((size_t)1, BUFSIZE); 165 if (cmd == NULL) { 166 *err = errno; 167 return (NULL); 168 } 169 sprintf(cmd, "share "); 170 if (new_entry->fstype) { 171 sprintf(tempstr, "-F %s ", new_entry->fstype); 172 strlcat(cmd, tempstr, BUFSIZE); 173 } 174 if (new_entry->options) { 175 sprintf(tempstr, "-o %s ", new_entry->options); 176 strlcat(cmd, tempstr, BUFSIZE); 177 } 178 if (new_entry->description) { 179 sprintf(tempstr, "-d %s ", 180 new_entry->description); 181 strlcat(cmd, tempstr, BUFSIZE); 182 } 183 sprintf(tempstr, "%s\n", new_entry->path); 184 strlcat(cmd, tempstr, BUFSIZE); 185 if (temp_line != NULL && strchr(temp_line, '#')) { 186 sprintf(tempstr, " %s", strchr(temp_line, '#')); 187 strlcat(cmd, tempstr, BUFSIZE); 188 } 189 ret_val = strdup(cmd); 190 free(cmd); 191 return (ret_val); 192 } /* create_share_cmd */ 193 194 /* 195 * dfstab_line_to_dfstab_entry - parses a line from dfstab and fills in 196 * the fields of a dfstab_entry_t structure 197 * Parameters: 198 * char *cmd - the share command or dfstab line to be parsed 199 * int *err - a pointer for returning any error codes encountered 200 */ 201 static dfstab_entry_t * 202 dfstab_line_to_dfstab_entry(char *cmd, int *err) 203 { 204 205 dfstab_entry_t *dfstablist; 206 extern char *optarg; 207 extern int optind; 208 int c, argcount = 0; 209 char *temp_str; 210 char *arglist[LINESZ]; 211 212 c = 0; 213 optind = 1; 214 215 temp_str = strdup(cmd); 216 if (temp_str == NULL) { 217 *err = ENOMEM; 218 return (NULL); 219 } 220 221 for (arglist[argcount] = strtok(temp_str, whitespace); 222 arglist[argcount] != NULL; /* CSTYLED */) { 223 arglist[++argcount] = strtok(NULL, whitespace); 224 } 225 argcount--; 226 dfstablist = 227 (dfstab_entry_t *)calloc((size_t)1, 228 sizeof (dfstab_entry_t)); 229 if (dfstablist == NULL) { 230 *err = ENOMEM; 231 free(temp_str); 232 return (NULL); 233 } 234 while ((c = getopt(argcount, arglist, "F:d:o:")) != -1) { 235 switch (c) { 236 case 'F': 237 /* file system type */ 238 /* at most one -F */ 239 *err |= (dfstablist->fstype != NULL); 240 dfstablist->fstype = strdup(optarg); 241 if (dfstablist->fstype == NULL) { 242 *err = ENOMEM; 243 free_dfstab_list(dfstablist); 244 free(temp_str); 245 return (NULL); 246 } 247 break; 248 case 'd': /* description */ 249 /* at most one -d */ 250 *err |= (dfstablist->description != NULL); 251 dfstablist->description = strdup(optarg); 252 if (dfstablist->description == NULL) { 253 *err = ENOMEM; 254 free_dfstab_list(dfstablist); 255 free(temp_str); 256 return (NULL); 257 } 258 break; 259 case 'o': /* fs specific options */ 260 /* at most one - o */ 261 *err |= (dfstablist->options != NULL); 262 dfstablist->options = strdup(optarg); 263 if (dfstablist->options == NULL) { 264 *err = ENOMEM; 265 free_dfstab_list(dfstablist); 266 free(temp_str); 267 return (NULL); 268 } 269 break; 270 case '?': 271 *err = 1; 272 break; 273 } 274 } 275 if (dfstablist->fstype == NULL) { 276 FILE *fp; 277 278 if ((fp = fopen(DFSTYPES, "r")) == NULL) { 279 (void) fprintf(stderr, "%s: cannot open %s\n", 280 cmd, DFSTYPES); 281 free_dfstab_list(dfstablist); 282 free(temp_str); 283 return (NULL); 284 } 285 (void) mutex_lock(&dfstab_lock); 286 dfstablist->fstype = strdup(fileutil_getfs(fp)); 287 (void) mutex_unlock(&dfstab_lock); 288 fclose(fp); 289 } 290 dfstablist->path = strdup(arglist[argcount]); 291 if (dfstablist->path == NULL) { 292 *err = ENOMEM; 293 free_dfstab_list(dfstablist); 294 free(temp_str); 295 return (NULL); 296 } 297 free(temp_str); 298 return (dfstablist); 299 } /* dfstab_line_to_dfstab_entry */ 300 301 static dfstab_entry_t * 302 change_dfstab_ent( 303 dfstab_entry_t *old_entry, 304 dfstab_entry_t *new_entry, 305 int *err) 306 { 307 308 FILE *fp; 309 dfstab_entry_t *temp_list, *ret_val; 310 char cmd[BUFSIZE]; 311 char **temp_dfstab = NULL; 312 int line_found = 0; 313 314 if ((fp = fopen(DFSTAB, "r")) != NULL) { 315 char *share_cmd; 316 int count = 0; 317 (void) mutex_lock(&dfstab_lock); 318 while (fgets(cmd, BUFSIZE, fp) != NULL) { 319 if ((share_cmd = 320 fileutil_get_cmd_from_string(cmd)) == NULL) { 321 if (!fileutil_add_string_to_array( 322 &temp_dfstab, cmd, &count, err)) { 323 ret_val = NULL; 324 line_found = 0; 325 break; 326 } 327 continue; 328 } 329 if ((temp_list = 330 dfstab_line_to_dfstab_entry(share_cmd, err)) == 331 NULL) { 332 free(share_cmd); 333 ret_val = NULL; 334 break; 335 } 336 if (strcmp(old_entry->path, 337 temp_list->path) == 0) { 338 char *new_cmd = NULL; 339 line_found = 1; 340 if (new_entry != NULL && (new_cmd = 341 create_share_cmd(new_entry, cmd, 342 err)) != NULL) { 343 if (!fileutil_add_string_to_array( 344 &temp_dfstab, new_cmd, &count, 345 err)) { 346 ret_val = NULL; 347 line_found = 0; 348 free(share_cmd); 349 free(new_cmd); 350 break; 351 } 352 free(new_cmd); 353 } 354 } else { 355 if (!fileutil_add_string_to_array( 356 &temp_dfstab, cmd, &count, err)) { 357 free(share_cmd); 358 ret_val = NULL; 359 line_found = 0; 360 break; 361 } 362 } 363 free_dfstab_list(temp_list); 364 free(share_cmd); 365 } 366 fclose(fp); 367 368 if (line_found && temp_dfstab != NULL) { 369 if ((fp = fopen(DFSTAB, "w")) != NULL) { 370 int i; 371 for (i = 0; i < count; i++) { 372 fprintf(fp, "%s", temp_dfstab[i]); 373 } 374 fclose(fp); 375 (void) mutex_unlock(&dfstab_lock); 376 ret_val = get_dfstab_ents(err); 377 fileutil_free_string_array(temp_dfstab, count); 378 } else { 379 *err = errno; 380 (void) mutex_unlock(&dfstab_lock); 381 fileutil_free_string_array(temp_dfstab, count); 382 ret_val = NULL; 383 } 384 } else { 385 (void) mutex_unlock(&dfstab_lock); 386 if (temp_dfstab != NULL) { 387 fileutil_free_string_array(temp_dfstab, count); 388 } 389 ret_val = NULL; 390 } 391 } else { 392 *err = errno; 393 ret_val = NULL; 394 } 395 return (ret_val); 396 } /* change_dfstab_ent */ 397 398 /* 399 * Public accessor functions. 400 */ 401 402 /* 403 * fs_add_DFStab_ent - adds an entry to dfstab and to the list of dfstab 404 * entries. Returns a pointer to the head of the dfstab entry list. 405 * Parameters: 406 * char *cmd - the same command to be added to dstab 407 * int *err - an error pointer for retruning any errors 408 */ 409 fs_dfstab_entry_t 410 fs_add_DFStab_ent(char *cmd, int *err) 411 { 412 dfstab_entry_t *dfstab_ent; 413 414 dfstab_ent = dfstab_line_to_dfstab_entry(cmd, err); 415 if (dfstab_ent == NULL) { 416 *err = errno; 417 return (NULL); 418 } 419 add_entry_to_dfstab(dfstab_ent, err); 420 if (*err != 0) { 421 free_dfstab_list(dfstab_ent); 422 return (NULL); 423 } 424 free_dfstab_list(dfstab_ent); 425 return (get_dfstab_ents(err)); 426 } 427 428 /* 429 * set_DFStab_ent - adds an entry to dfstab and to the list of dfstab entries. 430 * returns a pointer to the head of the dfstab entry list. 431 */ 432 fs_dfstab_entry_t 433 fs_set_DFStab_ent( 434 char *path, 435 char *fstype, 436 char *options, 437 char *description, 438 int *err) 439 { 440 441 dfstab_entry_t *new_entry; 442 new_entry = (dfstab_entry_t *)calloc((size_t)1, 443 sizeof (dfstab_entry_t)); 444 if (new_entry == NULL) { 445 *err = ENOMEM; 446 return (NULL); 447 } 448 if (path != NULL) { 449 new_entry->path = strdup(path); 450 } else { 451 *err = EINVAL; 452 free_dfstab_list(new_entry); 453 return (NULL); 454 } 455 if (fstype != NULL) { 456 new_entry->fstype = strdup(fstype); 457 } else { 458 FILE *fp; 459 460 if ((fp = fopen(DFSTYPES, "r")) == NULL) { 461 /* change this to error handler */ 462 (void) fprintf(stderr, "cannot open %s\n", 463 DFSTYPES); 464 free_dfstab_list(new_entry); 465 return (NULL); 466 } 467 (void) mutex_lock(&dfstab_lock); 468 new_entry->fstype = strdup(fileutil_getfs(fp)); 469 (void) mutex_unlock(&dfstab_lock); 470 fclose(fp); 471 } 472 if (options != NULL) { 473 new_entry->options = strdup(options); 474 } 475 if (description != NULL) { 476 new_entry->description = strdup(description); 477 } 478 add_entry_to_dfstab(new_entry, err); 479 if (*err != 0) { 480 free_dfstab_list(new_entry); 481 return (NULL); 482 } 483 free_dfstab_list(new_entry); 484 return (get_dfstab_ents(err)); 485 } /* set_DFStab_ent */ 486 487 /* 488 * Accessor function for path element of dfstab entry. 489 */ 490 char * 491 fs_get_DFStab_ent_Path(void *entry) 492 { 493 dfstab_entry_t *entryptr = (dfstab_entry_t *)entry; 494 if (entryptr == NULL) { 495 return (NULL); 496 } 497 return (entryptr->path); 498 } /* get_DFStab_ent_Path */ 499 500 /* 501 * Accessor function for fstype element of dfstab entry. 502 */ 503 char * 504 fs_get_DFStab_ent_Fstype(void *entry) 505 { 506 dfstab_entry_t *entryptr = (dfstab_entry_t *)entry; 507 if (entryptr == NULL) { 508 return (NULL); 509 } 510 return (entryptr->fstype); 511 } 512 513 /* 514 * Accessor function for options element of dfstab entry. 515 */ 516 char * 517 fs_get_DFStab_ent_Options(void *entry) 518 { 519 dfstab_entry_t *entryptr = (dfstab_entry_t *)entry; 520 if (entryptr == NULL) { 521 return (NULL); 522 } 523 return (entryptr->options); 524 } 525 526 /* 527 * Accessor function for description element of dfstab entry. 528 */ 529 char * 530 fs_get_DFStab_ent_Desc(void *entry) 531 { 532 dfstab_entry_t *entryptr = (dfstab_entry_t *)entry; 533 if (entryptr == NULL) { 534 return (NULL); 535 } 536 return (entryptr->description); 537 } 538 539 /* 540 * Accessor function for resource element of dfstab entry. 541 */ 542 char * 543 fs_get_DFStab_ent_Res(void *entry) 544 { 545 dfstab_entry_t *entryptr = (dfstab_entry_t *)entry; 546 if (entryptr == NULL) { 547 return (NULL); 548 } 549 return (entryptr->resource); 550 } 551 552 553 /* 554 * Calls get_dfstab_ents to create the list of dfstab 555 * entries and returns that list. 556 */ 557 fs_dfstab_entry_t 558 fs_get_DFStab_ents(int *err) 559 { 560 dfstab_entry_t *list; 561 list = get_dfstab_ents(err); 562 return (list); 563 } 564 565 /* 566 * Retrives and returns the next entry in the list. 567 */ 568 fs_dfstab_entry_t 569 fs_get_DFStab_ent_Next(void *list) 570 { 571 dfstab_entry_t *listptr = (dfstab_entry_t *)list; 572 if (listptr == NULL) { 573 return (NULL); 574 } 575 return (listptr->next); 576 } 577 578 /* 579 * Retrives and returns a share command based on the dfstab entry passed in. 580 */ 581 char * 582 fs_get_Dfstab_share_cmd(fs_dfstab_entry_t dfstab_ent, int *err) 583 { 584 char *share_cmd; 585 if (dfstab_ent == NULL) { 586 return (NULL); 587 } 588 share_cmd = create_share_cmd((dfstab_entry_t *)dfstab_ent, NULL, err); 589 return (share_cmd); 590 } /* fs_get_Dfstab_share_cmd */ 591 592 /* 593 * edit_DFStab_ent - changes an entry in dfstab. 594 */ 595 fs_dfstab_entry_t 596 fs_edit_DFStab_ent(char *old_cmd, char *new_cmd, int *err) 597 { 598 dfstab_entry_t *old_dfstabent, *new_dfstabent, *ret_val; 599 600 if ((old_dfstabent = 601 dfstab_line_to_dfstab_entry(old_cmd, err)) == NULL) { 602 return (NULL); 603 } 604 if ((new_dfstabent = 605 dfstab_line_to_dfstab_entry(new_cmd, err)) == NULL) { 606 return (NULL); 607 } 608 if ((ret_val = 609 change_dfstab_ent(old_dfstabent, new_dfstabent, err)) == NULL) { 610 return (NULL); 611 } 612 free_dfstab_list(old_dfstabent); 613 free_dfstab_list(new_dfstabent); 614 return (ret_val); 615 } 616 617 /* 618 * del_DFStab_ent - deletes an entry in dfstab. 619 */ 620 fs_dfstab_entry_t 621 fs_del_DFStab_ent(char *del_cmd, int *err) 622 { 623 dfstab_entry_t *del_dfstabent, *ret_val; 624 625 if ((del_dfstabent = 626 dfstab_line_to_dfstab_entry(del_cmd, err)) == NULL) { 627 return (NULL); 628 } 629 if ((ret_val = 630 change_dfstab_ent(del_dfstabent, NULL, err)) == NULL) { 631 return (NULL); 632 } 633 free_dfstab_list(del_dfstabent); 634 return (ret_val); 635 } 636 637 /* 638 * del_All_DFStab_ents_with_Path - deletes all duplicate entries with 639 * the specified path. 640 */ 641 fs_dfstab_entry_t 642 fs_del_All_DFStab_ents_with_Path(char *path, int *err) 643 { 644 dfstab_entry_t del_dfstabent, *ret_val; 645 646 if (path != NULL) { 647 if ((del_dfstabent.path = strdup(path)) != NULL) { 648 if ((ret_val = change_dfstab_ent(&del_dfstabent, 649 NULL, err)) == NULL) { 650 ret_val = NULL; 651 } 652 free(del_dfstabent.path); 653 } else { 654 *err = ENOMEM; 655 ret_val = NULL; 656 } 657 } else { 658 *err = EINVAL; 659 ret_val = NULL; 660 } 661 return (ret_val); 662 } 663 664 665 int 666 fs_check_for_duplicate_DFStab_paths(char *path, int *err) 667 { 668 dfstab_entry_t *dfstablist; 669 int count = 0; 670 671 *err = 0; 672 if (path == NULL) { 673 count = -1; 674 } 675 dfstablist = get_dfstab_ents(err); 676 if (dfstablist != NULL) { 677 while (dfstablist != NULL) { 678 if (strcmp(dfstablist->path, path) == 0) { 679 count++; 680 } 681 dfstablist = dfstablist->next; 682 } 683 684 free_dfstab_list(dfstablist); 685 } else { 686 if (err != 0) 687 count = *err; 688 else 689 count = 0; 690 } 691 return (count); 692 } 693 694 void 695 fs_free_DFStab_ents(void *list) 696 { 697 dfstab_entry_t *headp = (dfstab_entry_t *)list; 698 free_dfstab_list(headp); 699 } 700 701 /* 702 * used for debugging only 703 */ 704 void 705 fs_print_dfstab_entries(void *list) 706 { 707 while (list != NULL) { 708 709 if (fs_get_DFStab_ent_Fstype(list) != NULL) 710 printf("fstype: %s", fs_get_DFStab_ent_Fstype(list)); 711 if (fs_get_DFStab_ent_Desc(list) != NULL) 712 printf(" description: %s", 713 fs_get_DFStab_ent_Desc(list)); 714 if (fs_get_DFStab_ent_Options(list) != NULL) 715 printf(" options: %s", 716 fs_get_DFStab_ent_Options(list)); 717 if (fs_get_DFStab_ent_Path(list) != NULL) 718 printf(" shared path is: %s\n", 719 fs_get_DFStab_ent_Path(list)); 720 list = (void *)fs_get_DFStab_ent_Next(list); 721 } 722 723 } 724