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