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 *
get_dfstab_ents(int * err)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
add_entry_to_dfstab(dfstab_entry_t * list,int * err)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
free_dfstab_list(dfstab_entry_t * headp)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 *
create_share_cmd(dfstab_entry_t * new_entry,char * temp_line,int * err)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 *
dfstab_line_to_dfstab_entry(char * cmd,int * err)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 *
change_dfstab_ent(dfstab_entry_t * old_entry,dfstab_entry_t * new_entry,int * err)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
fs_add_DFStab_ent(char * cmd,int * err)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
fs_set_DFStab_ent(char * path,char * fstype,char * options,char * description,int * err)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 *
fs_get_DFStab_ent_Path(void * entry)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 *
fs_get_DFStab_ent_Fstype(void * entry)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 *
fs_get_DFStab_ent_Options(void * entry)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 *
fs_get_DFStab_ent_Desc(void * entry)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 *
fs_get_DFStab_ent_Res(void * entry)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
fs_get_DFStab_ents(int * err)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
fs_get_DFStab_ent_Next(void * list)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 *
fs_get_Dfstab_share_cmd(fs_dfstab_entry_t dfstab_ent,int * err)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
fs_edit_DFStab_ent(char * old_cmd,char * new_cmd,int * err)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
fs_del_DFStab_ent(char * del_cmd,int * err)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
fs_del_All_DFStab_ents_with_Path(char * path,int * err)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
fs_check_for_duplicate_DFStab_paths(char * path,int * err)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
fs_free_DFStab_ents(void * list)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
fs_print_dfstab_entries(void * list)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