xref: /illumos-gate/usr/src/lib/libfsmgt/common/fs_dfstab.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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