xref: /illumos-gate/usr/src/lib/libfsmgt/common/fs_mount_defaults.c (revision 012e6ce759c490003aed29439cc47d3d73a99ad3)
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 /*
28  * Traverses /etc/vfstab in order to find default mount information about
29  * file systems on the current host.
30  */
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <sys/vfstab.h>
35 #include <sys/types.h>
36 #include <strings.h>
37 #include <thread.h>
38 #include <synch.h>
39 #include "libfsmgt.h"
40 
41 /*
42  * Private constants
43  */
44 
45 static const char sepstr[] = "\t\n";
46 
47 /*
48  * Private variables
49  */
50 static mutex_t		vfstab_lock = DEFAULTMUTEX;
51 
52 
53 /*
54  * Private method declarations
55  */
56 static int cmp_fields(char *, char *, int);
57 static fs_mntdefaults_t	*create_mntdefaults_entry(struct vfstab vfstab_entry,
58 					    int *errp);
59 static struct vfstab	*create_vfstab_filter(fs_mntdefaults_t *filter,
60 					    int *errp);
61 static void		free_vfstab_entry(struct vfstab *vfstab_entry);
62 static char		*create_vfstab_entry_line(struct vfstab *, int *);
63 static int		vfstab_line_cmp(fs_mntdefaults_t *, struct vfstab *);
64 
65 /*
66  * Public methods
67  */
68 
69 void fs_free_mntdefaults_list(fs_mntdefaults_t *headp) {
70 	fs_mntdefaults_t	*tmp;
71 
72 	while (headp != NULL) {
73 		tmp = headp->next;
74 		free(headp->resource);
75 		free(headp->fsckdevice);
76 		free(headp->mountp);
77 		free(headp->fstype);
78 		free(headp->fsckpass);
79 		free(headp->mountatboot);
80 		free(headp->mntopts);
81 		headp->next = NULL;
82 		free(headp);
83 
84 		headp = tmp;
85 	}
86 } /* fs_free_mntdefaults_list */
87 
88 /*
89  * Filter by the fields that are filled in on the filter parameter.
90  * Fields that aren't used in filtering the defaults will be NULL.
91  */
92 fs_mntdefaults_t *fs_get_filtered_mount_defaults(fs_mntdefaults_t *filter,
93     int *errp) {
94 
95 	fs_mntdefaults_t	*newp;
96 	fs_mntdefaults_t	*headp;
97 	fs_mntdefaults_t	*tailp;
98 	FILE			*fp;
99 
100 	headp = NULL;
101 	tailp = NULL;
102 
103 
104 	if ((fp = fopen(VFSTAB, "r")) != NULL) {
105 		struct vfstab	vfstab_entry;
106 		struct vfstab	*search_entry;
107 		(void) mutex_lock(&vfstab_lock);
108 		search_entry = create_vfstab_filter(filter, errp);
109 		if (search_entry == NULL) {
110 			/*
111 			 * Out of memory, the error pointer (errp) gets
112 			 * set in create_vfstab_filter.
113 			 */
114 			fs_free_mntdefaults_list(headp);
115 			(void) mutex_unlock(&vfstab_lock);
116 			(void) fclose(fp);
117 			return (NULL);
118 		}
119 
120 		while (getvfsany(fp, &vfstab_entry, search_entry) == 0) {
121 			/*
122 			 * Add to list to be returned
123 			 */
124 			newp = create_mntdefaults_entry(vfstab_entry, errp);
125 			if (newp == NULL) {
126 				/*
127 				 * Out of memory, the error pointer (errp)
128 				 * gets set in create_mntdefaults_entry.
129 				 */
130 				fs_free_mntdefaults_list(headp);
131 				(void) mutex_unlock(&vfstab_lock);
132 				(void) fclose(fp);
133 				return (NULL);
134 			}
135 
136 			if (headp == NULL) {
137 				headp = newp;
138 				tailp = newp;
139 			} else {
140 				tailp->next = newp;
141 				tailp = newp;
142 			}
143 		}
144 		free_vfstab_entry(search_entry);
145 		(void) mutex_unlock(&vfstab_lock);
146 		(void) fclose(fp);
147 
148 	} else {
149 		*errp = errno;
150 	} /* if ((fp = fopen(VFSTAB, "r")) != NULL) */
151 
152 	return (headp);
153 } /* fs_get_filtered_mount_defaults */
154 
155 
156 fs_mntdefaults_t *
157 fs_get_mount_defaults(int *errp)
158 {
159 	fs_mntdefaults_t	*newp;
160 	fs_mntdefaults_t	*headp;
161 	fs_mntdefaults_t	*tailp;
162 	FILE			*fp;
163 
164 	headp = NULL;
165 	tailp = NULL;
166 
167 	if ((fp = fopen(VFSTAB, "r")) != NULL) {
168 		struct vfstab 	vfstab_entry;
169 		(void) mutex_lock(&vfstab_lock);
170 		while (getvfsent(fp, &vfstab_entry) == 0) {
171 			/*
172 			 * Add entry to list
173 			 */
174 			newp = create_mntdefaults_entry(vfstab_entry, errp);
175 
176 			if (newp == NULL) {
177 				/*
178 				 * Out of memory, the error pointer (errp)
179 				 * gets set in create_mntdefaults_entry.
180 				 */
181 				(void) fclose(fp);
182 				(void) mutex_unlock(&vfstab_lock);
183 				fs_free_mntdefaults_list(headp);
184 				return (NULL);
185 			}
186 
187 			if (headp == NULL) {
188 				headp = newp;
189 				tailp = newp;
190 			} else {
191 				tailp->next = newp;
192 				tailp = newp;
193 			}
194 		}
195 		(void) fclose(fp);
196 		(void) mutex_unlock(&vfstab_lock);
197 	} else {
198 		*errp = errno;
199 	} /* if ((fp = fopen(VFSTAB, "r")) != NULL) */
200 
201 	/*
202 	 * Caller must free the returned list
203 	 */
204 	return (headp);
205 
206 } /* fs_get_mount_defaults */
207 
208 fs_mntdefaults_t *
209 fs_add_mount_default(fs_mntdefaults_t *newp, int *errp) {
210 
211 	FILE *fp;
212 	struct vfstab *new_entry;
213 	fs_mntdefaults_t *ret_val;
214 
215 	new_entry = create_vfstab_filter(newp, errp);
216 	if (new_entry != NULL) {
217 		if ((fp = fopen(VFSTAB, "a")) != NULL) {
218 			(void) mutex_lock(&vfstab_lock);
219 			putvfsent(fp, new_entry);
220 			free_vfstab_entry(new_entry);
221 			(void) fclose(fp);
222 			(void) mutex_unlock(&vfstab_lock);
223 			ret_val = fs_get_mount_defaults(errp);
224 		} else {
225 			*errp = errno;
226 			free_vfstab_entry(new_entry);
227 			ret_val = NULL;
228 		}
229 	} else {
230 		ret_val = NULL;
231 	}
232 	return (ret_val);
233 } /* fs_add_mount_default */
234 
235 
236 fs_mntdefaults_t *
237 fs_edit_mount_defaults(
238     fs_mntdefaults_t *old_vfstab_ent,
239     fs_mntdefaults_t *new_vfstab_ent,
240     int *errp)
241 {
242 	FILE *fp;
243 	fs_mntdefaults_t *ret_val;
244 	char vfstab_line[VFS_LINE_MAX];
245 	char **temp_vfstab = NULL;
246 	char *new_line;
247 	struct vfstab vfstabp, *new_vfstab;
248 	int line_found = 0;
249 
250 	if ((fp = fopen(VFSTAB, "r")) != NULL) {
251 		char *tmp;
252 		int count = 0;
253 		(void) mutex_lock(&vfstab_lock);
254 		while (fgets(vfstab_line, VFS_LINE_MAX, fp) != NULL) {
255 			char *charp;
256 			struct vfstab *vp;
257 			char *orig_line = strdup(vfstab_line);
258 			if (orig_line == NULL) {
259 				*errp = ENOMEM;
260 				(void) fclose(fp);
261 				(void) mutex_unlock(&vfstab_lock);
262 				return (NULL);
263 			}
264 			vp = &vfstabp;
265 			for (charp = vfstab_line;
266 			    *charp == ' ' || *charp == '\t'; charp++);
267 			if (*charp == '#' || *charp == '\n') {
268 				/*
269 				 * Write comments out to temp vfstab
270 				 * image
271 				 */
272 				if (!fileutil_add_string_to_array(
273 				    &temp_vfstab, vfstab_line, &count, errp)) {
274 				    ret_val = NULL;
275 				    line_found = 0;
276 					break;
277 				}
278 				continue;
279 			}
280 			vp->vfs_special = (char *)strtok_r(
281 			    vfstab_line, sepstr, &tmp);
282 			vp->vfs_fsckdev = (char *)strtok_r(
283 			    NULL, sepstr, &tmp);
284 			vp->vfs_mountp = (char *)strtok_r(
285 			    NULL, sepstr, &tmp);
286 			vp->vfs_fstype = (char *)strtok_r(
287 			    NULL, sepstr, &tmp);
288 			vp->vfs_fsckpass = (char *)strtok_r(
289 			    NULL, sepstr, &tmp);
290 			vp->vfs_automnt = (char *)strtok_r(
291 			    NULL, sepstr, &tmp);
292 			vp->vfs_mntopts = (char *)strtok_r(
293 			    NULL, sepstr, &tmp);
294 			if (strtok_r(NULL, sepstr, &tmp) != NULL) {
295 				/*
296 				 * Invalid vfstab line.
297 				 */
298 				*errp = EINVAL;
299 				(void) mutex_unlock(&vfstab_lock);
300 				(void) fclose(fp);
301 				return (NULL);
302 			}
303 
304 			if (vfstab_line_cmp(old_vfstab_ent, vp)) {
305 				line_found = 1;
306 				new_vfstab =
307 				    create_vfstab_filter(
308 				    new_vfstab_ent, errp);
309 				new_line =
310 				    create_vfstab_entry_line(new_vfstab, errp);
311 				if (!fileutil_add_string_to_array(
312 				    &temp_vfstab, new_line, &count, errp)) {
313 					ret_val = NULL;
314 					line_found = 0;
315 					free(new_line);
316 					break;
317 				}
318 				free(new_line);
319 			} else {
320 				if (!fileutil_add_string_to_array(
321 				    &temp_vfstab, orig_line, &count, errp)) {
322 					ret_val = NULL;
323 					line_found = 0;
324 					break;
325 				}
326 			}
327 			free(orig_line);
328 		}
329 		(void) fclose(fp);
330 
331 		if (line_found && temp_vfstab != NULL) {
332 			if ((fp = fopen(VFSTAB, "w")) != NULL) {
333 				int i;
334 				for (i = 0; i < count; i++) {
335 					fprintf(fp, "%s", temp_vfstab[i]);
336 				}
337 				(void) fclose(fp);
338 				(void) mutex_unlock(&vfstab_lock);
339 				ret_val = fs_get_mount_defaults(errp);
340 				fileutil_free_string_array(temp_vfstab, count);
341 			} else {
342 				*errp = errno;
343 				(void) mutex_unlock(&vfstab_lock);
344 				ret_val = NULL;
345 			}
346 		} else {
347 			*errp = errno;
348 			(void) mutex_unlock(&vfstab_lock);
349 			ret_val = NULL;
350 		}
351 	} else {
352 		*errp = errno;
353 		ret_val = NULL;
354 	}
355 	return (ret_val);
356 } /* fs_edit_mount_defaults */
357 
358 fs_mntdefaults_t *
359 fs_del_mount_default_ent(fs_mntdefaults_t *old_vfstab_ent, int *errp)
360 {
361 	FILE *fp;
362 	fs_mntdefaults_t *ret_val;
363 	char vfstab_line[VFS_LINE_MAX];
364 	struct vfstab vfstabp;
365 	int line_found = 0;
366 
367 	if ((fp = fopen(VFSTAB, "r")) != NULL) {
368 		struct vfstab *vp;
369 		char *tmp;
370 		char *charp;
371 		char *orig_line = NULL;
372 		char **temp_vfstab = NULL;
373 		int count = 0;
374 		vp = &vfstabp;
375 		(void) mutex_lock(&vfstab_lock);
376 		while (fgets(vfstab_line, VFS_LINE_MAX, fp) != NULL) {
377 
378 			orig_line = strdup(vfstab_line);
379 			if (orig_line == NULL) {
380 				*errp = ENOMEM;
381 				(void) fclose(fp);
382 				(void) mutex_unlock(&vfstab_lock);
383 				return (NULL);
384 			}
385 
386 			for (charp = vfstab_line;
387 			    *charp == ' ' || *charp == '\t'; charp++);
388 
389 			if (*charp == '#' || *charp == '\n') {
390 				/*
391 				 * Write comments out to temp vfstab
392 				 * image
393 				 */
394 				if (!fileutil_add_string_to_array(
395 				    &temp_vfstab, vfstab_line, &count, errp)) {
396 					ret_val = NULL;
397 					line_found = 0;
398 					free(orig_line);
399 					break;
400 				}
401 				continue;
402 			}
403 
404 			vp->vfs_special = (char *)strtok_r(
405 			    vfstab_line, sepstr, &tmp);
406 			vp->vfs_fsckdev = (char *)strtok_r(
407 			    NULL, sepstr, &tmp);
408 			vp->vfs_mountp = (char *)strtok_r(
409 			    NULL, sepstr, &tmp);
410 			vp->vfs_fstype = (char *)strtok_r(
411 			    NULL, sepstr, &tmp);
412 			vp->vfs_fsckpass = (char *)strtok_r(
413 			    NULL, sepstr, &tmp);
414 			vp->vfs_automnt = (char *)strtok_r(
415 			    NULL, sepstr, &tmp);
416 			vp->vfs_mntopts = (char *)strtok_r(
417 			    NULL, sepstr, &tmp);
418 
419 			if (strtok_r(NULL, sepstr, &tmp) != NULL) {
420 				/*
421 				 * Invalid vfstab line.
422 				 */
423 				*errp = EINVAL;
424 				free(orig_line);
425 				(void) fclose(fp);
426 				(void) mutex_unlock(&vfstab_lock);
427 				return (NULL);
428 			}
429 
430 			if (vfstab_line_cmp(old_vfstab_ent, vp)) {
431 				line_found = 1;
432 			} else {
433 				if (!fileutil_add_string_to_array(
434 				    &temp_vfstab, orig_line, &count, errp)) {
435 					ret_val = NULL;
436 					line_found = 0;
437 					free(orig_line);
438 					break;
439 				}
440 			}
441 			free(orig_line);
442 		}
443 
444 		(void) fclose(fp);
445 
446 		if (line_found && temp_vfstab != NULL) {
447 			if ((fp = fopen(VFSTAB, "w")) != NULL) {
448 				int i;
449 				for (i = 0; i < count; i++) {
450 					fprintf(fp, "%s", temp_vfstab[i]);
451 				}
452 				(void) fclose(fp);
453 				(void) mutex_unlock(&vfstab_lock);
454 				ret_val = fs_get_mount_defaults(errp);
455 				fileutil_free_string_array(temp_vfstab, count);
456 			} else {
457 				*errp = errno;
458 				(void) mutex_unlock(&vfstab_lock);
459 				fileutil_free_string_array(temp_vfstab, count);
460 				ret_val = NULL;
461 			}
462 		} else {
463 			(void) mutex_unlock(&vfstab_lock);
464 			if (temp_vfstab != NULL) {
465 				fileutil_free_string_array(temp_vfstab, count);
466 			}
467 			ret_val = NULL;
468 		}
469 	} else {
470 		*errp = errno;
471 		ret_val = NULL;
472 	}
473 	return (ret_val);
474 }
475 
476 /*
477  * Private methods
478  */
479 
480 static fs_mntdefaults_t *
481 create_mntdefaults_entry(struct vfstab vfstab_entry, int *errp) {
482 	fs_mntdefaults_t	*newp;
483 
484 	newp = (fs_mntdefaults_t *)calloc((size_t)1,
485 	    (size_t)sizeof (fs_mntdefaults_t));
486 
487 	if (newp == NULL) {
488 		/*
489 		 * Out of memory
490 		 */
491 		*errp = errno;
492 		return (NULL);
493 	}
494 
495 
496 	if (vfstab_entry.vfs_special != NULL) {
497 		newp->resource = strdup(vfstab_entry.vfs_special);
498 		if (newp->resource == NULL) {
499 			/*
500 			 * Out of memory
501 			 */
502 			*errp = errno;
503 			fs_free_mntdefaults_list(newp);
504 			return (NULL);
505 		}
506 	}
507 
508 
509 	if (vfstab_entry.vfs_fsckdev != NULL) {
510 		newp->fsckdevice = strdup(vfstab_entry.vfs_fsckdev);
511 		if (newp->fsckdevice == NULL) {
512 			/*
513 			 * Out of memory
514 			 */
515 			*errp = errno;
516 			fs_free_mntdefaults_list(newp);
517 			return (NULL);
518 		}
519 	}
520 
521 	if (vfstab_entry.vfs_mountp != NULL) {
522 		newp->mountp = strdup(vfstab_entry.vfs_mountp);
523 		if (newp->mountp == NULL) {
524 			/*
525 			 * Out of memory
526 			 */
527 			*errp = errno;
528 			fs_free_mntdefaults_list(newp);
529 			return (NULL);
530 		}
531 	}
532 
533 	if (vfstab_entry.vfs_fstype != NULL) {
534 		newp->fstype = strdup(vfstab_entry.vfs_fstype);
535 		if (newp->fstype == NULL) {
536 			/*
537 			 * Out of memory
538 			 */
539 			*errp = errno;
540 			fs_free_mntdefaults_list(newp);
541 			return (NULL);
542 		}
543 	}
544 
545 	if (vfstab_entry.vfs_fsckpass != NULL) {
546 		newp->fsckpass = strdup(vfstab_entry.vfs_fsckpass);
547 		if (newp->fsckpass == NULL) {
548 			/*
549 			 * Out of memory
550 			 */
551 			*errp = errno;
552 			fs_free_mntdefaults_list(newp);
553 			return (NULL);
554 		}
555 	}
556 
557 	if (vfstab_entry.vfs_automnt != NULL) {
558 		newp->mountatboot = strdup(vfstab_entry.vfs_automnt);
559 		if (newp->mountatboot == NULL) {
560 			/*
561 			 * Out of memory
562 			 */
563 			*errp = errno;
564 			fs_free_mntdefaults_list(newp);
565 			return (NULL);
566 		}
567 	}
568 
569 	if (vfstab_entry.vfs_mntopts != NULL) {
570 		newp->mntopts = strdup(vfstab_entry.vfs_mntopts);
571 		if (newp->mntopts == NULL) {
572 			/*
573 			 * Out of memory
574 			 */
575 			*errp = errno;
576 			fs_free_mntdefaults_list(newp);
577 			return (NULL);
578 		}
579 	}
580 	newp->next = NULL;
581 
582 	return (newp);
583 
584 } /* create_mntdefaults_entry */
585 
586 static struct vfstab *
587 create_vfstab_filter(fs_mntdefaults_t *filter, int *errp) {
588 	struct vfstab *search_entry;
589 
590 	search_entry = (struct vfstab *)calloc((size_t)1,
591 	    (size_t)sizeof (struct vfstab));
592 	if (search_entry == NULL) {
593 		/*
594 		 * Out of memory
595 		 */
596 		*errp = errno;
597 		return (NULL);
598 	}
599 
600 	/*
601 	 * Populate the filter criteria
602 	 */
603 	if (filter->resource != NULL) {
604 		search_entry->vfs_special = strdup(filter->resource);
605 		if (search_entry->vfs_special == NULL) {
606 			/*
607 			 * Out of memory
608 			 */
609 			*errp = errno;
610 			free_vfstab_entry(search_entry);
611 			return (NULL);
612 		}
613 
614 	}
615 
616 	if (filter->fsckdevice != NULL) {
617 		search_entry->vfs_fsckdev = strdup(filter->fsckdevice);
618 		if (search_entry->vfs_fsckdev ==  NULL) {
619 			/*
620 			 * Out of memory
621 			 */
622 			*errp = errno;
623 			free_vfstab_entry(search_entry);
624 			return (NULL);
625 		}
626 	}
627 
628 	if (filter->mountp != NULL) {
629 		search_entry->vfs_mountp = strdup(filter->mountp);
630 		if (search_entry->vfs_mountp == NULL) {
631 			/*
632 			 * Out of memory
633 			 */
634 			*errp = errno;
635 			free_vfstab_entry(search_entry);
636 			return (NULL);
637 		}
638 	}
639 
640 	if (filter->fstype != NULL) {
641 		search_entry->vfs_fstype = strdup(filter->fstype);
642 		if (search_entry->vfs_fstype == NULL) {
643 			/*
644 			 * Out of memory
645 			 */
646 			*errp = errno;
647 			free_vfstab_entry(search_entry);
648 			return (NULL);
649 		}
650 	}
651 
652 	if (filter->fsckpass != NULL) {
653 		search_entry->vfs_fsckpass = strdup(filter->fsckpass);
654 		if (search_entry->vfs_fsckpass == NULL) {
655 			/*
656 			 * Out of memory
657 			 */
658 			*errp = errno;
659 			free_vfstab_entry(search_entry);
660 			return (NULL);
661 		}
662 	}
663 
664 	if (filter->mountatboot != NULL) {
665 		search_entry->vfs_automnt = strdup(filter->mountatboot);
666 		if (search_entry->vfs_automnt == NULL) {
667 			/*
668 			 * Out of memory
669 			 */
670 			*errp = errno;
671 			free_vfstab_entry(search_entry);
672 			return (NULL);
673 		}
674 	}
675 
676 	if (filter->mntopts != NULL) {
677 		search_entry->vfs_mntopts = strdup(filter->mntopts);
678 		if (search_entry->vfs_mntopts == NULL) {
679 			/*
680 			 * Out of memory
681 			 */
682 			*errp = errno;
683 			free_vfstab_entry(search_entry);
684 			return (NULL);
685 		}
686 	}
687 
688 	return (search_entry);
689 } /* create_vfstab_filter */
690 
691 static void free_vfstab_entry(struct vfstab *vfstab_entry) {
692 
693 	free(vfstab_entry->vfs_special);
694 	free(vfstab_entry->vfs_fsckdev);
695 	free(vfstab_entry->vfs_mountp);
696 	free(vfstab_entry->vfs_fstype);
697 	free(vfstab_entry->vfs_fsckpass);
698 	free(vfstab_entry->vfs_automnt);
699 	free(vfstab_entry->vfs_mntopts);
700 
701 	free(vfstab_entry);
702 } /* free_vfstab_entry */
703 
704 static int
705 vfstab_line_cmp(fs_mntdefaults_t *mntdftp, struct vfstab *vp) {
706 
707 	int ret_val = 1;
708 
709 	ret_val = cmp_fields(mntdftp->resource, vp->vfs_special, ret_val);
710 	ret_val = cmp_fields(mntdftp->mountp, vp->vfs_mountp, ret_val);
711 
712 	return (ret_val);
713 } /* vfstab_line_cmp */
714 
715 /*
716  * Helper function for comparing fields in a fs_mntdefaults_t to a
717  * vfstab structure. Used in vfstab_line_cmp().
718  */
719 static int
720 cmp_fields(char *mntdflt_str, char *vfstab_str, int ret_val) {
721 	if (ret_val != 0) {
722 		if (mntdflt_str != NULL && vfstab_str != NULL) {
723 			if (strcmp(mntdflt_str, vfstab_str) != 0) {
724 				ret_val = 0;
725 			}
726 		} else if (mntdflt_str == NULL || vfstab_str == NULL) {
727 			ret_val = 0;
728 		}
729 	}
730 	return (ret_val);
731 } /* cmp_fields */
732 
733 /*
734  * Helper fuction used by del_vfstab_ent() and edit_vfstab_ent() to
735  * create a vfstab line for writing out to the vfstab file.
736  */
737 char *
738 create_vfstab_entry_line(struct vfstab *vfstab_ent, int *errp) {
739 	char *line;
740 	int line_length;
741 	line_length = (
742 	    (vfstab_ent->vfs_special ?
743 		(strlen(vfstab_ent->vfs_special) +1) : 2) +
744 	    (vfstab_ent->vfs_fsckdev ?
745 		(strlen(vfstab_ent->vfs_fsckdev) +1) : 2) +
746 	    (vfstab_ent->vfs_mountp ?
747 		(strlen(vfstab_ent->vfs_mountp) +1) : 2) +
748 	    (vfstab_ent->vfs_fstype ?
749 		(strlen(vfstab_ent->vfs_fstype) +1) : 2) +
750 	    (vfstab_ent->vfs_fsckpass ?
751 		(strlen(vfstab_ent->vfs_fsckpass) +1) : 2) +
752 	    (vfstab_ent->vfs_automnt ?
753 		(strlen(vfstab_ent->vfs_automnt) +1) : 2) +
754 	    (vfstab_ent->vfs_mntopts ?
755 		(strlen(vfstab_ent->vfs_mntopts) +1) : 2));
756 	line = (char *)malloc(line_length + 1);
757 	if (line != NULL) {
758 		sprintf(line, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
759 		    vfstab_ent->vfs_special ? vfstab_ent->vfs_special : "-",
760 		    vfstab_ent->vfs_fsckdev ? vfstab_ent->vfs_fsckdev : "-",
761 		    vfstab_ent->vfs_mountp ? vfstab_ent->vfs_mountp : "-",
762 		    vfstab_ent->vfs_fstype ? vfstab_ent->vfs_fstype : "-",
763 		    vfstab_ent->vfs_fsckpass ? vfstab_ent->vfs_fsckpass : "-",
764 		    vfstab_ent->vfs_automnt ? vfstab_ent->vfs_automnt : "-",
765 		    vfstab_ent->vfs_mntopts ? vfstab_ent->vfs_mntopts : "-");
766 	} else {
767 		*errp = errno;
768 	}
769 	return (line);
770 } /* create_vfstab_entry_line */
771