1*6185db85Sdougm /*
2*6185db85Sdougm  * CDDL HEADER START
3*6185db85Sdougm  *
4*6185db85Sdougm  * The contents of this file are subject to the terms of the
5*6185db85Sdougm  * Common Development and Distribution License (the "License").
6*6185db85Sdougm  * You may not use this file except in compliance with the License.
7*6185db85Sdougm  *
8*6185db85Sdougm  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6185db85Sdougm  * or http://www.opensolaris.org/os/licensing.
10*6185db85Sdougm  * See the License for the specific language governing permissions
11*6185db85Sdougm  * and limitations under the License.
12*6185db85Sdougm  *
13*6185db85Sdougm  * When distributing Covered Code, include this CDDL HEADER in each
14*6185db85Sdougm  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6185db85Sdougm  * If applicable, add the following below this CDDL HEADER, with the
16*6185db85Sdougm  * fields enclosed by brackets "[]" replaced with your own identifying
17*6185db85Sdougm  * information: Portions Copyright [yyyy] [name of copyright owner]
18*6185db85Sdougm  *
19*6185db85Sdougm  * CDDL HEADER END
20*6185db85Sdougm  */
21*6185db85Sdougm 
22*6185db85Sdougm /*
23*6185db85Sdougm  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*6185db85Sdougm  * Use is subject to license terms.
25*6185db85Sdougm  */
26*6185db85Sdougm 
27*6185db85Sdougm #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*6185db85Sdougm 
29*6185db85Sdougm /*
30*6185db85Sdougm  * core library for common functions across all config store types
31*6185db85Sdougm  * and file systems to be exported. This includes legacy dfstab/sharetab
32*6185db85Sdougm  * parsing. Need to eliminate XML where possible.
33*6185db85Sdougm  */
34*6185db85Sdougm 
35*6185db85Sdougm #include <stdio.h>
36*6185db85Sdougm #include <string.h>
37*6185db85Sdougm #include <ctype.h>
38*6185db85Sdougm #include <unistd.h>
39*6185db85Sdougm #include <limits.h>
40*6185db85Sdougm #include <errno.h>
41*6185db85Sdougm #include <sys/types.h>
42*6185db85Sdougm #include <sys/stat.h>
43*6185db85Sdougm #include <libxml/parser.h>
44*6185db85Sdougm #include <libxml/tree.h>
45*6185db85Sdougm #include "libshare.h"
46*6185db85Sdougm #include "libshare_impl.h"
47*6185db85Sdougm #include "libfsmgt.h"
48*6185db85Sdougm #include <fcntl.h>
49*6185db85Sdougm #include <sys/stat.h>
50*6185db85Sdougm #include <grp.h>
51*6185db85Sdougm #include <limits.h>
52*6185db85Sdougm #include <sys/param.h>
53*6185db85Sdougm #include <signal.h>
54*6185db85Sdougm #include <libintl.h>
55*6185db85Sdougm 
56*6185db85Sdougm #include "sharetab.h"
57*6185db85Sdougm 
58*6185db85Sdougm #define	DFSTAB_NOTICE_LINES	5
59*6185db85Sdougm static char *notice[DFSTAB_NOTICE_LINES] =	{
60*6185db85Sdougm 	"# Do not modify this file directly.\n",
61*6185db85Sdougm 	"# Use the sharemgr(1m) command for all share management\n",
62*6185db85Sdougm 	"# This file is reconstructed and only maintained for backward\n",
63*6185db85Sdougm 	"# compatibility. Configuration lines could be lost.\n",
64*6185db85Sdougm 	"#\n"
65*6185db85Sdougm };
66*6185db85Sdougm 
67*6185db85Sdougm #define	STRNCAT(x, y, z)	(xmlChar *)strncat((char *)x, (char *)y, z)
68*6185db85Sdougm 
69*6185db85Sdougm /* will be much smaller, but this handles bad syntax in the file */
70*6185db85Sdougm #define	MAXARGSFORSHARE	256
71*6185db85Sdougm 
72*6185db85Sdougm /* used internally only */
73*6185db85Sdougm typedef
74*6185db85Sdougm struct sharelist {
75*6185db85Sdougm     struct sharelist *next;
76*6185db85Sdougm     int   persist;
77*6185db85Sdougm     char *path;
78*6185db85Sdougm     char *resource;
79*6185db85Sdougm     char *fstype;
80*6185db85Sdougm     char *options;
81*6185db85Sdougm     char *description;
82*6185db85Sdougm     char *group;
83*6185db85Sdougm     char *origline;
84*6185db85Sdougm     int lineno;
85*6185db85Sdougm } xfs_sharelist_t;
86*6185db85Sdougm static void parse_dfstab(char *, xmlNodePtr);
87*6185db85Sdougm extern char *get_token(char *);
88*6185db85Sdougm static void dfs_free_list(xfs_sharelist_t *);
89*6185db85Sdougm /* prototypes */
90*6185db85Sdougm void getlegacyconfig(char *, xmlNodePtr *);
91*6185db85Sdougm extern sa_share_t _sa_add_share(sa_group_t, char *, int, int *);
92*6185db85Sdougm extern xmlNodePtr _sa_get_next_error(xmlNodePtr);
93*6185db85Sdougm extern sa_group_t _sa_create_group(char *);
94*6185db85Sdougm static void outdfstab(FILE *, xfs_sharelist_t *);
95*6185db85Sdougm extern int _sa_remove_optionset(sa_optionset_t);
96*6185db85Sdougm extern int set_node_share(void *, char *, char *);
97*6185db85Sdougm extern void set_node_attr(void *, char *, char *);
98*6185db85Sdougm 
99*6185db85Sdougm /*
100*6185db85Sdougm  * alloc_sharelist()
101*6185db85Sdougm  *
102*6185db85Sdougm  * allocator function to return an zfs_sharelist_t
103*6185db85Sdougm  */
104*6185db85Sdougm 
105*6185db85Sdougm static xfs_sharelist_t *
106*6185db85Sdougm alloc_sharelist()
107*6185db85Sdougm {
108*6185db85Sdougm 	xfs_sharelist_t *item;
109*6185db85Sdougm 
110*6185db85Sdougm 	item = (xfs_sharelist_t *)malloc(sizeof (xfs_sharelist_t));
111*6185db85Sdougm 	if (item != NULL)
112*6185db85Sdougm 	    (void) memset(item, '\0', sizeof (xfs_sharelist_t));
113*6185db85Sdougm 	return (item);
114*6185db85Sdougm }
115*6185db85Sdougm 
116*6185db85Sdougm /*
117*6185db85Sdougm  * fix_notice(list)
118*6185db85Sdougm  *
119*6185db85Sdougm  * Look at the beginning of the current /etc/dfs/dfstab file and add
120*6185db85Sdougm  * the do not modify notice if it doesn't exist.
121*6185db85Sdougm  */
122*6185db85Sdougm 
123*6185db85Sdougm static xfs_sharelist_t *
124*6185db85Sdougm fix_notice(xfs_sharelist_t *list)
125*6185db85Sdougm {
126*6185db85Sdougm 	xfs_sharelist_t *item, *prev;
127*6185db85Sdougm 	int i;
128*6185db85Sdougm 
129*6185db85Sdougm 	if (list->path == NULL && list->description != NULL &&
130*6185db85Sdougm 	    strcmp(list->description, notice[0]) != 0) {
131*6185db85Sdougm 	    for (prev = NULL, i = 0; i < DFSTAB_NOTICE_LINES; i++) {
132*6185db85Sdougm 		item = alloc_sharelist();
133*6185db85Sdougm 		if (item != NULL) {
134*6185db85Sdougm 		    item->description = strdup(notice[i]);
135*6185db85Sdougm 		    if (prev == NULL) {
136*6185db85Sdougm 			item->next = list;
137*6185db85Sdougm 			prev = item;
138*6185db85Sdougm 			list = item;
139*6185db85Sdougm 		    } else {
140*6185db85Sdougm 			item->next = prev->next;
141*6185db85Sdougm 			prev->next = item;
142*6185db85Sdougm 			prev = item;
143*6185db85Sdougm 		    }
144*6185db85Sdougm 		}
145*6185db85Sdougm 	    }
146*6185db85Sdougm 	}
147*6185db85Sdougm 	return (list);
148*6185db85Sdougm }
149*6185db85Sdougm 
150*6185db85Sdougm /*
151*6185db85Sdougm  * getdfstab(dfs)
152*6185db85Sdougm  *
153*6185db85Sdougm  * Returns an zfs_sharelist_t list of lines from the dfstab file
154*6185db85Sdougm  * pointed to by the FILE pointer dfs. Each entry is parsed and the
155*6185db85Sdougm  * original line is also preserved. Used in parsing and updating the
156*6185db85Sdougm  * dfstab file.
157*6185db85Sdougm  */
158*6185db85Sdougm 
159*6185db85Sdougm static xfs_sharelist_t *
160*6185db85Sdougm getdfstab(FILE *dfs)
161*6185db85Sdougm {
162*6185db85Sdougm 	char buff[_POSIX_ARG_MAX]; /* reasonable size given syntax of share */
163*6185db85Sdougm 	char *bp;
164*6185db85Sdougm 	char *token;
165*6185db85Sdougm 	char *args[MAXARGSFORSHARE];
166*6185db85Sdougm 	int argc;
167*6185db85Sdougm 	int c;
168*6185db85Sdougm 	static int line = 0;
169*6185db85Sdougm 	xfs_sharelist_t *item, *first, *last;
170*6185db85Sdougm 
171*6185db85Sdougm 	if (dfs != NULL) {
172*6185db85Sdougm 	    first = NULL;
173*6185db85Sdougm 	    line = 0;
174*6185db85Sdougm 	    while (fgets(buff, sizeof (buff), dfs) != NULL) {
175*6185db85Sdougm 		line++;
176*6185db85Sdougm 		bp = buff;
177*6185db85Sdougm 		if (buff[0] == '#') {
178*6185db85Sdougm 		    item = alloc_sharelist();
179*6185db85Sdougm 		    if (item != NULL) {
180*6185db85Sdougm 			/* if no path, then comment */
181*6185db85Sdougm 			item->lineno = line;
182*6185db85Sdougm 			item->description = strdup(buff);
183*6185db85Sdougm 			if (first == NULL) {
184*6185db85Sdougm 			    first = item;
185*6185db85Sdougm 			    last = item;
186*6185db85Sdougm 			} else {
187*6185db85Sdougm 			    last->next = item;
188*6185db85Sdougm 			    last = item;
189*6185db85Sdougm 			}
190*6185db85Sdougm 		    } else {
191*6185db85Sdougm 			break;
192*6185db85Sdougm 		    }
193*6185db85Sdougm 		    continue;
194*6185db85Sdougm 		} else if (buff[0] == '\n') {
195*6185db85Sdougm 		    continue;
196*6185db85Sdougm 		}
197*6185db85Sdougm 		optind = 1;
198*6185db85Sdougm 		item = alloc_sharelist();
199*6185db85Sdougm 		if (item == NULL) {
200*6185db85Sdougm 		    break;
201*6185db85Sdougm 		} else if (first == NULL) {
202*6185db85Sdougm 		    first = item;
203*6185db85Sdougm 		    last = item;
204*6185db85Sdougm 		} else {
205*6185db85Sdougm 		    last->next = item;
206*6185db85Sdougm 		    last = item;
207*6185db85Sdougm 		}
208*6185db85Sdougm 		item->lineno = line;
209*6185db85Sdougm 		item->origline = strdup(buff);
210*6185db85Sdougm 		(void) get_token(NULL); /* reset to new pointers */
211*6185db85Sdougm 		argc = 0;
212*6185db85Sdougm 		while ((token = get_token(bp)) != NULL) {
213*6185db85Sdougm 		    if (argc < MAXARGSFORSHARE) {
214*6185db85Sdougm 			args[argc++] = token;
215*6185db85Sdougm 		    }
216*6185db85Sdougm 		}
217*6185db85Sdougm 		while ((c = getopt(argc, args, "F:o:d:pg:")) != -1) {
218*6185db85Sdougm 		    switch (c) {
219*6185db85Sdougm 		    case 'p':
220*6185db85Sdougm 			item->persist = 1;
221*6185db85Sdougm 			break;
222*6185db85Sdougm 		    case 'F':
223*6185db85Sdougm 			item->fstype = strdup(optarg);
224*6185db85Sdougm 			break;
225*6185db85Sdougm 		    case 'o':
226*6185db85Sdougm 			item->options = strdup(optarg);
227*6185db85Sdougm 			break;
228*6185db85Sdougm 		    case 'd':
229*6185db85Sdougm 			item->description = strdup(optarg);
230*6185db85Sdougm 			break;
231*6185db85Sdougm 		    case 'g':
232*6185db85Sdougm 			item->group = strdup(optarg);
233*6185db85Sdougm 			break;
234*6185db85Sdougm 		    default:
235*6185db85Sdougm 			break;
236*6185db85Sdougm 		    }
237*6185db85Sdougm 		}
238*6185db85Sdougm 		if (optind < argc) {
239*6185db85Sdougm 		    item->path = strdup(args[optind]);
240*6185db85Sdougm 		    optind++;
241*6185db85Sdougm 		    if (optind < argc) {
242*6185db85Sdougm 			char *resource;
243*6185db85Sdougm 			char *optgroup;
244*6185db85Sdougm 			/* resource and/or groupname */
245*6185db85Sdougm 			resource = args[optind];
246*6185db85Sdougm 			optgroup = strchr(resource, '@');
247*6185db85Sdougm 			if (optgroup != NULL) {
248*6185db85Sdougm 			    *optgroup++ = '\0';
249*6185db85Sdougm 			}
250*6185db85Sdougm 			if (optgroup != NULL)
251*6185db85Sdougm 			    item->group = strdup(optgroup);
252*6185db85Sdougm 			if (resource != NULL && strlen(resource) > 0)
253*6185db85Sdougm 			    item->resource = strdup(resource);
254*6185db85Sdougm 		    }
255*6185db85Sdougm 		}
256*6185db85Sdougm 	    }
257*6185db85Sdougm 	    if (item->fstype == NULL)
258*6185db85Sdougm 		item->fstype = strdup("nfs"); /* this is the default */
259*6185db85Sdougm 	}
260*6185db85Sdougm 	first = fix_notice(first);
261*6185db85Sdougm 	return (first);
262*6185db85Sdougm }
263*6185db85Sdougm 
264*6185db85Sdougm /*
265*6185db85Sdougm  * finddfsentry(list, path)
266*6185db85Sdougm  *
267*6185db85Sdougm  * Look for path in the zfs_sharelist_t list and return the tnry if it
268*6185db85Sdougm  * exists.
269*6185db85Sdougm  */
270*6185db85Sdougm 
271*6185db85Sdougm static xfs_sharelist_t *
272*6185db85Sdougm finddfsentry(xfs_sharelist_t *list, char *path)
273*6185db85Sdougm {
274*6185db85Sdougm 	xfs_sharelist_t *item;
275*6185db85Sdougm 
276*6185db85Sdougm 	for (item = list; item != NULL; item = item->next) {
277*6185db85Sdougm 	    if (item->path != NULL && strcmp(item->path, path) == 0)
278*6185db85Sdougm 		return (item);
279*6185db85Sdougm 	}
280*6185db85Sdougm 	return (NULL);
281*6185db85Sdougm }
282*6185db85Sdougm 
283*6185db85Sdougm /*
284*6185db85Sdougm  * remdfsentry(list, path, proto)
285*6185db85Sdougm  *
286*6185db85Sdougm  * Remove the specified path (with protocol) from the list. This will
287*6185db85Sdougm  * remove it from dfstab when the file is rewritten.
288*6185db85Sdougm  */
289*6185db85Sdougm 
290*6185db85Sdougm static xfs_sharelist_t *
291*6185db85Sdougm remdfsentry(xfs_sharelist_t *list, char *path, char *proto)
292*6185db85Sdougm {
293*6185db85Sdougm 	xfs_sharelist_t *item, *prev = NULL;
294*6185db85Sdougm 
295*6185db85Sdougm 
296*6185db85Sdougm 	for (item = prev = list; item != NULL; item = item->next) {
297*6185db85Sdougm 	    /* skip comment entry but don't lose it */
298*6185db85Sdougm 	    if (item->path == NULL) {
299*6185db85Sdougm 		prev = item;
300*6185db85Sdougm 		continue;
301*6185db85Sdougm 	    }
302*6185db85Sdougm 	    /* if proto is NULL, remove all protocols */
303*6185db85Sdougm 	    if (proto == NULL || (strcmp(item->path, path) == 0 &&
304*6185db85Sdougm 		(item->fstype != NULL && strcmp(item->fstype, proto) == 0)))
305*6185db85Sdougm 		break;
306*6185db85Sdougm 	    if (item->fstype == NULL &&
307*6185db85Sdougm 		(proto == NULL || strcmp(proto, "nfs") == 0))
308*6185db85Sdougm 		break;
309*6185db85Sdougm 	    prev = item;
310*6185db85Sdougm 	}
311*6185db85Sdougm 	if (item != NULL) {
312*6185db85Sdougm 	    if (item == prev) {
313*6185db85Sdougm 		list = item->next; /* this must be the first one */
314*6185db85Sdougm 	    } else {
315*6185db85Sdougm 		prev->next = item->next;
316*6185db85Sdougm 	    }
317*6185db85Sdougm 	    item->next = NULL;
318*6185db85Sdougm 	    dfs_free_list(item);
319*6185db85Sdougm 	}
320*6185db85Sdougm 	return (list);
321*6185db85Sdougm }
322*6185db85Sdougm 
323*6185db85Sdougm /*
324*6185db85Sdougm  * remdfsline(list, line)
325*6185db85Sdougm  *
326*6185db85Sdougm  * Remove the line specified from the list.
327*6185db85Sdougm  */
328*6185db85Sdougm 
329*6185db85Sdougm static xfs_sharelist_t *
330*6185db85Sdougm remdfsline(xfs_sharelist_t *list, char *line)
331*6185db85Sdougm {
332*6185db85Sdougm 	xfs_sharelist_t *item, *prev = NULL;
333*6185db85Sdougm 
334*6185db85Sdougm 	for (item = prev = list; item != NULL; item = item->next) {
335*6185db85Sdougm 	    /* skip comment entry but don't lose it */
336*6185db85Sdougm 	    if (item->path == NULL) {
337*6185db85Sdougm 		prev = item;
338*6185db85Sdougm 		continue;
339*6185db85Sdougm 	    }
340*6185db85Sdougm 	    if (strcmp(item->origline, line) == 0) {
341*6185db85Sdougm 		break;
342*6185db85Sdougm 	    }
343*6185db85Sdougm 	    prev = item;
344*6185db85Sdougm 	}
345*6185db85Sdougm 	if (item != NULL) {
346*6185db85Sdougm 	    if (item == prev) {
347*6185db85Sdougm 		list = item->next; /* this must be the first one */
348*6185db85Sdougm 	    } else {
349*6185db85Sdougm 		prev->next = item->next;
350*6185db85Sdougm 	    }
351*6185db85Sdougm 	    item->next = NULL;
352*6185db85Sdougm 	    dfs_free_list(item);
353*6185db85Sdougm 	}
354*6185db85Sdougm 	return (list);
355*6185db85Sdougm }
356*6185db85Sdougm 
357*6185db85Sdougm /*
358*6185db85Sdougm  * adddfsentry(list, share, proto)
359*6185db85Sdougm  *
360*6185db85Sdougm  * Add an entry to the dfstab list for share (relative to proto). This
361*6185db85Sdougm  * is used to update dfstab for legacy purposes.
362*6185db85Sdougm  */
363*6185db85Sdougm 
364*6185db85Sdougm static xfs_sharelist_t *
365*6185db85Sdougm adddfsentry(xfs_sharelist_t *list, sa_share_t share, char *proto)
366*6185db85Sdougm {
367*6185db85Sdougm 	xfs_sharelist_t *item, *tmp;
368*6185db85Sdougm 	sa_group_t parent;
369*6185db85Sdougm 	char *groupname;
370*6185db85Sdougm 
371*6185db85Sdougm 	item = alloc_sharelist();
372*6185db85Sdougm 	if (item != NULL) {
373*6185db85Sdougm 	    parent = sa_get_parent_group(share);
374*6185db85Sdougm 	    groupname = sa_get_group_attr(parent, "name");
375*6185db85Sdougm 	    if (strcmp(groupname, "default") == 0) {
376*6185db85Sdougm 		sa_free_attr_string(groupname);
377*6185db85Sdougm 		groupname = NULL;
378*6185db85Sdougm 	    }
379*6185db85Sdougm 	    item->path = sa_get_share_attr(share, "path");
380*6185db85Sdougm 	    item->resource = sa_get_share_attr(share, "resource");
381*6185db85Sdougm 	    item->group = groupname;
382*6185db85Sdougm 	    item->fstype = strdup(proto);
383*6185db85Sdougm 	    item->options = sa_proto_legacy_format(proto, share, 1);
384*6185db85Sdougm 	    if (item->options != NULL && strlen(item->options) == 0) {
385*6185db85Sdougm 		free(item->options);
386*6185db85Sdougm 		item->options = NULL;
387*6185db85Sdougm 	    }
388*6185db85Sdougm 	    item->description = sa_get_share_description(share);
389*6185db85Sdougm 	    if (item->description != NULL && strlen(item->description) == 0) {
390*6185db85Sdougm 		sa_free_share_description(item->description);
391*6185db85Sdougm 		item->description = NULL;
392*6185db85Sdougm 	    }
393*6185db85Sdougm 	    if (list == NULL) {
394*6185db85Sdougm 		list = item;
395*6185db85Sdougm 	    } else {
396*6185db85Sdougm 		for (tmp = list; tmp->next != NULL; tmp = tmp->next)
397*6185db85Sdougm 		    /* do nothing */;
398*6185db85Sdougm 		tmp->next = item;
399*6185db85Sdougm 	    }
400*6185db85Sdougm 	}
401*6185db85Sdougm 	return (list);
402*6185db85Sdougm }
403*6185db85Sdougm 
404*6185db85Sdougm /*
405*6185db85Sdougm  * outdfstab(dfstab, list)
406*6185db85Sdougm  *
407*6185db85Sdougm  * Output the list to dfstab making sure the file is truncated.
408*6185db85Sdougm  * Comments and errors are preserved.
409*6185db85Sdougm  */
410*6185db85Sdougm 
411*6185db85Sdougm static void
412*6185db85Sdougm outdfstab(FILE *dfstab, xfs_sharelist_t *list)
413*6185db85Sdougm {
414*6185db85Sdougm 	xfs_sharelist_t *item;
415*6185db85Sdougm 
416*6185db85Sdougm 	(void) ftruncate(fileno(dfstab), 0);
417*6185db85Sdougm 
418*6185db85Sdougm 	for (item = list; item != NULL; item = item->next) {
419*6185db85Sdougm 	    if (item->path != NULL) {
420*6185db85Sdougm 		if (*item->path == '/')
421*6185db85Sdougm 		    (void) fprintf(dfstab, "share %s%s%s%s%s%s%s %s%s%s%s%s\n",
422*6185db85Sdougm 			    (item->fstype != NULL) ? "-F " : "",
423*6185db85Sdougm 			    (item->fstype != NULL) ? item->fstype : "",
424*6185db85Sdougm 			    (item->options != NULL) ? " -o " : "",
425*6185db85Sdougm 			    (item->options != NULL) ? item->options : "",
426*6185db85Sdougm 			    (item->description != NULL) ? " -d \"" : "",
427*6185db85Sdougm 			    (item->description != NULL) ?
428*6185db85Sdougm 				item->description : "",
429*6185db85Sdougm 			    (item->description != NULL) ? "\"" : "",
430*6185db85Sdougm 			    item->path,
431*6185db85Sdougm 			    ((item->resource != NULL) ||
432*6185db85Sdougm 				(item->group != NULL)) ? " " : "",
433*6185db85Sdougm 			    (item->resource != NULL) ? item->resource : "",
434*6185db85Sdougm 			    item->group != NULL ? "@" : "",
435*6185db85Sdougm 			    item->group != NULL ? item->group : "");
436*6185db85Sdougm 		else
437*6185db85Sdougm 		    (void) fprintf(dfstab, "%s", item->origline);
438*6185db85Sdougm 	    } else {
439*6185db85Sdougm 		if (item->description != NULL) {
440*6185db85Sdougm 		    (void) fprintf(dfstab, "%s", item->description);
441*6185db85Sdougm 		} else {
442*6185db85Sdougm 		    (void) fprintf(dfstab, "%s", item->origline);
443*6185db85Sdougm 		}
444*6185db85Sdougm 	    }
445*6185db85Sdougm 	}
446*6185db85Sdougm }
447*6185db85Sdougm 
448*6185db85Sdougm /*
449*6185db85Sdougm  * open_dfstab(file)
450*6185db85Sdougm  *
451*6185db85Sdougm  * Open the specified dfstab file. If the owner/group/perms are wrong,
452*6185db85Sdougm  * fix them.
453*6185db85Sdougm  */
454*6185db85Sdougm 
455*6185db85Sdougm static FILE *
456*6185db85Sdougm open_dfstab(char *file)
457*6185db85Sdougm {
458*6185db85Sdougm 	struct group *grp;
459*6185db85Sdougm 	struct group group;
460*6185db85Sdougm 	char *buff;
461*6185db85Sdougm 	int grsize;
462*6185db85Sdougm 	FILE *dfstab;
463*6185db85Sdougm 
464*6185db85Sdougm 	dfstab = fopen(file, "r+");
465*6185db85Sdougm 	if (dfstab == NULL) {
466*6185db85Sdougm 	    dfstab = fopen(file, "w+");
467*6185db85Sdougm 	}
468*6185db85Sdougm 	if (dfstab != NULL) {
469*6185db85Sdougm 		grsize = sysconf(_SC_GETGR_R_SIZE_MAX);
470*6185db85Sdougm 		buff = malloc(grsize);
471*6185db85Sdougm 		if (buff != NULL)
472*6185db85Sdougm 		    grp = getgrnam_r(SA_DEFAULT_FILE_GRP, &group, buff, grsize);
473*6185db85Sdougm 		else
474*6185db85Sdougm 		    grp = getgrnam(SA_DEFAULT_FILE_GRP); /* take the risk */
475*6185db85Sdougm 		(void) fchmod(fileno(dfstab), 0644);
476*6185db85Sdougm 		(void) fchown(fileno(dfstab), 0,
477*6185db85Sdougm 				grp != NULL ? grp->gr_gid : 3);
478*6185db85Sdougm 		if (buff != NULL)
479*6185db85Sdougm 		    free(buff);
480*6185db85Sdougm 		rewind(dfstab);
481*6185db85Sdougm 	}
482*6185db85Sdougm 	return (dfstab);
483*6185db85Sdougm }
484*6185db85Sdougm 
485*6185db85Sdougm /*
486*6185db85Sdougm  * sa_comment_line(line, err)
487*6185db85Sdougm  *
488*6185db85Sdougm  * Add a comment to the dfstab file with err as a prefix to the
489*6185db85Sdougm  * original line.
490*6185db85Sdougm  */
491*6185db85Sdougm 
492*6185db85Sdougm static void
493*6185db85Sdougm sa_comment_line(char *line, char *err)
494*6185db85Sdougm {
495*6185db85Sdougm 	FILE *dfstab;
496*6185db85Sdougm 	xfs_sharelist_t *list;
497*6185db85Sdougm 	sigset_t old, new;
498*6185db85Sdougm 
499*6185db85Sdougm 	dfstab = open_dfstab(SA_LEGACY_DFSTAB);
500*6185db85Sdougm 	if (dfstab != NULL) {
501*6185db85Sdougm 		(void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8);
502*6185db85Sdougm 		(void) sigprocmask(SIG_BLOCK, NULL, &new);
503*6185db85Sdougm 		(void) sigaddset(&new, SIGHUP);
504*6185db85Sdougm 		(void) sigaddset(&new, SIGINT);
505*6185db85Sdougm 		(void) sigaddset(&new, SIGQUIT);
506*6185db85Sdougm 		(void) sigaddset(&new, SIGTSTP);
507*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &new, &old);
508*6185db85Sdougm 		(void) lockf(fileno(dfstab), F_LOCK, 0);
509*6185db85Sdougm 		list = getdfstab(dfstab);
510*6185db85Sdougm 		rewind(dfstab);
511*6185db85Sdougm 		(void) remdfsline(list, line);
512*6185db85Sdougm 		outdfstab(dfstab, list);
513*6185db85Sdougm 		(void) fprintf(dfstab, "# Error: %s: %s", err, line);
514*6185db85Sdougm 		(void) fsync(fileno(dfstab));
515*6185db85Sdougm 		(void) lockf(fileno(dfstab), F_ULOCK, 0);
516*6185db85Sdougm 		(void) fclose(dfstab);
517*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &old, NULL);
518*6185db85Sdougm 		if (list != NULL)
519*6185db85Sdougm 		    dfs_free_list(list);
520*6185db85Sdougm 	}
521*6185db85Sdougm }
522*6185db85Sdougm 
523*6185db85Sdougm /*
524*6185db85Sdougm  * sa_delete_legacy(share)
525*6185db85Sdougm  *
526*6185db85Sdougm  * Delete the specified share from the legacy config file.
527*6185db85Sdougm  */
528*6185db85Sdougm 
529*6185db85Sdougm int
530*6185db85Sdougm sa_delete_legacy(sa_share_t share)
531*6185db85Sdougm {
532*6185db85Sdougm 	FILE *dfstab;
533*6185db85Sdougm 	int err;
534*6185db85Sdougm 	int ret = SA_OK;
535*6185db85Sdougm 	xfs_sharelist_t *list;
536*6185db85Sdougm 	char *path;
537*6185db85Sdougm 	sa_optionset_t optionset;
538*6185db85Sdougm 	sa_group_t parent;
539*6185db85Sdougm 	sigset_t old, new;
540*6185db85Sdougm 
541*6185db85Sdougm 	dfstab = open_dfstab(SA_LEGACY_DFSTAB);
542*6185db85Sdougm 	if (dfstab != NULL) {
543*6185db85Sdougm 		(void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8);
544*6185db85Sdougm 		(void) sigprocmask(SIG_BLOCK, NULL, &new);
545*6185db85Sdougm 		(void) sigaddset(&new, SIGHUP);
546*6185db85Sdougm 		(void) sigaddset(&new, SIGINT);
547*6185db85Sdougm 		(void) sigaddset(&new, SIGQUIT);
548*6185db85Sdougm 		(void) sigaddset(&new, SIGTSTP);
549*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &new, &old);
550*6185db85Sdougm 		path = sa_get_share_attr(share, "path");
551*6185db85Sdougm 		parent = sa_get_parent_group(share);
552*6185db85Sdougm 		if (parent != NULL) {
553*6185db85Sdougm 		    (void) lockf(fileno(dfstab), F_LOCK, 0);
554*6185db85Sdougm 		    list = getdfstab(dfstab);
555*6185db85Sdougm 		    rewind(dfstab);
556*6185db85Sdougm 		    for (optionset = sa_get_optionset(parent, NULL);
557*6185db85Sdougm 			optionset != NULL;
558*6185db85Sdougm 			optionset = sa_get_next_optionset(optionset)) {
559*6185db85Sdougm 			char *proto = sa_get_optionset_attr(optionset, "type");
560*6185db85Sdougm 			if (list != NULL && proto != NULL)
561*6185db85Sdougm 			    (void) remdfsentry(list, path, proto);
562*6185db85Sdougm 			if (proto == NULL)
563*6185db85Sdougm 			    ret = SA_NO_MEMORY;
564*6185db85Sdougm 			/*
565*6185db85Sdougm 			 * may want to only do the dfstab if this call
566*6185db85Sdougm 			 * returns NOT IMPLEMENTED but it shouldn't
567*6185db85Sdougm 			 * hurt.
568*6185db85Sdougm 			 */
569*6185db85Sdougm 			if (ret == SA_OK) {
570*6185db85Sdougm 			    err = sa_proto_delete_legacy(proto, share);
571*6185db85Sdougm 			    if (err != SA_NOT_IMPLEMENTED)
572*6185db85Sdougm 				ret = err;
573*6185db85Sdougm 			}
574*6185db85Sdougm 			if (proto != NULL)
575*6185db85Sdougm 			    sa_free_attr_string(proto);
576*6185db85Sdougm 		    }
577*6185db85Sdougm 		    outdfstab(dfstab, list);
578*6185db85Sdougm 		    if (list != NULL)
579*6185db85Sdougm 			dfs_free_list(list);
580*6185db85Sdougm 		    (void) fflush(dfstab);
581*6185db85Sdougm 		    (void) lockf(fileno(dfstab), F_ULOCK, 0);
582*6185db85Sdougm 		}
583*6185db85Sdougm 		(void) fsync(fileno(dfstab));
584*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &old, NULL);
585*6185db85Sdougm 		(void) fclose(dfstab);
586*6185db85Sdougm 		sa_free_attr_string(path);
587*6185db85Sdougm 	} else {
588*6185db85Sdougm 		if (errno == EACCES || errno == EPERM) {
589*6185db85Sdougm 		    ret = SA_NO_PERMISSION;
590*6185db85Sdougm 		} else {
591*6185db85Sdougm 		    ret = SA_CONFIG_ERR;
592*6185db85Sdougm 		}
593*6185db85Sdougm 	}
594*6185db85Sdougm 	return (ret);
595*6185db85Sdougm }
596*6185db85Sdougm 
597*6185db85Sdougm /*
598*6185db85Sdougm  * sa_update_legacy(share, proto)
599*6185db85Sdougm  *
600*6185db85Sdougm  * There is an assumption that dfstab will be the most common form of
601*6185db85Sdougm  * legacy configuration file for shares, but not the only one. Because
602*6185db85Sdougm  * of that, dfstab handling is done in the main code with calls to
603*6185db85Sdougm  * this function and protocol specific calls to deal with formating
604*6185db85Sdougm  * options into dfstab/share compatible syntax. Since not everything
605*6185db85Sdougm  * will be dfstab, there is a provision for calling a protocol
606*6185db85Sdougm  * specific plugin interface that allows the protocol plugin to do its
607*6185db85Sdougm  * own legacy files and skip the dfstab update.
608*6185db85Sdougm  */
609*6185db85Sdougm 
610*6185db85Sdougm int
611*6185db85Sdougm sa_update_legacy(sa_share_t share, char *proto)
612*6185db85Sdougm {
613*6185db85Sdougm 	FILE *dfstab;
614*6185db85Sdougm 	int ret = SA_OK;
615*6185db85Sdougm 	xfs_sharelist_t *list;
616*6185db85Sdougm 	char *path;
617*6185db85Sdougm 	sigset_t old, new;
618*6185db85Sdougm 	char *persist;
619*6185db85Sdougm 
620*6185db85Sdougm 	ret = sa_proto_update_legacy(proto, share);
621*6185db85Sdougm 	if (ret != SA_NOT_IMPLEMENTED)
622*6185db85Sdougm 	    return (ret);
623*6185db85Sdougm 	/* do the dfstab format */
624*6185db85Sdougm 	persist = sa_get_share_attr(share, "type");
625*6185db85Sdougm 	/*
626*6185db85Sdougm 	 * only update if the share is not transient -- no share type
627*6185db85Sdougm 	 * set or the type is not "transient".
628*6185db85Sdougm 	 */
629*6185db85Sdougm 	if (persist == NULL || strcmp(persist, "transient") != 0) {
630*6185db85Sdougm 	    dfstab = open_dfstab(SA_LEGACY_DFSTAB);
631*6185db85Sdougm 	    if (dfstab != NULL) {
632*6185db85Sdougm 		(void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8);
633*6185db85Sdougm 		(void) sigprocmask(SIG_BLOCK, NULL, &new);
634*6185db85Sdougm 		(void) sigaddset(&new, SIGHUP);
635*6185db85Sdougm 		(void) sigaddset(&new, SIGINT);
636*6185db85Sdougm 		(void) sigaddset(&new, SIGQUIT);
637*6185db85Sdougm 		(void) sigaddset(&new, SIGTSTP);
638*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &new, &old);
639*6185db85Sdougm 		path = sa_get_share_attr(share, "path");
640*6185db85Sdougm 		(void) lockf(fileno(dfstab), F_LOCK, 0);
641*6185db85Sdougm 		list = getdfstab(dfstab);
642*6185db85Sdougm 		rewind(dfstab);
643*6185db85Sdougm 		if (list != NULL)
644*6185db85Sdougm 		    list = remdfsentry(list, path, proto);
645*6185db85Sdougm 		list = adddfsentry(list, share, proto);
646*6185db85Sdougm 		outdfstab(dfstab, list);
647*6185db85Sdougm 		(void) fflush(dfstab);
648*6185db85Sdougm 		(void) lockf(fileno(dfstab), F_ULOCK, 0);
649*6185db85Sdougm 		(void) fsync(fileno(dfstab));
650*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &old, NULL);
651*6185db85Sdougm 		(void) fclose(dfstab);
652*6185db85Sdougm 		sa_free_attr_string(path);
653*6185db85Sdougm 		if (list != NULL)
654*6185db85Sdougm 		    dfs_free_list(list);
655*6185db85Sdougm 	    } else {
656*6185db85Sdougm 		if (errno == EACCES || errno == EPERM) {
657*6185db85Sdougm 		    ret = SA_NO_PERMISSION;
658*6185db85Sdougm 		} else {
659*6185db85Sdougm 		    ret = SA_CONFIG_ERR;
660*6185db85Sdougm 		}
661*6185db85Sdougm 	    }
662*6185db85Sdougm 	}
663*6185db85Sdougm 	if (persist != NULL)
664*6185db85Sdougm 	    sa_free_attr_string(persist);
665*6185db85Sdougm 	return (ret);
666*6185db85Sdougm }
667*6185db85Sdougm 
668*6185db85Sdougm /*
669*6185db85Sdougm  * sa_is_security(optname, proto)
670*6185db85Sdougm  *
671*6185db85Sdougm  * Check to see if optname is a security (named optionset) specific
672*6185db85Sdougm  * property for the specified protocol.
673*6185db85Sdougm  */
674*6185db85Sdougm 
675*6185db85Sdougm int
676*6185db85Sdougm sa_is_security(char *optname, char *proto)
677*6185db85Sdougm {
678*6185db85Sdougm 	int ret = 0;
679*6185db85Sdougm 	if (proto != NULL)
680*6185db85Sdougm 	    ret = sa_proto_security_prop(proto, optname);
681*6185db85Sdougm 	return (ret);
682*6185db85Sdougm }
683*6185db85Sdougm 
684*6185db85Sdougm /*
685*6185db85Sdougm  * add_syntax_comment(root, line, err, todfstab)
686*6185db85Sdougm  *
687*6185db85Sdougm  * add a comment to the document indicating a syntax error. If
688*6185db85Sdougm  * todfstab is set, write it back to the dfstab file as well.
689*6185db85Sdougm  */
690*6185db85Sdougm 
691*6185db85Sdougm static void
692*6185db85Sdougm add_syntax_comment(xmlNodePtr root, char *line, char *err, int todfstab)
693*6185db85Sdougm {
694*6185db85Sdougm 	xmlNodePtr node;
695*6185db85Sdougm 
696*6185db85Sdougm 	node = xmlNewChild(root, NULL, (xmlChar *)"error", (xmlChar *)line);
697*6185db85Sdougm 	if (node != NULL) {
698*6185db85Sdougm 	    xmlSetProp(node, (xmlChar *)"type", (xmlChar *)err);
699*6185db85Sdougm 	}
700*6185db85Sdougm 	if (todfstab)
701*6185db85Sdougm 	    sa_comment_line(line, err);
702*6185db85Sdougm }
703*6185db85Sdougm 
704*6185db85Sdougm /*
705*6185db85Sdougm  * sa_is_share(object)
706*6185db85Sdougm  *
707*6185db85Sdougm  * returns true of the object is of type "share".
708*6185db85Sdougm  */
709*6185db85Sdougm 
710*6185db85Sdougm int
711*6185db85Sdougm sa_is_share(void *object)
712*6185db85Sdougm {
713*6185db85Sdougm 	if (object != NULL) {
714*6185db85Sdougm 	    if (strcmp((char *)((xmlNodePtr)object)->name, "share") == 0)
715*6185db85Sdougm 		return (1);
716*6185db85Sdougm 	}
717*6185db85Sdougm 	return (0);
718*6185db85Sdougm }
719*6185db85Sdougm 
720*6185db85Sdougm /*
721*6185db85Sdougm  * _sa_remove_property(property)
722*6185db85Sdougm  *
723*6185db85Sdougm  * remove a property only from the document.
724*6185db85Sdougm  */
725*6185db85Sdougm 
726*6185db85Sdougm static void
727*6185db85Sdougm _sa_remove_property(sa_property_t property)
728*6185db85Sdougm {
729*6185db85Sdougm 	xmlUnlinkNode((xmlNodePtr)property);
730*6185db85Sdougm 	xmlFreeNode((xmlNodePtr)property);
731*6185db85Sdougm }
732*6185db85Sdougm 
733*6185db85Sdougm /*
734*6185db85Sdougm  * sa_parse_legacy_options(group, options, proto)
735*6185db85Sdougm  *
736*6185db85Sdougm  * In order to support legacy configurations, we allow the protocol
737*6185db85Sdougm  * specific plugin to parse legacy syntax options (like those in
738*6185db85Sdougm  * /etc/dfs/dfstab). This adds a new optionset to the group (or
739*6185db85Sdougm  * share).
740*6185db85Sdougm  *
741*6185db85Sdougm  * Once the optionset has been created, we then get the derived
742*6185db85Sdougm  * optionset of the parent (options from the optionset of the parent
743*6185db85Sdougm  * and any parent it might have) and remove those from the created
744*6185db85Sdougm  * optionset. This avoids duplication of options.
745*6185db85Sdougm  */
746*6185db85Sdougm 
747*6185db85Sdougm int
748*6185db85Sdougm sa_parse_legacy_options(sa_group_t group, char *options, char *proto)
749*6185db85Sdougm {
750*6185db85Sdougm 	int ret = SA_INVALID_PROTOCOL;
751*6185db85Sdougm 	sa_group_t parent;
752*6185db85Sdougm 	parent = sa_get_parent_group(group);
753*6185db85Sdougm 
754*6185db85Sdougm 	if (proto != NULL)
755*6185db85Sdougm 	    ret = sa_proto_legacy_opts(proto, group, options);
756*6185db85Sdougm 	/*
757*6185db85Sdougm 	 * if in a group, remove the inherited options and security
758*6185db85Sdougm 	 */
759*6185db85Sdougm 	if (ret == SA_OK) {
760*6185db85Sdougm 	    if (parent != NULL) {
761*6185db85Sdougm 		sa_optionset_t optionset;
762*6185db85Sdougm 		sa_property_t popt, prop;
763*6185db85Sdougm 		sa_optionset_t localoptions;
764*6185db85Sdougm 		/* find parent options to remove from child */
765*6185db85Sdougm 		optionset = sa_get_derived_optionset(parent, proto, 1);
766*6185db85Sdougm 		localoptions = sa_get_optionset(group, proto);
767*6185db85Sdougm 		if (optionset != NULL) {
768*6185db85Sdougm 		    for (popt = sa_get_property(optionset, NULL);
769*6185db85Sdougm 			popt != NULL;
770*6185db85Sdougm 			popt = sa_get_next_property(popt)) {
771*6185db85Sdougm 			char *tag;
772*6185db85Sdougm 			char *value1;
773*6185db85Sdougm 			char *value2;
774*6185db85Sdougm 
775*6185db85Sdougm 			tag = sa_get_property_attr(popt, "type");
776*6185db85Sdougm 			if (tag != NULL) {
777*6185db85Sdougm 			    prop = sa_get_property(localoptions, tag);
778*6185db85Sdougm 			    if (prop != NULL) {
779*6185db85Sdougm 				value1 = sa_get_property_attr(popt, "value");
780*6185db85Sdougm 				value2 = sa_get_property_attr(prop, "value");
781*6185db85Sdougm 				if (value1 != NULL && value2 != NULL &&
782*6185db85Sdougm 				    strcmp(value1, value2) == 0) {
783*6185db85Sdougm 				    /* remove the property from the child */
784*6185db85Sdougm 				    (void) _sa_remove_property(prop);
785*6185db85Sdougm 				}
786*6185db85Sdougm 				if (value1 != NULL)
787*6185db85Sdougm 				    sa_free_attr_string(value1);
788*6185db85Sdougm 				if (value2 != NULL)
789*6185db85Sdougm 				    sa_free_attr_string(value2);
790*6185db85Sdougm 			    }
791*6185db85Sdougm 			    sa_free_attr_string(tag);
792*6185db85Sdougm 			}
793*6185db85Sdougm 		    }
794*6185db85Sdougm 		    prop = sa_get_property(localoptions, NULL);
795*6185db85Sdougm 		    if (prop == NULL && sa_is_share(group)) {
796*6185db85Sdougm 			/*
797*6185db85Sdougm 			 * all properties removed so remove the
798*6185db85Sdougm 			 * optionset if it is on a share
799*6185db85Sdougm 			 */
800*6185db85Sdougm 			(void) _sa_remove_optionset(localoptions);
801*6185db85Sdougm 		    }
802*6185db85Sdougm 		    sa_free_derived_optionset(optionset);
803*6185db85Sdougm 		}
804*6185db85Sdougm 		/*
805*6185db85Sdougm 		 * need to remove security here. If there are no
806*6185db85Sdougm 		 * security options on the local group/share, don't
807*6185db85Sdougm 		 * bother since those are the only ones that would be
808*6185db85Sdougm 		 * affected.
809*6185db85Sdougm 		 */
810*6185db85Sdougm 		localoptions = sa_get_all_security_types(group, proto, 0);
811*6185db85Sdougm 		if (localoptions != NULL) {
812*6185db85Sdougm 		    for (prop = sa_get_property(localoptions, NULL);
813*6185db85Sdougm 			prop != NULL; prop = sa_get_next_property(prop)) {
814*6185db85Sdougm 			char *tag;
815*6185db85Sdougm 			sa_security_t security;
816*6185db85Sdougm 			tag = sa_get_property_attr(prop, "type");
817*6185db85Sdougm 			if (tag != NULL) {
818*6185db85Sdougm 			    security = sa_get_security(group, tag, proto);
819*6185db85Sdougm 			    sa_free_attr_string(tag);
820*6185db85Sdougm 			    for (popt = sa_get_property(security, NULL);
821*6185db85Sdougm 				popt != NULL;
822*6185db85Sdougm 				popt = sa_get_next_property(popt)) {
823*6185db85Sdougm 				char *value1;
824*6185db85Sdougm 				char *value2;
825*6185db85Sdougm 
826*6185db85Sdougm 				/* remove duplicates from this level */
827*6185db85Sdougm 				value1 = sa_get_property_attr(popt, "value");
828*6185db85Sdougm 				value2 = sa_get_property_attr(prop, "value");
829*6185db85Sdougm 				if (value1 != NULL && value2 != NULL &&
830*6185db85Sdougm 				    strcmp(value1, value2) == 0) {
831*6185db85Sdougm 				    /* remove the property from the child */
832*6185db85Sdougm 				    (void) _sa_remove_property(prop);
833*6185db85Sdougm 				}
834*6185db85Sdougm 				if (value1 != NULL)
835*6185db85Sdougm 				    sa_free_attr_string(value1);
836*6185db85Sdougm 				if (value2 != NULL)
837*6185db85Sdougm 				    sa_free_attr_string(value2);
838*6185db85Sdougm 			    }
839*6185db85Sdougm 			}
840*6185db85Sdougm 		    }
841*6185db85Sdougm 		    (void) sa_destroy_optionset(localoptions);
842*6185db85Sdougm 		}
843*6185db85Sdougm 	    }
844*6185db85Sdougm 	}
845*6185db85Sdougm 	return (ret);
846*6185db85Sdougm }
847*6185db85Sdougm 
848*6185db85Sdougm /*
849*6185db85Sdougm  * dfs_free_list(list)
850*6185db85Sdougm  *
851*6185db85Sdougm  * Free the data in each list entry of the list as well as freeing the
852*6185db85Sdougm  * entries themselves. We need to avoid memory leaks and don't want to
853*6185db85Sdougm  * dereference any NULL members.
854*6185db85Sdougm  */
855*6185db85Sdougm 
856*6185db85Sdougm static void
857*6185db85Sdougm dfs_free_list(xfs_sharelist_t *list)
858*6185db85Sdougm {
859*6185db85Sdougm 	xfs_sharelist_t *entry;
860*6185db85Sdougm 	for (entry = list; entry != NULL; entry = list) {
861*6185db85Sdougm 	    if (entry->path != NULL)
862*6185db85Sdougm 		free(entry->path);
863*6185db85Sdougm 	    if (entry->resource != NULL)
864*6185db85Sdougm 		free(entry->resource);
865*6185db85Sdougm 	    if (entry->fstype != NULL)
866*6185db85Sdougm 		free(entry->fstype);
867*6185db85Sdougm 	    if (entry->options != NULL)
868*6185db85Sdougm 		free(entry->options);
869*6185db85Sdougm 	    if (entry->description != NULL)
870*6185db85Sdougm 		free(entry->description);
871*6185db85Sdougm 	    if (entry->origline != NULL)
872*6185db85Sdougm 		free(entry->origline);
873*6185db85Sdougm 	    if (entry->group != NULL)
874*6185db85Sdougm 		free(entry->group);
875*6185db85Sdougm 	    list = list->next;
876*6185db85Sdougm 	    free(entry);
877*6185db85Sdougm 	}
878*6185db85Sdougm }
879*6185db85Sdougm 
880*6185db85Sdougm /*
881*6185db85Sdougm  * parse_dfstab(dfstab, root)
882*6185db85Sdougm  *
883*6185db85Sdougm  * Open and read the existing dfstab, parsing each line and adding it
884*6185db85Sdougm  * to the internal configuration. Make sure syntax errors, etc are
885*6185db85Sdougm  * preserved as comments.
886*6185db85Sdougm  */
887*6185db85Sdougm 
888*6185db85Sdougm static void
889*6185db85Sdougm parse_dfstab(char *dfstab, xmlNodePtr root)
890*6185db85Sdougm {
891*6185db85Sdougm 	sa_share_t share;
892*6185db85Sdougm 	sa_group_t group;
893*6185db85Sdougm 	sa_group_t sgroup = NULL;
894*6185db85Sdougm 	sa_group_t defgroup;
895*6185db85Sdougm 	xfs_sharelist_t *head, *list;
896*6185db85Sdougm 	int err;
897*6185db85Sdougm 	int defined_group;
898*6185db85Sdougm 	FILE *dfs;
899*6185db85Sdougm 	char *oldprops;
900*6185db85Sdougm 
901*6185db85Sdougm 	/* read the dfstab format file and fill in the doc tree */
902*6185db85Sdougm 
903*6185db85Sdougm 	dfs = fopen(dfstab, "r");
904*6185db85Sdougm 	if (dfs == NULL) {
905*6185db85Sdougm 	    return;
906*6185db85Sdougm 	}
907*6185db85Sdougm 
908*6185db85Sdougm 	defgroup = sa_get_group("default");
909*6185db85Sdougm 
910*6185db85Sdougm 	for (head = list = getdfstab(dfs);
911*6185db85Sdougm 		list != NULL;
912*6185db85Sdougm 		list = list->next) {
913*6185db85Sdougm 	    share = NULL;
914*6185db85Sdougm 	    group = NULL;
915*6185db85Sdougm 	    defined_group = 0;
916*6185db85Sdougm 	    err = 0;
917*6185db85Sdougm 
918*6185db85Sdougm 	    if (list->origline == NULL) {
919*6185db85Sdougm 		/*
920*6185db85Sdougm 		 * Comment line that we will likely skip.
921*6185db85Sdougm 		 * If the line has the syntax:
922*6185db85Sdougm 		 *	# error: string: string
923*6185db85Sdougm 		 * It should be preserved until manually deleted.
924*6185db85Sdougm 		 */
925*6185db85Sdougm 		if (list->description != NULL &&
926*6185db85Sdougm 		    strncmp(list->description, "# Error: ", 9) == 0) {
927*6185db85Sdougm 		    char *line;
928*6185db85Sdougm 		    char *error;
929*6185db85Sdougm 		    char *cmd;
930*6185db85Sdougm 		    line = strdup(list->description);
931*6185db85Sdougm 		    if (line != NULL) {
932*6185db85Sdougm 			error = line + 9;
933*6185db85Sdougm 			cmd = strchr(error, ':');
934*6185db85Sdougm 			if (cmd != NULL) {
935*6185db85Sdougm 			    int len;
936*6185db85Sdougm 			    *cmd = '\0';
937*6185db85Sdougm 			    cmd += 2;
938*6185db85Sdougm 			    len = strlen(cmd);
939*6185db85Sdougm 			    cmd[len - 1] = '\0';
940*6185db85Sdougm 			    add_syntax_comment(root, cmd, error, 0);
941*6185db85Sdougm 			}
942*6185db85Sdougm 			free(line);
943*6185db85Sdougm 		    }
944*6185db85Sdougm 		}
945*6185db85Sdougm 		continue;
946*6185db85Sdougm 	    }
947*6185db85Sdougm 	    if (list->path != NULL && strlen(list->path) > 0 &&
948*6185db85Sdougm 		*list->path == '/') {
949*6185db85Sdougm 		share = sa_find_share(list->path);
950*6185db85Sdougm 		if (share != NULL)
951*6185db85Sdougm 		    sgroup = sa_get_parent_group(share);
952*6185db85Sdougm 		else
953*6185db85Sdougm 		    sgroup = NULL;
954*6185db85Sdougm 	    } else {
955*6185db85Sdougm 		(void) printf(gettext("No share specified in dfstab: "
956*6185db85Sdougm 					"line %d: %s\n"),
957*6185db85Sdougm 			list->lineno, list->origline);
958*6185db85Sdougm 		add_syntax_comment(root, list->origline,
959*6185db85Sdougm 				    gettext("No share specified"),
960*6185db85Sdougm 				    1);
961*6185db85Sdougm 		continue;
962*6185db85Sdougm 	    }
963*6185db85Sdougm 	    if (list->group != NULL && strlen(list->group) > 0) {
964*6185db85Sdougm 		group = sa_get_group(list->group);
965*6185db85Sdougm 		defined_group = 1;
966*6185db85Sdougm 	    } else {
967*6185db85Sdougm 		group = defgroup;
968*6185db85Sdougm 	    }
969*6185db85Sdougm 	    if (defined_group && group == NULL) {
970*6185db85Sdougm 		(void) printf(gettext("Unknown group used in dfstab: "
971*6185db85Sdougm 					"line %d: %s\n"),
972*6185db85Sdougm 			list->lineno, list->origline);
973*6185db85Sdougm 		add_syntax_comment(root, list->origline,
974*6185db85Sdougm 				    gettext("Unknown group specified"), 1);
975*6185db85Sdougm 		continue;
976*6185db85Sdougm 	    }
977*6185db85Sdougm 	    if (group != NULL) {
978*6185db85Sdougm 		if (share == NULL) {
979*6185db85Sdougm 		    if (!defined_group && group == defgroup) {
980*6185db85Sdougm 			/* this is an OK add for legacy */
981*6185db85Sdougm 			share = sa_add_share(defgroup, list->path,
982*6185db85Sdougm 					SA_SHARE_PERMANENT | SA_SHARE_PARSER,
983*6185db85Sdougm 					&err);
984*6185db85Sdougm 			if (share != NULL) {
985*6185db85Sdougm 			    if (list->description != NULL &&
986*6185db85Sdougm 				strlen(list->description) > 0)
987*6185db85Sdougm 				(void) sa_set_share_description(share,
988*6185db85Sdougm 							    list->description);
989*6185db85Sdougm 			    if (list->options != NULL &&
990*6185db85Sdougm 				strlen(list->options) > 0) {
991*6185db85Sdougm 				(void) sa_parse_legacy_options(share,
992*6185db85Sdougm 								list->options,
993*6185db85Sdougm 								list->fstype);
994*6185db85Sdougm 			    }
995*6185db85Sdougm 			    if (list->resource != NULL)
996*6185db85Sdougm 				(void) sa_set_share_attr(share, "resource",
997*6185db85Sdougm 						    list->resource);
998*6185db85Sdougm 			} else {
999*6185db85Sdougm 			    (void) printf(gettext("Error in dfstab: "
1000*6185db85Sdougm 					    "line %d: %s\n"),
1001*6185db85Sdougm 				    list->lineno, list->origline);
1002*6185db85Sdougm 			    if (err != SA_BAD_PATH)
1003*6185db85Sdougm 				add_syntax_comment(root, list->origline,
1004*6185db85Sdougm 						gettext("Syntax"), 1);
1005*6185db85Sdougm 			    else
1006*6185db85Sdougm 				add_syntax_comment(root, list->origline,
1007*6185db85Sdougm 						gettext("Path"), 1);
1008*6185db85Sdougm 			    continue;
1009*6185db85Sdougm 			}
1010*6185db85Sdougm 		    }
1011*6185db85Sdougm 		} else {
1012*6185db85Sdougm 		    if (group != sgroup) {
1013*6185db85Sdougm 			(void) printf(gettext("Attempt to change"
1014*6185db85Sdougm 						"configuration in"
1015*6185db85Sdougm 						"dfstab: line %d: %s\n"),
1016*6185db85Sdougm 				list->lineno, list->origline);
1017*6185db85Sdougm 			add_syntax_comment(root, list->origline,
1018*6185db85Sdougm 				gettext("Attempt to change configuration"), 1);
1019*6185db85Sdougm 			continue;
1020*6185db85Sdougm 		    }
1021*6185db85Sdougm 		    /* its the same group but could have changed options */
1022*6185db85Sdougm 		    oldprops = sa_proto_legacy_format(list->fstype, share, 0);
1023*6185db85Sdougm 		    if (oldprops != NULL) {
1024*6185db85Sdougm 			if (list->options != NULL &&
1025*6185db85Sdougm 				strcmp(oldprops, list->options) != 0) {
1026*6185db85Sdougm 			    sa_optionset_t opts;
1027*6185db85Sdougm 			    sa_security_t secs;
1028*6185db85Sdougm 			    /* possibly different values */
1029*6185db85Sdougm 			    opts = sa_get_optionset((sa_group_t)share,
1030*6185db85Sdougm 							list->fstype);
1031*6185db85Sdougm 			    (void) sa_destroy_optionset(opts);
1032*6185db85Sdougm 			    for (secs = sa_get_security((sa_group_t)share,
1033*6185db85Sdougm 							NULL, list->fstype);
1034*6185db85Sdougm 				secs != NULL;
1035*6185db85Sdougm 				secs = sa_get_security((sa_group_t)share,
1036*6185db85Sdougm 							NULL, list->fstype)) {
1037*6185db85Sdougm 				(void) sa_destroy_security(secs);
1038*6185db85Sdougm 			    }
1039*6185db85Sdougm 			    (void) sa_parse_legacy_options(share,
1040*6185db85Sdougm 							    list->options,
1041*6185db85Sdougm 							    list->fstype);
1042*6185db85Sdougm 			}
1043*6185db85Sdougm 		    }
1044*6185db85Sdougm 		}
1045*6185db85Sdougm 	    } else {
1046*6185db85Sdougm 		/* shouldn't happen */
1047*6185db85Sdougm 		err = SA_CONFIG_ERR;
1048*6185db85Sdougm 	    }
1049*6185db85Sdougm 
1050*6185db85Sdougm 	}
1051*6185db85Sdougm 	dfs_free_list(head);
1052*6185db85Sdougm }
1053*6185db85Sdougm 
1054*6185db85Sdougm /*
1055*6185db85Sdougm  * legacy_removes(group, file)
1056*6185db85Sdougm  *
1057*6185db85Sdougm  * Find any shares that are "missing" from the legacy file. These
1058*6185db85Sdougm  * should be removed from the configuration since they are likely from
1059*6185db85Sdougm  * a legacy app or the admin modified the dfstab file directly. We
1060*6185db85Sdougm  * have to support this even if it is not the recommended way to do
1061*6185db85Sdougm  * things.
1062*6185db85Sdougm  */
1063*6185db85Sdougm 
1064*6185db85Sdougm static void
1065*6185db85Sdougm legacy_removes(sa_group_t group, char *file)
1066*6185db85Sdougm {
1067*6185db85Sdougm 	sa_share_t share;
1068*6185db85Sdougm 	char *path;
1069*6185db85Sdougm 	xfs_sharelist_t *list, *item;
1070*6185db85Sdougm 	FILE *dfstab;
1071*6185db85Sdougm 
1072*6185db85Sdougm 	dfstab = fopen(file, "r");
1073*6185db85Sdougm 	if (dfstab != NULL) {
1074*6185db85Sdougm 	    list = getdfstab(dfstab);
1075*6185db85Sdougm 	    (void) fclose(dfstab);
1076*6185db85Sdougm 	    for (share = sa_get_share(group, NULL); share != NULL;
1077*6185db85Sdougm 		share = sa_get_next_share(share)) {
1078*6185db85Sdougm 		/* now see if the share is in the dfstab file */
1079*6185db85Sdougm 		path = sa_get_share_attr(share, "path");
1080*6185db85Sdougm 		if (path != NULL) {
1081*6185db85Sdougm 		    item = finddfsentry(list, path);
1082*6185db85Sdougm 		    if (item == NULL) {
1083*6185db85Sdougm 			/* the share was removed this way */
1084*6185db85Sdougm 			(void) sa_remove_share(share);
1085*6185db85Sdougm 			/* start over since the list was broken */
1086*6185db85Sdougm 			share = sa_get_share(group, NULL);
1087*6185db85Sdougm 		    }
1088*6185db85Sdougm 		    sa_free_attr_string(path);
1089*6185db85Sdougm 		}
1090*6185db85Sdougm 	    }
1091*6185db85Sdougm 	    if (list != NULL)
1092*6185db85Sdougm 		dfs_free_list(list);
1093*6185db85Sdougm 	}
1094*6185db85Sdougm }
1095*6185db85Sdougm 
1096*6185db85Sdougm /*
1097*6185db85Sdougm  * getlegacyconfig(path, root)
1098*6185db85Sdougm  *
1099*6185db85Sdougm  * Parse dfstab and build the legacy configuration. This only gets
1100*6185db85Sdougm  * called when a change was detected.
1101*6185db85Sdougm  */
1102*6185db85Sdougm 
1103*6185db85Sdougm void
1104*6185db85Sdougm getlegacyconfig(char *path, xmlNodePtr *root)
1105*6185db85Sdougm {
1106*6185db85Sdougm 	sa_group_t defgroup;
1107*6185db85Sdougm 
1108*6185db85Sdougm 	if (root != NULL) {
1109*6185db85Sdougm 	    if (*root == NULL)
1110*6185db85Sdougm 		*root = xmlNewNode(NULL, (xmlChar *)"sharecfg");
1111*6185db85Sdougm 	    if (*root != NULL) {
1112*6185db85Sdougm 		if (strcmp(path, SA_LEGACY_DFSTAB) == 0) {
1113*6185db85Sdougm 			/*
1114*6185db85Sdougm 			 * walk the default shares and find anything
1115*6185db85Sdougm 			 * missing.  we do this first to make sure it
1116*6185db85Sdougm 			 * is cleaned up since there may be legacy
1117*6185db85Sdougm 			 * code add/del via dfstab and we need to
1118*6185db85Sdougm 			 * cleanup SMF.
1119*6185db85Sdougm 			 */
1120*6185db85Sdougm 		    defgroup = sa_get_group("default");
1121*6185db85Sdougm 		    if (defgroup != NULL) {
1122*6185db85Sdougm 			legacy_removes(defgroup, path);
1123*6185db85Sdougm 		    }
1124*6185db85Sdougm 		    /* parse the dfstab and add anything new */
1125*6185db85Sdougm 		    parse_dfstab(path, *root);
1126*6185db85Sdougm 		}
1127*6185db85Sdougm 	    }
1128*6185db85Sdougm 	}
1129*6185db85Sdougm }
1130*6185db85Sdougm 
1131*6185db85Sdougm /*
1132*6185db85Sdougm  * parse_sharetab(void)
1133*6185db85Sdougm  *
1134*6185db85Sdougm  * Read the /etc/dfs/sharetab file via libfsmgt and see which entries
1135*6185db85Sdougm  * don't exist in the repository. These shares are marked transient.
1136*6185db85Sdougm  * We also need to see if they are ZFS shares since ZFS bypasses the
1137*6185db85Sdougm  * SMF repository.
1138*6185db85Sdougm  */
1139*6185db85Sdougm 
1140*6185db85Sdougm int
1141*6185db85Sdougm parse_sharetab(void)
1142*6185db85Sdougm {
1143*6185db85Sdougm 	fs_sharelist_t *list, *tmplist;
1144*6185db85Sdougm 	int err = 0;
1145*6185db85Sdougm 	sa_share_t share;
1146*6185db85Sdougm 	sa_group_t group;
1147*6185db85Sdougm 	sa_group_t lgroup;
1148*6185db85Sdougm 	char *groupname;
1149*6185db85Sdougm 	int legacy = 0;
1150*6185db85Sdougm 
1151*6185db85Sdougm 	list = fs_get_share_list(&err);
1152*6185db85Sdougm 	if (list == NULL)
1153*6185db85Sdougm 	    return (legacy);
1154*6185db85Sdougm 
1155*6185db85Sdougm 	lgroup = sa_get_group("default");
1156*6185db85Sdougm 
1157*6185db85Sdougm 	for (tmplist = list; tmplist != NULL; tmplist = tmplist->next) {
1158*6185db85Sdougm 	    group = NULL;
1159*6185db85Sdougm 	    share = sa_find_share(tmplist->path);
1160*6185db85Sdougm 	    if (share == NULL) {
1161*6185db85Sdougm 		/*
1162*6185db85Sdougm 		 * this share is transient so needs to be
1163*6185db85Sdougm 		 * added. Initially, this will be under
1164*6185db85Sdougm 		 * default(legacy) unless it is a ZFS
1165*6185db85Sdougm 		 * share. If zfs, we need a zfs group.
1166*6185db85Sdougm 		 */
1167*6185db85Sdougm 		if (tmplist->resource != NULL &&
1168*6185db85Sdougm 		    (groupname = strchr(tmplist->resource, '@')) != NULL) {
1169*6185db85Sdougm 		    /* there is a defined group */
1170*6185db85Sdougm 		    *groupname++ = '\0';
1171*6185db85Sdougm 		    group = sa_get_group(groupname);
1172*6185db85Sdougm 		    if (group != NULL) {
1173*6185db85Sdougm 			share = _sa_add_share(group, tmplist->path,
1174*6185db85Sdougm 						SA_SHARE_TRANSIENT, &err);
1175*6185db85Sdougm 		    } else {
1176*6185db85Sdougm 			(void) printf(gettext("Group for temporary share"
1177*6185db85Sdougm 						"not found: %s\n"),
1178*6185db85Sdougm 					tmplist->path);
1179*6185db85Sdougm 			share = _sa_add_share(lgroup, tmplist->path,
1180*6185db85Sdougm 						SA_SHARE_TRANSIENT, &err);
1181*6185db85Sdougm 		    }
1182*6185db85Sdougm 		} else {
1183*6185db85Sdougm 		    if (sa_zfs_is_shared(tmplist->path)) {
1184*6185db85Sdougm 			group = sa_get_group("zfs");
1185*6185db85Sdougm 			if (group == NULL) {
1186*6185db85Sdougm 			    group = sa_create_group("zfs", &err);
1187*6185db85Sdougm 			    if (group == NULL && err == SA_NO_PERMISSION) {
1188*6185db85Sdougm 				group = _sa_create_group("zfs");
1189*6185db85Sdougm 			    }
1190*6185db85Sdougm 			    if (group != NULL) {
1191*6185db85Sdougm 				(void) sa_create_optionset(group,
1192*6185db85Sdougm 							    tmplist->fstype);
1193*6185db85Sdougm 				(void) sa_set_group_attr(group, "zfs", "true");
1194*6185db85Sdougm 			    }
1195*6185db85Sdougm 			}
1196*6185db85Sdougm 			if (group != NULL) {
1197*6185db85Sdougm 			    share = _sa_add_share(group, tmplist->path,
1198*6185db85Sdougm 						    SA_SHARE_TRANSIENT, &err);
1199*6185db85Sdougm 			}
1200*6185db85Sdougm 		    } else {
1201*6185db85Sdougm 			share = _sa_add_share(lgroup, tmplist->path,
1202*6185db85Sdougm 						SA_SHARE_TRANSIENT, &err);
1203*6185db85Sdougm 		    }
1204*6185db85Sdougm 		}
1205*6185db85Sdougm 		if (share == NULL)
1206*6185db85Sdougm 		    (void) printf(gettext("Problem with transient: %s\n"),
1207*6185db85Sdougm 				    sa_errorstr(err));
1208*6185db85Sdougm 		if (share != NULL)
1209*6185db85Sdougm 		    set_node_attr(share, "shared", "true");
1210*6185db85Sdougm 
1211*6185db85Sdougm 		if (err == SA_OK) {
1212*6185db85Sdougm 		    if (tmplist->options != NULL &&
1213*6185db85Sdougm 			strlen(tmplist->options) > 0) {
1214*6185db85Sdougm 			(void) sa_parse_legacy_options(share,
1215*6185db85Sdougm 							tmplist->options,
1216*6185db85Sdougm 							tmplist->fstype);
1217*6185db85Sdougm 		    }
1218*6185db85Sdougm 		    if (tmplist->resource != NULL &&
1219*6185db85Sdougm 			strcmp(tmplist->resource, "-") != 0)
1220*6185db85Sdougm 			set_node_attr(share, "resource", tmplist->resource);
1221*6185db85Sdougm 		    if (tmplist->description != NULL) {
1222*6185db85Sdougm 			xmlNodePtr node;
1223*6185db85Sdougm 			node = xmlNewChild((xmlNodePtr)share, NULL,
1224*6185db85Sdougm 						(xmlChar *)"description", NULL);
1225*6185db85Sdougm 			xmlNodeSetContent(node,
1226*6185db85Sdougm 					    (xmlChar *)tmplist->description);
1227*6185db85Sdougm 		    }
1228*6185db85Sdougm 		    legacy = 1;
1229*6185db85Sdougm 		}
1230*6185db85Sdougm 	    } else {
1231*6185db85Sdougm 		/*
1232*6185db85Sdougm 		 * if this is a legacy share, mark as shared so we
1233*6185db85Sdougm 		 * only update sharetab appropriately.
1234*6185db85Sdougm 		 */
1235*6185db85Sdougm 		set_node_attr(share, "shared", "true");
1236*6185db85Sdougm 	    }
1237*6185db85Sdougm 	}
1238*6185db85Sdougm 	fs_free_share_list(list);
1239*6185db85Sdougm 	return (legacy);
1240*6185db85Sdougm }
1241*6185db85Sdougm 
1242*6185db85Sdougm /*
1243*6185db85Sdougm  * get the transient shares from the sharetab (or other) file.  since
1244*6185db85Sdougm  * these are transient, they only appear in the working file and not
1245*6185db85Sdougm  * in a repository.
1246*6185db85Sdougm  */
1247*6185db85Sdougm int
1248*6185db85Sdougm gettransients(xmlNodePtr *root)
1249*6185db85Sdougm {
1250*6185db85Sdougm 	int legacy = 0;
1251*6185db85Sdougm 
1252*6185db85Sdougm 	if (root != NULL) {
1253*6185db85Sdougm 	    if (*root == NULL)
1254*6185db85Sdougm 		*root = xmlNewNode(NULL, (xmlChar *)"sharecfg");
1255*6185db85Sdougm 	    if (*root != NULL) {
1256*6185db85Sdougm 		legacy = parse_sharetab();
1257*6185db85Sdougm 	    }
1258*6185db85Sdougm 	}
1259*6185db85Sdougm 	return (legacy);
1260*6185db85Sdougm }
1261*6185db85Sdougm 
1262*6185db85Sdougm /*
1263*6185db85Sdougm  * sa_has_prop(optionset, prop)
1264*6185db85Sdougm  *
1265*6185db85Sdougm  * Is the specified property a member of the optionset?
1266*6185db85Sdougm  */
1267*6185db85Sdougm 
1268*6185db85Sdougm int
1269*6185db85Sdougm sa_has_prop(sa_optionset_t optionset, sa_property_t prop)
1270*6185db85Sdougm {
1271*6185db85Sdougm 	char *name;
1272*6185db85Sdougm 	sa_property_t otherprop;
1273*6185db85Sdougm 	int result = 0;
1274*6185db85Sdougm 
1275*6185db85Sdougm 	if (optionset != NULL) {
1276*6185db85Sdougm 	    name = sa_get_property_attr(prop, "type");
1277*6185db85Sdougm 	    if (name != NULL) {
1278*6185db85Sdougm 		otherprop = sa_get_property(optionset, name);
1279*6185db85Sdougm 		if (otherprop != NULL)
1280*6185db85Sdougm 		    result = 1;
1281*6185db85Sdougm 		sa_free_attr_string(name);
1282*6185db85Sdougm 	    }
1283*6185db85Sdougm 	}
1284*6185db85Sdougm 	return (result);
1285*6185db85Sdougm }
1286*6185db85Sdougm 
1287*6185db85Sdougm /*
1288*6185db85Sdougm  * Update legacy files
1289*6185db85Sdougm  *
1290*6185db85Sdougm  * Provides functions to add/remove/modify individual entries
1291*6185db85Sdougm  * in dfstab and sharetab
1292*6185db85Sdougm  */
1293*6185db85Sdougm 
1294*6185db85Sdougm void
1295*6185db85Sdougm update_legacy_config(void)
1296*6185db85Sdougm {
1297*6185db85Sdougm 	/*
1298*6185db85Sdougm 	 * no longer used -- this is a placeholder in case we need to
1299*6185db85Sdougm 	 * add it back later.
1300*6185db85Sdougm 	 */
1301*6185db85Sdougm }
1302*6185db85Sdougm 
1303*6185db85Sdougm /*
1304*6185db85Sdougm  * sa_valid_property(object, proto, property)
1305*6185db85Sdougm  *
1306*6185db85Sdougm  * check to see if the specified property is valid relative to the
1307*6185db85Sdougm  * specified protocol. The protocol plugin is called to do the work.
1308*6185db85Sdougm  */
1309*6185db85Sdougm 
1310*6185db85Sdougm int
1311*6185db85Sdougm sa_valid_property(void *object, char *proto, sa_property_t property)
1312*6185db85Sdougm {
1313*6185db85Sdougm 	int ret = SA_OK;
1314*6185db85Sdougm 
1315*6185db85Sdougm 	if (proto != NULL && property != NULL) {
1316*6185db85Sdougm 	    ret = sa_proto_valid_prop(proto, property, object);
1317*6185db85Sdougm 	}
1318*6185db85Sdougm 
1319*6185db85Sdougm 	return (ret);
1320*6185db85Sdougm }
1321*6185db85Sdougm 
1322*6185db85Sdougm /*
1323*6185db85Sdougm  * sa_fstype(path)
1324*6185db85Sdougm  *
1325*6185db85Sdougm  * Given path, return the string representing the path's file system
1326*6185db85Sdougm  * type. This is used to discover ZFS shares.
1327*6185db85Sdougm  */
1328*6185db85Sdougm 
1329*6185db85Sdougm char *
1330*6185db85Sdougm sa_fstype(char *path)
1331*6185db85Sdougm {
1332*6185db85Sdougm 	int err;
1333*6185db85Sdougm 	struct stat st;
1334*6185db85Sdougm 
1335*6185db85Sdougm 	err = stat(path, &st);
1336*6185db85Sdougm 	if (err < 0) {
1337*6185db85Sdougm 	    err = SA_NO_SUCH_PATH;
1338*6185db85Sdougm 	} else {
1339*6185db85Sdougm 	    err = SA_OK;
1340*6185db85Sdougm 	}
1341*6185db85Sdougm 	if (err == SA_OK) {
1342*6185db85Sdougm 		/* have a valid path at this point */
1343*6185db85Sdougm 	    return (strdup(st.st_fstype));
1344*6185db85Sdougm 	}
1345*6185db85Sdougm 	return (NULL);
1346*6185db85Sdougm }
1347*6185db85Sdougm 
1348*6185db85Sdougm void
1349*6185db85Sdougm sa_free_fstype(char *type)
1350*6185db85Sdougm {
1351*6185db85Sdougm 	free(type);
1352*6185db85Sdougm }
1353*6185db85Sdougm 
1354*6185db85Sdougm /*
1355*6185db85Sdougm  * sa_get_derived_optionset(object, proto, hier)
1356*6185db85Sdougm  *
1357*6185db85Sdougm  *	Work backward to the top of the share object tree and start
1358*6185db85Sdougm  *	copying protocol specific optionsets into a newly created
1359*6185db85Sdougm  *	optionset that doesn't have a parent (it will be freed
1360*6185db85Sdougm  *	later). This provides for the property inheritence model. That
1361*6185db85Sdougm  *	is, properties closer to the share take precedence over group
1362*6185db85Sdougm  *	level. This also provides for groups of groups in the future.
1363*6185db85Sdougm  */
1364*6185db85Sdougm 
1365*6185db85Sdougm sa_optionset_t
1366*6185db85Sdougm sa_get_derived_optionset(void *object, char *proto, int hier)
1367*6185db85Sdougm {
1368*6185db85Sdougm 	sa_optionset_t newoptionset;
1369*6185db85Sdougm 	sa_optionset_t optionset;
1370*6185db85Sdougm 	sa_group_t group;
1371*6185db85Sdougm 
1372*6185db85Sdougm 	if (hier &&
1373*6185db85Sdougm 	    (group = sa_get_parent_group((sa_share_t)object)) != NULL) {
1374*6185db85Sdougm 	    newoptionset = sa_get_derived_optionset((void *)group, proto, hier);
1375*6185db85Sdougm 	} else {
1376*6185db85Sdougm 	    newoptionset = (sa_optionset_t)xmlNewNode(NULL,
1377*6185db85Sdougm 						    (xmlChar *)"optionset");
1378*6185db85Sdougm 	    if (newoptionset != NULL) {
1379*6185db85Sdougm 		sa_set_optionset_attr(newoptionset, "type", proto);
1380*6185db85Sdougm 	    }
1381*6185db85Sdougm 	}
1382*6185db85Sdougm 	/* dont' do anything if memory wasn't allocated */
1383*6185db85Sdougm 	if (newoptionset == NULL)
1384*6185db85Sdougm 	    return (NULL);
1385*6185db85Sdougm 
1386*6185db85Sdougm 	/* found the top so working back down the stack */
1387*6185db85Sdougm 	optionset = sa_get_optionset((sa_optionset_t)object, proto);
1388*6185db85Sdougm 	if (optionset != NULL) {
1389*6185db85Sdougm 	    sa_property_t prop;
1390*6185db85Sdougm 	    /* add optionset to the newoptionset */
1391*6185db85Sdougm 	    for (prop = sa_get_property(optionset, NULL);
1392*6185db85Sdougm 		prop != NULL; prop = sa_get_next_property(prop)) {
1393*6185db85Sdougm 		sa_property_t newprop;
1394*6185db85Sdougm 		char *name;
1395*6185db85Sdougm 		char *value;
1396*6185db85Sdougm 		name = sa_get_property_attr(prop, "type");
1397*6185db85Sdougm 		value = sa_get_property_attr(prop, "value");
1398*6185db85Sdougm 		if (name != NULL) {
1399*6185db85Sdougm 		    newprop = sa_get_property(newoptionset, name);
1400*6185db85Sdougm 		    /* replace the value with the new value */
1401*6185db85Sdougm 		    if (newprop != NULL) {
1402*6185db85Sdougm 			/*
1403*6185db85Sdougm 			 * only set if value is non NULL, old value ok
1404*6185db85Sdougm 			 * if it is NULL.
1405*6185db85Sdougm 			 */
1406*6185db85Sdougm 			if (value != NULL)
1407*6185db85Sdougm 			    set_node_attr(newprop, "value", value);
1408*6185db85Sdougm 		    } else {
1409*6185db85Sdougm 			/* an entirely new property */
1410*6185db85Sdougm 			if (value != NULL) {
1411*6185db85Sdougm 			    newprop = sa_create_property(name, value);
1412*6185db85Sdougm 			    if (newprop != NULL) {
1413*6185db85Sdougm 				newprop = (sa_property_t)
1414*6185db85Sdougm 				    xmlAddChild((xmlNodePtr)newoptionset,
1415*6185db85Sdougm 						(xmlNodePtr)newprop);
1416*6185db85Sdougm 			    }
1417*6185db85Sdougm 			}
1418*6185db85Sdougm 		    }
1419*6185db85Sdougm 		    sa_free_attr_string(name);
1420*6185db85Sdougm 		}
1421*6185db85Sdougm 		if (value != NULL)
1422*6185db85Sdougm 		    sa_free_attr_string(value);
1423*6185db85Sdougm 	    }
1424*6185db85Sdougm 	}
1425*6185db85Sdougm 	return (newoptionset);
1426*6185db85Sdougm }
1427*6185db85Sdougm 
1428*6185db85Sdougm void
1429*6185db85Sdougm sa_free_derived_optionset(sa_optionset_t optionset)
1430*6185db85Sdougm {
1431*6185db85Sdougm 	/* while it shouldn't be linked, it doesn't hurt */
1432*6185db85Sdougm 	if (optionset != NULL) {
1433*6185db85Sdougm 	    xmlUnlinkNode((xmlNodePtr) optionset);
1434*6185db85Sdougm 	    xmlFreeNode((xmlNodePtr) optionset);
1435*6185db85Sdougm 	}
1436*6185db85Sdougm }
1437*6185db85Sdougm 
1438*6185db85Sdougm /*
1439*6185db85Sdougm  *  sa_get_all_security_types(object, proto, hier)
1440*6185db85Sdougm  *
1441*6185db85Sdougm  *	find all the security types set for this object.  This is
1442*6185db85Sdougm  *	preliminary to getting a derived security set. The return value is an
1443*6185db85Sdougm  *	optionset containg properties which are the sectype values found by
1444*6185db85Sdougm  *	walking up the XML document struture. The returned optionset
1445*6185db85Sdougm  *	is a derived optionset.
1446*6185db85Sdougm  *
1447*6185db85Sdougm  *	If hier is 0, only look at object. If non-zero, walk up the tree.
1448*6185db85Sdougm  */
1449*6185db85Sdougm sa_optionset_t
1450*6185db85Sdougm sa_get_all_security_types(void *object, char *proto, int hier)
1451*6185db85Sdougm {
1452*6185db85Sdougm 	sa_optionset_t options;
1453*6185db85Sdougm 	sa_security_t security;
1454*6185db85Sdougm 	sa_group_t group;
1455*6185db85Sdougm 	sa_property_t prop;
1456*6185db85Sdougm 
1457*6185db85Sdougm 	options = NULL;
1458*6185db85Sdougm 
1459*6185db85Sdougm 	if (hier &&
1460*6185db85Sdougm 	    (group = sa_get_parent_group((sa_share_t)object)) != NULL) {
1461*6185db85Sdougm 	    options = sa_get_all_security_types((void *)group, proto, hier);
1462*6185db85Sdougm 	} else {
1463*6185db85Sdougm 	    options = (sa_optionset_t)xmlNewNode(NULL,
1464*6185db85Sdougm 						    (xmlChar *)"optionset");
1465*6185db85Sdougm 	}
1466*6185db85Sdougm 	/* hit the top so collect the security types working back */
1467*6185db85Sdougm 	if (options != NULL) {
1468*6185db85Sdougm 	    for (security = sa_get_security((sa_group_t)object, NULL, NULL);
1469*6185db85Sdougm 		security != NULL; security = sa_get_next_security(security)) {
1470*6185db85Sdougm 		char *type;
1471*6185db85Sdougm 		char *sectype;
1472*6185db85Sdougm 
1473*6185db85Sdougm 		type = sa_get_security_attr(security, "type");
1474*6185db85Sdougm 		if (type != NULL) {
1475*6185db85Sdougm 		    if (strcmp(type, proto) != 0) {
1476*6185db85Sdougm 			sa_free_attr_string(type);
1477*6185db85Sdougm 			continue;
1478*6185db85Sdougm 		    }
1479*6185db85Sdougm 		    sectype = sa_get_security_attr(security, "sectype");
1480*6185db85Sdougm 		    if (sectype != NULL) {
1481*6185db85Sdougm 			/*
1482*6185db85Sdougm 			 * have a security type, check to see if
1483*6185db85Sdougm 			 * already present in optionset and add if it
1484*6185db85Sdougm 			 * isn't.
1485*6185db85Sdougm 			 */
1486*6185db85Sdougm 			if (sa_get_property(options, sectype) == NULL) {
1487*6185db85Sdougm 			    prop = sa_create_property(sectype, "true");
1488*6185db85Sdougm 			    if (prop != NULL)
1489*6185db85Sdougm 				prop = (sa_property_t)
1490*6185db85Sdougm 				    xmlAddChild((xmlNodePtr)options,
1491*6185db85Sdougm 						(xmlNodePtr)prop);
1492*6185db85Sdougm 			}
1493*6185db85Sdougm 			sa_free_attr_string(sectype);
1494*6185db85Sdougm 		    }
1495*6185db85Sdougm 		    sa_free_attr_string(type);
1496*6185db85Sdougm 		}
1497*6185db85Sdougm 	    }
1498*6185db85Sdougm 	}
1499*6185db85Sdougm 	return (options);
1500*6185db85Sdougm }
1501*6185db85Sdougm 
1502*6185db85Sdougm /*
1503*6185db85Sdougm  * sa_get_derived_security(object, sectype, proto, hier)
1504*6185db85Sdougm  *
1505*6185db85Sdougm  * Get the derived security(named optionset) for the object given the
1506*6185db85Sdougm  * sectype and proto. If hier is non-zero, walk up the tree to get all
1507*6185db85Sdougm  * properties defined for this object, otherwise just those on the
1508*6185db85Sdougm  * object.
1509*6185db85Sdougm  */
1510*6185db85Sdougm 
1511*6185db85Sdougm sa_security_t
1512*6185db85Sdougm sa_get_derived_security(void *object, char *sectype, char *proto, int hier)
1513*6185db85Sdougm {
1514*6185db85Sdougm 	sa_security_t newsecurity;
1515*6185db85Sdougm 	sa_security_t security;
1516*6185db85Sdougm 	sa_group_t group;
1517*6185db85Sdougm 
1518*6185db85Sdougm 	if (hier &&
1519*6185db85Sdougm 	    (group = sa_get_parent_group((sa_share_t)object)) != NULL) {
1520*6185db85Sdougm 	    newsecurity = sa_get_derived_security((void *)group,
1521*6185db85Sdougm 						    sectype, proto, hier);
1522*6185db85Sdougm 	} else {
1523*6185db85Sdougm 	    newsecurity = (sa_security_t)xmlNewNode(NULL,
1524*6185db85Sdougm 						    (xmlChar *)"security");
1525*6185db85Sdougm 	    if (newsecurity != NULL) {
1526*6185db85Sdougm 		sa_set_security_attr(newsecurity, "type", proto);
1527*6185db85Sdougm 		sa_set_security_attr(newsecurity, "sectype", sectype);
1528*6185db85Sdougm 	    }
1529*6185db85Sdougm 	}
1530*6185db85Sdougm 	/* dont' do anything if memory wasn't allocated */
1531*6185db85Sdougm 	if (newsecurity == NULL)
1532*6185db85Sdougm 	    return (NULL);
1533*6185db85Sdougm 
1534*6185db85Sdougm 	/* found the top so working back down the stack */
1535*6185db85Sdougm 	security = sa_get_security((sa_security_t)object, sectype, proto);
1536*6185db85Sdougm 	if (security != NULL) {
1537*6185db85Sdougm 	    sa_property_t prop;
1538*6185db85Sdougm 	    /* add security to the newsecurity */
1539*6185db85Sdougm 	    for (prop = sa_get_property(security, NULL);
1540*6185db85Sdougm 		prop != NULL; prop = sa_get_next_property(prop)) {
1541*6185db85Sdougm 		sa_property_t newprop;
1542*6185db85Sdougm 		char *name;
1543*6185db85Sdougm 		char *value;
1544*6185db85Sdougm 		name = sa_get_property_attr(prop, "type");
1545*6185db85Sdougm 		value = sa_get_property_attr(prop, "value");
1546*6185db85Sdougm 		if (name != NULL) {
1547*6185db85Sdougm 		    newprop = sa_get_property(newsecurity, name);
1548*6185db85Sdougm 		    /* replace the value with the new value */
1549*6185db85Sdougm 		    if (newprop != NULL) {
1550*6185db85Sdougm 			/*
1551*6185db85Sdougm 			 * only set if value is non NULL, old value ok
1552*6185db85Sdougm 			 * if it is NULL.
1553*6185db85Sdougm 			 */
1554*6185db85Sdougm 			if (value != NULL)
1555*6185db85Sdougm 			    set_node_attr(newprop, name, value);
1556*6185db85Sdougm 		    } else {
1557*6185db85Sdougm 			/* an entirely new property */
1558*6185db85Sdougm 			if (value != NULL) {
1559*6185db85Sdougm 			    newprop = sa_create_property(name, value);
1560*6185db85Sdougm 			    newprop = (sa_property_t)
1561*6185db85Sdougm 				xmlAddChild((xmlNodePtr)newsecurity,
1562*6185db85Sdougm 					    (xmlNodePtr)newprop);
1563*6185db85Sdougm 			}
1564*6185db85Sdougm 		    }
1565*6185db85Sdougm 		    sa_free_attr_string(name);
1566*6185db85Sdougm 		}
1567*6185db85Sdougm 		if (value != NULL)
1568*6185db85Sdougm 		    sa_free_attr_string(value);
1569*6185db85Sdougm 	    }
1570*6185db85Sdougm 	}
1571*6185db85Sdougm 	return (newsecurity);
1572*6185db85Sdougm }
1573*6185db85Sdougm 
1574*6185db85Sdougm void
1575*6185db85Sdougm sa_free_derived_security(sa_security_t security)
1576*6185db85Sdougm {
1577*6185db85Sdougm 	/* while it shouldn't be linked, it doesn't hurt */
1578*6185db85Sdougm 	if (security != NULL) {
1579*6185db85Sdougm 	    xmlUnlinkNode((xmlNodePtr)security);
1580*6185db85Sdougm 	    xmlFreeNode((xmlNodePtr)security);
1581*6185db85Sdougm 	}
1582*6185db85Sdougm }
1583*6185db85Sdougm 
1584*6185db85Sdougm /*
1585*6185db85Sdougm  * sharetab utility functions
1586*6185db85Sdougm  *
1587*6185db85Sdougm  * makes use of the original sharetab.c from fs.d/nfs/lib
1588*6185db85Sdougm  */
1589*6185db85Sdougm 
1590*6185db85Sdougm /*
1591*6185db85Sdougm  * fillshare(share, proto, sh)
1592*6185db85Sdougm  *
1593*6185db85Sdougm  * Fill the struct share with values obtained from the share object.
1594*6185db85Sdougm  */
1595*6185db85Sdougm static void
1596*6185db85Sdougm fillshare(sa_share_t share, char *proto, struct share *sh)
1597*6185db85Sdougm {
1598*6185db85Sdougm 	char *groupname = NULL;
1599*6185db85Sdougm 	char *value;
1600*6185db85Sdougm 	sa_group_t group;
1601*6185db85Sdougm 	char *buff;
1602*6185db85Sdougm 	char *zfs;
1603*6185db85Sdougm 
1604*6185db85Sdougm 	group = sa_get_parent_group(share);
1605*6185db85Sdougm 	if (group != NULL) {
1606*6185db85Sdougm 	    zfs = sa_get_group_attr(group, "zfs");
1607*6185db85Sdougm 	    groupname = sa_get_group_attr(group, "name");
1608*6185db85Sdougm 
1609*6185db85Sdougm 	    if (groupname != NULL &&
1610*6185db85Sdougm 		(strcmp(groupname, "default") == 0 || zfs != NULL)) {
1611*6185db85Sdougm 		/*
1612*6185db85Sdougm 		 * since the groupname is either "default" or the
1613*6185db85Sdougm 		 * group is a ZFS group, we don't want to keep
1614*6185db85Sdougm 		 * groupname. We do want it if it is any other type of
1615*6185db85Sdougm 		 * group.
1616*6185db85Sdougm 		 */
1617*6185db85Sdougm 		sa_free_attr_string(groupname);
1618*6185db85Sdougm 		groupname = NULL;
1619*6185db85Sdougm 	    }
1620*6185db85Sdougm 	    if (zfs != NULL)
1621*6185db85Sdougm 		sa_free_attr_string(zfs);
1622*6185db85Sdougm 	}
1623*6185db85Sdougm 
1624*6185db85Sdougm 	value = sa_get_share_attr(share, "path");
1625*6185db85Sdougm 	if (value != NULL) {
1626*6185db85Sdougm 	    sh->sh_path = strdup(value);
1627*6185db85Sdougm 	    sa_free_attr_string(value);
1628*6185db85Sdougm 	}
1629*6185db85Sdougm 
1630*6185db85Sdougm 	value = sa_get_share_attr(share, "resource");
1631*6185db85Sdougm 	if (value != NULL || groupname != NULL) {
1632*6185db85Sdougm 	    int len = 0;
1633*6185db85Sdougm 
1634*6185db85Sdougm 	    if (value != NULL)
1635*6185db85Sdougm 		len += strlen(value);
1636*6185db85Sdougm 	    if (groupname != NULL)
1637*6185db85Sdougm 		len += strlen(groupname);
1638*6185db85Sdougm 	    len += 3; /* worst case */
1639*6185db85Sdougm 	    buff = malloc(len);
1640*6185db85Sdougm 	    (void) snprintf(buff, len, "%s%s%s",
1641*6185db85Sdougm 		    (value != NULL && strlen(value) > 0) ? value : "-",
1642*6185db85Sdougm 		    groupname != NULL ? "@" : "",
1643*6185db85Sdougm 		    groupname != NULL ? groupname : "");
1644*6185db85Sdougm 	    sh->sh_res = buff;
1645*6185db85Sdougm 	    if (value != NULL)
1646*6185db85Sdougm 		sa_free_attr_string(value);
1647*6185db85Sdougm 	    if (groupname != NULL) {
1648*6185db85Sdougm 		sa_free_attr_string(groupname);
1649*6185db85Sdougm 		groupname = NULL;
1650*6185db85Sdougm 	    }
1651*6185db85Sdougm 	} else {
1652*6185db85Sdougm 	    sh->sh_res = strdup("-");
1653*6185db85Sdougm 	}
1654*6185db85Sdougm 
1655*6185db85Sdougm 	sh->sh_fstype = strdup(proto);
1656*6185db85Sdougm 	value = sa_proto_legacy_format(proto, share, 1);
1657*6185db85Sdougm 	if (value != NULL) {
1658*6185db85Sdougm 	    if (strlen(value) > 0)
1659*6185db85Sdougm 		sh->sh_opts = strdup(value);
1660*6185db85Sdougm 	    else
1661*6185db85Sdougm 		sh->sh_opts = strdup("rw");
1662*6185db85Sdougm 	    free(value);
1663*6185db85Sdougm 	} else
1664*6185db85Sdougm 	    sh->sh_opts = strdup("rw");
1665*6185db85Sdougm 
1666*6185db85Sdougm 	value = sa_get_share_description(share);
1667*6185db85Sdougm 	if (value != NULL) {
1668*6185db85Sdougm 	    sh->sh_descr = strdup(value);
1669*6185db85Sdougm 	    sa_free_share_description(value);
1670*6185db85Sdougm 	} else
1671*6185db85Sdougm 	    sh->sh_descr = strdup("");
1672*6185db85Sdougm }
1673*6185db85Sdougm 
1674*6185db85Sdougm /*
1675*6185db85Sdougm  * emptyshare(sh)
1676*6185db85Sdougm  *
1677*6185db85Sdougm  * Free the strings in the non-NULL members of sh.
1678*6185db85Sdougm  */
1679*6185db85Sdougm 
1680*6185db85Sdougm static void
1681*6185db85Sdougm emptyshare(struct share *sh)
1682*6185db85Sdougm {
1683*6185db85Sdougm 	if (sh->sh_path != NULL)
1684*6185db85Sdougm 	    free(sh->sh_path);
1685*6185db85Sdougm 	sh->sh_path = NULL;
1686*6185db85Sdougm 	if (sh->sh_res != NULL)
1687*6185db85Sdougm 	    free(sh->sh_res);
1688*6185db85Sdougm 	sh->sh_res = NULL;
1689*6185db85Sdougm 	if (sh->sh_fstype != NULL)
1690*6185db85Sdougm 	    free(sh->sh_fstype);
1691*6185db85Sdougm 	sh->sh_fstype = NULL;
1692*6185db85Sdougm 	if (sh->sh_opts != NULL)
1693*6185db85Sdougm 	    free(sh->sh_opts);
1694*6185db85Sdougm 	sh->sh_opts = NULL;
1695*6185db85Sdougm 	if (sh->sh_descr != NULL)
1696*6185db85Sdougm 	    free(sh->sh_descr);
1697*6185db85Sdougm 	sh->sh_descr = NULL;
1698*6185db85Sdougm }
1699*6185db85Sdougm 
1700*6185db85Sdougm /*
1701*6185db85Sdougm  * sa_update_sharetab(share, proto)
1702*6185db85Sdougm  *
1703*6185db85Sdougm  * Update the sharetab file with info from the specified share.
1704*6185db85Sdougm  * This could be an update or add.
1705*6185db85Sdougm  */
1706*6185db85Sdougm 
1707*6185db85Sdougm int
1708*6185db85Sdougm sa_update_sharetab(sa_share_t share, char *proto)
1709*6185db85Sdougm {
1710*6185db85Sdougm 	int ret = SA_OK;
1711*6185db85Sdougm 	struct share shtab;
1712*6185db85Sdougm 	char *path;
1713*6185db85Sdougm 	int logging = 0;
1714*6185db85Sdougm 	FILE *sharetab;
1715*6185db85Sdougm 	sigset_t old, new;
1716*6185db85Sdougm 
1717*6185db85Sdougm 	path = sa_get_share_attr(share, "path");
1718*6185db85Sdougm 	if (path != NULL) {
1719*6185db85Sdougm 	    (void) memset(&shtab, '\0', sizeof (shtab));
1720*6185db85Sdougm 	    sharetab = fopen(SA_LEGACY_SHARETAB, "r+");
1721*6185db85Sdougm 	    if (sharetab == NULL) {
1722*6185db85Sdougm 		sharetab = fopen(SA_LEGACY_SHARETAB, "w+");
1723*6185db85Sdougm 	    }
1724*6185db85Sdougm 	    if (sharetab != NULL) {
1725*6185db85Sdougm 		(void) setvbuf(sharetab, NULL, _IOLBF, BUFSIZ * 8);
1726*6185db85Sdougm 		(void) sigprocmask(SIG_BLOCK, NULL, &new);
1727*6185db85Sdougm 		(void) sigaddset(&new, SIGHUP);
1728*6185db85Sdougm 		(void) sigaddset(&new, SIGINT);
1729*6185db85Sdougm 		(void) sigaddset(&new, SIGQUIT);
1730*6185db85Sdougm 		(void) sigaddset(&new, SIGTSTP);
1731*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &new, &old);
1732*6185db85Sdougm 		(void) lockf(fileno(sharetab), F_LOCK, 0);
1733*6185db85Sdougm 		(void) remshare(sharetab, path, &logging);
1734*6185db85Sdougm 		/* fill in share structure and write it out */
1735*6185db85Sdougm 		(void) fillshare(share, proto, &shtab);
1736*6185db85Sdougm 		(void) putshare(sharetab, &shtab);
1737*6185db85Sdougm 		emptyshare(&shtab);
1738*6185db85Sdougm 		(void) fflush(sharetab);
1739*6185db85Sdougm 		(void) lockf(fileno(sharetab), F_ULOCK, 0);
1740*6185db85Sdougm 		(void) fsync(fileno(sharetab));
1741*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &old, NULL);
1742*6185db85Sdougm 		(void) fclose(sharetab);
1743*6185db85Sdougm 	    } else {
1744*6185db85Sdougm 		if (errno == EACCES || errno == EPERM) {
1745*6185db85Sdougm 		    ret = SA_NO_PERMISSION;
1746*6185db85Sdougm 		} else {
1747*6185db85Sdougm 		    ret = SA_CONFIG_ERR;
1748*6185db85Sdougm 		}
1749*6185db85Sdougm 	    }
1750*6185db85Sdougm 	    sa_free_attr_string(path);
1751*6185db85Sdougm 	}
1752*6185db85Sdougm 	return (ret);
1753*6185db85Sdougm }
1754*6185db85Sdougm 
1755*6185db85Sdougm /*
1756*6185db85Sdougm  * sa_delete_sharetab(path, proto)
1757*6185db85Sdougm  *
1758*6185db85Sdougm  * remove the specified share from sharetab.
1759*6185db85Sdougm  */
1760*6185db85Sdougm 
1761*6185db85Sdougm int
1762*6185db85Sdougm sa_delete_sharetab(char *path, char *proto)
1763*6185db85Sdougm {
1764*6185db85Sdougm 	int ret = SA_OK;
1765*6185db85Sdougm 	int logging = 0;
1766*6185db85Sdougm 	FILE *sharetab;
1767*6185db85Sdougm 	sigset_t old, new;
1768*6185db85Sdougm #ifdef lint
1769*6185db85Sdougm 	proto = proto;
1770*6185db85Sdougm #endif
1771*6185db85Sdougm 
1772*6185db85Sdougm 	if (path != NULL) {
1773*6185db85Sdougm 	    sharetab = fopen(SA_LEGACY_SHARETAB, "r+");
1774*6185db85Sdougm 	    if (sharetab == NULL) {
1775*6185db85Sdougm 		sharetab = fopen(SA_LEGACY_SHARETAB, "w+");
1776*6185db85Sdougm 	    }
1777*6185db85Sdougm 	    if (sharetab != NULL) {
1778*6185db85Sdougm 		/* should block keyboard level signals around the lock */
1779*6185db85Sdougm 		(void) sigprocmask(SIG_BLOCK, NULL, &new);
1780*6185db85Sdougm 		(void) sigaddset(&new, SIGHUP);
1781*6185db85Sdougm 		(void) sigaddset(&new, SIGINT);
1782*6185db85Sdougm 		(void) sigaddset(&new, SIGQUIT);
1783*6185db85Sdougm 		(void) sigaddset(&new, SIGTSTP);
1784*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &new, &old);
1785*6185db85Sdougm 		(void) lockf(fileno(sharetab), F_LOCK, 0);
1786*6185db85Sdougm 		ret = remshare(sharetab, path, &logging);
1787*6185db85Sdougm 		(void) fflush(sharetab);
1788*6185db85Sdougm 		(void) lockf(fileno(sharetab), F_ULOCK, 0);
1789*6185db85Sdougm 		(void) fsync(fileno(sharetab));
1790*6185db85Sdougm 		(void) sigprocmask(SIG_SETMASK, &old, NULL);
1791*6185db85Sdougm 		(void) fclose(sharetab);
1792*6185db85Sdougm 	    } else {
1793*6185db85Sdougm 		if (errno == EACCES || errno == EPERM) {
1794*6185db85Sdougm 		    ret = SA_NO_PERMISSION;
1795*6185db85Sdougm 		} else {
1796*6185db85Sdougm 		    ret = SA_CONFIG_ERR;
1797*6185db85Sdougm 		}
1798*6185db85Sdougm 	    }
1799*6185db85Sdougm 	}
1800*6185db85Sdougm 	return (ret);
1801*6185db85Sdougm }
1802