13034Sdougm /*
23034Sdougm * CDDL HEADER START
33034Sdougm *
43034Sdougm * The contents of this file are subject to the terms of the
53034Sdougm * Common Development and Distribution License (the "License").
63034Sdougm * You may not use this file except in compliance with the License.
73034Sdougm *
83034Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93034Sdougm * or http://www.opensolaris.org/os/licensing.
103034Sdougm * See the License for the specific language governing permissions
113034Sdougm * and limitations under the License.
123034Sdougm *
133034Sdougm * When distributing Covered Code, include this CDDL HEADER in each
143034Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153034Sdougm * If applicable, add the following below this CDDL HEADER, with the
163034Sdougm * fields enclosed by brackets "[]" replaced with your own identifying
173034Sdougm * information: Portions Copyright [yyyy] [name of copyright owner]
183034Sdougm *
193034Sdougm * CDDL HEADER END
203034Sdougm */
213034Sdougm
223034Sdougm /*
23*12508Samw@Sun.COM * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
243034Sdougm */
253034Sdougm
263034Sdougm /*
273034Sdougm * core library for common functions across all config store types
283034Sdougm * and file systems to be exported. This includes legacy dfstab/sharetab
293034Sdougm * parsing. Need to eliminate XML where possible.
303034Sdougm */
313034Sdougm
323034Sdougm #include <stdio.h>
333034Sdougm #include <string.h>
343034Sdougm #include <ctype.h>
353034Sdougm #include <unistd.h>
363034Sdougm #include <limits.h>
373034Sdougm #include <errno.h>
383034Sdougm #include <sys/types.h>
393034Sdougm #include <sys/stat.h>
403034Sdougm #include <libxml/parser.h>
413034Sdougm #include <libxml/tree.h>
423034Sdougm #include "libshare.h"
433034Sdougm #include "libshare_impl.h"
443034Sdougm #include <fcntl.h>
458334SJose.Borrego@Sun.COM #include <thread.h>
463034Sdougm #include <grp.h>
473034Sdougm #include <limits.h>
483034Sdougm #include <sys/param.h>
493034Sdougm #include <signal.h>
503034Sdougm #include <libintl.h>
515331Samw #include <dirent.h>
523034Sdougm
533957Sth199096 #include <sharefs/share.h>
543034Sdougm #include "sharetab.h"
553034Sdougm
563034Sdougm #define DFSTAB_NOTICE_LINES 5
573034Sdougm static char *notice[DFSTAB_NOTICE_LINES] = {
583034Sdougm "# Do not modify this file directly.\n",
593034Sdougm "# Use the sharemgr(1m) command for all share management\n",
603034Sdougm "# This file is reconstructed and only maintained for backward\n",
613034Sdougm "# compatibility. Configuration lines could be lost.\n",
623034Sdougm "#\n"
633034Sdougm };
643034Sdougm
653034Sdougm #define STRNCAT(x, y, z) (xmlChar *)strncat((char *)x, (char *)y, z)
663034Sdougm
673034Sdougm /* will be much smaller, but this handles bad syntax in the file */
683034Sdougm #define MAXARGSFORSHARE 256
693034Sdougm
708334SJose.Borrego@Sun.COM static mutex_t sharetab_lock = DEFAULTMUTEX;
71*12508Samw@Sun.COM extern mutex_t sa_dfstab_lock;
728334SJose.Borrego@Sun.COM
733034Sdougm /* used internally only */
743034Sdougm typedef
753034Sdougm struct sharelist {
763034Sdougm struct sharelist *next;
773034Sdougm int persist;
783034Sdougm char *path;
793034Sdougm char *resource;
803034Sdougm char *fstype;
813034Sdougm char *options;
823034Sdougm char *description;
833034Sdougm char *group;
843034Sdougm char *origline;
853034Sdougm int lineno;
863034Sdougm } xfs_sharelist_t;
873910Sdougm static void parse_dfstab(sa_handle_t, char *, xmlNodePtr);
888334SJose.Borrego@Sun.COM extern char *_sa_get_token(char *);
893034Sdougm static void dfs_free_list(xfs_sharelist_t *);
903034Sdougm /* prototypes */
913910Sdougm void getlegacyconfig(sa_handle_t, char *, xmlNodePtr *);
925331Samw extern sa_share_t _sa_add_share(sa_group_t, char *, int, int *, uint64_t);
933910Sdougm extern sa_group_t _sa_create_group(sa_handle_impl_t, char *);
943034Sdougm static void outdfstab(FILE *, xfs_sharelist_t *);
953034Sdougm extern int _sa_remove_optionset(sa_optionset_t);
963034Sdougm extern int set_node_share(void *, char *, char *);
973034Sdougm extern void set_node_attr(void *, char *, char *);
983034Sdougm
993034Sdougm /*
1003663Sdougm * sablocksigs(*sigs)
1013663Sdougm *
1023663Sdougm * block important signals for a critical region. Arg is a pointer to
1033663Sdougm * a sigset_t that is used later for the unblock.
1043663Sdougm */
1053663Sdougm void
sablocksigs(sigset_t * sigs)1063663Sdougm sablocksigs(sigset_t *sigs)
1073663Sdougm {
1083663Sdougm sigset_t new;
1093663Sdougm
1103663Sdougm if (sigs != NULL) {
1114653Sdougm (void) sigprocmask(SIG_BLOCK, NULL, &new);
1124653Sdougm (void) sigaddset(&new, SIGHUP);
1134653Sdougm (void) sigaddset(&new, SIGINT);
1144653Sdougm (void) sigaddset(&new, SIGQUIT);
1154653Sdougm (void) sigaddset(&new, SIGTSTP);
1164653Sdougm (void) sigprocmask(SIG_SETMASK, &new, sigs);
1173663Sdougm }
1183663Sdougm }
1193663Sdougm
1203663Sdougm /*
1213663Sdougm * saunblocksigs(*sigs)
1223663Sdougm *
1233663Sdougm * unblock previously blocked signals from the sigs arg.
1243663Sdougm */
1253663Sdougm void
saunblocksigs(sigset_t * sigs)1263663Sdougm saunblocksigs(sigset_t *sigs)
1273663Sdougm {
1283663Sdougm if (sigs != NULL)
1294653Sdougm (void) sigprocmask(SIG_SETMASK, sigs, NULL);
1303663Sdougm }
1313663Sdougm
1323663Sdougm /*
1333034Sdougm * alloc_sharelist()
1343034Sdougm *
1353034Sdougm * allocator function to return an zfs_sharelist_t
1363034Sdougm */
1373034Sdougm
1383034Sdougm static xfs_sharelist_t *
alloc_sharelist()1393034Sdougm alloc_sharelist()
1403034Sdougm {
1413034Sdougm xfs_sharelist_t *item;
1423034Sdougm
1433034Sdougm item = (xfs_sharelist_t *)malloc(sizeof (xfs_sharelist_t));
1443034Sdougm if (item != NULL)
1454653Sdougm (void) memset(item, '\0', sizeof (xfs_sharelist_t));
1463034Sdougm return (item);
1473034Sdougm }
1483034Sdougm
1493034Sdougm /*
1503034Sdougm * fix_notice(list)
1513034Sdougm *
1523034Sdougm * Look at the beginning of the current /etc/dfs/dfstab file and add
1533034Sdougm * the do not modify notice if it doesn't exist.
1543034Sdougm */
1553034Sdougm
1563034Sdougm static xfs_sharelist_t *
fix_notice(xfs_sharelist_t * list)1573034Sdougm fix_notice(xfs_sharelist_t *list)
1583034Sdougm {
1593034Sdougm xfs_sharelist_t *item, *prev;
1603034Sdougm int i;
1613034Sdougm
1623082Sdougm if (list == NULL) {
1634653Sdougm /* zero length dfstab */
1644653Sdougm list = alloc_sharelist();
1654653Sdougm if (list == NULL)
1664653Sdougm return (NULL);
1674653Sdougm list->description = strdup("#\n");
1683082Sdougm }
1693034Sdougm if (list->path == NULL && list->description != NULL &&
1703034Sdougm strcmp(list->description, notice[0]) != 0) {
1714653Sdougm for (prev = NULL, i = 0; i < DFSTAB_NOTICE_LINES; i++) {
1724653Sdougm item = alloc_sharelist();
1734653Sdougm if (item != NULL) {
1744653Sdougm item->description = strdup(notice[i]);
1754653Sdougm if (prev == NULL) {
1764653Sdougm item->next = list;
1774653Sdougm prev = item;
1784653Sdougm list = item;
1794653Sdougm } else {
1804653Sdougm item->next = prev->next;
1814653Sdougm prev->next = item;
1824653Sdougm prev = item;
1834653Sdougm }
1844653Sdougm }
1853034Sdougm }
1863034Sdougm }
1873034Sdougm return (list);
1883034Sdougm }
1893034Sdougm
1903034Sdougm /*
1913034Sdougm * getdfstab(dfs)
1923034Sdougm *
1933034Sdougm * Returns an zfs_sharelist_t list of lines from the dfstab file
1943034Sdougm * pointed to by the FILE pointer dfs. Each entry is parsed and the
1953034Sdougm * original line is also preserved. Used in parsing and updating the
1963034Sdougm * dfstab file.
1973034Sdougm */
1983034Sdougm
1993034Sdougm static xfs_sharelist_t *
getdfstab(FILE * dfs)2003034Sdougm getdfstab(FILE *dfs)
2013034Sdougm {
2023034Sdougm char buff[_POSIX_ARG_MAX]; /* reasonable size given syntax of share */
2033034Sdougm char *bp;
2043034Sdougm char *token;
2053034Sdougm char *args[MAXARGSFORSHARE];
2063034Sdougm int argc;
2073034Sdougm int c;
2083034Sdougm static int line = 0;
2093082Sdougm xfs_sharelist_t *item = NULL, *first = NULL, *last;
2103034Sdougm
2113034Sdougm if (dfs != NULL) {
2124653Sdougm first = NULL;
2134653Sdougm line = 0;
2144653Sdougm while (fgets(buff, sizeof (buff), dfs) != NULL) {
2154653Sdougm line++;
2164653Sdougm bp = buff;
2174653Sdougm if (buff[0] == '#') {
2184653Sdougm item = alloc_sharelist();
2194653Sdougm if (item != NULL) {
2204653Sdougm /* if no path, then comment */
2214653Sdougm item->lineno = line;
2224653Sdougm item->description = strdup(buff);
2234653Sdougm if (first == NULL) {
2244653Sdougm first = item;
2254653Sdougm last = item;
2264653Sdougm } else {
2274653Sdougm last->next = item;
2284653Sdougm last = item;
2294653Sdougm }
2304653Sdougm } else {
2314653Sdougm break;
2324653Sdougm }
2334653Sdougm continue;
2344653Sdougm } else if (buff[0] == '\n') {
2354653Sdougm continue;
2364653Sdougm }
2374653Sdougm optind = 1;
2384653Sdougm item = alloc_sharelist();
2394653Sdougm if (item == NULL) {
2404653Sdougm break;
2414653Sdougm } else if (first == NULL) {
2424653Sdougm first = item;
2434653Sdougm last = item;
2444653Sdougm } else {
2454653Sdougm last->next = item;
2464653Sdougm last = item;
2474653Sdougm }
2483034Sdougm item->lineno = line;
2494653Sdougm item->origline = strdup(buff);
2508334SJose.Borrego@Sun.COM (void) _sa_get_token(NULL); /* reset to new pointers */
2514653Sdougm argc = 0;
2528334SJose.Borrego@Sun.COM while ((token = _sa_get_token(bp)) != NULL) {
2534653Sdougm if (argc < MAXARGSFORSHARE)
2544653Sdougm args[argc++] = token;
2553034Sdougm }
2564653Sdougm while ((c = getopt(argc, args, "F:o:d:pg:")) != -1) {
2574653Sdougm switch (c) {
2584653Sdougm case 'p':
2594653Sdougm item->persist = 1;
2604653Sdougm break;
2614653Sdougm case 'F':
2624653Sdougm item->fstype = strdup(optarg);
2634653Sdougm break;
2644653Sdougm case 'o':
2654653Sdougm item->options = strdup(optarg);
2664653Sdougm break;
2674653Sdougm case 'd':
2684653Sdougm item->description = strdup(optarg);
2694653Sdougm break;
2704653Sdougm case 'g':
2714653Sdougm item->group = strdup(optarg);
2724653Sdougm break;
2734653Sdougm default:
2744653Sdougm break;
2754653Sdougm }
2764653Sdougm }
2774653Sdougm if (optind < argc) {
2784653Sdougm item->path = strdup(args[optind]);
2794653Sdougm optind++;
2804653Sdougm if (optind < argc) {
2814653Sdougm char *resource;
2824653Sdougm char *optgroup;
2834653Sdougm /* resource and/or groupname */
2844653Sdougm resource = args[optind];
2854653Sdougm optgroup = strchr(resource, '@');
2864653Sdougm if (optgroup != NULL)
2874653Sdougm *optgroup++ = '\0';
2884653Sdougm if (optgroup != NULL)
2894653Sdougm item->group = strdup(optgroup);
2904653Sdougm if (resource != NULL &&
2914653Sdougm strlen(resource) > 0)
2924653Sdougm item->resource =
2934653Sdougm strdup(resource);
2944653Sdougm }
2954653Sdougm }
2964653Sdougm /* NFS is the default if none defined */
2974653Sdougm if (item != NULL && item->fstype == NULL)
2984653Sdougm item->fstype = strdup("nfs");
2993034Sdougm }
3003034Sdougm }
3013034Sdougm first = fix_notice(first);
3023034Sdougm return (first);
3033034Sdougm }
3043034Sdougm
3053034Sdougm /*
3063034Sdougm * finddfsentry(list, path)
3073034Sdougm *
3083082Sdougm * Look for path in the zfs_sharelist_t list and return the entry if it
3093034Sdougm * exists.
3103034Sdougm */
3113034Sdougm
3123034Sdougm static xfs_sharelist_t *
finddfsentry(xfs_sharelist_t * list,char * path)3133034Sdougm finddfsentry(xfs_sharelist_t *list, char *path)
3143034Sdougm {
3153034Sdougm xfs_sharelist_t *item;
3163034Sdougm
3173034Sdougm for (item = list; item != NULL; item = item->next) {
3184653Sdougm if (item->path != NULL && strcmp(item->path, path) == 0)
3193034Sdougm return (item);
3203034Sdougm }
3213034Sdougm return (NULL);
3223034Sdougm }
3233034Sdougm
3243034Sdougm /*
3253034Sdougm * remdfsentry(list, path, proto)
3263034Sdougm *
3273034Sdougm * Remove the specified path (with protocol) from the list. This will
3283034Sdougm * remove it from dfstab when the file is rewritten.
3293034Sdougm */
3303034Sdougm
3313034Sdougm static xfs_sharelist_t *
remdfsentry(xfs_sharelist_t * list,char * path,char * proto)3323034Sdougm remdfsentry(xfs_sharelist_t *list, char *path, char *proto)
3333034Sdougm {
3343034Sdougm xfs_sharelist_t *item, *prev = NULL;
3353034Sdougm
3363034Sdougm
3373034Sdougm for (item = prev = list; item != NULL; item = item->next) {
3383034Sdougm /* skip comment entry but don't lose it */
3394653Sdougm if (item->path == NULL) {
3404653Sdougm prev = item;
3414653Sdougm continue;
3424653Sdougm }
3434653Sdougm /* if proto is NULL, remove all protocols */
3444653Sdougm if (proto == NULL || (strcmp(item->path, path) == 0 &&
3454653Sdougm (item->fstype != NULL && strcmp(item->fstype, proto) == 0)))
3464653Sdougm break;
3474653Sdougm if (item->fstype == NULL &&
3484653Sdougm (proto == NULL || strcmp(proto, "nfs") == 0))
3494653Sdougm break;
3503034Sdougm prev = item;
3513034Sdougm }
3523034Sdougm if (item != NULL) {
3534653Sdougm if (item == prev)
3544653Sdougm list = item->next; /* this must be the first one */
3554653Sdougm else
3564653Sdougm prev->next = item->next;
3574653Sdougm item->next = NULL;
3584653Sdougm dfs_free_list(item);
3593034Sdougm }
3603034Sdougm return (list);
3613034Sdougm }
3623034Sdougm
3633034Sdougm /*
3643034Sdougm * remdfsline(list, line)
3653034Sdougm *
3663034Sdougm * Remove the line specified from the list.
3673034Sdougm */
3683034Sdougm
3693034Sdougm static xfs_sharelist_t *
remdfsline(xfs_sharelist_t * list,char * line)3703034Sdougm remdfsline(xfs_sharelist_t *list, char *line)
3713034Sdougm {
3723034Sdougm xfs_sharelist_t *item, *prev = NULL;
3733034Sdougm
3743034Sdougm for (item = prev = list; item != NULL; item = item->next) {
3754653Sdougm /* skip comment entry but don't lose it */
3764653Sdougm if (item->path == NULL) {
3773034Sdougm prev = item;
3783034Sdougm continue;
3794653Sdougm }
3804653Sdougm if (strcmp(item->origline, line) == 0)
3814653Sdougm break;
3824653Sdougm prev = item;
3833034Sdougm }
3843034Sdougm if (item != NULL) {
3854653Sdougm if (item == prev)
3864653Sdougm list = item->next; /* this must be the first one */
3874653Sdougm else
3884653Sdougm prev->next = item->next;
3894653Sdougm item->next = NULL;
3904653Sdougm dfs_free_list(item);
3913034Sdougm }
3923034Sdougm return (list);
3933034Sdougm }
3943034Sdougm
3953034Sdougm /*
3963034Sdougm * adddfsentry(list, share, proto)
3973034Sdougm *
3983034Sdougm * Add an entry to the dfstab list for share (relative to proto). This
3993034Sdougm * is used to update dfstab for legacy purposes.
4003034Sdougm */
4013034Sdougm
4023034Sdougm static xfs_sharelist_t *
adddfsentry(xfs_sharelist_t * list,sa_share_t share,char * proto)4033034Sdougm adddfsentry(xfs_sharelist_t *list, sa_share_t share, char *proto)
4043034Sdougm {
4053034Sdougm xfs_sharelist_t *item, *tmp;
4063034Sdougm sa_group_t parent;
4073034Sdougm char *groupname;
4083034Sdougm
4093034Sdougm item = alloc_sharelist();
4103034Sdougm if (item != NULL) {
4114653Sdougm parent = sa_get_parent_group(share);
4124653Sdougm groupname = sa_get_group_attr(parent, "name");
41311337SWilliam.Krier@Sun.COM if (groupname != NULL && strcmp(groupname, "default") == 0) {
4144653Sdougm sa_free_attr_string(groupname);
4154653Sdougm groupname = NULL;
4164653Sdougm }
4174653Sdougm item->path = sa_get_share_attr(share, "path");
4184653Sdougm item->resource = sa_get_share_attr(share, "resource");
4194653Sdougm item->group = groupname;
4204653Sdougm item->fstype = strdup(proto);
4214653Sdougm item->options = sa_proto_legacy_format(proto, share, 1);
4224653Sdougm if (item->options != NULL && strlen(item->options) == 0) {
4234653Sdougm free(item->options);
4244653Sdougm item->options = NULL;
4254653Sdougm }
4264653Sdougm item->description = sa_get_share_description(share);
4274653Sdougm if (item->description != NULL &&
4284653Sdougm strlen(item->description) == 0) {
4294653Sdougm sa_free_share_description(item->description);
4304653Sdougm item->description = NULL;
4314653Sdougm }
4324653Sdougm if (list == NULL) {
4334653Sdougm list = item;
4344653Sdougm } else {
4354653Sdougm for (tmp = list; tmp->next != NULL; tmp = tmp->next)
4364653Sdougm /* do nothing */;
4374653Sdougm tmp->next = item;
4384653Sdougm }
4393034Sdougm }
4403034Sdougm return (list);
4413034Sdougm }
4423034Sdougm
4433034Sdougm /*
4443034Sdougm * outdfstab(dfstab, list)
4453034Sdougm *
4463034Sdougm * Output the list to dfstab making sure the file is truncated.
4473034Sdougm * Comments and errors are preserved.
4483034Sdougm */
4493034Sdougm
4503034Sdougm static void
outdfstab(FILE * dfstab,xfs_sharelist_t * list)4513034Sdougm outdfstab(FILE *dfstab, xfs_sharelist_t *list)
4523034Sdougm {
4533034Sdougm xfs_sharelist_t *item;
4543034Sdougm
4553034Sdougm (void) ftruncate(fileno(dfstab), 0);
4563034Sdougm
4573034Sdougm for (item = list; item != NULL; item = item->next) {
4584653Sdougm if (item->path != NULL) {
4594653Sdougm if (*item->path == '/') {
4604653Sdougm (void) fprintf(dfstab,
4614653Sdougm "share %s%s%s%s%s%s%s %s%s%s%s%s\n",
4624653Sdougm (item->fstype != NULL) ? "-F " : "",
4634653Sdougm (item->fstype != NULL) ? item->fstype : "",
4644653Sdougm (item->options != NULL) ? " -o " : "",
4654653Sdougm (item->options != NULL) ?
4664653Sdougm item->options : "",
4674653Sdougm (item->description != NULL) ?
4684653Sdougm " -d \"" : "",
4694653Sdougm (item->description != NULL) ?
4704653Sdougm item->description : "",
4714653Sdougm (item->description != NULL) ? "\"" : "",
4724653Sdougm item->path,
4734653Sdougm ((item->resource != NULL) ||
4744653Sdougm (item->group != NULL)) ? " " : "",
4754653Sdougm (item->resource != NULL) ?
4764653Sdougm item->resource : "",
4774653Sdougm item->group != NULL ? "@" : "",
4784653Sdougm item->group != NULL ? item->group : "");
4794653Sdougm } else {
4804653Sdougm (void) fprintf(dfstab, "%s", item->origline);
4814653Sdougm }
4823034Sdougm } else {
4834653Sdougm if (item->description != NULL)
4844653Sdougm (void) fprintf(dfstab, "%s", item->description);
4854653Sdougm else
4864653Sdougm (void) fprintf(dfstab, "%s", item->origline);
4873034Sdougm }
4883034Sdougm }
4893034Sdougm }
4903034Sdougm
4913034Sdougm /*
4923034Sdougm * open_dfstab(file)
4933034Sdougm *
4943034Sdougm * Open the specified dfstab file. If the owner/group/perms are wrong,
4953034Sdougm * fix them.
4963034Sdougm */
4973034Sdougm
4983034Sdougm static FILE *
open_dfstab(char * file)4993034Sdougm open_dfstab(char *file)
5003034Sdougm {
5013034Sdougm struct group *grp;
5023034Sdougm struct group group;
5033034Sdougm char *buff;
5043034Sdougm int grsize;
5053034Sdougm FILE *dfstab;
5063034Sdougm
5073034Sdougm dfstab = fopen(file, "r+");
5083034Sdougm if (dfstab == NULL) {
5094653Sdougm dfstab = fopen(file, "w+");
5103034Sdougm }
5113034Sdougm if (dfstab != NULL) {
5123034Sdougm grsize = sysconf(_SC_GETGR_R_SIZE_MAX);
5133034Sdougm buff = malloc(grsize);
5143034Sdougm if (buff != NULL)
5154653Sdougm grp = getgrnam_r(SA_DEFAULT_FILE_GRP, &group, buff,
5164653Sdougm grsize);
5173034Sdougm else
5184653Sdougm grp = getgrnam(SA_DEFAULT_FILE_GRP);
5193034Sdougm (void) fchmod(fileno(dfstab), 0644);
5203034Sdougm (void) fchown(fileno(dfstab), 0,
5214653Sdougm grp != NULL ? grp->gr_gid : 3);
5223034Sdougm if (buff != NULL)
5234653Sdougm free(buff);
5243034Sdougm rewind(dfstab);
5253034Sdougm }
5263034Sdougm return (dfstab);
5273034Sdougm }
5283034Sdougm
5293034Sdougm /*
5303034Sdougm * sa_comment_line(line, err)
5313034Sdougm *
5323034Sdougm * Add a comment to the dfstab file with err as a prefix to the
5333034Sdougm * original line.
5343034Sdougm */
5353034Sdougm
5363034Sdougm static void
sa_comment_line(char * line,char * err)5373034Sdougm sa_comment_line(char *line, char *err)
5383034Sdougm {
5393034Sdougm FILE *dfstab;
5403034Sdougm xfs_sharelist_t *list;
5413663Sdougm sigset_t old;
5423034Sdougm
5433034Sdougm dfstab = open_dfstab(SA_LEGACY_DFSTAB);
5443034Sdougm if (dfstab != NULL) {
5453034Sdougm (void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8);
5463663Sdougm sablocksigs(&old);
5473034Sdougm (void) lockf(fileno(dfstab), F_LOCK, 0);
548*12508Samw@Sun.COM (void) mutex_lock(&sa_dfstab_lock);
5493034Sdougm list = getdfstab(dfstab);
5503034Sdougm rewind(dfstab);
5513348Sdougm /*
5523348Sdougm * don't ignore the return since the list could have
5533348Sdougm * gone to NULL if the file only had one line in it.
5543348Sdougm */
5553348Sdougm list = remdfsline(list, line);
5563034Sdougm outdfstab(dfstab, list);
5573034Sdougm (void) fprintf(dfstab, "# Error: %s: %s", err, line);
5583034Sdougm (void) fsync(fileno(dfstab));
559*12508Samw@Sun.COM (void) mutex_unlock(&sa_dfstab_lock);
5603034Sdougm (void) lockf(fileno(dfstab), F_ULOCK, 0);
5613034Sdougm (void) fclose(dfstab);
5623663Sdougm saunblocksigs(&old);
5633034Sdougm if (list != NULL)
5644653Sdougm dfs_free_list(list);
5653034Sdougm }
5663034Sdougm }
5673034Sdougm
5683034Sdougm /*
5695331Samw * sa_delete_legacy(share, protocol)
5703034Sdougm *
5713034Sdougm * Delete the specified share from the legacy config file.
5723034Sdougm */
5733034Sdougm
5743034Sdougm int
sa_delete_legacy(sa_share_t share,char * protocol)5755331Samw sa_delete_legacy(sa_share_t share, char *protocol)
5763034Sdougm {
5773034Sdougm FILE *dfstab;
5783034Sdougm int err;
5793034Sdougm int ret = SA_OK;
5803034Sdougm xfs_sharelist_t *list;
5813034Sdougm char *path;
5823034Sdougm sa_optionset_t optionset;
5833034Sdougm sa_group_t parent;
5843663Sdougm sigset_t old;
5853034Sdougm
5865331Samw /*
5875331Samw * Protect against shares that don't have paths. This is not
5885331Samw * really an error at this point.
5895331Samw */
5905331Samw path = sa_get_share_attr(share, "path");
5915331Samw if (path == NULL)
5925331Samw return (ret);
5935331Samw
5943034Sdougm dfstab = open_dfstab(SA_LEGACY_DFSTAB);
5953034Sdougm if (dfstab != NULL) {
5963034Sdougm (void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8);
5973663Sdougm sablocksigs(&old);
5983034Sdougm parent = sa_get_parent_group(share);
5993034Sdougm if (parent != NULL) {
6004653Sdougm (void) lockf(fileno(dfstab), F_LOCK, 0);
601*12508Samw@Sun.COM (void) mutex_lock(&sa_dfstab_lock);
6024653Sdougm list = getdfstab(dfstab);
6034653Sdougm rewind(dfstab);
6045331Samw if (protocol != NULL) {
6055331Samw if (list != NULL)
6064653Sdougm list = remdfsentry(list, path,
6075331Samw protocol);
6085331Samw } else {
6095331Samw for (optionset = sa_get_optionset(parent, NULL);
6105331Samw optionset != NULL;
6115331Samw optionset =
6125331Samw sa_get_next_optionset(optionset)) {
6135331Samw char *proto = sa_get_optionset_attr(
6145331Samw optionset, "type");
6155331Samw
6165331Samw if (list != NULL && proto != NULL)
6175331Samw list = remdfsentry(list, path,
6185331Samw proto);
6195331Samw if (proto == NULL)
6205331Samw ret = SA_NO_MEMORY;
6215331Samw /*
6225331Samw * may want to only do the dfstab if
6235331Samw * this call returns NOT IMPLEMENTED
6245331Samw * but it shouldn't hurt.
6255331Samw */
6265331Samw if (ret == SA_OK) {
6275331Samw err = sa_proto_delete_legacy(
6285331Samw proto, share);
6295331Samw if (err != SA_NOT_IMPLEMENTED)
6305331Samw ret = err;
6315331Samw }
6325331Samw if (proto != NULL)
6335331Samw sa_free_attr_string(proto);
6344653Sdougm }
6353034Sdougm }
6364653Sdougm outdfstab(dfstab, list);
6374653Sdougm if (list != NULL)
6384653Sdougm dfs_free_list(list);
6394653Sdougm (void) fflush(dfstab);
640*12508Samw@Sun.COM (void) mutex_unlock(&sa_dfstab_lock);
6414653Sdougm (void) lockf(fileno(dfstab), F_ULOCK, 0);
6423034Sdougm }
6433034Sdougm (void) fsync(fileno(dfstab));
6443663Sdougm saunblocksigs(&old);
6453034Sdougm (void) fclose(dfstab);
6463034Sdougm } else {
6474653Sdougm if (errno == EACCES || errno == EPERM)
6484653Sdougm ret = SA_NO_PERMISSION;
6494653Sdougm else
6504653Sdougm ret = SA_CONFIG_ERR;
6513034Sdougm }
6525331Samw
6535331Samw if (path != NULL)
6545331Samw sa_free_attr_string(path);
6555331Samw
6563034Sdougm return (ret);
6573034Sdougm }
6583034Sdougm
6593034Sdougm /*
6603034Sdougm * sa_update_legacy(share, proto)
6613034Sdougm *
6623034Sdougm * There is an assumption that dfstab will be the most common form of
6633034Sdougm * legacy configuration file for shares, but not the only one. Because
6643034Sdougm * of that, dfstab handling is done in the main code with calls to
6655331Samw * this function and protocol specific calls to deal with formatting
6663034Sdougm * options into dfstab/share compatible syntax. Since not everything
6673034Sdougm * will be dfstab, there is a provision for calling a protocol
6683034Sdougm * specific plugin interface that allows the protocol plugin to do its
6693034Sdougm * own legacy files and skip the dfstab update.
6703034Sdougm */
6713034Sdougm
6723034Sdougm int
sa_update_legacy(sa_share_t share,char * proto)6733034Sdougm sa_update_legacy(sa_share_t share, char *proto)
6743034Sdougm {
6753034Sdougm FILE *dfstab;
6763034Sdougm int ret = SA_OK;
6773034Sdougm xfs_sharelist_t *list;
6783034Sdougm char *path;
6793663Sdougm sigset_t old;
6803034Sdougm char *persist;
6815331Samw uint64_t features;
6823034Sdougm
6833034Sdougm ret = sa_proto_update_legacy(proto, share);
6843034Sdougm if (ret != SA_NOT_IMPLEMENTED)
6854653Sdougm return (ret);
6865331Samw
6875331Samw features = sa_proto_get_featureset(proto);
6885331Samw if (!(features & SA_FEATURE_DFSTAB))
6895331Samw return (ret);
6905331Samw
6913034Sdougm /* do the dfstab format */
6923034Sdougm persist = sa_get_share_attr(share, "type");
6933034Sdougm /*
6943034Sdougm * only update if the share is not transient -- no share type
6953034Sdougm * set or the type is not "transient".
6963034Sdougm */
6973034Sdougm if (persist == NULL || strcmp(persist, "transient") != 0) {
69811337SWilliam.Krier@Sun.COM path = sa_get_share_attr(share, "path");
69911337SWilliam.Krier@Sun.COM if (path == NULL) {
70011337SWilliam.Krier@Sun.COM ret = SA_NO_MEMORY;
70111337SWilliam.Krier@Sun.COM goto out;
70211337SWilliam.Krier@Sun.COM }
7034653Sdougm dfstab = open_dfstab(SA_LEGACY_DFSTAB);
7044653Sdougm if (dfstab != NULL) {
7054653Sdougm (void) setvbuf(dfstab, NULL, _IOLBF, BUFSIZ * 8);
7064653Sdougm sablocksigs(&old);
7074653Sdougm (void) lockf(fileno(dfstab), F_LOCK, 0);
708*12508Samw@Sun.COM (void) mutex_lock(&sa_dfstab_lock);
7094653Sdougm list = getdfstab(dfstab);
7104653Sdougm rewind(dfstab);
7114653Sdougm if (list != NULL)
7124653Sdougm list = remdfsentry(list, path, proto);
7134653Sdougm list = adddfsentry(list, share, proto);
7144653Sdougm outdfstab(dfstab, list);
7154653Sdougm (void) fflush(dfstab);
716*12508Samw@Sun.COM (void) mutex_unlock(&sa_dfstab_lock);
7174653Sdougm (void) lockf(fileno(dfstab), F_ULOCK, 0);
7184653Sdougm (void) fsync(fileno(dfstab));
7194653Sdougm saunblocksigs(&old);
7204653Sdougm (void) fclose(dfstab);
7214653Sdougm if (list != NULL)
7224653Sdougm dfs_free_list(list);
7233034Sdougm } else {
7244653Sdougm if (errno == EACCES || errno == EPERM)
7254653Sdougm ret = SA_NO_PERMISSION;
7264653Sdougm else
7274653Sdougm ret = SA_CONFIG_ERR;
7283034Sdougm }
72911337SWilliam.Krier@Sun.COM sa_free_attr_string(path);
7303034Sdougm }
73111337SWilliam.Krier@Sun.COM out:
7323034Sdougm if (persist != NULL)
7334653Sdougm sa_free_attr_string(persist);
7343034Sdougm return (ret);
7353034Sdougm }
7363034Sdougm
7373034Sdougm /*
7383034Sdougm * sa_is_security(optname, proto)
7393034Sdougm *
7403034Sdougm * Check to see if optname is a security (named optionset) specific
7413034Sdougm * property for the specified protocol.
7423034Sdougm */
7433034Sdougm
7443034Sdougm int
sa_is_security(char * optname,char * proto)7453034Sdougm sa_is_security(char *optname, char *proto)
7463034Sdougm {
7473034Sdougm int ret = 0;
7483034Sdougm if (proto != NULL)
7494653Sdougm ret = sa_proto_security_prop(proto, optname);
7503034Sdougm return (ret);
7513034Sdougm }
7523034Sdougm
7533034Sdougm /*
7543034Sdougm * add_syntax_comment(root, line, err, todfstab)
7553034Sdougm *
7564653Sdougm * Add a comment to the document indicating a syntax error. If
7573034Sdougm * todfstab is set, write it back to the dfstab file as well.
7583034Sdougm */
7593034Sdougm
7603034Sdougm static void
add_syntax_comment(xmlNodePtr root,char * line,char * err,int todfstab)7613034Sdougm add_syntax_comment(xmlNodePtr root, char *line, char *err, int todfstab)
7623034Sdougm {
7633034Sdougm xmlNodePtr node;
7643034Sdougm
7653034Sdougm node = xmlNewChild(root, NULL, (xmlChar *)"error", (xmlChar *)line);
7664653Sdougm if (node != NULL)
7676012Sthurlow (void) xmlSetProp(node, (xmlChar *)"type", (xmlChar *)err);
7683034Sdougm if (todfstab)
7694653Sdougm sa_comment_line(line, err);
7703034Sdougm }
7713034Sdougm
7723034Sdougm /*
7733034Sdougm * sa_is_share(object)
7743034Sdougm *
7753034Sdougm * returns true of the object is of type "share".
7763034Sdougm */
7773034Sdougm
7783034Sdougm int
sa_is_share(void * object)7793034Sdougm sa_is_share(void *object)
7803034Sdougm {
7813034Sdougm if (object != NULL) {
7824653Sdougm if (strcmp((char *)((xmlNodePtr)object)->name, "share") == 0)
7833034Sdougm return (1);
7843034Sdougm }
7853034Sdougm return (0);
7863034Sdougm }
7875331Samw /*
7885331Samw * sa_is_resource(object)
7895331Samw *
7905331Samw * returns true of the object is of type "share".
7915331Samw */
7925331Samw
7935331Samw int
sa_is_resource(void * object)7945331Samw sa_is_resource(void *object)
7955331Samw {
7965331Samw if (object != NULL) {
7975331Samw if (strcmp((char *)((xmlNodePtr)object)->name, "resource") == 0)
7985331Samw return (1);
7995331Samw }
8005331Samw return (0);
8015331Samw }
8023034Sdougm
8033034Sdougm /*
8043034Sdougm * _sa_remove_property(property)
8053034Sdougm *
8063034Sdougm * remove a property only from the document.
8073034Sdougm */
8083034Sdougm
8093034Sdougm static void
_sa_remove_property(sa_property_t property)8103034Sdougm _sa_remove_property(sa_property_t property)
8113034Sdougm {
8123034Sdougm xmlUnlinkNode((xmlNodePtr)property);
8133034Sdougm xmlFreeNode((xmlNodePtr)property);
8143034Sdougm }
8153034Sdougm
8163034Sdougm /*
8174180Sdougm * _sa_create_dummy_share()
8184180Sdougm *
8194180Sdougm * Create a share entry suitable for parsing but not tied to any real
8204180Sdougm * config tree. Need to have a parent as well as the node to parse
8214180Sdougm * on. Free using _sa_free_dummy_share(share);
8224180Sdougm */
8234180Sdougm
8244180Sdougm static sa_group_t
_sa_create_dummy_share()8254180Sdougm _sa_create_dummy_share()
8264180Sdougm {
8274180Sdougm xmlNodePtr parent_node = NULL;
8284180Sdougm xmlNodePtr child_node = NULL;
8294180Sdougm
8304180Sdougm parent_node = xmlNewNode(NULL, (xmlChar *)"group");
8314180Sdougm if (parent_node != NULL) {
8324653Sdougm child_node = xmlNewChild(parent_node, NULL, (xmlChar *)"share",
8334653Sdougm NULL);
8344653Sdougm if (child_node != NULL) {
8354653Sdougm /*
8364653Sdougm * Use a "zfs" tag since that will make sure nothing
8374653Sdougm * really attempts to put values into the
8384653Sdougm * repository. Also ZFS is currently the only user of
8394653Sdougm * this interface.
8404653Sdougm */
8414653Sdougm set_node_attr(parent_node, "type", "transient");
8424653Sdougm set_node_attr(parent_node, "zfs", "true");
8434653Sdougm set_node_attr(child_node, "type", "transient");
8444653Sdougm set_node_attr(child_node, "zfs", "true");
8454653Sdougm } else {
8464653Sdougm xmlFreeNode(parent_node);
8474653Sdougm }
8484180Sdougm }
8494180Sdougm return (child_node);
8504180Sdougm }
8514180Sdougm
8524180Sdougm /*
8534180Sdougm * _sa_free_dummy_share(share)
8544180Sdougm *
8554180Sdougm * Free the dummy share and its parent. It is an error to try and
8564180Sdougm * free something that isn't a dummy.
8574180Sdougm */
8584180Sdougm
8594180Sdougm static int
_sa_free_dummy_share(sa_share_t share)8604180Sdougm _sa_free_dummy_share(sa_share_t share)
8614180Sdougm {
8624180Sdougm xmlNodePtr node = (xmlNodePtr)share;
8634180Sdougm xmlNodePtr parent;
8644180Sdougm int ret = SA_OK;
8654180Sdougm char *name;
8664180Sdougm
8674180Sdougm if (node != NULL) {
8684653Sdougm parent = node->parent;
8694653Sdougm name = (char *)xmlGetProp(node, (xmlChar *)"path");
8704653Sdougm if (name != NULL) {
8714653Sdougm /* Real shares always have a path but a dummy doesn't */
8724653Sdougm ret = SA_NOT_ALLOWED;
8734653Sdougm sa_free_attr_string(name);
8744653Sdougm } else {
8754653Sdougm /*
8764653Sdougm * If there is a parent, do the free on that since
8774653Sdougm * xmlFreeNode is a recursive function and free's an
8784653Sdougm * child nodes.
8794653Sdougm */
8804653Sdougm if (parent != NULL) {
8814653Sdougm node = parent;
8824653Sdougm }
8834653Sdougm xmlUnlinkNode(node);
8844653Sdougm xmlFreeNode(node);
8854180Sdougm }
8864180Sdougm }
8874180Sdougm return (ret);
8884180Sdougm }
8894180Sdougm
8904180Sdougm
8914180Sdougm /*
8923034Sdougm * sa_parse_legacy_options(group, options, proto)
8933034Sdougm *
8943034Sdougm * In order to support legacy configurations, we allow the protocol
8953034Sdougm * specific plugin to parse legacy syntax options (like those in
8963034Sdougm * /etc/dfs/dfstab). This adds a new optionset to the group (or
8973034Sdougm * share).
8983034Sdougm *
8993034Sdougm * Once the optionset has been created, we then get the derived
9003034Sdougm * optionset of the parent (options from the optionset of the parent
9013034Sdougm * and any parent it might have) and remove those from the created
9023034Sdougm * optionset. This avoids duplication of options.
9033034Sdougm */
9043034Sdougm
9053034Sdougm int
sa_parse_legacy_options(sa_group_t group,char * options,char * proto)9063034Sdougm sa_parse_legacy_options(sa_group_t group, char *options, char *proto)
9073034Sdougm {
9083034Sdougm int ret = SA_INVALID_PROTOCOL;
9093034Sdougm sa_group_t parent;
9104180Sdougm int using_dummy = B_FALSE;
9114461Sdougm char *pvalue;
9124653Sdougm sa_optionset_t optionset;
9134653Sdougm sa_property_t popt, prop;
9144653Sdougm sa_optionset_t localoptions;
9154180Sdougm
9164180Sdougm /*
9174653Sdougm * If "group" is NULL, this is just a parse without saving
9184180Sdougm * anything in either SMF or ZFS. Create a dummy group to
9194180Sdougm * handle this case.
9204180Sdougm */
9214180Sdougm if (group == NULL) {
9224653Sdougm group = (sa_group_t)_sa_create_dummy_share();
9234653Sdougm using_dummy = B_TRUE;
9244180Sdougm }
9254180Sdougm
9263034Sdougm parent = sa_get_parent_group(group);
9273034Sdougm
9283034Sdougm if (proto != NULL)
9294653Sdougm ret = sa_proto_legacy_opts(proto, group, options);
9304180Sdougm
9314180Sdougm if (using_dummy) {
9324653Sdougm /* Since this is a dummy parse, cleanup and quit here */
9334653Sdougm (void) _sa_free_dummy_share(parent);
9344653Sdougm return (ret);
9354180Sdougm }
9364653Sdougm
9374653Sdougm if (ret != SA_OK)
9384653Sdougm return (ret);
9394653Sdougm
9403034Sdougm /*
9414653Sdougm * If in a group, remove the inherited options and security
9423034Sdougm */
9434653Sdougm
9444653Sdougm if (parent == NULL)
9454653Sdougm return (ret);
9464653Sdougm
9474653Sdougm /* Find parent options to remove from child */
9484653Sdougm optionset = sa_get_derived_optionset(parent, proto, 1);
9494653Sdougm localoptions = sa_get_optionset(group, proto);
9504653Sdougm if (optionset != NULL) {
9514653Sdougm for (popt = sa_get_property(optionset, NULL);
9524653Sdougm popt != NULL;
9534653Sdougm popt = sa_get_next_property(popt)) {
9543034Sdougm char *tag;
9554461Sdougm char *value;
9563034Sdougm tag = sa_get_property_attr(popt, "type");
9574653Sdougm if (tag == NULL)
9584653Sdougm continue;
9594653Sdougm prop = sa_get_property(localoptions, tag);
9604653Sdougm if (prop != NULL) {
9614653Sdougm value = sa_get_property_attr(popt,
9624653Sdougm "value");
9634653Sdougm pvalue = sa_get_property_attr(prop,
9644653Sdougm "value");
9654461Sdougm if (value != NULL && pvalue != NULL &&
9664461Sdougm strcmp(value, pvalue) == 0) {
9674461Sdougm /*
9684653Sdougm * Remove the property
9694653Sdougm * from the
9704653Sdougm * child. While we
9714653Sdougm * removed it, we
9724653Sdougm * don't need to reset
9734653Sdougm * as we do below
9744653Sdougm * since we always
9754653Sdougm * search from the
9764653Sdougm * beginning.
9774461Sdougm */
9784653Sdougm (void) _sa_remove_property(
9794653Sdougm prop);
9803034Sdougm }
9814461Sdougm if (value != NULL)
9824653Sdougm sa_free_attr_string(value);
9834461Sdougm if (pvalue != NULL)
9844653Sdougm sa_free_attr_string(pvalue);
9853034Sdougm }
9864653Sdougm sa_free_attr_string(tag);
9874653Sdougm }
9884653Sdougm prop = sa_get_property(localoptions, NULL);
9894653Sdougm if (prop == NULL && sa_is_share(group)) {
9903034Sdougm /*
9914653Sdougm * All properties removed so remove the
9923034Sdougm * optionset if it is on a share
9933034Sdougm */
9943034Sdougm (void) _sa_remove_optionset(localoptions);
9953034Sdougm }
9964653Sdougm sa_free_derived_optionset(optionset);
9974653Sdougm }
9984653Sdougm /*
9994653Sdougm * Need to remove security here. If there are no
10004653Sdougm * security options on the local group/share, don't
10014653Sdougm * bother since those are the only ones that would be
10024653Sdougm * affected.
10034653Sdougm */
10044653Sdougm localoptions = sa_get_all_security_types(group, proto, 0);
10054653Sdougm if (localoptions != NULL) {
10064653Sdougm for (prop = sa_get_property(localoptions, NULL);
10074653Sdougm prop != NULL;
10084653Sdougm prop = sa_get_next_property(prop)) {
10093034Sdougm char *tag;
10103034Sdougm sa_security_t security;
10113034Sdougm tag = sa_get_property_attr(prop, "type");
10123034Sdougm if (tag != NULL) {
10134653Sdougm sa_property_t nextpopt = NULL;
10144653Sdougm security = sa_get_security(group, tag, proto);
10154653Sdougm sa_free_attr_string(tag);
10164461Sdougm /*
10174653Sdougm * prop's value only changes outside this loop
10184461Sdougm */
10194653Sdougm pvalue = sa_get_property_attr(prop, "value");
10204653Sdougm for (popt = sa_get_property(security, NULL);
10214653Sdougm popt != NULL;
10224653Sdougm popt = nextpopt) {
10234653Sdougm char *value;
10244653Sdougm /*
10254653Sdougm * Need to get the next prop
10264653Sdougm * now since we could break
10274653Sdougm * the list during removal.
10284653Sdougm */
10294653Sdougm nextpopt = sa_get_next_property(popt);
10304653Sdougm /* remove Duplicates from this level */
10314653Sdougm value = sa_get_property_attr(popt,
10324653Sdougm "value");
10334653Sdougm if (value != NULL && pvalue != NULL &&
10344653Sdougm strcmp(value, pvalue) == 0) {
10354653Sdougm /*
10364653Sdougm * remove the property
10374653Sdougm * from the child
10384653Sdougm */
10394653Sdougm (void) _sa_remove_property
10404653Sdougm (popt);
10414653Sdougm }
10424653Sdougm if (value != NULL)
10434653Sdougm sa_free_attr_string(value);
10443034Sdougm }
10454653Sdougm if (pvalue != NULL)
10464653Sdougm sa_free_attr_string(pvalue);
10473034Sdougm }
10483034Sdougm }
10494653Sdougm (void) sa_destroy_optionset(localoptions);
10503034Sdougm }
10513034Sdougm return (ret);
10523034Sdougm }
10533034Sdougm
10543034Sdougm /*
10553034Sdougm * dfs_free_list(list)
10563034Sdougm *
10573034Sdougm * Free the data in each list entry of the list as well as freeing the
10583034Sdougm * entries themselves. We need to avoid memory leaks and don't want to
10593034Sdougm * dereference any NULL members.
10603034Sdougm */
10613034Sdougm
10623034Sdougm static void
dfs_free_list(xfs_sharelist_t * list)10633034Sdougm dfs_free_list(xfs_sharelist_t *list)
10643034Sdougm {
10653034Sdougm xfs_sharelist_t *entry;
10663034Sdougm for (entry = list; entry != NULL; entry = list) {
10674653Sdougm if (entry->path != NULL)
10684653Sdougm free(entry->path);
10694653Sdougm if (entry->resource != NULL)
10704653Sdougm free(entry->resource);
10714653Sdougm if (entry->fstype != NULL)
10724653Sdougm free(entry->fstype);
10734653Sdougm if (entry->options != NULL)
10744653Sdougm free(entry->options);
10754653Sdougm if (entry->description != NULL)
10764653Sdougm free(entry->description);
10774653Sdougm if (entry->origline != NULL)
10784653Sdougm free(entry->origline);
10794653Sdougm if (entry->group != NULL)
10804653Sdougm free(entry->group);
10814653Sdougm list = list->next;
10824653Sdougm free(entry);
10833034Sdougm }
10843034Sdougm }
10853034Sdougm
10863034Sdougm /*
10873034Sdougm * parse_dfstab(dfstab, root)
10883034Sdougm *
10893034Sdougm * Open and read the existing dfstab, parsing each line and adding it
10903034Sdougm * to the internal configuration. Make sure syntax errors, etc are
10913034Sdougm * preserved as comments.
10923034Sdougm */
10933034Sdougm
10943034Sdougm static void
parse_dfstab(sa_handle_t handle,char * dfstab,xmlNodePtr root)10953910Sdougm parse_dfstab(sa_handle_t handle, char *dfstab, xmlNodePtr root)
10963034Sdougm {
10973034Sdougm sa_share_t share;
10983034Sdougm sa_group_t group;
10993034Sdougm sa_group_t sgroup = NULL;
11003034Sdougm sa_group_t defgroup;
11013034Sdougm xfs_sharelist_t *head, *list;
11023034Sdougm int err;
11033034Sdougm int defined_group;
11043034Sdougm FILE *dfs;
11053034Sdougm char *oldprops;
11063034Sdougm
11073034Sdougm /* read the dfstab format file and fill in the doc tree */
11083034Sdougm
11093034Sdougm dfs = fopen(dfstab, "r");
11104653Sdougm if (dfs == NULL)
11114653Sdougm return;
11123034Sdougm
11133910Sdougm defgroup = sa_get_group(handle, "default");
11143034Sdougm
11153034Sdougm for (head = list = getdfstab(dfs);
11164653Sdougm list != NULL;
11174653Sdougm list = list->next) {
11184653Sdougm share = NULL;
11194653Sdougm group = NULL;
11204653Sdougm defined_group = 0;
11214653Sdougm err = 0;
11223034Sdougm
11234653Sdougm if (list->origline == NULL) {
11244653Sdougm /*
11254653Sdougm * Comment line that we will likely skip.
11264653Sdougm * If the line has the syntax:
11274653Sdougm * # error: string: string
11284653Sdougm * It should be preserved until manually deleted.
11294653Sdougm */
11304653Sdougm if (list->description != NULL &&
11314653Sdougm strncmp(list->description, "# Error: ", 9) == 0) {
11324653Sdougm char *line;
11334653Sdougm char *error;
11344653Sdougm char *cmd;
11354653Sdougm line = strdup(list->description);
11364653Sdougm if (line != NULL) {
11374653Sdougm error = line + 9;
11384653Sdougm cmd = strchr(error, ':');
11394653Sdougm if (cmd != NULL) {
11404653Sdougm int len;
11414653Sdougm *cmd = '\0';
11424653Sdougm cmd += 2;
11434653Sdougm len = strlen(cmd);
11444653Sdougm cmd[len - 1] = '\0';
11454653Sdougm add_syntax_comment(root, cmd,
11464653Sdougm error, 0);
11474653Sdougm }
11484653Sdougm free(line);
11494653Sdougm }
11503034Sdougm }
11514653Sdougm continue;
11523034Sdougm }
11534653Sdougm if (list->path != NULL && strlen(list->path) > 0 &&
11543910Sdougm *list->path == '/') {
11554653Sdougm share = sa_find_share(handle, list->path);
11564653Sdougm if (share != NULL)
11574653Sdougm sgroup = sa_get_parent_group(share);
11584653Sdougm else
11594653Sdougm sgroup = NULL;
11604653Sdougm } else {
11614653Sdougm (void) printf(dgettext(TEXT_DOMAIN,
11624653Sdougm "No share specified in dfstab: "
11634653Sdougm "line %d: %s\n"),
11644653Sdougm list->lineno, list->origline);
11654653Sdougm add_syntax_comment(root, list->origline,
11664653Sdougm dgettext(TEXT_DOMAIN, "No share specified"), 1);
11674653Sdougm continue;
11684653Sdougm }
11694653Sdougm if (list->group != NULL && strlen(list->group) > 0) {
11704653Sdougm group = sa_get_group(handle, list->group);
11714653Sdougm defined_group = 1;
11724653Sdougm } else {
11734653Sdougm group = defgroup;
11744653Sdougm }
11754653Sdougm if (defined_group && group == NULL) {
11764653Sdougm (void) printf(dgettext(TEXT_DOMAIN,
11774653Sdougm "Unknown group used in dfstab: line %d: %s\n"),
11784653Sdougm list->lineno, list->origline);
11794653Sdougm add_syntax_comment(root, list->origline,
11804653Sdougm dgettext(TEXT_DOMAIN, "Unknown group specified"),
11814653Sdougm 1);
11824653Sdougm continue;
11834653Sdougm }
11844653Sdougm if (group == NULL) {
11854653Sdougm /* Shouldn't happen unless an SMF error */
11864653Sdougm err = SA_CONFIG_ERR;
11874653Sdougm continue;
11884653Sdougm }
11893034Sdougm if (share == NULL) {
11904653Sdougm if (defined_group || group != defgroup)
11914653Sdougm continue;
11924653Sdougm /* This is an OK add for legacy */
11933034Sdougm share = sa_add_share(defgroup, list->path,
11944653Sdougm SA_SHARE_PERMANENT | SA_SHARE_PARSER, &err);
11953034Sdougm if (share != NULL) {
11964653Sdougm if (list->description != NULL &&
11974653Sdougm strlen(list->description) > 0)
11984653Sdougm (void) sa_set_share_description(share,
11994653Sdougm list->description);
12004653Sdougm if (list->options != NULL &&
12014653Sdougm strlen(list->options) > 0) {
12024653Sdougm (void) sa_parse_legacy_options(share,
12034653Sdougm list->options, list->fstype);
12044653Sdougm }
12054653Sdougm if (list->resource != NULL)
12064653Sdougm (void) sa_set_share_attr(share,
12074653Sdougm "resource", list->resource);
12083034Sdougm } else {
12094653Sdougm (void) printf(dgettext(TEXT_DOMAIN,
12104653Sdougm "Error in dfstab: line %d: %s\n"),
12113034Sdougm list->lineno, list->origline);
12124653Sdougm if (err != SA_BAD_PATH)
12134653Sdougm add_syntax_comment(root, list->origline,
12144653Sdougm dgettext(TEXT_DOMAIN, "Syntax"), 1);
12154653Sdougm else
12164653Sdougm add_syntax_comment(root, list->origline,
12174653Sdougm dgettext(TEXT_DOMAIN,
12184653Sdougm "Path"), 1);
12194653Sdougm continue;
12204653Sdougm }
12214653Sdougm } else {
12224653Sdougm if (group != sgroup) {
12234653Sdougm (void) printf(dgettext(TEXT_DOMAIN,
12244653Sdougm "Attempt to change configuration in "
12254653Sdougm "dfstab: line %d: %s\n"),
12264653Sdougm list->lineno, list->origline);
12273034Sdougm add_syntax_comment(root, list->origline,
12284653Sdougm dgettext(TEXT_DOMAIN,
12294653Sdougm "Attempt to change configuration"), 1);
12304653Sdougm continue;
12313034Sdougm }
12324524Sdougm /*
12334524Sdougm * It is the same group but could have changed
12344524Sdougm * options. Make sure we include the group's
12354524Sdougm * properties so we don't end up moving them to
12364524Sdougm * the share inadvertantly. The last arg being
12374524Sdougm * true says to get the inherited properties as well
12384524Sdougm * as the local properties.
12394524Sdougm */
12404653Sdougm oldprops = sa_proto_legacy_format(list->fstype, share,
12414653Sdougm B_TRUE);
12424653Sdougm
12434653Sdougm if (oldprops == NULL)
12444653Sdougm continue;
12454653Sdougm
12463034Sdougm if (list->options != NULL &&
12474653Sdougm strcmp(oldprops, list->options) != 0) {
12484653Sdougm sa_optionset_t opts;
12494653Sdougm sa_security_t secs;
12504653Sdougm
12514653Sdougm /* possibly different values */
12524653Sdougm opts = sa_get_optionset((sa_group_t)
12534653Sdougm share, list->fstype);
12544653Sdougm (void) sa_destroy_optionset(opts);
12554653Sdougm
12564653Sdougm for (secs = sa_get_security(
12574653Sdougm (sa_group_t)share, NULL, list->fstype);
12584653Sdougm secs != NULL;
12594653Sdougm secs = sa_get_security((sa_group_t)share,
12604653Sdougm NULL, list->fstype)) {
12614653Sdougm (void) sa_destroy_security(
12624653Sdougm secs);
12634653Sdougm }
12644653Sdougm (void) sa_parse_legacy_options(share,
12654653Sdougm list->options, list->fstype);
12663034Sdougm }
12673663Sdougm sa_format_free(oldprops);
12683034Sdougm }
12693034Sdougm }
12703034Sdougm dfs_free_list(head);
12713034Sdougm }
12723034Sdougm
12733034Sdougm /*
12743034Sdougm * legacy_removes(group, file)
12753034Sdougm *
12763034Sdougm * Find any shares that are "missing" from the legacy file. These
12773034Sdougm * should be removed from the configuration since they are likely from
12783034Sdougm * a legacy app or the admin modified the dfstab file directly. We
12793034Sdougm * have to support this even if it is not the recommended way to do
12803034Sdougm * things.
12813034Sdougm */
12823034Sdougm
12833034Sdougm static void
legacy_removes(sa_group_t group,char * file)12843034Sdougm legacy_removes(sa_group_t group, char *file)
12853034Sdougm {
12863034Sdougm sa_share_t share;
12873034Sdougm char *path;
12883034Sdougm xfs_sharelist_t *list, *item;
12893034Sdougm FILE *dfstab;
12903034Sdougm
12913034Sdougm dfstab = fopen(file, "r");
12923034Sdougm if (dfstab != NULL) {
12934653Sdougm list = getdfstab(dfstab);
12944653Sdougm (void) fclose(dfstab);
12953348Sdougm retry:
12964653Sdougm for (share = sa_get_share(group, NULL);
12974653Sdougm share != NULL;
12984653Sdougm share = sa_get_next_share(share)) {
12994653Sdougm /* now see if the share is in the dfstab file */
13004653Sdougm path = sa_get_share_attr(share, "path");
13014653Sdougm if (path != NULL) {
13024653Sdougm item = finddfsentry(list, path);
13034653Sdougm sa_free_attr_string(path);
13044653Sdougm if (item == NULL) {
13054653Sdougm /* The share was removed this way */
13064653Sdougm (void) sa_remove_share(share);
13073348Sdougm
13084653Sdougm /*
13094653Sdougm * Start over since the list was broken
13104653Sdougm */
13114653Sdougm goto retry;
13124653Sdougm }
13134653Sdougm }
13143034Sdougm }
13154653Sdougm if (list != NULL)
13164653Sdougm dfs_free_list(list);
13173034Sdougm }
13183034Sdougm }
13193034Sdougm
13203034Sdougm /*
13213034Sdougm * getlegacyconfig(path, root)
13223034Sdougm *
13233034Sdougm * Parse dfstab and build the legacy configuration. This only gets
13243034Sdougm * called when a change was detected.
13253034Sdougm */
13263034Sdougm
13273034Sdougm void
getlegacyconfig(sa_handle_t handle,char * path,xmlNodePtr * root)13283910Sdougm getlegacyconfig(sa_handle_t handle, char *path, xmlNodePtr *root)
13293034Sdougm {
13303034Sdougm sa_group_t defgroup;
13313034Sdougm
13323034Sdougm if (root != NULL) {
13334653Sdougm if (*root == NULL)
13344653Sdougm *root = xmlNewNode(NULL, (xmlChar *)"sharecfg");
13354653Sdougm if (*root != NULL) {
13364653Sdougm if (strcmp(path, SA_LEGACY_DFSTAB) == 0) {
13374653Sdougm /*
13384653Sdougm * Walk the default shares and find anything
13394653Sdougm * missing. we do this first to make sure it
13404653Sdougm * is cleaned up since there may be legacy
13414653Sdougm * code add/del via dfstab and we need to
13424653Sdougm * cleanup SMF.
13434653Sdougm */
13444653Sdougm defgroup = sa_get_group(handle, "default");
13454653Sdougm if (defgroup != NULL)
13464653Sdougm legacy_removes(defgroup, path);
13474653Sdougm /* Parse the dfstab and add anything new */
13484653Sdougm parse_dfstab(handle, path, *root);
13494653Sdougm }
13503034Sdougm }
13513034Sdougm }
13523034Sdougm }
13533034Sdougm
13543034Sdougm /*
13553218Sdougm * get_share_list(&err)
13563218Sdougm *
13573218Sdougm * Get a linked list of all the shares on the system from
13583218Sdougm * /etc/dfs/sharetab. This is partially copied from libfsmgt which we
13593218Sdougm * can't use due to package dependencies.
13603218Sdougm */
13613218Sdougm static xfs_sharelist_t *
get_share_list(int * errp)13623218Sdougm get_share_list(int *errp)
13633218Sdougm {
13643218Sdougm xfs_sharelist_t *newp;
13653218Sdougm xfs_sharelist_t *headp;
13663218Sdougm xfs_sharelist_t *tailp;
13673218Sdougm FILE *fp;
13683218Sdougm
13693218Sdougm headp = NULL;
13703218Sdougm tailp = NULL;
13713218Sdougm
13723218Sdougm if ((fp = fopen(SHARETAB, "r")) != NULL) {
13733218Sdougm struct share *sharetab_entry;
13743218Sdougm
13758334SJose.Borrego@Sun.COM (void) lockf(fileno(fp), F_LOCK, 0);
13768334SJose.Borrego@Sun.COM (void) mutex_lock(&sharetab_lock);
13778334SJose.Borrego@Sun.COM
13783218Sdougm while (getshare(fp, &sharetab_entry) > 0) {
13794653Sdougm newp = alloc_sharelist();
13808334SJose.Borrego@Sun.COM if (newp == NULL) {
13818334SJose.Borrego@Sun.COM (void) mutex_unlock(&sharetab_lock);
13828334SJose.Borrego@Sun.COM (void) lockf(fileno(fp), F_ULOCK, 0);
13834653Sdougm goto err;
13848334SJose.Borrego@Sun.COM }
13853218Sdougm
13863218Sdougm /*
13874653Sdougm * Link into the list here so we don't leak
13883218Sdougm * memory on a failure from strdup().
13893218Sdougm */
13904653Sdougm if (headp == NULL) {
13914653Sdougm headp = newp;
13924653Sdougm tailp = newp;
13934653Sdougm } else {
13944653Sdougm tailp->next = newp;
13954653Sdougm tailp = newp;
13964653Sdougm }
13973218Sdougm
13984653Sdougm newp->path = strdup(sharetab_entry->sh_path);
13994653Sdougm newp->resource = strdup(sharetab_entry->sh_res);
14004653Sdougm newp->fstype = strdup(sharetab_entry->sh_fstype);
14018334SJose.Borrego@Sun.COM newp->options = strdup(sharetab_entry->sh_opts);
14028334SJose.Borrego@Sun.COM newp->description = strdup(sharetab_entry->sh_descr);
14038334SJose.Borrego@Sun.COM
14048334SJose.Borrego@Sun.COM if (newp->path == NULL || newp->resource == NULL ||
14058334SJose.Borrego@Sun.COM newp->fstype == NULL || newp->options == NULL ||
14068334SJose.Borrego@Sun.COM newp->description == NULL) {
14078334SJose.Borrego@Sun.COM (void) mutex_unlock(&sharetab_lock);
14088334SJose.Borrego@Sun.COM (void) lockf(fileno(fp), F_ULOCK, 0);
14094653Sdougm goto err;
14108334SJose.Borrego@Sun.COM }
14113218Sdougm }
14128334SJose.Borrego@Sun.COM
14138334SJose.Borrego@Sun.COM (void) mutex_unlock(&sharetab_lock);
14143663Sdougm (void) lockf(fileno(fp), F_ULOCK, 0);
14153218Sdougm (void) fclose(fp);
14163218Sdougm } else {
14174653Sdougm *errp = errno;
14183218Sdougm }
14193218Sdougm
14203218Sdougm /*
14213218Sdougm * Caller must free the mount list
14223218Sdougm */
14233218Sdougm return (headp);
14243218Sdougm err:
14253218Sdougm /*
14263218Sdougm * Out of memory so cleanup and leave.
14273218Sdougm */
14283218Sdougm dfs_free_list(headp);
14293218Sdougm (void) fclose(fp);
14303218Sdougm return (NULL);
14313218Sdougm }
14323218Sdougm
14333218Sdougm /*
14343910Sdougm * parse_sharetab(handle)
14353034Sdougm *
14363218Sdougm * Read the /etc/dfs/sharetab file and see which entries don't exist
14373218Sdougm * in the repository. These shares are marked transient. We also need
14383218Sdougm * to see if they are ZFS shares since ZFS bypasses the SMF
14393218Sdougm * repository.
14403034Sdougm */
14413034Sdougm
14423034Sdougm int
parse_sharetab(sa_handle_t handle)14433910Sdougm parse_sharetab(sa_handle_t handle)
14443034Sdougm {
14453218Sdougm xfs_sharelist_t *list, *tmplist;
14463034Sdougm int err = 0;
14473034Sdougm sa_share_t share;
14483034Sdougm sa_group_t group;
14493034Sdougm sa_group_t lgroup;
14503034Sdougm char *groupname;
14513034Sdougm int legacy = 0;
14525331Samw char shareopts[MAXNAMLEN];
14533034Sdougm
14543218Sdougm list = get_share_list(&err);
14553034Sdougm if (list == NULL)
14564653Sdougm return (legacy);
14573034Sdougm
14583910Sdougm lgroup = sa_get_group(handle, "default");
14593034Sdougm
14603034Sdougm for (tmplist = list; tmplist != NULL; tmplist = tmplist->next) {
14614653Sdougm group = NULL;
14624653Sdougm share = sa_find_share(handle, tmplist->path);
14634653Sdougm if (share != NULL) {
14644653Sdougm /*
14654653Sdougm * If this is a legacy share, mark as shared so we
14664653Sdougm * only update sharetab appropriately. We also keep
14674653Sdougm * the sharetab options in order to display for legacy
14684653Sdougm * share with no arguments.
14694653Sdougm */
14704653Sdougm set_node_attr(share, "shared", "true");
14715331Samw (void) snprintf(shareopts, MAXNAMLEN, "shareopts-%s",
14725331Samw tmplist->fstype);
14735331Samw set_node_attr(share, shareopts, tmplist->options);
14744653Sdougm continue;
14754653Sdougm }
14764653Sdougm
14773034Sdougm /*
14784653Sdougm * This share is transient so needs to be
14793034Sdougm * added. Initially, this will be under
14803034Sdougm * default(legacy) unless it is a ZFS
14813034Sdougm * share. If zfs, we need a zfs group.
14823034Sdougm */
14833034Sdougm if (tmplist->resource != NULL &&
14843034Sdougm (groupname = strchr(tmplist->resource, '@')) != NULL) {
14854653Sdougm /* There is a defined group */
14864653Sdougm *groupname++ = '\0';
14874653Sdougm group = sa_get_group(handle, groupname);
14884653Sdougm if (group != NULL) {
14895331Samw share = _sa_add_share(group, tmplist->path,
14905331Samw SA_SHARE_TRANSIENT, &err,
14915331Samw (uint64_t)SA_FEATURE_NONE);
14924653Sdougm } else {
14934653Sdougm /*
14944653Sdougm * While this case shouldn't
14954653Sdougm * occur very often, it does
14964653Sdougm * occur out of a "zfs set
14974653Sdougm * sharenfs=off" when the
14984653Sdougm * dataset is also set to
14994653Sdougm * canmount=off. A warning
15004653Sdougm * will then cause the zfs
15014653Sdougm * command to abort. Since we
15024653Sdougm * add it to the default list,
15034653Sdougm * everything works properly
15044653Sdougm * anyway and the library
15054653Sdougm * doesn't need to give a
15064653Sdougm * warning.
15074653Sdougm */
15084653Sdougm share = _sa_add_share(lgroup,
15094653Sdougm tmplist->path, SA_SHARE_TRANSIENT,
15105331Samw &err, (uint64_t)SA_FEATURE_NONE);
15114653Sdougm }
15123034Sdougm } else {
15134653Sdougm if (sa_zfs_is_shared(handle, tmplist->path)) {
15144653Sdougm group = sa_get_group(handle, "zfs");
15154653Sdougm if (group == NULL) {
15164653Sdougm group = sa_create_group(handle,
15174653Sdougm "zfs", &err);
15184653Sdougm if (group == NULL &&
15194653Sdougm err == SA_NO_PERMISSION) {
15204653Sdougm group = _sa_create_group(
15214653Sdougm (sa_handle_impl_t)
15224653Sdougm handle,
15234653Sdougm "zfs");
15244653Sdougm }
15254653Sdougm if (group != NULL) {
15264653Sdougm (void) sa_create_optionset(
15274653Sdougm group, tmplist->fstype);
15284653Sdougm (void) sa_set_group_attr(group,
15294653Sdougm "zfs", "true");
15304653Sdougm }
15314653Sdougm }
15324653Sdougm if (group != NULL) {
15334653Sdougm share = _sa_add_share(group,
15344653Sdougm tmplist->path, SA_SHARE_TRANSIENT,
15355331Samw &err, (uint64_t)SA_FEATURE_NONE);
15364653Sdougm }
15374653Sdougm } else {
15384653Sdougm share = _sa_add_share(lgroup, tmplist->path,
15395331Samw SA_SHARE_TRANSIENT, &err,
15405331Samw (uint64_t)SA_FEATURE_NONE);
15413034Sdougm }
15423034Sdougm }
15433034Sdougm if (share == NULL)
15444653Sdougm (void) printf(dgettext(TEXT_DOMAIN,
15454653Sdougm "Problem with transient: %s\n"), sa_errorstr(err));
15463034Sdougm if (share != NULL)
15474653Sdougm set_node_attr(share, "shared", "true");
15483034Sdougm if (err == SA_OK) {
15494653Sdougm if (tmplist->options != NULL &&
15504653Sdougm strlen(tmplist->options) > 0) {
15514653Sdougm (void) sa_parse_legacy_options(share,
15524653Sdougm tmplist->options, tmplist->fstype);
15534653Sdougm }
15544653Sdougm if (tmplist->resource != NULL &&
15554653Sdougm strcmp(tmplist->resource, "-") != 0)
15564653Sdougm set_node_attr(share, "resource",
15574653Sdougm tmplist->resource);
15584653Sdougm if (tmplist->description != NULL) {
15594653Sdougm xmlNodePtr node;
15604653Sdougm node = xmlNewChild((xmlNodePtr)share, NULL,
15614653Sdougm (xmlChar *)"description", NULL);
15624653Sdougm xmlNodeSetContent(node,
15634653Sdougm (xmlChar *)tmplist->description);
15644653Sdougm }
15654653Sdougm legacy = 1;
15663034Sdougm }
15673034Sdougm }
15683218Sdougm dfs_free_list(list);
15693034Sdougm return (legacy);
15703034Sdougm }
15713034Sdougm
15723034Sdougm /*
15734653Sdougm * Get the transient shares from the sharetab (or other) file. since
15743034Sdougm * these are transient, they only appear in the working file and not
15753034Sdougm * in a repository.
15763034Sdougm */
15773034Sdougm int
gettransients(sa_handle_impl_t ihandle,xmlNodePtr * root)15783910Sdougm gettransients(sa_handle_impl_t ihandle, xmlNodePtr *root)
15793034Sdougm {
15803034Sdougm int legacy = 0;
15815331Samw int numproto;
15825331Samw char **protocols = NULL;
15835331Samw int i;
15843034Sdougm
15853034Sdougm if (root != NULL) {
15864653Sdougm if (*root == NULL)
15874653Sdougm *root = xmlNewNode(NULL, (xmlChar *)"sharecfg");
15885331Samw if (*root != NULL) {
15894653Sdougm legacy = parse_sharetab(ihandle);
15905331Samw numproto = sa_get_protocols(&protocols);
15915331Samw for (i = 0; i < numproto; i++)
15925331Samw legacy |= sa_proto_get_transients(
15935331Samw (sa_handle_t)ihandle, protocols[i]);
15945331Samw if (protocols != NULL)
15955331Samw free(protocols);
15965331Samw }
15973034Sdougm }
15983034Sdougm return (legacy);
15993034Sdougm }
16003034Sdougm
16013034Sdougm /*
16023034Sdougm * sa_has_prop(optionset, prop)
16033034Sdougm *
16043034Sdougm * Is the specified property a member of the optionset?
16053034Sdougm */
16063034Sdougm
16073034Sdougm int
sa_has_prop(sa_optionset_t optionset,sa_property_t prop)16083034Sdougm sa_has_prop(sa_optionset_t optionset, sa_property_t prop)
16093034Sdougm {
16103034Sdougm char *name;
16113034Sdougm sa_property_t otherprop;
16123034Sdougm int result = 0;
16133034Sdougm
16143034Sdougm if (optionset != NULL) {
16154653Sdougm name = sa_get_property_attr(prop, "type");
16164653Sdougm if (name != NULL) {
16174653Sdougm otherprop = sa_get_property(optionset, name);
16184653Sdougm if (otherprop != NULL)
16194653Sdougm result = 1;
16204653Sdougm sa_free_attr_string(name);
16214653Sdougm }
16223034Sdougm }
16233034Sdougm return (result);
16243034Sdougm }
16253034Sdougm
16263034Sdougm /*
16273034Sdougm * Update legacy files
16283034Sdougm *
16293034Sdougm * Provides functions to add/remove/modify individual entries
16303034Sdougm * in dfstab and sharetab
16313034Sdougm */
16323034Sdougm
16333034Sdougm void
update_legacy_config(sa_handle_t handle)16343910Sdougm update_legacy_config(sa_handle_t handle)
16353034Sdougm {
16363034Sdougm /*
16373034Sdougm * no longer used -- this is a placeholder in case we need to
16383034Sdougm * add it back later.
16393034Sdougm */
16403910Sdougm #ifdef lint
16413910Sdougm handle = handle;
16423910Sdougm #endif
16433034Sdougm }
16443034Sdougm
16453034Sdougm /*
16466214Sdougm * sa_valid_property(handle, object, proto, property)
16473034Sdougm *
16483034Sdougm * check to see if the specified property is valid relative to the
16493034Sdougm * specified protocol. The protocol plugin is called to do the work.
16503034Sdougm */
16513034Sdougm
16523034Sdougm int
sa_valid_property(sa_handle_t handle,void * object,char * proto,sa_property_t property)16536214Sdougm sa_valid_property(sa_handle_t handle, void *object, char *proto,
16546214Sdougm sa_property_t property)
16553034Sdougm {
16563034Sdougm int ret = SA_OK;
16573034Sdougm
16583034Sdougm if (proto != NULL && property != NULL) {
16596214Sdougm ret = sa_proto_valid_prop(handle, proto, property, object);
16603034Sdougm }
16613034Sdougm
16623034Sdougm return (ret);
16633034Sdougm }
16643034Sdougm
16653034Sdougm /*
16663034Sdougm * sa_fstype(path)
16673034Sdougm *
16683034Sdougm * Given path, return the string representing the path's file system
16693034Sdougm * type. This is used to discover ZFS shares.
16703034Sdougm */
16713034Sdougm
16723034Sdougm char *
sa_fstype(char * path)16733034Sdougm sa_fstype(char *path)
16743034Sdougm {
16753034Sdougm int err;
16763034Sdougm struct stat st;
16773034Sdougm
16783034Sdougm err = stat(path, &st);
16794653Sdougm if (err < 0)
16804653Sdougm err = SA_NO_SUCH_PATH;
16814653Sdougm else
16824653Sdougm err = SA_OK;
16834653Sdougm
16844653Sdougm /*
16854653Sdougm * If we have a valid path at this point ret, return the fstype.
16864653Sdougm */
16874653Sdougm if (err == SA_OK)
16884653Sdougm return (strdup(st.st_fstype));
16894653Sdougm
16903034Sdougm return (NULL);
16913034Sdougm }
16923034Sdougm
16933034Sdougm void
sa_free_fstype(char * type)16943034Sdougm sa_free_fstype(char *type)
16953034Sdougm {
16963034Sdougm free(type);
16973034Sdougm }
16983034Sdougm
16993034Sdougm /*
17003034Sdougm * sa_get_derived_optionset(object, proto, hier)
17013034Sdougm *
17023034Sdougm * Work backward to the top of the share object tree and start
17033034Sdougm * copying protocol specific optionsets into a newly created
17043034Sdougm * optionset that doesn't have a parent (it will be freed
17055331Samw * later). This provides for the property inheritance model. That
17063034Sdougm * is, properties closer to the share take precedence over group
17073034Sdougm * level. This also provides for groups of groups in the future.
17083034Sdougm */
17093034Sdougm
17103034Sdougm sa_optionset_t
sa_get_derived_optionset(void * object,char * proto,int hier)17113034Sdougm sa_get_derived_optionset(void *object, char *proto, int hier)
17123034Sdougm {
17133034Sdougm sa_optionset_t newoptionset;
17143034Sdougm sa_optionset_t optionset;
17153034Sdougm sa_group_t group;
17163034Sdougm
17173034Sdougm if (hier &&
17183034Sdougm (group = sa_get_parent_group((sa_share_t)object)) != NULL) {
17194653Sdougm newoptionset = sa_get_derived_optionset((void *)group, proto,
17204653Sdougm hier);
17213034Sdougm } else {
17224653Sdougm newoptionset = (sa_optionset_t)xmlNewNode(NULL,
17234653Sdougm (xmlChar *)"optionset");
17244653Sdougm if (newoptionset != NULL) {
17254653Sdougm sa_set_optionset_attr(newoptionset, "type", proto);
17264653Sdougm }
17273034Sdougm }
17284653Sdougm /* Dont' do anything if memory wasn't allocated */
17293034Sdougm if (newoptionset == NULL)
17304653Sdougm return (NULL);
17313034Sdougm
17324653Sdougm /* Found the top so working back down the stack */
17333034Sdougm optionset = sa_get_optionset((sa_optionset_t)object, proto);
17343034Sdougm if (optionset != NULL) {
17354653Sdougm sa_property_t prop;
17364653Sdougm /* add optionset to the newoptionset */
17374653Sdougm for (prop = sa_get_property(optionset, NULL);
17384653Sdougm prop != NULL;
17394653Sdougm prop = sa_get_next_property(prop)) {
17404653Sdougm sa_property_t newprop;
17414653Sdougm char *name;
17424653Sdougm char *value;
17434653Sdougm name = sa_get_property_attr(prop, "type");
17444653Sdougm value = sa_get_property_attr(prop, "value");
17454653Sdougm if (name == NULL)
17464653Sdougm continue;
17474653Sdougm newprop = sa_get_property(newoptionset, name);
17484653Sdougm /* Replace the value with the new value */
17494653Sdougm if (newprop != NULL) {
17504653Sdougm /*
17514653Sdougm * Only set if value is non NULL, old value ok
17524653Sdougm * if it is NULL.
17534653Sdougm */
17544653Sdougm if (value != NULL)
17554653Sdougm set_node_attr(newprop, "value", value);
17564653Sdougm } else {
17574653Sdougm /* an entirely new property */
17584653Sdougm if (value != NULL) {
17594653Sdougm newprop = sa_create_property(name,
17604653Sdougm value);
17614653Sdougm if (newprop != NULL) {
17624653Sdougm newprop = (sa_property_t)
17634653Sdougm xmlAddChild(
17644653Sdougm (xmlNodePtr)newoptionset,
17654653Sdougm (xmlNodePtr)newprop);
17664653Sdougm }
17674653Sdougm }
17684653Sdougm }
17694653Sdougm sa_free_attr_string(name);
17704653Sdougm
17713034Sdougm if (value != NULL)
17724653Sdougm sa_free_attr_string(value);
17733034Sdougm }
17743034Sdougm }
17753034Sdougm return (newoptionset);
17763034Sdougm }
17773034Sdougm
17783034Sdougm void
sa_free_derived_optionset(sa_optionset_t optionset)17793034Sdougm sa_free_derived_optionset(sa_optionset_t optionset)
17803034Sdougm {
17814653Sdougm /* While it shouldn't be linked, it doesn't hurt */
17823034Sdougm if (optionset != NULL) {
17834653Sdougm xmlUnlinkNode((xmlNodePtr) optionset);
17844653Sdougm xmlFreeNode((xmlNodePtr) optionset);
17853034Sdougm }
17863034Sdougm }
17873034Sdougm
17883034Sdougm /*
17893034Sdougm * sa_get_all_security_types(object, proto, hier)
17903034Sdougm *
17914653Sdougm * Find all the security types set for this object. This is
17923034Sdougm * preliminary to getting a derived security set. The return value is an
17933034Sdougm * optionset containg properties which are the sectype values found by
17945331Samw * walking up the XML document structure. The returned optionset
17953034Sdougm * is a derived optionset.
17963034Sdougm *
17973034Sdougm * If hier is 0, only look at object. If non-zero, walk up the tree.
17983034Sdougm */
17993034Sdougm sa_optionset_t
sa_get_all_security_types(void * object,char * proto,int hier)18003034Sdougm sa_get_all_security_types(void *object, char *proto, int hier)
18013034Sdougm {
18023034Sdougm sa_optionset_t options;
18033034Sdougm sa_security_t security;
18043034Sdougm sa_group_t group;
18053034Sdougm sa_property_t prop;
18063034Sdougm
18073034Sdougm options = NULL;
18083034Sdougm
18093034Sdougm if (hier &&
18104653Sdougm (group = sa_get_parent_group((sa_share_t)object)) != NULL)
18114653Sdougm options = sa_get_all_security_types((void *)group, proto, hier);
18124653Sdougm else
18134653Sdougm options = (sa_optionset_t)xmlNewNode(NULL,
18144653Sdougm (xmlChar *)"optionset");
18154653Sdougm
18164653Sdougm if (options == NULL)
18174653Sdougm return (options);
18184653Sdougm
18194653Sdougm /* Hit the top so collect the security types working back. */
18204653Sdougm for (security = sa_get_security((sa_group_t)object, NULL, NULL);
18214653Sdougm security != NULL;
18224653Sdougm security = sa_get_next_security(security)) {
18233034Sdougm char *type;
18243034Sdougm char *sectype;
18253034Sdougm
18263034Sdougm type = sa_get_security_attr(security, "type");
18273034Sdougm if (type != NULL) {
18284653Sdougm if (strcmp(type, proto) != 0) {
18294653Sdougm sa_free_attr_string(type);
18304653Sdougm continue;
18314653Sdougm }
18324653Sdougm sectype = sa_get_security_attr(security, "sectype");
18334653Sdougm if (sectype != NULL) {
18344653Sdougm /*
18354653Sdougm * Have a security type, check to see if
18364653Sdougm * already present in optionset and add if it
18374653Sdougm * isn't.
18384653Sdougm */
18394653Sdougm if (sa_get_property(options, sectype) == NULL) {
18404653Sdougm prop = sa_create_property(sectype,
18414653Sdougm "true");
18424653Sdougm if (prop != NULL)
18434653Sdougm prop = (sa_property_t)
18444653Sdougm xmlAddChild(
18454653Sdougm (xmlNodePtr)options,
18464653Sdougm (xmlNodePtr)prop);
18474653Sdougm }
18484653Sdougm sa_free_attr_string(sectype);
18494653Sdougm }
18503034Sdougm sa_free_attr_string(type);
18513034Sdougm }
18523034Sdougm }
18534653Sdougm
18543034Sdougm return (options);
18553034Sdougm }
18563034Sdougm
18573034Sdougm /*
18583034Sdougm * sa_get_derived_security(object, sectype, proto, hier)
18593034Sdougm *
18603034Sdougm * Get the derived security(named optionset) for the object given the
18613034Sdougm * sectype and proto. If hier is non-zero, walk up the tree to get all
18623034Sdougm * properties defined for this object, otherwise just those on the
18633034Sdougm * object.
18643034Sdougm */
18653034Sdougm
18663034Sdougm sa_security_t
sa_get_derived_security(void * object,char * sectype,char * proto,int hier)18673034Sdougm sa_get_derived_security(void *object, char *sectype, char *proto, int hier)
18683034Sdougm {
18693034Sdougm sa_security_t newsecurity;
18703034Sdougm sa_security_t security;
18713034Sdougm sa_group_t group;
18724653Sdougm sa_property_t prop;
18733034Sdougm
18743034Sdougm if (hier &&
18753034Sdougm (group = sa_get_parent_group((sa_share_t)object)) != NULL) {
18764653Sdougm newsecurity = sa_get_derived_security((void *)group,
18774653Sdougm sectype, proto, hier);
18783034Sdougm } else {
18794653Sdougm newsecurity = (sa_security_t)xmlNewNode(NULL,
18804653Sdougm (xmlChar *)"security");
18814653Sdougm if (newsecurity != NULL) {
18824653Sdougm sa_set_security_attr(newsecurity, "type", proto);
18834653Sdougm sa_set_security_attr(newsecurity, "sectype", sectype);
18844653Sdougm }
18853034Sdougm }
18864653Sdougm /* Don't do anything if memory wasn't allocated */
18873034Sdougm if (newsecurity == NULL)
18884653Sdougm return (newsecurity);
18893034Sdougm
18904653Sdougm /* Found the top so working back down the stack. */
18913034Sdougm security = sa_get_security((sa_security_t)object, sectype, proto);
18924653Sdougm if (security == NULL)
18934653Sdougm return (newsecurity);
18944653Sdougm
18954653Sdougm /* add security to the newsecurity */
18964653Sdougm for (prop = sa_get_property(security, NULL);
18974653Sdougm prop != NULL; prop = sa_get_next_property(prop)) {
18983034Sdougm sa_property_t newprop;
18993034Sdougm char *name;
19003034Sdougm char *value;
19013034Sdougm name = sa_get_property_attr(prop, "type");
19023034Sdougm value = sa_get_property_attr(prop, "value");
19033034Sdougm if (name != NULL) {
19044653Sdougm newprop = sa_get_property(newsecurity, name);
19054653Sdougm /* Replace the value with the new value */
19064653Sdougm if (newprop != NULL) {
19074653Sdougm /*
19085454Sdougm * Only set if value is non NULL, old
19095454Sdougm * value ok if it is NULL. The value
19105454Sdougm * must be associated with the "value"
19115454Sdougm * tag within XML.
19124653Sdougm */
19134653Sdougm if (value != NULL)
19145454Sdougm set_node_attr(newprop, "value", value);
19154653Sdougm } else {
19164653Sdougm /* An entirely new property */
19174653Sdougm if (value != NULL) {
19184653Sdougm newprop = sa_create_property(name,
19194653Sdougm value);
19204653Sdougm newprop = (sa_property_t)
19214653Sdougm xmlAddChild((xmlNodePtr)newsecurity,
19223034Sdougm (xmlNodePtr)newprop);
19234653Sdougm }
19243034Sdougm }
19254653Sdougm sa_free_attr_string(name);
19263034Sdougm }
19273034Sdougm if (value != NULL)
19284653Sdougm sa_free_attr_string(value);
19293034Sdougm }
19303034Sdougm return (newsecurity);
19313034Sdougm }
19323034Sdougm
19333034Sdougm void
sa_free_derived_security(sa_security_t security)19343034Sdougm sa_free_derived_security(sa_security_t security)
19353034Sdougm {
19363034Sdougm /* while it shouldn't be linked, it doesn't hurt */
19373034Sdougm if (security != NULL) {
19384653Sdougm xmlUnlinkNode((xmlNodePtr)security);
19394653Sdougm xmlFreeNode((xmlNodePtr)security);
19403034Sdougm }
19413034Sdougm }
19423034Sdougm
19433034Sdougm /*
19443034Sdougm * sharetab utility functions
19453034Sdougm *
19464653Sdougm * Makes use of the original sharetab.c from fs.d/nfs/lib
19473034Sdougm */
19483034Sdougm
19493034Sdougm /*
19504543Smarks * sa_fillshare(share, proto, sh)
19513034Sdougm *
19523034Sdougm * Fill the struct share with values obtained from the share object.
19533034Sdougm */
19544543Smarks void
sa_fillshare(sa_share_t share,char * proto,struct share * sh)19554543Smarks sa_fillshare(sa_share_t share, char *proto, struct share *sh)
19563034Sdougm {
19573034Sdougm char *groupname = NULL;
19583034Sdougm char *value;
19593034Sdougm sa_group_t group;
19603034Sdougm char *buff;
19613034Sdougm char *zfs;
19625331Samw sa_resource_t resource;
19635331Samw char *rsrcname = NULL;
19645331Samw char *defprop;
19655331Samw
19665331Samw /*
19675331Samw * We only want to deal with the path level shares for the
19685331Samw * sharetab file. If a resource, get the parent.
19695331Samw */
19705331Samw if (sa_is_resource(share)) {
19715331Samw resource = (sa_resource_t)share;
19725331Samw share = sa_get_resource_parent(resource);
19735331Samw rsrcname = sa_get_resource_attr(resource, "name");
19745331Samw }
19753034Sdougm
19763034Sdougm group = sa_get_parent_group(share);
19773034Sdougm if (group != NULL) {
19784653Sdougm zfs = sa_get_group_attr(group, "zfs");
19794653Sdougm groupname = sa_get_group_attr(group, "name");
19803034Sdougm
19814653Sdougm if (groupname != NULL &&
19824653Sdougm (strcmp(groupname, "default") == 0 || zfs != NULL)) {
19834653Sdougm /*
19844653Sdougm * since the groupname is either "default" or the
19854653Sdougm * group is a ZFS group, we don't want to keep
19864653Sdougm * groupname. We do want it if it is any other type of
19874653Sdougm * group.
19884653Sdougm */
19894653Sdougm sa_free_attr_string(groupname);
19904653Sdougm groupname = NULL;
19914653Sdougm }
19924653Sdougm if (zfs != NULL)
19934653Sdougm sa_free_attr_string(zfs);
19943034Sdougm }
19953034Sdougm
19963034Sdougm value = sa_get_share_attr(share, "path");
19973034Sdougm if (value != NULL) {
19984653Sdougm sh->sh_path = strdup(value);
19994653Sdougm sa_free_attr_string(value);
20003034Sdougm }
20013034Sdougm
20025331Samw if (rsrcname != NULL || groupname != NULL) {
20034653Sdougm int len = 0;
20043034Sdougm
20055331Samw if (rsrcname != NULL)
20065331Samw len += strlen(rsrcname);
20074653Sdougm if (groupname != NULL)
20084653Sdougm len += strlen(groupname);
20094653Sdougm len += 3; /* worst case */
20104653Sdougm buff = malloc(len);
20114653Sdougm (void) snprintf(buff, len, "%s%s%s",
20125331Samw (rsrcname != NULL &&
20135331Samw strlen(rsrcname) > 0) ? rsrcname : "-",
20143034Sdougm groupname != NULL ? "@" : "",
20153034Sdougm groupname != NULL ? groupname : "");
20164653Sdougm sh->sh_res = buff;
20175331Samw if (rsrcname != NULL)
20185331Samw sa_free_attr_string(rsrcname);
20195331Samw if (groupname != NULL)
20204653Sdougm sa_free_attr_string(groupname);
20213034Sdougm } else {
20224653Sdougm sh->sh_res = strdup("-");
20233034Sdougm }
20243034Sdougm
20255331Samw /*
20265331Samw * Get correct default prop string. NFS uses "rw", others use
20275331Samw * "".
20285331Samw */
20295331Samw if (strcmp(proto, "nfs") != 0)
20305331Samw defprop = "\"\"";
20315331Samw else
20325331Samw defprop = "rw";
20335331Samw
20343034Sdougm sh->sh_fstype = strdup(proto);
20353034Sdougm value = sa_proto_legacy_format(proto, share, 1);
20363034Sdougm if (value != NULL) {
20374653Sdougm if (strlen(value) > 0)
20384653Sdougm sh->sh_opts = strdup(value);
20394653Sdougm else
20405331Samw sh->sh_opts = strdup(defprop);
20414653Sdougm free(value);
20424653Sdougm } else {
20435331Samw sh->sh_opts = strdup(defprop);
20444653Sdougm }
20453034Sdougm
20463034Sdougm value = sa_get_share_description(share);
20473034Sdougm if (value != NULL) {
20484653Sdougm sh->sh_descr = strdup(value);
20494653Sdougm sa_free_share_description(value);
20504653Sdougm } else {
20514653Sdougm sh->sh_descr = strdup("");
20524653Sdougm }
20533034Sdougm }
20543034Sdougm
20553034Sdougm /*
20564543Smarks * sa_emptyshare(sh)
20573034Sdougm *
20583034Sdougm * Free the strings in the non-NULL members of sh.
20593034Sdougm */
20603034Sdougm
20614543Smarks void
sa_emptyshare(struct share * sh)20624543Smarks sa_emptyshare(struct share *sh)
20633034Sdougm {
20643034Sdougm if (sh->sh_path != NULL)
20654653Sdougm free(sh->sh_path);
20663034Sdougm sh->sh_path = NULL;
20673034Sdougm if (sh->sh_res != NULL)
20684653Sdougm free(sh->sh_res);
20693034Sdougm sh->sh_res = NULL;
20703034Sdougm if (sh->sh_fstype != NULL)
20714653Sdougm free(sh->sh_fstype);
20723034Sdougm sh->sh_fstype = NULL;
20733034Sdougm if (sh->sh_opts != NULL)
20744653Sdougm free(sh->sh_opts);
20753034Sdougm sh->sh_opts = NULL;
20763034Sdougm if (sh->sh_descr != NULL)
20774653Sdougm free(sh->sh_descr);
20783034Sdougm sh->sh_descr = NULL;
20793034Sdougm }
20803034Sdougm
20813034Sdougm /*
20825951Sdougm * sa_update_sharetab_ts(handle)
20835951Sdougm *
20845951Sdougm * Update the internal timestamp of when sharetab was last
20855951Sdougm * changed. This needs to be public for ZFS to get at it.
20865951Sdougm */
20875951Sdougm
20885951Sdougm void
sa_update_sharetab_ts(sa_handle_t handle)20895951Sdougm sa_update_sharetab_ts(sa_handle_t handle)
20905951Sdougm {
20915951Sdougm struct stat st;
20925951Sdougm sa_handle_impl_t implhandle = (sa_handle_impl_t)handle;
20935951Sdougm
20945951Sdougm if (implhandle != NULL && stat(SA_LEGACY_SHARETAB, &st) == 0)
20955951Sdougm implhandle->tssharetab = TSTAMP(st.st_mtim);
20965951Sdougm }
20975951Sdougm
20985951Sdougm /*
20993034Sdougm * sa_update_sharetab(share, proto)
21003034Sdougm *
21013034Sdougm * Update the sharetab file with info from the specified share.
21023034Sdougm * This could be an update or add.
21033034Sdougm */
21043034Sdougm
21053034Sdougm int
sa_update_sharetab(sa_share_t share,char * proto)21063034Sdougm sa_update_sharetab(sa_share_t share, char *proto)
21073034Sdougm {
21083957Sth199096 int ret = SA_OK;
21093957Sth199096 share_t sh;
21103957Sth199096 char *path;
21115951Sdougm sa_handle_t handle;
21123034Sdougm
21133034Sdougm path = sa_get_share_attr(share, "path");
21143034Sdougm if (path != NULL) {
21153957Sth199096 (void) memset(&sh, '\0', sizeof (sh));
21163957Sth199096
21175951Sdougm handle = sa_find_group_handle((sa_group_t)share);
21185951Sdougm if (handle != NULL) {
21195951Sdougm /*
21205951Sdougm * Fill in share structure and send it to the kernel.
21215951Sdougm */
21225951Sdougm (void) sa_fillshare(share, proto, &sh);
21235951Sdougm (void) _sharefs(SHAREFS_ADD, &sh);
21245951Sdougm /*
21255951Sdougm * We need the timestamp of the sharetab file right
21265951Sdougm * after the update was done. This lets us detect a
21275951Sdougm * change that made by a different process.
21285951Sdougm */
21295951Sdougm sa_update_sharetab_ts(handle);
21305951Sdougm sa_emptyshare(&sh);
21315951Sdougm } else {
21325951Sdougm ret = SA_CONFIG_ERR;
21335951Sdougm }
21343957Sth199096 sa_free_attr_string(path);
21353034Sdougm }
21363957Sth199096
21373034Sdougm return (ret);
21383034Sdougm }
21393034Sdougm
21403034Sdougm /*
21415951Sdougm * sa_delete_sharetab(handle, path, proto)
21423034Sdougm *
21433034Sdougm * remove the specified share from sharetab.
21443034Sdougm */
21453034Sdougm
21463034Sdougm int
sa_delete_sharetab(sa_handle_t handle,char * path,char * proto)21475951Sdougm sa_delete_sharetab(sa_handle_t handle, char *path, char *proto)
21483034Sdougm {
21493957Sth199096 int ret = SA_OK;
21505951Sdougm struct stat st;
21513957Sth199096
21523957Sth199096 share_t sh;
21533957Sth199096 /*
21543957Sth199096 * Both the path and the proto are
21553957Sth199096 * keys into the sharetab.
21563957Sth199096 */
21573957Sth199096 if (path != NULL && proto != NULL) {
21583957Sth199096 (void) memset(&sh, '\0', sizeof (sh));
21593957Sth199096 sh.sh_path = path;
21603957Sth199096 sh.sh_fstype = proto;
21613957Sth199096
21624995Sth199096 ret = _sharefs(SHAREFS_REMOVE, &sh);
21635951Sdougm if (handle != NULL && stat(SA_LEGACY_SHARETAB, &st) == 0)
21645951Sdougm sa_update_sharetab_ts(handle);
21655951Sdougm }
21665951Sdougm return (ret);
21675951Sdougm }
21685951Sdougm
21695951Sdougm /*
21705951Sdougm * sa_needs_refresh(handle)
21715951Sdougm *
21725951Sdougm * Returns B_TRUE if the internal cache needs to be refreshed do to a
21735951Sdougm * change by another process. B_FALSE returned otherwise.
21745951Sdougm */
21755951Sdougm boolean_t
sa_needs_refresh(sa_handle_t handle)21765958Sdougm sa_needs_refresh(sa_handle_t handle)
21775951Sdougm {
21785951Sdougm sa_handle_impl_t implhandle = (sa_handle_impl_t)handle;
21795951Sdougm struct stat st;
21805951Sdougm char *str;
21815951Sdougm uint64_t tstamp;
21825951Sdougm scf_simple_prop_t *prop;
21835951Sdougm
21845951Sdougm if (handle == NULL)
21855951Sdougm return (B_TRUE);
21865951Sdougm
21875951Sdougm /*
21885951Sdougm * If sharetab has changed, then there was an external
21895951Sdougm * change. Check sharetab first since it is updated by ZFS as
21905951Sdougm * well as sharemgr. This is where external ZFS changes are
21915951Sdougm * caught.
21925951Sdougm */
21935951Sdougm if (stat(SA_LEGACY_SHARETAB, &st) == 0 &&
21945951Sdougm TSTAMP(st.st_mtim) != implhandle->tssharetab)
21955951Sdougm return (B_TRUE);
21965951Sdougm
21975951Sdougm /*
21985951Sdougm * If sharetab wasn't changed, check whether there were any
21995951Sdougm * SMF transactions that modified the config but didn't
22005951Sdougm * initiate a share. This is less common but does happen.
22015951Sdougm */
22025951Sdougm prop = scf_simple_prop_get(implhandle->scfhandle->handle,
22035951Sdougm (const char *)SA_SVC_FMRI_BASE ":default", "state",
22045951Sdougm "lastupdate");
22055951Sdougm if (prop != NULL) {
22065951Sdougm str = scf_simple_prop_next_astring(prop);
22075951Sdougm if (str != NULL)
22085951Sdougm tstamp = strtoull(str, NULL, 0);
22095951Sdougm else
22105951Sdougm tstamp = 0;
22115951Sdougm scf_simple_prop_free(prop);
22125951Sdougm if (tstamp != implhandle->tstrans)
22135951Sdougm return (B_TRUE);
22143034Sdougm }
22153957Sth199096
22165951Sdougm return (B_FALSE);
22173034Sdougm }
22185951Sdougm
22195331Samw /*
22205331Samw * sa_fix_resource_name(path)
22215331Samw *
22228474SJose.Borrego@Sun.COM * Convert invalid characters in a resource name (SMB share name)
22238474SJose.Borrego@Sun.COM * to underscores ('_'). The list of invalid characters includes
22248474SJose.Borrego@Sun.COM * control characters and the following:
22258474SJose.Borrego@Sun.COM *
22268474SJose.Borrego@Sun.COM * " / \ [ ] : | < > + ; , ? * =
22278474SJose.Borrego@Sun.COM *
22288474SJose.Borrego@Sun.COM * The caller must pass a valid path. Leading and trailing slashes
22298474SJose.Borrego@Sun.COM * are stripped from the path before converting invalid characters.
22308474SJose.Borrego@Sun.COM * Resource names are restricted to SA_MAX_RESOURCE_NAME characters.
22315331Samw */
22325331Samw void
sa_fix_resource_name(char * path)22335331Samw sa_fix_resource_name(char *path)
22345331Samw {
22358474SJose.Borrego@Sun.COM char *invalid = "\"/\\[]:|<>+;,?*=";
22368474SJose.Borrego@Sun.COM char *p = path;
22378474SJose.Borrego@Sun.COM char *q;
22385331Samw size_t len;
22395331Samw
22405331Samw assert(path != NULL);
22415331Samw
22428474SJose.Borrego@Sun.COM /*
22438474SJose.Borrego@Sun.COM * Strip leading and trailing /'s.
22448474SJose.Borrego@Sun.COM */
22458474SJose.Borrego@Sun.COM p += strspn(p, "/");
22468474SJose.Borrego@Sun.COM q = strchr(p, '\0');
22478474SJose.Borrego@Sun.COM if (q != NULL && q != path) {
22488474SJose.Borrego@Sun.COM while ((--q, *q == '/'))
22498474SJose.Borrego@Sun.COM *q = '\0';
22505331Samw }
22518474SJose.Borrego@Sun.COM
22528474SJose.Borrego@Sun.COM if (*p == '\0') {
22538474SJose.Borrego@Sun.COM (void) strcpy(path, "_");
22548474SJose.Borrego@Sun.COM return;
22555331Samw }
22565331Samw
22575331Samw /*
22588474SJose.Borrego@Sun.COM * Stride over path components until the remaining
22598474SJose.Borrego@Sun.COM * path is no longer than SA_MAX_RESOURCE_NAME.
22605331Samw */
22618474SJose.Borrego@Sun.COM q = p;
22628474SJose.Borrego@Sun.COM while ((q != NULL) && (strlen(q) > SA_MAX_RESOURCE_NAME)) {
22638474SJose.Borrego@Sun.COM if ((q = strchr(q, '/')) != NULL) {
22648474SJose.Borrego@Sun.COM ++q;
22658474SJose.Borrego@Sun.COM p = q;
22665331Samw }
22678474SJose.Borrego@Sun.COM }
22688474SJose.Borrego@Sun.COM
22698474SJose.Borrego@Sun.COM /*
22708474SJose.Borrego@Sun.COM * If the path is still longer than SA_MAX_RESOURCE_NAME,
22718474SJose.Borrego@Sun.COM * take the trailing SA_MAX_RESOURCE_NAME characters.
22728474SJose.Borrego@Sun.COM */
22738474SJose.Borrego@Sun.COM if ((len = strlen(p)) > SA_MAX_RESOURCE_NAME) {
22748474SJose.Borrego@Sun.COM len = SA_MAX_RESOURCE_NAME;
22758474SJose.Borrego@Sun.COM p = strchr(p, '\0') - (SA_MAX_RESOURCE_NAME - 1);
22768474SJose.Borrego@Sun.COM }
22778474SJose.Borrego@Sun.COM
22788474SJose.Borrego@Sun.COM (void) memmove(path, p, len);
22798474SJose.Borrego@Sun.COM path[len] = '\0';
22808474SJose.Borrego@Sun.COM
22818474SJose.Borrego@Sun.COM for (p = path; *p != '\0'; ++p) {
22828474SJose.Borrego@Sun.COM if ((iscntrl(*p)) || strchr(invalid, *p))
22838474SJose.Borrego@Sun.COM *p = '_';
22845331Samw }
22855331Samw }
2286