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