16185db85Sdougm /*
26185db85Sdougm  * CDDL HEADER START
36185db85Sdougm  *
46185db85Sdougm  * The contents of this file are subject to the terms of the
56185db85Sdougm  * Common Development and Distribution License (the "License").
66185db85Sdougm  * You may not use this file except in compliance with the License.
76185db85Sdougm  *
86185db85Sdougm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96185db85Sdougm  * or http://www.opensolaris.org/os/licensing.
106185db85Sdougm  * See the License for the specific language governing permissions
116185db85Sdougm  * and limitations under the License.
126185db85Sdougm  *
136185db85Sdougm  * When distributing Covered Code, include this CDDL HEADER in each
146185db85Sdougm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156185db85Sdougm  * If applicable, add the following below this CDDL HEADER, with the
166185db85Sdougm  * fields enclosed by brackets "[]" replaced with your own identifying
176185db85Sdougm  * information: Portions Copyright [yyyy] [name of copyright owner]
186185db85Sdougm  *
196185db85Sdougm  * CDDL HEADER END
206185db85Sdougm  */
216185db85Sdougm 
226185db85Sdougm /*
23148c5f43SAlan Wright  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
245cb0d679SMarcel Telka  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
2509c9e6dcSChris Williamson  * Copyright (c) 2016 by Delphix. All rights reserved.
266185db85Sdougm  */
276185db85Sdougm 
286185db85Sdougm /*
296185db85Sdougm  * core library for common functions across all config store types
306185db85Sdougm  * and file systems to be exported. This includes legacy dfstab/sharetab
316185db85Sdougm  * parsing. Need to eliminate XML where possible.
326185db85Sdougm  */
336185db85Sdougm 
346185db85Sdougm #include <stdio.h>
356185db85Sdougm #include <string.h>
366185db85Sdougm #include <ctype.h>
376185db85Sdougm #include <unistd.h>
386185db85Sdougm #include <limits.h>
396185db85Sdougm #include <errno.h>
406185db85Sdougm #include <sys/types.h>
416185db85Sdougm #include <sys/stat.h>
426185db85Sdougm #include <libxml/parser.h>
436185db85Sdougm #include <libxml/tree.h>
446185db85Sdougm #include "libshare.h"
456185db85Sdougm #include "libshare_impl.h"
466185db85Sdougm #include <fcntl.h>
478d7e4166Sjose borrego #include <thread.h>
486185db85Sdougm #include <grp.h>
496185db85Sdougm #include <limits.h>
506185db85Sdougm #include <sys/param.h>
516185db85Sdougm #include <signal.h>
526185db85Sdougm #include <libintl.h>
53da6c28aaSamw #include <dirent.h>
546185db85Sdougm 
55a237e38eSth #include <sharefs/share.h>
566185db85Sdougm #include "sharetab.h"
576185db85Sdougm 
586185db85Sdougm #define	DFSTAB_NOTICE_LINES	5
596185db85Sdougm static char *notice[DFSTAB_NOTICE_LINES] =	{
606185db85Sdougm 	"# Do not modify this file directly.\n",
616185db85Sdougm 	"# Use the sharemgr(1m) command for all share management\n",
626185db85Sdougm 	"# This file is reconstructed and only maintained for backward\n",
636185db85Sdougm 	"# compatibility. Configuration lines could be lost.\n",
646185db85Sdougm 	"#\n"
656185db85Sdougm };
666185db85Sdougm 
676185db85Sdougm #define	STRNCAT(x, y, z)	(xmlChar *)strncat((char *)x, (char *)y, z)
686185db85Sdougm 
696185db85Sdougm /* will be much smaller, but this handles bad syntax in the file */
706185db85Sdougm #define	MAXARGSFORSHARE	256
716185db85Sdougm 
728d7e4166Sjose borrego static mutex_t sharetab_lock = DEFAULTMUTEX;
73148c5f43SAlan Wright extern mutex_t sa_dfstab_lock;
748d7e4166Sjose borrego 
756185db85Sdougm /* used internally only */
766185db85Sdougm typedef
776185db85Sdougm struct sharelist {
786185db85Sdougm     struct sharelist *next;
796185db85Sdougm     int   persist;
806185db85Sdougm     char *path;
816185db85Sdougm     char *resource;
826185db85Sdougm     char *fstype;
836185db85Sdougm     char *options;
846185db85Sdougm     char *description;
856185db85Sdougm     char *group;
866185db85Sdougm     char *origline;
876185db85Sdougm     int lineno;
886185db85Sdougm } xfs_sharelist_t;
89549ec3ffSdougm static void parse_dfstab(sa_handle_t, char *, xmlNodePtr);
908d7e4166Sjose borrego extern char *_sa_get_token(char *);
916185db85Sdougm static void dfs_free_list(xfs_sharelist_t *);
926185db85Sdougm /* prototypes */
93549ec3ffSdougm void getlegacyconfig(sa_handle_t, char *, xmlNodePtr *);
94da6c28aaSamw extern sa_share_t _sa_add_share(sa_group_t, char *, int, int *, uint64_t);
95549ec3ffSdougm extern sa_group_t _sa_create_group(sa_handle_impl_t, char *);
966185db85Sdougm static void outdfstab(FILE *, xfs_sharelist_t *);
976185db85Sdougm extern int _sa_remove_optionset(sa_optionset_t);
986185db85Sdougm extern int set_node_share(void *, char *, char *);
996185db85Sdougm extern void set_node_attr(void *, char *, char *);
1006185db85Sdougm 
101a99982a7Sdougm /*
102a99982a7Sdougm  * sablocksigs(*sigs)
103a99982a7Sdougm  *
104a99982a7Sdougm  * block important signals for a critical region. Arg is a pointer to
105a99982a7Sdougm  * a sigset_t that is used later for the unblock.
106a99982a7Sdougm  */
107a99982a7Sdougm void
sablocksigs(sigset_t * sigs)108a99982a7Sdougm sablocksigs(sigset_t *sigs)
109a99982a7Sdougm {
110a99982a7Sdougm 	sigset_t new;
111a99982a7Sdougm 
112a99982a7Sdougm 	if (sigs != NULL) {
11325a68471Sdougm 		(void) sigprocmask(SIG_BLOCK, NULL, &new);
11425a68471Sdougm 		(void) sigaddset(&new, SIGHUP);
11525a68471Sdougm 		(void) sigaddset(&new, SIGINT);
11625a68471Sdougm 		(void) sigaddset(&new, SIGQUIT);
11725a68471Sdougm 		(void) sigaddset(&new, SIGTSTP);
11825a68471Sdougm 		(void) sigprocmask(SIG_SETMASK, &new, sigs);
119a99982a7Sdougm 	}
120a99982a7Sdougm }
121a99982a7Sdougm 
122a99982a7Sdougm /*
123a99982a7Sdougm  * saunblocksigs(*sigs)
124a99982a7Sdougm  *
125a99982a7Sdougm  * unblock previously blocked signals from the sigs arg.
126a99982a7Sdougm  */
127a99982a7Sdougm void
saunblocksigs(sigset_t * sigs)128a99982a7Sdougm saunblocksigs(sigset_t *sigs)
129a99982a7Sdougm {
130a99982a7Sdougm 	if (sigs != NULL)
13125a68471Sdougm 		(void) sigprocmask(SIG_SETMASK, sigs, NULL);
132a99982a7Sdougm }
133a99982a7Sdougm 
1346185db85Sdougm /*
1356185db85Sdougm  * alloc_sharelist()
1366185db85Sdougm  *
1376185db85Sdougm  * allocator function to return an zfs_sharelist_t
1386185db85Sdougm  */
1396185db85Sdougm 
1406185db85Sdougm static xfs_sharelist_t *
alloc_sharelist()1416185db85Sdougm alloc_sharelist()
1426185db85Sdougm {
1436185db85Sdougm 	xfs_sharelist_t *item;
1446185db85Sdougm 
1456185db85Sdougm 	item = (xfs_sharelist_t *)malloc(sizeof (xfs_sharelist_t));
1466185db85Sdougm 	if (item != NULL)
14725a68471Sdougm 		(void) memset(item, '\0', sizeof (xfs_sharelist_t));
1486185db85Sdougm 	return (item);
1496185db85Sdougm }
1506185db85Sdougm 
1516185db85Sdougm /*
1526185db85Sdougm  * fix_notice(list)
1536185db85Sdougm  *
1546185db85Sdougm  * Look at the beginning of the current /etc/dfs/dfstab file and add
1556185db85Sdougm  * the do not modify notice if it doesn't exist.
1566185db85Sdougm  */
1576185db85Sdougm 
1586185db85Sdougm static xfs_sharelist_t *
fix_notice(xfs_sharelist_t * list)1596185db85Sdougm fix_notice(xfs_sharelist_t *list)
1606185db85Sdougm {
1616185db85Sdougm 	xfs_sharelist_t *item, *prev;
1626185db85Sdougm 	int i;
1636185db85Sdougm 
1647d968cb8Sdougm 	if (list == NULL) {
16525a68471Sdougm 		/* zero length dfstab */
16625a68471Sdougm 		list = alloc_sharelist();
16725a68471Sdougm 		if (list == NULL)
16825a68471Sdougm 			return (NULL);
16925a68471Sdougm 		list->description = strdup("#\n");
1707d968cb8Sdougm 	}
1716185db85Sdougm 	if (list->path == NULL && list->description != NULL &&
1726185db85Sdougm 	    strcmp(list->description, notice[0]) != 0) {
17325a68471Sdougm 		for (prev = NULL, i = 0; i < DFSTAB_NOTICE_LINES; i++) {
17425a68471Sdougm 			item = alloc_sharelist();
17525a68471Sdougm 			if (item != NULL) {
17625a68471Sdougm 				item->description = strdup(notice[i]);
17725a68471Sdougm 				if (prev == NULL) {
17825a68471Sdougm 					item->next = list;
17925a68471Sdougm 					prev = item;
18025a68471Sdougm 					list = item;
18125a68471Sdougm 				} else {
18225a68471Sdougm 					item->next = prev->next;
18325a68471Sdougm 					prev->next = item;
18425a68471Sdougm 					prev = item;
18525a68471Sdougm 				}
18625a68471Sdougm 			}
1876185db85Sdougm 		}
1886185db85Sdougm 	}
1896185db85Sdougm 	return (list);
1906185db85Sdougm }
1916185db85Sdougm 
1926185db85Sdougm /*
1936185db85Sdougm  * getdfstab(dfs)
1946185db85Sdougm  *
1956185db85Sdougm  * Returns an zfs_sharelist_t list of lines from the dfstab file
1966185db85Sdougm  * pointed to by the FILE pointer dfs. Each entry is parsed and the
1976185db85Sdougm  * original line is also preserved. Used in parsing and updating the
1986185db85Sdougm  * dfstab file.
1996185db85Sdougm  */
2006185db85Sdougm 
2016185db85Sdougm static xfs_sharelist_t *
getdfstab(FILE * dfs)2026185db85Sdougm getdfstab(FILE *dfs)
2036185db85Sdougm {
2046185db85Sdougm 	char buff[_POSIX_ARG_MAX]; /* reasonable size given syntax of share */
2056185db85Sdougm 	char *bp;
2066185db85Sdougm 	char *token;
2076185db85Sdougm 	char *args[MAXARGSFORSHARE];
2086185db85Sdougm 	int argc;
2096185db85Sdougm 	int c;
2106185db85Sdougm 	static int line = 0;
2117d968cb8Sdougm 	xfs_sharelist_t *item = NULL, *first = NULL, *last;
2126185db85Sdougm 
2136185db85Sdougm 	if (dfs != NULL) {
21425a68471Sdougm 		first = NULL;
21525a68471Sdougm 		line = 0;
21625a68471Sdougm 		while (fgets(buff, sizeof (buff), dfs) != NULL) {
21725a68471Sdougm 			line++;
21825a68471Sdougm 			bp = buff;
21925a68471Sdougm 			if (buff[0] == '#') {
22025a68471Sdougm 				item = alloc_sharelist();
22125a68471Sdougm 				if (item != NULL) {
22225a68471Sdougm 					/* if no path, then comment */
22325a68471Sdougm 					item->lineno = line;
22425a68471Sdougm 					item->description = strdup(buff);
22525a68471Sdougm 					if (first == NULL) {
22625a68471Sdougm 						first = item;
22725a68471Sdougm 						last = item;
22825a68471Sdougm 					} else {
22925a68471Sdougm 						last->next = item;
23025a68471Sdougm 						last = item;
23125a68471Sdougm 					}
23225a68471Sdougm 				} else {
23325a68471Sdougm 					break;
23425a68471Sdougm 				}
23525a68471Sdougm 				continue;
23625a68471Sdougm 			} else if (buff[0] == '\n') {
23725a68471Sdougm 				continue;
23825a68471Sdougm 			}
23925a68471Sdougm 			optind = 1;
24025a68471Sdougm 			item = alloc_sharelist();
24125a68471Sdougm 			if (item == NULL) {
24225a68471Sdougm 				break;
24325a68471Sdougm 			} else if (first == NULL) {
24425a68471Sdougm 				first = item;
24525a68471Sdougm 				last = item;
2466185db85Sdougm 			} else {
24725a68471Sdougm 				last->next = item;
24825a68471Sdougm 				last = item;
2496185db85Sdougm 			}
25025a68471Sdougm 			item->lineno = line;
25125a68471Sdougm 			item->origline = strdup(buff);
2528d7e4166Sjose borrego 			(void) _sa_get_token(NULL); /* reset to new pointers */
25325a68471Sdougm 			argc = 0;
2548d7e4166Sjose borrego 			while ((token = _sa_get_token(bp)) != NULL) {
25525a68471Sdougm 				if (argc < MAXARGSFORSHARE)
25625a68471Sdougm 					args[argc++] = token;
2576185db85Sdougm 			}
25825a68471Sdougm 			while ((c = getopt(argc, args, "F:o:d:pg:")) != -1) {
25925a68471Sdougm 				switch (c) {
26025a68471Sdougm 				case 'p':
26125a68471Sdougm 					item->persist = 1;
26225a68471Sdougm 					break;
26325a68471Sdougm 				case 'F':
26425a68471Sdougm 					item->fstype = strdup(optarg);
26525a68471Sdougm 					break;
26625a68471Sdougm 				case 'o':
26725a68471Sdougm 					item->options = strdup(optarg);
26825a68471Sdougm 					break;
26925a68471Sdougm 				case 'd':
27025a68471Sdougm 					item->description = strdup(optarg);
27125a68471Sdougm 					break;
27225a68471Sdougm 				case 'g':
27325a68471Sdougm 					item->group = strdup(optarg);
27425a68471Sdougm 					break;
27525a68471Sdougm 				default:
27625a68471Sdougm 					break;
27725a68471Sdougm 				}
27825a68471Sdougm 			}
27925a68471Sdougm 			if (optind < argc) {
28025a68471Sdougm 				item->path = strdup(args[optind]);
28125a68471Sdougm 				optind++;
28225a68471Sdougm 				if (optind < argc) {
28325a68471Sdougm 					char *resource;
28425a68471Sdougm 					char *optgroup;
28525a68471Sdougm 					/* resource and/or groupname */
28625a68471Sdougm 					resource = args[optind];
28725a68471Sdougm 					optgroup = strchr(resource, '@');
28825a68471Sdougm 					if (optgroup != NULL)
28925a68471Sdougm 						*optgroup++ = '\0';
29025a68471Sdougm 					if (optgroup != NULL)
29125a68471Sdougm 						item->group = strdup(optgroup);
29225a68471Sdougm 					if (resource != NULL &&
29325a68471Sdougm 					    strlen(resource) > 0)
29425a68471Sdougm 						item->resource =
29525a68471Sdougm 						    strdup(resource);
29625a68471Sdougm 				}
29725a68471Sdougm 			}
29825a68471Sdougm 			/* NFS is the default if none defined */
29925a68471Sdougm 			if (item != NULL && item->fstype == NULL)
30025a68471Sdougm 				item->fstype = strdup("nfs");
301a99982a7Sdougm 		}
3026185db85Sdougm 	}
3036185db85Sdougm 	first = fix_notice(first);
3046185db85Sdougm 	return (first);
3056185db85Sdougm }
3066185db85Sdougm 
3076185db85Sdougm /*
3086185db85Sdougm  * finddfsentry(list, path)
3096185db85Sdougm  *
3107d968cb8Sdougm  * Look for path in the zfs_sharelist_t list and return the entry if it
3116185db85Sdougm  * exists.
3126185db85Sdougm  */
3136185db85Sdougm 
3146185db85Sdougm static xfs_sharelist_t *
finddfsentry(xfs_sharelist_t * list,char * path)3156185db85Sdougm finddfsentry(xfs_sharelist_t *list, char *path)
3166185db85Sdougm {
3176185db85Sdougm 	xfs_sharelist_t *item;
3186185db85Sdougm 
3196185db85Sdougm 	for (item = list; item != NULL; item = item->next) {
32025a68471Sdougm 		if (item->path != NULL && strcmp(item->path, path) == 0)
3216185db85Sdougm 		return (item);
3226185db85Sdougm 	}
3236185db85Sdougm 	return (NULL);
3246185db85Sdougm }
3256185db85Sdougm 
3266185db85Sdougm /*
3276185db85Sdougm  * remdfsentry(list, path, proto)
3286185db85Sdougm  *
3296185db85Sdougm  * Remove the specified path (with protocol) from the list. This will
3306185db85Sdougm  * remove it from dfstab when the file is rewritten.
3316185db85Sdougm  */
3326185db85Sdougm 
3336185db85Sdougm static xfs_sharelist_t *
remdfsentry(xfs_sharelist_t * list,char * path,char * proto)3346185db85Sdougm remdfsentry(xfs_sharelist_t *list, char *path, char *proto)
3356185db85Sdougm {
3366185db85Sdougm 	xfs_sharelist_t *item, *prev = NULL;
3376185db85Sdougm 
3386185db85Sdougm 
3396185db85Sdougm 	for (item = prev = list; item != NULL; item = item->next) {
3406185db85Sdougm 	    /* skip comment entry but don't lose it */
34125a68471Sdougm 		if (item->path == NULL) {
34225a68471Sdougm 			prev = item;
34325a68471Sdougm 			continue;
34425a68471Sdougm 		}
34525a68471Sdougm 		/* if proto is NULL, remove all protocols */
34625a68471Sdougm 		if (proto == NULL || (strcmp(item->path, path) == 0 &&
34725a68471Sdougm 		    (item->fstype != NULL && strcmp(item->fstype, proto) == 0)))
34825a68471Sdougm 			break;
34925a68471Sdougm 		if (item->fstype == NULL &&
35025a68471Sdougm 		    (proto == NULL || strcmp(proto, "nfs") == 0))
35125a68471Sdougm 			break;
3526185db85Sdougm 		prev = item;
3536185db85Sdougm 	}
3546185db85Sdougm 	if (item != NULL) {
35525a68471Sdougm 		if (item == prev)
35625a68471Sdougm 			list = item->next; /* this must be the first one */
35725a68471Sdougm 		else
35825a68471Sdougm 			prev->next = item->next;
35925a68471Sdougm 		item->next = NULL;
36025a68471Sdougm 		dfs_free_list(item);
3616185db85Sdougm 	}
3626185db85Sdougm 	return (list);
3636185db85Sdougm }
3646185db85Sdougm 
3656185db85Sdougm /*
3666185db85Sdougm  * remdfsline(list, line)
3676185db85Sdougm  *
3686185db85Sdougm  * Remove the line specified from the list.
3696185db85Sdougm  */
3706185db85Sdougm 
3716185db85Sdougm static xfs_sharelist_t *
remdfsline(xfs_sharelist_t * list,char * line)3726185db85Sdougm remdfsline(xfs_sharelist_t *list, char *line)
3736185db85Sdougm {
3746185db85Sdougm 	xfs_sharelist_t *item, *prev = NULL;
3756185db85Sdougm 
3766185db85Sdougm 	for (item = prev = list; item != NULL; item = item->next) {
37725a68471Sdougm 		/* skip comment entry but don't lose it */
37825a68471Sdougm 		if (item->path == NULL) {
3796185db85Sdougm 		prev = item;
3806185db85Sdougm 		continue;
38125a68471Sdougm 		}
38225a68471Sdougm 		if (strcmp(item->origline, line) == 0)
38325a68471Sdougm 			break;
38425a68471Sdougm 		prev = item;
3856185db85Sdougm 	}
3866185db85Sdougm 	if (item != NULL) {
38725a68471Sdougm 		if (item == prev)
38825a68471Sdougm 			list = item->next; /* this must be the first one */
38925a68471Sdougm 		else
39025a68471Sdougm 			prev->next = item->next;
39125a68471Sdougm 		item->next = NULL;
39225a68471Sdougm 		dfs_free_list(item);
3936185db85Sdougm 	}
3946185db85Sdougm 	return (list);
3956185db85Sdougm }
3966185db85Sdougm 
3976185db85Sdougm /*
3986185db85Sdougm  * adddfsentry(list, share, proto)
3996185db85Sdougm  *
4006185db85Sdougm  * Add an entry to the dfstab list for share (relative to proto). This
4016185db85Sdougm  * is used to update dfstab for legacy purposes.
4026185db85Sdougm  */
4036185db85Sdougm 
4046185db85Sdougm static xfs_sharelist_t *
adddfsentry(xfs_sharelist_t * list,sa_share_t share,char * proto)4056185db85Sdougm adddfsentry(xfs_sharelist_t *list, sa_share_t share, char *proto)
4066185db85Sdougm {
4076185db85Sdougm 	xfs_sharelist_t *item, *tmp;
4086185db85Sdougm 	sa_group_t parent;
4096185db85Sdougm 	char *groupname;
4106185db85Sdougm 
4116185db85Sdougm 	item = alloc_sharelist();
4126185db85Sdougm 	if (item != NULL) {
41325a68471Sdougm 		parent = sa_get_parent_group(share);
41425a68471Sdougm 		groupname = sa_get_group_attr(parent, "name");
415fe1c642dSBill Krier 		if (groupname != NULL && strcmp(groupname, "default") == 0) {
41625a68471Sdougm 			sa_free_attr_string(groupname);
41725a68471Sdougm 			groupname = NULL;
41825a68471Sdougm 		}
41925a68471Sdougm 		item->path = sa_get_share_attr(share, "path");
42025a68471Sdougm 		item->resource = sa_get_share_attr(share, "resource");
42125a68471Sdougm 		item->group = groupname;
42225a68471Sdougm 		item->fstype = strdup(proto);
42325a68471Sdougm 		item->options = sa_proto_legacy_format(proto, share, 1);
42425a68471Sdougm 		if (item->options != NULL && strlen(item->options) == 0) {
42525a68471Sdougm 			free(item->options);
42625a68471Sdougm 			item->options = NULL;
42725a68471Sdougm 		}
42825a68471Sdougm 		item->description = sa_get_share_description(share);
42925a68471Sdougm 		if (item->description != NULL &&
43025a68471Sdougm 		    strlen(item->description) == 0) {
43125a68471Sdougm 			sa_free_share_description(item->description);
43225a68471Sdougm 			item->description = NULL;
43325a68471Sdougm 		}
43425a68471Sdougm 		if (list == NULL) {
43525a68471Sdougm 			list = item;
43625a68471Sdougm 		} else {
43725a68471Sdougm 			for (tmp = list; tmp->next != NULL; tmp = tmp->next)
43825a68471Sdougm 				/* do nothing */;
439*41e1be47SToomas Soome 			tmp->next = item;
44025a68471Sdougm 		}
4416185db85Sdougm 	}
4426185db85Sdougm 	return (list);
4436185db85Sdougm }
4446185db85Sdougm 
4456185db85Sdougm /*
4466185db85Sdougm  * outdfstab(dfstab, list)
4476185db85Sdougm  *
4486185db85Sdougm  * Output the list to dfstab making sure the file is truncated.
4496185db85Sdougm  * Comments and errors are preserved.
4506185db85Sdougm  */
4516185db85Sdougm 
4526185db85Sdougm static void
outdfstab(FILE * dfstab,xfs_sharelist_t * list)4536185db85Sdougm outdfstab(FILE *dfstab, xfs_sharelist_t *list)
4546185db85Sdougm {
4556185db85Sdougm 	xfs_sharelist_t *item;
4566185db85Sdougm 
4576185db85Sdougm 	(void) ftruncate(fileno(dfstab), 0);
4586185db85Sdougm 
4596185db85Sdougm 	for (item = list; item != NULL; item = item->next) {
46025a68471Sdougm 		if (item->path != NULL) {
46125a68471Sdougm 			if (*item->path == '/') {
46225a68471Sdougm 				(void) fprintf(dfstab,
46325a68471Sdougm 				    "share %s%s%s%s%s%s%s %s%s%s%s%s\n",
46425a68471Sdougm 				    (item->fstype != NULL) ? "-F " : "",
46525a68471Sdougm 				    (item->fstype != NULL) ? item->fstype : "",
46625a68471Sdougm 				    (item->options != NULL) ? " -o " : "",
46725a68471Sdougm 				    (item->options != NULL) ?
46825a68471Sdougm 				    item->options : "",
46925a68471Sdougm 				    (item->description != NULL) ?
47025a68471Sdougm 				    " -d \"" : "",
47125a68471Sdougm 				    (item->description != NULL) ?
47225a68471Sdougm 				    item->description : "",
47325a68471Sdougm 				    (item->description != NULL) ? "\"" : "",
47425a68471Sdougm 				    item->path,
47525a68471Sdougm 				    ((item->resource != NULL) ||
47625a68471Sdougm 				    (item->group != NULL)) ? " " : "",
47725a68471Sdougm 				    (item->resource != NULL) ?
47825a68471Sdougm 				    item->resource : "",
47925a68471Sdougm 				    item->group != NULL ? "@" : "",
48025a68471Sdougm 				    item->group != NULL ? item->group : "");
48125a68471Sdougm 			} else {
48225a68471Sdougm 				(void) fprintf(dfstab, "%s", item->origline);
48325a68471Sdougm 			}
4846185db85Sdougm 		} else {
48525a68471Sdougm 			if (item->description != NULL)
48625a68471Sdougm 				(void) fprintf(dfstab, "%s", item->description);
48725a68471Sdougm 			else
48825a68471Sdougm 				(void) fprintf(dfstab, "%s", item->origline);
4896185db85Sdougm 		}
4906185db85Sdougm 	}
4916185db85Sdougm }
4926185db85Sdougm 
4936185db85Sdougm /*
4946185db85Sdougm  * open_dfstab(file)
4956185db85Sdougm  *
4966185db85Sdougm  * Open the specified dfstab file. If the owner/group/perms are wrong,
4976185db85Sdougm  * fix them.
4986185db85Sdougm  */
4996185db85Sdougm 
5006185db85Sdougm static FILE *
open_dfstab(char * file)5016185db85Sdougm open_dfstab(char *file)
5026185db85Sdougm {
5036185db85Sdougm 	struct group *grp;
5046185db85Sdougm 	struct group group;
5056185db85Sdougm 	char *buff;
5066185db85Sdougm 	int grsize;
5076185db85Sdougm 	FILE *dfstab;
5086185db85Sdougm 
5096185db85Sdougm 	dfstab = fopen(file, "r+");
5106185db85Sdougm 	if (dfstab == NULL) {
51125a68471Sdougm 		dfstab = fopen(file, "w+");
5126185db85Sdougm 	}
5136185db85Sdougm 	if (dfstab != NULL) {
5146185db85Sdougm 		grsize = sysconf(_SC_GETGR_R_SIZE_MAX);
5156185db85Sdougm 		buff = malloc(grsize);
5166185db85Sdougm 		if (buff != NULL)
51725a68471Sdougm 			grp = getgrnam_r(SA_DEFAULT_FILE_GRP, &group, buff,
51825a68471Sdougm 			    grsize);
5196185db85Sdougm 		else
52025a68471Sdougm 			grp = getgrnam(SA_DEFAULT_FILE_GRP);
5216185db85Sdougm 		(void) fchmod(fileno(dfstab), 0644);
5226185db85Sdougm 		(void) fchown(fileno(dfstab), 0,
52325a68471Sdougm 		    grp != NULL ? grp->gr_gid : 3);
5246185db85Sdougm 		if (buff != NULL)
52525a68471Sdougm 			free(buff);
5266185db85Sdougm 		rewind(dfstab);
5276185db85Sdougm 	}
5286185db85Sdougm 	return (dfstab);
5296185db85Sdougm }
5306185db85Sdougm 
5316185db85Sdougm /*
5326185db85Sdougm  * sa_comment_line(line, err)
5336185db85Sdougm  *
5346185db85Sdougm  * Add a comment to the dfstab file with err as a prefix to the
5356185db85Sdougm  * original line.
5366185db85Sdougm  */
5376185db85Sdougm 
5386185db85Sdougm static void
sa_comment_line(char * line,char * err)5396185db85Sdougm sa_comment_line(char *line, char *err)
5406185db85Sdougm {
5416185db85Sdougm 	FILE *dfstab;
5426185db85Sdougm 	xfs_sharelist_t *list;
543a99982a7Sdougm 	sigset_t old;
5446185db85Sdougm 
5456185db85Sdougm 	dfstab = open_dfstab(SA_LEGACY_DFSTAB);
5466185db85Sdougm 	if (dfstab != NULL) {
5476185db85Sdougm 		(void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8);
548a99982a7Sdougm 		sablocksigs(&old);
5496185db85Sdougm 		(void) lockf(fileno(dfstab), F_LOCK, 0);
550148c5f43SAlan Wright 		(void) mutex_lock(&sa_dfstab_lock);
5516185db85Sdougm 		list = getdfstab(dfstab);
5526185db85Sdougm 		rewind(dfstab);
553f345c0beSdougm 		/*
554f345c0beSdougm 		 * don't ignore the return since the list could have
555f345c0beSdougm 		 * gone to NULL if the file only had one line in it.
556f345c0beSdougm 		 */
557f345c0beSdougm 		list = remdfsline(list, line);
5586185db85Sdougm 		outdfstab(dfstab, list);
5596185db85Sdougm 		(void) fprintf(dfstab, "# Error: %s: %s", err, line);
5606185db85Sdougm 		(void) fsync(fileno(dfstab));
561148c5f43SAlan Wright 		(void) mutex_unlock(&sa_dfstab_lock);
5626185db85Sdougm 		(void) lockf(fileno(dfstab), F_ULOCK, 0);
5636185db85Sdougm 		(void) fclose(dfstab);
564a99982a7Sdougm 		saunblocksigs(&old);
5656185db85Sdougm 		if (list != NULL)
56625a68471Sdougm 			dfs_free_list(list);
5676185db85Sdougm 	}
5686185db85Sdougm }
5696185db85Sdougm 
5706185db85Sdougm /*
571da6c28aaSamw  * sa_delete_legacy(share, protocol)
5726185db85Sdougm  *
5736185db85Sdougm  * Delete the specified share from the legacy config file.
5746185db85Sdougm  */
5756185db85Sdougm 
5766185db85Sdougm int
sa_delete_legacy(sa_share_t share,char * protocol)577da6c28aaSamw sa_delete_legacy(sa_share_t share, char *protocol)
5786185db85Sdougm {
5796185db85Sdougm 	FILE *dfstab;
5806185db85Sdougm 	int err;
5816185db85Sdougm 	int ret = SA_OK;
5826185db85Sdougm 	xfs_sharelist_t *list;
5836185db85Sdougm 	char *path;
5846185db85Sdougm 	sa_optionset_t optionset;
5856185db85Sdougm 	sa_group_t parent;
586a99982a7Sdougm 	sigset_t old;
5876185db85Sdougm 
588da6c28aaSamw 	/*
589da6c28aaSamw 	 * Protect against shares that don't have paths. This is not
590da6c28aaSamw 	 * really an error at this point.
591da6c28aaSamw 	 */
592da6c28aaSamw 	path = sa_get_share_attr(share, "path");
593