# HG changeset patch # User dougm # Date 1175097043 25200 # Node ID 00586900e34c29441c9fbd42dfaed0b4ea0587ea # Parent 9f4024db0edfb3f7e71a1ce80818bc371d62283c 6516085 sharemgr: should deliver 64-bit library objects for libshare.so and plugin(s) 6516121 sharemgr: libshare should provide better support for multithreaded apps diff -r 9f4024db0edf -r 00586900e34c usr/src/Targetdirs --- a/usr/src/Targetdirs Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/Targetdirs Wed Mar 28 08:50:43 2007 -0700 @@ -379,7 +379,8 @@ ROOT.SYS64.2 = \ $($(MACH64)_ROOT.SYS64.2) \ /usr/lib/mdb/kvm/$(MACH64) \ - /usr/lib/mdb/proc/$(MACH64) + /usr/lib/mdb/proc/$(MACH64) \ + /usr/lib/fs/nfs/$(MACH64) UUCP.UUCP= \ /var/spool/uucp \ diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharectl/sharectl.c --- a/usr/src/cmd/dfs.cmds/sharectl/sharectl.c Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/cmd/dfs.cmds/sharectl/sharectl.c Wed Mar 28 08:50:43 2007 -0700 @@ -40,7 +40,7 @@ #include #include -static int run_command(char *, int, char **); +static int run_command(char *, int, char **, sa_handle_t); static void sub_command_help(char *proto); static void @@ -57,6 +57,7 @@ int help = 0; int rval; char *command; + sa_handle_t handle; /* * make sure locale and gettext domain is setup @@ -64,7 +65,7 @@ (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); - sa_init(SA_INIT_CONTROL_API); + handle = sa_init(SA_INIT_CONTROL_API); while ((c = getopt(argc, argv, "h?")) != EOF) { switch (c) { @@ -87,9 +88,9 @@ * now have enough to parse rest of command line */ command = argv[optind]; - rval = run_command(command, argc - optind, argv + optind); + rval = run_command(command, argc - optind, argv + optind, handle); - sa_fini(); + sa_fini(handle); return (rval); } @@ -112,16 +113,14 @@ return (ret); } +/*ARGSUSED*/ static int -sc_get(int flags, int argc, char *argv[]) +sc_get(sa_handle_t handle, int flags, int argc, char *argv[]) { char *proto = NULL; struct options *optlist = NULL; int ret = SA_OK; int c; -#ifdef lint - flags = flags; -#endif while ((c = getopt(argc, argv, "?hp:")) != EOF) { switch (c) { @@ -203,16 +202,14 @@ return (ret); } +/*ARGSUSED*/ static int -sc_set(int flags, int argc, char *argv[]) +sc_set(sa_handle_t handle, int flags, int argc, char *argv[]) { char *proto = NULL; struct options *optlist = NULL; int ret = SA_OK; int c; -#ifdef lint - flags = flags; -#endif while ((c = getopt(argc, argv, "?hp:")) != EOF) { switch (c) { @@ -316,8 +313,9 @@ return (0); } +/*ARGSUSED*/ static int -sc_status(int flags, int argc, char *argv[]) +sc_status(sa_handle_t handle, int flags, int argc, char *argv[]) { char **protos; int ret = SA_OK; @@ -325,9 +323,6 @@ int i; int num_proto; int verbose = 0; -#ifdef lint - flags = flags; -#endif while ((c = getopt(argc, argv, "?hv")) != EOF) { switch (c) { @@ -374,13 +369,11 @@ {NULL, 0, NULL, 0}, }; +/*ARGSUSED*/ void sub_command_help(char *proto) { int i; -#ifdef lint - proto = proto; -#endif (void) printf("\tsub-commands:\n"); for (i = 0; commands[i].cmdname != NULL; i++) { @@ -405,7 +398,7 @@ } static int -run_command(char *command, int argc, char *argv[]) +run_command(char *command, int argc, char *argv[], sa_handle_t handle) { sa_command_t *cmdvec; int ret; @@ -435,6 +428,6 @@ * need to check priviledges and restrict what can be done * based on least priviledge and sub-command. */ - ret = cmdvec->cmdfunc(NULL, argc, argv); + ret = cmdvec->cmdfunc(handle, NULL, argc, argv); return (ret); } diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/Makefile --- a/usr/src/cmd/dfs.cmds/sharemgr/Makefile Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/cmd/dfs.cmds/sharemgr/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -21,10 +21,9 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -DEFAULTFILES = MANIFEST = group.xml @@ -33,7 +32,8 @@ # # One for each ISA. # -SUBDIRS = $(MACH) plugins +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) ROOTMANIFESTDIR = $(ROOTSVCNETWORKSHARES) $(ROOTMANIFEST) := FILEMODE= 444 @@ -49,9 +49,9 @@ all clean clobber lint _msg: $(SUBDIRS) -install: $(SUBDIRS) $(ROOTETCDEFAULTFILES) $(ROOTMANIFEST) +install: $(SUBDIRS) $(ROOTMANIFEST) -$(SUBDIRS): FRC +$(SUBDIRS) $(TESTSUBS): FRC @cd $@; pwd; $(MAKE) $(TARGET) FRC: diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/Makefile.com --- a/usr/src/cmd/dfs.cmds/sharemgr/Makefile.com Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/cmd/dfs.cmds/sharemgr/Makefile.com Wed Mar 28 08:50:43 2007 -0700 @@ -21,7 +21,7 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -31,10 +31,6 @@ PROG= sharemgr -LINK_SRCS = libshare_nfs.c -LINK_OBJS = libshare_nfs.o -LINK_MODS = libshare_nfs.so - SHAREMGR_MOD = sharemgr COMMONSRC = sharemgr_main.c commands.c shareutil.c @@ -51,6 +47,7 @@ LDLIBS += -lshare -lscf -lsecdb -lumem all install := LDLIBS += -lxml2 LINTFLAGS += -u +LINTFLAGS64 += -u SRCS = $(SHAREMGR_SRC) OBJS = $(SHAREMGR_OBJ) @@ -78,7 +75,7 @@ $(LINK.c) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS) $(POST_PROCESS) -install: all $(ROOTUSRSBINPROG) $(ROOTLINKS) +install: all $(ROOTLINKS): $(ROOTUSRSBINPROG) $(RM) $@ diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/amd64/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/dfs.cmds/sharemgr/amd64/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../../Makefile.cmd.64 + +install: all $(ROOTUSRSBINPROG64) diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/commands.c --- a/usr/src/cmd/dfs.cmds/sharemgr/commands.c Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/cmd/dfs.cmds/sharemgr/commands.c Wed Mar 28 08:50:43 2007 -0700 @@ -255,8 +255,8 @@ * was passed in. */ static int -enable_all_groups(struct list *work, int setstate, int online, - char *updateproto) +enable_all_groups(sa_handle_t handle, struct list *work, int setstate, + int online, char *updateproto) { int ret = SA_OK; char instance[SA_MAX_NAME_LEN + sizeof (SA_SVC_FMRI_BASE) + 1]; @@ -319,7 +319,7 @@ } } if (ret == SA_OK) { - ret = sa_update_config(); + ret = sa_update_config(handle); } return (ret); } @@ -517,7 +517,7 @@ * No protocol means "all" protocols in this case. */ static int -sa_create(int flags, int argc, char *argv[]) +sa_create(sa_handle_t handle, int flags, int argc, char *argv[]) { char *groupname; @@ -612,7 +612,7 @@ auth = check_authorizations(groupname, flags); - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group != NULL) { /* group exists so must be a protocol add */ if (protocol != NULL) { @@ -647,7 +647,7 @@ } if (ret == SA_OK && !dryrun) { if (group == NULL) { - group = sa_create_group((char *)groupname, &err); + group = sa_create_group(handle, (char *)groupname, &err); } if (group != NULL) { sa_optionset_t optionset; @@ -678,7 +678,7 @@ * all protocols that implement the * appropriate plugin. */ - ret = sa_update_config(); + ret = sa_update_config(handle); } else { if (group != NULL) (void) sa_remove_group(group); @@ -727,7 +727,7 @@ */ static int -sa_delete(int flags, int argc, char *argv[]) +sa_delete(sa_handle_t handle, int flags, int argc, char *argv[]) { char *groupname; sa_group_t group; @@ -803,7 +803,7 @@ */ groupname = argv[optind]; - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group == NULL) { ret = SA_NO_SUCH_GROUP; } else { @@ -832,7 +832,7 @@ } /* commit to configuration if not a dryrun */ if (!dryrun && ret == SA_OK) { - ret = sa_update_config(); + ret = sa_update_config(handle); } } else { /* a protocol delete */ @@ -969,7 +969,7 @@ */ static int -sa_list(int flags, int argc, char *argv[]) +sa_list(sa_handle_t handle, int flags, int argc, char *argv[]) { sa_group_t group; int verbose = 0; @@ -1001,7 +1001,7 @@ } } - for (group = sa_get_group(NULL); group != NULL; + for (group = sa_get_group(handle, NULL); group != NULL; group = sa_get_next_group(group)) { char *name; char *proto; @@ -1302,7 +1302,7 @@ */ int -sa_show(int flags, int argc, char *argv[]) +sa_show(sa_handle_t handle, int flags, int argc, char *argv[]) { sa_group_t group; int verbose = 0; @@ -1351,7 +1351,7 @@ if (optind == argc) { /* no group specified so go through them all */ - for (group = sa_get_group(NULL); group != NULL; + for (group = sa_get_group(handle, NULL); group != NULL; group = sa_get_next_group(group)) { /* * have a group so check if one we want and then list @@ -1365,7 +1365,7 @@ } else { /* have a specified list of groups */ for (; optind < argc; optind++) { - group = sa_get_group(argv[optind]); + group = sa_get_group(handle, argv[optind]); if (group != NULL) { if (xml) show_group_xml(doc, group); @@ -1392,7 +1392,8 @@ */ static int -enable_share(sa_group_t group, sa_share_t share, int update_legacy) +enable_share(sa_handle_t handle, sa_group_t group, sa_share_t share, + int update_legacy) { char *value; int enabled; @@ -1438,7 +1439,7 @@ } } if (ret == SA_OK) - (void) sa_update_config(); + (void) sa_update_config(handle); return (ret); } @@ -1449,7 +1450,7 @@ */ int -sa_addshare(int flags, int argc, char *argv[]) +sa_addshare(sa_handle_t handle, int flags, int argc, char *argv[]) { int verbose = 0; int dryrun = 0; @@ -1539,10 +1540,10 @@ } } if (ret == SA_OK) { - group = sa_get_group(argv[optind]); + group = sa_get_group(handle, argv[optind]); if (group != NULL) { auth = check_authorizations(argv[optind], flags); - share = sa_find_share(sharepath); + share = sa_find_share(handle, sharepath); if (share != NULL) { group = sa_get_parent_group(share); if (group != NULL) { @@ -1596,8 +1597,8 @@ } if (ret == SA_OK) { /* now enable the share(s) */ - ret = enable_share(group, share, 1); - ret = sa_update_config(); + ret = enable_share(handle, group, share, 1); + ret = sa_update_config(handle); } switch (ret) { case SA_DUPLICATE_NAME: @@ -1639,7 +1640,7 @@ */ int -sa_moveshare(int flags, int argc, char *argv[]) +sa_moveshare(sa_handle_t handle, int flags, int argc, char *argv[]) { int verbose = 0; int dryrun = 0; @@ -1698,9 +1699,9 @@ "the -s option\n")); ret = SA_BAD_PATH; } else { - group = sa_get_group(argv[optind]); + group = sa_get_group(handle, argv[optind]); if (group != NULL) { - share = sa_find_share(sharepath); + share = sa_find_share(handle, sharepath); authdst = check_authorizations(argv[optind], flags); if (share == NULL) { (void) printf(gettext("Share not found: %s\n"), @@ -1735,7 +1736,7 @@ } if (ret == SA_OK && parent != group && !dryrun) { char *oldstate; - ret = sa_update_config(); + ret = sa_update_config(handle); /* * note that the share may need to be * "unshared" if the new group is @@ -1748,7 +1749,7 @@ if (strcmp(oldstate, "enabled") == 0) { (void) sa_disable_share(share, NULL); } - (void) enable_share(group, share, 1); + (void) enable_share(handle, group, share, 1); if (oldstate != NULL) sa_free_attr_string(oldstate); } @@ -1779,7 +1780,7 @@ */ int -sa_removeshare(int flags, int argc, char *argv[]) +sa_removeshare(sa_handle_t handle, int flags, int argc, char *argv[]) { int verbose = 0; int dryrun = 0; @@ -1841,7 +1842,7 @@ "command\n")); ret = SA_SYNTAX_ERR; } else { - group = sa_get_group(argv[optind]); + group = sa_get_group(handle, argv[optind]); if (group == NULL) { (void) printf(gettext("Group \"%s\" not found\n"), argv[optind]); @@ -1862,7 +1863,7 @@ if (group != NULL) share = sa_get_share(group, sharepath); else - share = sa_find_share(sharepath); + share = sa_find_share(handle, sharepath); /* * If we didn't find the share with the provided path, * it may be a symlink so attempt to resolve it using @@ -1882,7 +1883,7 @@ if (group != NULL) share = sa_get_share(group, dir); else - share = sa_find_share(dir); + share = sa_find_share(handle, dir); } } } @@ -1923,7 +1924,7 @@ ret = sa_remove_share(share); } if (ret == SA_OK) - ret = sa_update_config(); + ret = sa_update_config(handle); } if (ret != SA_OK) { (void) printf(gettext("Could not remove share:" @@ -1955,7 +1956,7 @@ */ int -sa_set_share(int flags, int argc, char *argv[]) +sa_set_share(sa_handle_t handle, int flags, int argc, char *argv[]) { int dryrun = 0; int c; @@ -2022,12 +2023,12 @@ char *groupname; if (optind < argc) { groupname = argv[optind]; - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); } else { group = NULL; groupname = NULL; } - share = sa_find_share(sharepath); + share = sa_find_share(handle, sharepath); if (share != NULL) { sharegroup = sa_get_parent_group(share); if (group != NULL && group != sharegroup) { @@ -2073,7 +2074,7 @@ } } if (!dryrun && ret == SA_OK) { - ret = sa_update_config(); + ret = sa_update_config(handle); } switch (ret) { case SA_DUPLICATE_NAME: @@ -2184,15 +2185,15 @@ */ static int -basic_set(char *groupname, struct options *optlist, char *protocol, - char *sharepath, int dryrun) +basic_set(sa_handle_t handle, char *groupname, struct options *optlist, + char *protocol, char *sharepath, int dryrun) { sa_group_t group; int ret = SA_OK; int change = 0; struct list *worklist = NULL; - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group != NULL) { sa_share_t share = NULL; if (sharepath != NULL) { @@ -2232,7 +2233,7 @@ if (!dryrun && ret == SA_OK) { if (change && worklist != NULL) { /* properties changed, so update all shares */ - (void) enable_all_groups(worklist, 0, 0, protocol); + (void) enable_all_groups(handle, worklist, 0, 0, protocol); } } if (worklist != NULL) @@ -2249,8 +2250,8 @@ */ static int -space_set(char *groupname, struct options *optlist, char *protocol, - char *sharepath, int dryrun, char *sectype) +space_set(sa_handle_t handle, char *groupname, struct options *optlist, + char *protocol, char *sharepath, int dryrun, char *sectype) { sa_group_t group; int ret = SA_OK; @@ -2268,7 +2269,7 @@ return (SA_INVALID_SECURITY); } - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group != NULL) { sa_share_t share = NULL; if (sharepath != NULL) { @@ -2312,9 +2313,9 @@ if (!dryrun && ret == 0) { if (change && worklist != NULL) { /* properties changed, so update all shares */ - (void) enable_all_groups(worklist, 0, 0, protocol); + (void) enable_all_groups(handle, worklist, 0, 0, protocol); } - ret = sa_update_config(); + ret = sa_update_config(handle); } if (worklist != NULL) free_list(worklist); @@ -2329,7 +2330,7 @@ */ int -sa_set(int flags, int argc, char *argv[]) +sa_set(sa_handle_t handle, int flags, int argc, char *argv[]) { char *groupname; int verbose = 0; @@ -2422,10 +2423,10 @@ groupname = argv[optind]; auth = check_authorizations(groupname, flags); if (optset == NULL) - ret = basic_set(groupname, optlist, protocol, + ret = basic_set(handle, groupname, optlist, protocol, sharepath, dryrun); else - ret = space_set(groupname, optlist, protocol, + ret = space_set(handle, groupname, optlist, protocol, sharepath, dryrun, optset); if (dryrun && ret == SA_OK && !auth && verbose) { (void) printf(gettext("Command would fail: %s\n"), @@ -2594,15 +2595,15 @@ */ static int -basic_unset(char *groupname, struct options *optlist, char *protocol, - char *sharepath, int dryrun) +basic_unset(sa_handle_t handle, char *groupname, struct options *optlist, + char *protocol, char *sharepath, int dryrun) { sa_group_t group; int ret = SA_OK; int change = 0; struct list *worklist = NULL; - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group != NULL) { sa_share_t share = NULL; if (sharepath != NULL) { @@ -2656,7 +2657,7 @@ if (!dryrun && ret == SA_OK) { if (change && worklist != NULL) { /* properties changed, so update all shares */ - (void) enable_all_groups(worklist, 0, 0, protocol); + (void) enable_all_groups(handle, worklist, 0, 0, protocol); } } if (worklist != NULL) @@ -2670,15 +2671,15 @@ * unset named optionset properties. */ static int -space_unset(char *groupname, struct options *optlist, char *protocol, - char *sharepath, int dryrun, char *sectype) +space_unset(sa_handle_t handle, char *groupname, struct options *optlist, + char *protocol, char *sharepath, int dryrun, char *sectype) { sa_group_t group; int ret = SA_OK; int change = 0; struct list *worklist = NULL; - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group != NULL) { sa_share_t share = NULL; if (sharepath != NULL) { @@ -2750,9 +2751,9 @@ if (!dryrun && ret == 0) { if (change && worklist != NULL) { /* properties changed, so update all shares */ - (void) enable_all_groups(worklist, 0, 0, protocol); + (void) enable_all_groups(handle, worklist, 0, 0, protocol); } - ret = sa_update_config(); + ret = sa_update_config(handle); } if (worklist != NULL) free_list(worklist); @@ -2767,7 +2768,7 @@ */ int -sa_unset(int flags, int argc, char *argv[]) +sa_unset(sa_handle_t handle, int flags, int argc, char *argv[]) { char *groupname; int verbose = 0; @@ -2862,10 +2863,10 @@ groupname = argv[optind]; auth = check_authorizations(groupname, flags); if (optset == NULL) - ret = basic_unset(groupname, optlist, protocol, + ret = basic_unset(handle, groupname, optlist, protocol, sharepath, dryrun); else - ret = space_unset(groupname, optlist, protocol, + ret = space_unset(handle, groupname, optlist, protocol, sharepath, dryrun, optset); if (dryrun && ret == SA_OK && !auth && verbose) { @@ -2883,7 +2884,7 @@ */ int -sa_enable_group(int flags, int argc, char *argv[]) +sa_enable_group(sa_handle_t handle, int flags, int argc, char *argv[]) { int verbose = 0; int dryrun = 0; @@ -2931,7 +2932,7 @@ sa_group_t group; if (!all) { while (optind < argc) { - group = sa_get_group(argv[optind]); + group = sa_get_group(handle, argv[optind]); if (group != NULL) { auth &= check_authorizations(argv[optind], flags); state = sa_get_group_attr(group, "state"); @@ -2958,13 +2959,13 @@ optind++; } } else { - for (group = sa_get_group(NULL); group != NULL; + for (group = sa_get_group(handle, NULL); group != NULL; group = sa_get_next_group(group)) { worklist = add_list(worklist, group, 0); } } if (!dryrun && ret == SA_OK) { - ret = enable_all_groups(worklist, 1, 0, NULL); + ret = enable_all_groups(handle, worklist, 1, 0, NULL); } if (ret != SA_OK && ret != SA_BUSY) (void) printf(gettext("Could not enable group: %s\n"), @@ -3021,7 +3022,7 @@ */ static int -disable_all_groups(struct list *work, int setstate) +disable_all_groups(sa_handle_t handle, struct list *work, int setstate) { int ret = SA_OK; sa_group_t subgroup, group; @@ -3052,7 +3053,7 @@ work = work->next; } if (ret == SA_OK) - ret = sa_update_config(); + ret = sa_update_config(handle); return (ret); } @@ -3063,7 +3064,7 @@ */ int -sa_disable_group(int flags, int argc, char *argv[]) +sa_disable_group(sa_handle_t handle, int flags, int argc, char *argv[]) { int verbose = 0; int dryrun = 0; @@ -3112,7 +3113,7 @@ sa_group_t group; if (!all) { while (optind < argc) { - group = sa_get_group(argv[optind]); + group = sa_get_group(handle, argv[optind]); if (group != NULL) { auth &= check_authorizations(argv[optind], flags); state = sa_get_group_attr(group, "state"); @@ -3139,13 +3140,13 @@ optind++; } } else { - for (group = sa_get_group(NULL); group != NULL; + for (group = sa_get_group(handle, NULL); group != NULL; group = sa_get_next_group(group)) { worklist = add_list(worklist, group, 0); } } if (ret == SA_OK && !dryrun) { - ret = disable_all_groups(worklist, 1); + ret = disable_all_groups(handle, worklist, 1); } if (ret != SA_OK && ret != SA_BUSY) (void) printf(gettext("Could not disable group: %s\n"), @@ -3206,7 +3207,7 @@ */ int -sa_start_group(int flags, int argc, char *argv[]) +sa_start_group(sa_handle_t handle, int flags, int argc, char *argv[]) { int verbose = 0; int all = 0; @@ -3255,7 +3256,7 @@ if (!all) { while (optind < argc) { - group = sa_get_group(argv[optind]); + group = sa_get_group(handle, argv[optind]); if (group != NULL) { state = sa_get_group_attr(group, "state"); if (state == NULL || @@ -3282,7 +3283,7 @@ optind++; } } else { - for (group = sa_get_group(NULL); group != NULL; + for (group = sa_get_group(handle, NULL); group != NULL; group = sa_get_next_group(group)) { state = sa_get_group_attr(group, "state"); if (state == NULL || strcmp(state, "enabled") == 0) @@ -3291,7 +3292,7 @@ sa_free_attr_string(state); } } - (void) enable_all_groups(worklist, 0, 1, NULL); + (void) enable_all_groups(handle, worklist, 0, 1, NULL); } if (worklist != NULL) free_list(worklist); @@ -3308,7 +3309,7 @@ */ int -sa_stop_group(int flags, int argc, char *argv[]) +sa_stop_group(sa_handle_t handle, int flags, int argc, char *argv[]) { int verbose = 0; int all = 0; @@ -3353,7 +3354,7 @@ sa_group_t group; if (!all) { while (optind < argc) { - group = sa_get_group(argv[optind]); + group = sa_get_group(handle, argv[optind]); if (group != NULL) { state = sa_get_group_attr(group, "state"); if (state == NULL || @@ -3372,7 +3373,7 @@ optind++; } } else { - for (group = sa_get_group(NULL); group != NULL; + for (group = sa_get_group(handle, NULL); group != NULL; group = sa_get_next_group(group)) { state = sa_get_group_attr(group, "state"); if (state == NULL || strcmp(state, "enabled") == 0) @@ -3381,8 +3382,8 @@ sa_free_attr_string(state); } } - (void) disable_all_groups(worklist, 0); - ret = sa_update_config(); + (void) disable_all_groups(handle, worklist, 0); + ret = sa_update_config(handle); } if (worklist != NULL) free_list(worklist); @@ -3588,11 +3589,11 @@ */ static void -output_legacy_file(FILE *out, char *proto) +output_legacy_file(FILE *out, char *proto, sa_handle_t handle) { sa_group_t group; - for (group = sa_get_group(NULL); group != NULL; + for (group = sa_get_group(handle, NULL); group != NULL; group = sa_get_next_group(group)) { char *options; char *zfs; @@ -3624,7 +3625,7 @@ } int -sa_legacy_share(int flags, int argc, char *argv[]) +sa_legacy_share(sa_handle_t handle, int flags, int argc, char *argv[]) { char *protocol = "nfs"; char *options = NULL; @@ -3686,7 +3687,7 @@ /* have the info so construct what is needed */ if (!argsused && optind == argc) { /* display current info in share format */ - (void) output_legacy_file(stdout, "nfs"); + (void) output_legacy_file(stdout, "nfs", handle); } else { sa_group_t group = NULL; sa_share_t share; @@ -3717,7 +3718,7 @@ else sharepath = dir; if (ret == SA_OK) { - share = sa_find_share(sharepath); + share = sa_find_share(handle, sharepath); } else { share = NULL; } @@ -3738,7 +3739,7 @@ */ group = sa_get_parent_group(share); } else { - group = sa_get_group(legacygroup); + group = sa_get_group(handle, legacygroup); } if (group != NULL) { groupstatus = group_status(group); @@ -3746,9 +3747,9 @@ share = sa_add_share(group, sharepath, persist, &ret); if (share == NULL && ret == SA_DUPLICATE_NAME) { /* could be a ZFS path being started */ - if (sa_zfs_is_shared(sharepath)) { + if (sa_zfs_is_shared(handle, sharepath)) { ret = SA_OK; - group = sa_get_group("zfs"); + group = sa_get_group(handle, "zfs"); if (group == NULL) { /* this shouldn't happen */ ret = SA_CONFIG_ERR; @@ -3767,7 +3768,7 @@ * need to change them regardless of the * source. */ - if (sa_zfs_is_shared(sharepath)) { + if (sa_zfs_is_shared(handle, sharepath)) { zfs = 1; } remove_all_options(share, protocol); @@ -3810,7 +3811,7 @@ (void) sa_update_legacy(share, protocol); } if (ret == SA_OK) - ret = sa_update_config(); + ret = sa_update_config(handle); } } else { ret = SA_SYSTEM_ERR; @@ -3833,7 +3834,7 @@ */ int -sa_legacy_unshare(int flags, int argc, char *argv[]) +sa_legacy_unshare(sa_handle_t handle, int flags, int argc, char *argv[]) { char *protocol = "nfs"; /* for now */ char *options = NULL; @@ -3899,12 +3900,12 @@ * realpath() and try again. */ sharepath = argv[optind++]; - share = sa_find_share(sharepath); + share = sa_find_share(handle, sharepath); if (share == NULL) { if (realpath(sharepath, dir) == NULL) { ret = SA_NO_SUCH_PATH; } else { - share = sa_find_share(dir); + share = sa_find_share(handle, dir); } } if (share != NULL) { @@ -3920,7 +3921,7 @@ if (persist == SA_SHARE_PERMANENT) { ret = sa_remove_share(share); if (ret == SA_OK) - ret = sa_update_config(); + ret = sa_update_config(handle); } } else { ret = SA_NOT_SHARED; diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/i386/Makefile --- a/usr/src/cmd/dfs.cmds/sharemgr/i386/Makefile Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/cmd/dfs.cmds/sharemgr/i386/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -21,10 +21,10 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../Makefile.com -install: all +install: all $(ROOTUSRSBINPROG32) $(ROOTLINKS) diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/plugins/Makefile --- a/usr/src/cmd/dfs.cmds/sharemgr/plugins/Makefile Wed Mar 28 07:55:32 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -DEFAULTFILES = - -include ../../../Makefile.cmd - -# -# One for each ISA. -# -SUBDIRS = $(MACH) - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -_msg := TARGET= _msg -lint := TARGET= lint - -.KEEP_STATE: - -all clean clobber lint _msg: $(SUBDIRS) - -install: $(SUBDIRS) $(ROOTETCDEFAULTFILES) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/plugins/Makefile.com --- a/usr/src/cmd/dfs.cmds/sharemgr/plugins/Makefile.com Wed Mar 28 07:55:32 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include ../../../../Makefile.cmd - -COMMON = .. - -NFS_MOD = libshare_nfs.so -NFS_SRC = $(NFS_MOD:%.so=$(COMMON)/%.c) -NFSLIB_DIR = $(SRC)/cmd/fs.d/nfs/lib - -SHAREDSRC1 = nfs_sec.c -SHAREDSRC2 = nfslog_config.c -SHAREDSRC3 = nfslogtab.c -NFS_SRCS = $(COMMON)/$(SHAREDSRC1) \ - $(COMMON)/$(SHAREDSRC2) $(COMMON)/$(SHAREDSRC3) $(NFS_SRC) -NFS_OBJS = libshare_nfs.o nfs_sec.o nfslog_config.o nfslogtab.o - -LINK_SRCS = $(NFS_SRC) - -LINT_MODULES = $(LINK_SRCS:.c=.ln) -# -u to eliminate XML warnings. -LINTFLAGS += -u - -LINK_OBJS = $(NFS_OBJS) - -LINK_MODS = $(NFS_MOD) - -SRCS = $(LINK_SRCS) -OBJS = $(LINK_OBJS) -MODS = $(LINK_MODS) - -NFS_DIR = fs/nfs -ROOTLIB_NFS_LINKMOD = $(ROOTLIB)/$(NFS_DIR) -ROOTLIB_NFS_LINK_MODS = $(LINK_MODS:%=$(ROOTLIB_NFS_LINKMOD)/%) - -CLOBBERFILES = $(MODS) $(SHAREDSRC) - -MYCPPFLAGS = -I$(SRC)/lib/libshare/common -I$(SRC)/lib/libfsmgt/common \ - -I/usr/include/libxml2 -I.. -I../.. \ - -I../../../../fs.d/nfs/lib -CPPFLAGS += $(MYCPPFLAGS) -LDLIBS += -lshare -lnsl -lscf -lumem -lc -all install := LDLIBS += -lxml2 -LDFLAGS += -zdefs -zcombreloc -CFLAGS += -Kpic - -POFILES = $(LINK_SRCS:.c=.po) -POFILE = libshare_nfs.po - -OWNER= root -GROUP= sys -FILEMODE= 555 - -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -lint := TARGET= lint - - -.KEEP_STATE: - -all: $(MODS) - -install: all \ - $(ROOTLIB_NFS_LINKMOD) \ - $(ROOTLIB_NFS_LINK_MODS) - -%.so: %.o - $(LINK.c) -o $@ $(GSHARED) -h $@ $< - -%.o: $(COMMON)/%.c - $(COMPILE.c) -o $@ $< - -$(NFS_MOD): $(NFS_OBJS) - $(LINK.c) -o $@ $(GSHARED) $(LDLIBS) -h $@ $(NFS_OBJS) - $(POST_PROCESS) - -clean: - $(RM) $(OBJS) - -lint: $(LINT_MODULES) - -%.ln: FRC - $(LINT.c) $(@:.ln=.c) $(LDLIBS) - -FRC: - -include ../../../../Makefile.targ - -$(POFILE): $(POFILES) - $(RM) $@; cat $(POFILES) > $@ - -$(ROOTLIB_NFS): - $(INS.dir) - -$(ROOTLIB_NFS_LINKMOD): - $(INS.dir) - -$(ROOTLIB_NFS_LINKMOD)/%.so: %.so - $(INS.file) - -%.o: $(NFSLIB_DIR)/%.c - $(COMPILE.c) $(OUTPUT_OPTION) $< $(CTFCONVERT_HOOK) - $(POST_PROCESS_O) diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/plugins/i386/Makefile --- a/usr/src/cmd/dfs.cmds/sharemgr/plugins/i386/Makefile Wed Mar 28 07:55:32 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include ../Makefile.com - -install: all diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/plugins/libshare_nfs.c --- a/usr/src/cmd/dfs.cmds/sharemgr/plugins/libshare_nfs.c Wed Mar 28 07:55:32 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2696 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * NFS specific functions - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libshare.h" -#include "libshare_impl.h" -#include -#include -#include -#include -#include "nfslog_config.h" -#include "nfslogtab.h" -#include "libshare_nfs.h" -#include -#include - -/* should really be in some global place */ -#define DEF_WIN 30000 -#define OPT_CHUNK 1024 - -int debug = 0; - - -/* internal functions */ -static int nfs_init(); -static void nfs_fini(); -static int nfs_enable_share(sa_share_t); -static int nfs_disable_share(char *); -static int nfs_validate_property(sa_property_t, sa_optionset_t); -static int nfs_validate_security_mode(char *); -static int nfs_is_security_opt(char *); -static int nfs_parse_legacy_options(sa_group_t, char *); -static char *nfs_format_options(sa_group_t, int); -static int nfs_set_proto_prop(sa_property_t); -static sa_protocol_properties_t nfs_get_proto_set(); -static char *nfs_get_status(); -static char *nfs_space_alias(char *); - -/* - * ops vector that provides the protocol specific info and operations - * for share management. - */ - -struct sa_plugin_ops sa_plugin_ops = { - SA_PLUGIN_VERSION, - "nfs", - nfs_init, - nfs_fini, - nfs_enable_share, - nfs_disable_share, - nfs_validate_property, - nfs_validate_security_mode, - nfs_is_security_opt, - nfs_parse_legacy_options, - nfs_format_options, - nfs_set_proto_prop, - nfs_get_proto_set, - nfs_get_status, - nfs_space_alias, - NULL, - NULL -}; - -/* - * list of support services needed - * defines should come from head/rpcsvc/daemon_utils.h - */ - -static char *service_list_default[] = - { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, NULL }; -static char *service_list_logging[] = - { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, NFSLOGD, NULL }; - -/* - * option definitions. Make sure to keep the #define for the option - * index just before the entry it is the index for. Changing the order - * can cause breakage. E.g OPT_RW is index 1 and must precede the - * line that includes the SHOPT_RW and OPT_RW entries. - */ - -struct option_defs optdefs[] = { -#define OPT_RO 0 - {SHOPT_RO, OPT_RO, OPT_TYPE_ACCLIST}, -#define OPT_RW 1 - {SHOPT_RW, OPT_RW, OPT_TYPE_ACCLIST}, -#define OPT_ROOT 2 - {SHOPT_ROOT, OPT_ROOT, OPT_TYPE_ACCLIST}, -#define OPT_SECURE 3 - {SHOPT_SECURE, OPT_SECURE, OPT_TYPE_DEPRECATED}, -#define OPT_ANON 4 - {SHOPT_ANON, OPT_ANON, OPT_TYPE_USER}, -#define OPT_WINDOW 5 - {SHOPT_WINDOW, OPT_WINDOW, OPT_TYPE_NUMBER}, -#define OPT_NOSUID 6 - {SHOPT_NOSUID, OPT_NOSUID, OPT_TYPE_BOOLEAN}, -#define OPT_ACLOK 7 - {SHOPT_ACLOK, OPT_ACLOK, OPT_TYPE_BOOLEAN}, -#define OPT_NOSUB 8 - {SHOPT_NOSUB, OPT_NOSUB, OPT_TYPE_BOOLEAN}, -#define OPT_SEC 9 - {SHOPT_SEC, OPT_SEC, OPT_TYPE_SECURITY}, -#define OPT_PUBLIC 10 - {SHOPT_PUBLIC, OPT_PUBLIC, OPT_TYPE_BOOLEAN, OPT_SHARE_ONLY}, -#define OPT_INDEX 11 - {SHOPT_INDEX, OPT_INDEX, OPT_TYPE_FILE}, -#define OPT_LOG 12 - {SHOPT_LOG, OPT_LOG, OPT_TYPE_LOGTAG}, -#define OPT_CKSUM 13 - {SHOPT_CKSUM, OPT_CKSUM, OPT_TYPE_STRINGSET}, -#ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */ -#define OPT_VOLFH 14 - {SHOPT_VOLFH, OPT_VOLFH}, -#endif /* VOLATILE_FH_TEST */ - NULL -}; - -/* - * list of properties that are related to security flavors. - */ -static char *seclist[] = { - SHOPT_RO, - SHOPT_RW, - SHOPT_ROOT, - SHOPT_WINDOW, - NULL -}; - -/* structure for list of securities */ -struct securities { - sa_security_t security; - struct securities *next; -}; - -/* - * findopt(name) - * - * Lookup option "name" in the option table and return the table - * index. - */ - -static int -findopt(char *name) -{ - int i; - if (name != NULL) { - for (i = 0; optdefs[i].tag != NULL; i++) { - if (strcmp(optdefs[i].tag, name) == 0) - return (i); - } - } - return (-1); -} - -/* - * gettype(name) - * - * Return the type of option "name". - */ - -static int -gettype(char *name) -{ - int optdef; - - optdef = findopt(name); - if (optdef != -1) - return (optdefs[optdef].type); - return (OPT_TYPE_ANY); -} - -/* - * nfs_validate_security_mode(mode) - * - * is the specified mode string a valid one for use with NFS? - */ - -static int -nfs_validate_security_mode(char *mode) -{ - seconfig_t secinfo; - int err; - - (void) memset(&secinfo, '\0', sizeof (secinfo)); - err = nfs_getseconfig_byname(mode, &secinfo); - if (err == SC_NOERROR) - return (1); - return (0); -} - -/* - * nfs_is_security_opt(tok) - * - * check to see if tok represents an option that is only valid in some - * security flavor. - */ - -static int -nfs_is_security_opt(char *tok) -{ - int i; - - for (i = 0; seclist[i] != NULL; i++) { - if (strcmp(tok, seclist[i]) == 0) - return (1); - } - return (0); -} - -/* - * find_security(seclist, sec) - * - * Walk the current list of security flavors and return true if it is - * present, else return false. - */ - -static int -find_security(struct securities *seclist, sa_security_t sec) -{ - while (seclist != NULL) { - if (seclist->security == sec) - return (1); - seclist = seclist->next; - } - return (0); -} - -/* - * make_security_list(group, securitymodes, proto) - * go through the list of securitymodes and add them to the - * group's list of security optionsets. We also keep a list of - * those optionsets so we don't have to find them later. All of - * these will get copies of the same properties. - */ - -static struct securities * -make_security_list(sa_group_t group, char *securitymodes, char *proto) -{ - char *tok, *next = NULL; - struct securities *curp, *headp = NULL, *prev; - sa_security_t check; - int freetok = 0; - - for (tok = securitymodes; tok != NULL; tok = next) { - next = strchr(tok, ':'); - if (next != NULL) - *next++ = '\0'; - if (strcmp(tok, "default") == 0) { - /* resolve default into the real type */ - tok = nfs_space_alias(tok); - freetok = 1; - } - check = sa_get_security(group, tok, proto); - - /* add to the security list if it isn't there already */ - if (check == NULL || !find_security(headp, check)) { - curp = (struct securities *)calloc(1, - sizeof (struct securities)); - if (curp != NULL) { - if (check == NULL) { - curp->security = sa_create_security(group, tok, - proto); - } else { - curp->security = check; - } - /* - * note that the first time through the loop, - * headp will be NULL and prev will be - * undefined. Since headp is NULL, we set - * both it and prev to the curp (first - * structure to be allocated). - * - * later passes through the loop will have - * headp not being NULL and prev will be used - * to allocate at the end of the list. - */ - if (headp == NULL) { - headp = curp; - prev = curp; - } else { - prev->next = curp; - prev = curp; - } - } - } - - if (freetok) { - freetok = 0; - sa_free_attr_string(tok); - } - } - return (headp); -} - -static void -free_security_list(struct securities *sec) -{ - struct securities *next; - if (sec != NULL) { - for (next = sec->next; sec != NULL; sec = next) { - next = sec->next; - free(sec); - } - } -} - -/* - * nfs_alistcat(str1, str2, sep) - * - * concatenate str1 and str2 into a new string using sep as a separate - * character. If memory allocation fails, return NULL; - */ - -static char * -nfs_alistcat(char *str1, char *str2, char sep) -{ - char *newstr; - size_t len; - - len = strlen(str1) + strlen(str2) + 2; - newstr = (char *)malloc(len); - if (newstr != NULL) - (void) snprintf(newstr, len, "%s%c%s", str1, sep, str2); - return (newstr); -} - -/* - * add_security_prop(sec, name, value, persist) - * - * Add the property to the securities structure. This accumulates - * properties for as part of parsing legacy options. - */ - -static int -add_security_prop(struct securities *sec, char *name, char *value, - int persist, int iszfs) -{ - sa_property_t prop; - int ret = SA_OK; - - for (; sec != NULL; sec = sec->next) { - if (value == NULL) { - if (strcmp(name, SHOPT_RW) == 0 || strcmp(name, SHOPT_RO) == 0) - value = "*"; - else - value = "true"; - } - - /* - * Get the existing property, if it exists, so we can - * determine what to do with it. The ro/rw/root - * properties can be merged if multiple instances of - * these properies are given. For example, if "rw" - * exists with a value "host1" and a later token of - * rw="host2" is seen, the values are merged into a - * single rw="host1:host2". - */ - prop = sa_get_property(sec->security, name); - - if (prop != NULL) { - char *oldvalue; - char *newvalue; - - /* - * The security options of ro/rw/root might appear - * multiple times. If they do, the values need to be - * merged into an access list. If it was previously - * empty, the new value alone is added. - */ - oldvalue = sa_get_property_attr(prop, "value"); - if (oldvalue != NULL) { - /* - * The general case is to concatenate the new - * value onto the old value for multiple - * rw(ro/root) properties. A special case - * exists when either the old or new is the - * "all" case. In the special case, if both - * are "all", then it is "all", else if one is - * an access-list, that replaces the "all". - */ - if (strcmp(oldvalue, "*") == 0) { - /* Replace old value with new value. */ - newvalue = strdup(value); - } else if (strcmp(value, "*") == 0) { - /* Keep old value and ignore the new value. */ - newvalue = NULL; - } else { - /* Make a new list of old plus new access-list. */ - newvalue = nfs_alistcat(oldvalue, value, ':'); - } - - if (newvalue != NULL) { - (void) sa_remove_property(prop); - prop = sa_create_property(name, newvalue); - ret = sa_add_property(sec->security, prop); - free(newvalue); - } - if (oldvalue != NULL) - sa_free_attr_string(oldvalue); - } - } else { - prop = sa_create_property(name, value); - ret = sa_add_property(sec->security, prop); - } - if (ret == SA_OK && !iszfs) { - ret = sa_commit_properties(sec->security, !persist); - } - } - return (ret); -} - -/* - * check to see if group/share is persistent. - */ -static int -is_persistent(sa_group_t group) -{ - char *type; - int persist = 1; - - type = sa_get_group_attr(group, "type"); - if (type != NULL && strcmp(type, "persist") != 0) - persist = 0; - if (type != NULL) - sa_free_attr_string(type); - return (persist); -} - -/* - * invalid_security(options) - * - * search option string for any invalid sec= type. - * return true (1) if any are not valid else false (0) - */ -static int -invalid_security(char *options) -{ - char *copy, *base, *token, *value; - int ret = 0; - - copy = strdup(options); - token = base = copy; - while (token != NULL && ret == 0) { - token = strtok(base, ","); - base = NULL; - if (token != NULL) { - value = strchr(token, '='); - if (value != NULL) - *value++ = '\0'; - if (strcmp(token, "sec") == 0) { - /* have security flavors so check them */ - char *tok, *next; - for (next = NULL, tok = value; tok != NULL; tok = next) { - next = strchr(tok, ':'); - if (next != NULL) - *next++ = '\0'; - ret = !nfs_validate_security_mode(tok); - if (ret) - break; - } - } - } - } - if (copy != NULL) - free(copy); - return (ret); -} - -/* - * nfs_parse_legacy_options(group, options) - * - * Parse the old style options into internal format and store on the - * specified group. Group could be a share for full legacy support. - */ - -static int -nfs_parse_legacy_options(sa_group_t group, char *options) -{ - char *dup = strdup(options); - char *base; - char *token; - sa_optionset_t optionset; - struct securities *security_list = NULL; - sa_property_t prop; - int ret = SA_OK; - int iszfs = 0; - sa_group_t parent; - int persist = 0; - char *lasts; - - /* do we have an existing optionset? */ - optionset = sa_get_optionset(group, "nfs"); - if (optionset == NULL) { - /* didn't find existing optionset so create one */ - optionset = sa_create_optionset(group, "nfs"); - } else { - /* - * have an existing optionset so we need to compare - * options in order to detect errors. For now, we - * assume that the first optionset is the correct one - * and the others will be the same. This needs to be - * fixed before the final code is ready. - */ - return (ret); - } - - if (strcmp(options, SHOPT_RW) == 0) { - /* - * there is a special case of only the option "rw" - * being the default option. We don't have to do - * anything. - */ - return (ret); - } - - /* - * check if security types are present and validate them. If - * any are not legal, fail. - */ - - if (invalid_security(options)) { - return (SA_INVALID_SECURITY); - } - - /* - * in order to not attempt to change ZFS properties unless - * absolutely necessary, we never do it in the legacy parsing. - */ - if (sa_is_share(group)) { - char *zfs; - parent = sa_get_parent_group(group); - if (parent != NULL) { - zfs = sa_get_group_attr(parent, "zfs"); - if (zfs != NULL) { - sa_free_attr_string(zfs); - iszfs++; - } - } - } else { - iszfs = sa_group_is_zfs(group); - } - - /* - * we need to step through each option in the string and then - * add either the option or the security option as needed. If - * this is not a persistent share, don't commit to the - * repository. If there is an error, we also want to abort the - * processing and report it. - */ - persist = is_persistent(group); - base = dup; - token = dup; - lasts = NULL; - while (token != NULL && ret == SA_OK) { - ret = SA_OK; - token = strtok_r(base, ",", &lasts); - base = NULL; - if (token != NULL) { - char *value; - /* - * if the option has a value, it will have an '=' to - * separate the name from the value. The following - * code will result in value != NULL and token - * pointing to just the name if there is a value. - */ - value = strchr(token, '='); - if (value != NULL) { - *value++ = '\0'; - } - if (strcmp(token, "sec") == 0 || strcmp(token, "secure") == 0) { - /* - * Once in security parsing, we only - * do security. We do need to move - * between the security node and the - * toplevel. The security tag goes on - * the root while the following ones - * go on the security. - */ - if (security_list != NULL) { - /* have an old list so close it and start the new */ - free_security_list(security_list); - } - if (strcmp(token, "secure") == 0) { - value = "dh"; - } else { - if (value == NULL) { - ret = SA_SYNTAX_ERR; - break; - } - } - security_list = make_security_list(group, value, "nfs"); - } else { - /* - * Note that the "old" syntax allowed a - * default security model This must be - * accounted for and internally converted to - * "standard" security structure. - */ - if (nfs_is_security_opt(token)) { - if (security_list == NULL) { - /* - * need to have a security option. This - * will be "closed" when a defined "sec=" - * option is seen. This is technically an - * error but will be allowed with warning. - */ - security_list = make_security_list(group, - "default", - "nfs"); - } - if (security_list != NULL) { - ret = add_security_prop(security_list, token, - value, persist, - iszfs); - } else { - ret = SA_NO_MEMORY; - } - } else { - /* regular options */ - if (value == NULL) { - if (strcmp(token, SHOPT_RW) == 0 || - strcmp(token, SHOPT_RO) == 0) - value = "*"; - else if (strcmp(token, SHOPT_LOG) == 0) - value = "global"; - else - value = "true"; - } - prop = sa_create_property(token, value); - ret = sa_add_property(optionset, prop); - if (ret != SA_OK) { - break; - } - if (!iszfs) { - ret = sa_commit_properties(optionset, !persist); - } - } - } - } - } - if (security_list != NULL) - free_security_list(security_list); - if (dup != NULL) - free(dup); - return (ret); -} - -/* - * is_a_number(number) - * - * is the string a number in one of the forms we want to use? - */ - -static int -is_a_number(char *number) -{ - int ret = 1; - int hex = 0; - - if (strncmp(number, "0x", 2) == 0) { - number += 2; - hex = 1; - } else if (*number == '-') - number++; /* skip the minus */ - - while (ret == 1 && *number != '\0') { - if (hex) { - ret = isxdigit(*number++); - } else { - ret = isdigit(*number++); - } - } - return (ret); -} - -/* - * Look for the specified tag in the configuration file. If it is found, - * enable logging and set the logging configuration information for exp. - */ -static void -configlog(struct exportdata *exp, char *tag) -{ - nfsl_config_t *configlist = NULL, *configp; - int error = 0; - char globaltag[] = DEFAULTTAG; - - /* - * Sends config errors to stderr - */ - nfsl_errs_to_syslog = B_FALSE; - - /* - * get the list of configuration settings - */ - error = nfsl_getconfig_list(&configlist); - if (error) { - (void) fprintf(stderr, - gettext("Cannot get log configuration: %s\n"), - strerror(error)); - } - - if (tag == NULL) - tag = globaltag; - if ((configp = nfsl_findconfig(configlist, tag, &error)) == NULL) { - nfsl_freeconfig_list(&configlist); - (void) fprintf(stderr, - gettext("No tags matching \"%s\"\n"), tag); - /* bad configuration */ - error = ENOENT; - goto err; - } - - if ((exp->ex_tag = strdup(tag)) == NULL) { - error = ENOMEM; - goto out; - } - if ((exp->ex_log_buffer = strdup(configp->nc_bufferpath)) == NULL) { - error = ENOMEM; - goto out; - } - exp->ex_flags |= EX_LOG; - if (configp->nc_rpclogpath != NULL) - exp->ex_flags |= EX_LOG_ALLOPS; -out: - if (configlist != NULL) - nfsl_freeconfig_list(&configlist); - -err: - if (error != 0) { - if (exp->ex_flags != NULL) - free(exp->ex_tag); - if (exp->ex_log_buffer != NULL) - free(exp->ex_log_buffer); - (void) fprintf(stderr, - gettext("Cannot set log configuration: %s\n"), - strerror(error)); - } -} - -/* - * fill_export_from_optionset(export, optionset) - * - * In order to share, we need to set all the possible general options - * into the export structure. Share info will be filled in by the - * caller. Various property values get turned into structure specific - * values. - */ - -static int -fill_export_from_optionset(struct exportdata *export, sa_optionset_t optionset) -{ - sa_property_t option; - int ret = SA_OK; - - for (option = sa_get_property(optionset, NULL); - option != NULL; option = sa_get_next_property(option)) { - char *name; - char *value; - uint32_t val; - - /* - * since options may be set/reset multiple times, always do an - * explicit set or clear of the option. This allows defaults - * to be set and then the protocol specifici to override. - */ - - name = sa_get_property_attr(option, "type"); - value = sa_get_property_attr(option, "value"); - switch (findopt(name)) { - case OPT_ANON: - if (value != NULL && is_a_number(value)) { - val = strtoul(value, NULL, 0); - } else { - struct passwd *pw; - pw = getpwnam(value != NULL ? value : "nobody"); - if (pw != NULL) { - val = pw->pw_uid; - } else { - val = UID_NOBODY; - } - endpwent(); - } - export->ex_anon = val; - break; - case OPT_NOSUID: - if (value != NULL && - (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0)) - export->ex_flags |= EX_NOSUID; - else - export->ex_flags &= ~EX_NOSUID; - break; - case OPT_ACLOK: - if (value != NULL && - (strcasecmp(value, "true") == 0 || - strcmp(value, "1") == 0)) - export->ex_flags |= EX_ACLOK; - else - export->ex_flags &= ~EX_ACLOK; - break; - case OPT_NOSUB: - if (value != NULL && - (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0)) - export->ex_flags |= EX_NOSUB; - else - export->ex_flags &= ~EX_NOSUB; - break; - case OPT_PUBLIC: - if (value != NULL && - (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0)) - export->ex_flags |= EX_PUBLIC; - else - export->ex_flags &= ~EX_PUBLIC; - break; - case OPT_INDEX: - if (value != NULL && - (strcmp(value, "..") == 0 || strchr(value, '/') != NULL)) { - /* this is an error */ - (void) printf(gettext("NFS: index=\"%s\" not valid;" - "must be a filename.\n"), - value); - break; - } - if (value != NULL && *value != '\0' && - strcmp(value, ".") != 0) { - /* valid index file string */ - if (export->ex_index != NULL) { - /* left over from "default" */ - free(export->ex_index); - } - export->ex_index = strdup(value); /* remember to free */ - if (export->ex_index == NULL) { - (void) printf(gettext("NFS: out of memory setting " - "index property\n")); - break; - } - export->ex_flags |= EX_INDEX; - } - break; - case OPT_LOG: - if (value == NULL) - value = strdup("global"); - if (value != NULL) - configlog(export, strlen(value) ? value : "global"); - break; - case OPT_CKSUM: - /* TBD: not ready yet */ - break; - default: - /* have a syntactic error */ - (void) printf(gettext("NFS: unrecognized option %s=%s\n"), - name, value != NULL ? value : ""); - break; - } - if (name != NULL) - sa_free_attr_string(name); - if (value != NULL) - sa_free_attr_string(value); - } - return (ret); -} - -/* - * cleanup_export(export) - * - * Cleanup the allocated areas so we don't leak memory - */ - -static void -cleanup_export(struct exportdata *export) -{ - int i; - - if (export->ex_index != NULL) - free(export->ex_index); - if (export->ex_secinfo != NULL) { - for (i = 0; i < export->ex_seccnt; i++) - if (export->ex_secinfo[i].s_rootnames != NULL) { - free(export->ex_secinfo[i].s_rootnames); - } - free(export->ex_secinfo); - } -} - -/* - * Given a seconfig entry and a colon-separated - * list of names, allocate an array big enough - * to hold the root list, then convert each name to - * a principal name according to the security - * info and assign it to an array element. - * Return the array and its size. - */ -static caddr_t * -get_rootnames(seconfig_t *sec, char *list, int *count) -{ - caddr_t *a; - int c, i; - char *host, *p; - - /* - * Count the number of strings in the list. - * This is the number of colon separators + 1. - */ - c = 1; - for (p = list; *p; p++) - if (*p == ':') - c++; - *count = c; - - a = (caddr_t *)malloc(c * sizeof (char *)); - if (a == NULL) { - (void) printf(gettext("get_rootnames: no memory\n")); - } else { - for (i = 0; i < c; i++) { - host = strtok(list, ":"); - if (!nfs_get_root_principal(sec, host, &a[i])) { - free(a); - a = NULL; - break; - } - list = NULL; - } - } - - return (a); -} - -/* - * fill_security_from_secopts(sp, secopts) - * - * Fill the secinfo structure from the secopts optionset. - */ - -static int -fill_security_from_secopts(struct secinfo *sp, sa_security_t secopts) -{ - sa_property_t prop; - char *type; - int longform; - int err = SC_NOERROR; - - type = sa_get_security_attr(secopts, "sectype"); - if (type != NULL) { - /* named security type needs secinfo to be filled in */ - err = nfs_getseconfig_byname(type, &sp->s_secinfo); - sa_free_attr_string(type); - if (err != SC_NOERROR) - return (err); - } else { - /* default case */ - err = nfs_getseconfig_default(&sp->s_secinfo); - if (err != SC_NOERROR) - return (err); - } - - err = SA_OK; - for (prop = sa_get_property(secopts, NULL); - prop != NULL && err == SA_OK; - prop = sa_get_next_property(prop)) { - char *name; - char *value; - - name = sa_get_property_attr(prop, "type"); - value = sa_get_property_attr(prop, "value"); - - longform = value != NULL && strcmp(value, "*") != 0; - - switch (findopt(name)) { - case OPT_RO: - sp->s_flags |= longform ? M_ROL : M_RO; - break; - case OPT_RW: - sp->s_flags |= longform ? M_RWL : M_RW; - break; - case OPT_ROOT: - sp->s_flags |= M_ROOT; - /* - * if we are using AUTH_UNIX, handle like other things - * such as RO/RW - */ - if (sp->s_secinfo.sc_rpcnum == AUTH_UNIX) - continue; - /* not AUTH_UNIX */ - if (value != NULL) { - sp->s_rootnames = get_rootnames(&sp->s_secinfo, value, - &sp->s_rootcnt); - if (sp->s_rootnames == NULL) { - err = SA_BAD_VALUE; - (void) fprintf(stderr, gettext("Bad root list\n")); - } - } - break; - case OPT_WINDOW: - if (value != NULL) { - sp->s_window = atoi(value); - if (sp->s_window < 0) - sp->s_window = DEF_WIN; /* just in case */ - } - break; - default: - break; - } - if (name != NULL) - sa_free_attr_string(name); - if (value != NULL) - sa_free_attr_string(value); - } - /* if rw/ro options not set, use default of RW */ - if ((sp->s_flags & NFS_RWMODES) == 0) - sp->s_flags |= M_RW; - return (err); -} - -/* - * This is for testing only - * It displays the export structure that - * goes into the kernel. - */ -static void -printarg(char *path, struct exportdata *ep) -{ - int i, j; - struct secinfo *sp; - - if (debug == 0) - return; - - (void) printf("%s:\n", path); - (void) printf("\tex_version = %d\n", ep->ex_version); - (void) printf("\tex_path = %s\n", ep->ex_path); - (void) printf("\tex_pathlen = %d\n", ep->ex_pathlen); - (void) printf("\tex_flags: (0x%02x) ", ep->ex_flags); - if (ep->ex_flags & EX_NOSUID) - (void) printf("NOSUID "); - if (ep->ex_flags & EX_ACLOK) - (void) printf("ACLOK "); - if (ep->ex_flags & EX_PUBLIC) - (void) printf("PUBLIC "); - if (ep->ex_flags & EX_NOSUB) - (void) printf("NOSUB "); - if (ep->ex_flags & EX_LOG) - (void) printf("LOG "); - if (ep->ex_flags & EX_LOG_ALLOPS) - (void) printf("LOG_ALLOPS "); - if (ep->ex_flags == 0) - (void) printf("(none)"); - (void) printf("\n"); - if (ep->ex_flags & EX_LOG) { - (void) printf("\tex_log_buffer = %s\n", - (ep->ex_log_buffer ? ep->ex_log_buffer : "(NULL)")); - (void) printf("\tex_tag = %s\n", - (ep->ex_tag ? ep->ex_tag : "(NULL)")); - } - (void) printf("\tex_anon = %d\n", ep->ex_anon); - (void) printf("\tex_seccnt = %d\n", ep->ex_seccnt); - (void) printf("\n"); - for (i = 0; i < ep->ex_seccnt; i++) { - sp = &ep->ex_secinfo[i]; - (void) printf("\t\ts_secinfo = %s\n", sp->s_secinfo.sc_name); - (void) printf("\t\ts_flags: (0x%02x) ", sp->s_flags); - if (sp->s_flags & M_ROOT) (void) printf("M_ROOT "); - if (sp->s_flags & M_RO) (void) printf("M_RO "); - if (sp->s_flags & M_ROL) (void) printf("M_ROL "); - if (sp->s_flags & M_RW) (void) printf("M_RW "); - if (sp->s_flags & M_RWL) (void) printf("M_RWL "); - if (sp->s_flags == 0) (void) printf("(none)"); - (void) printf("\n"); - (void) printf("\t\ts_window = %d\n", sp->s_window); - (void) printf("\t\ts_rootcnt = %d ", sp->s_rootcnt); - (void) fflush(stdout); - for (j = 0; j < sp->s_rootcnt; j++) - (void) printf("%s ", sp->s_rootnames[j] ? - sp->s_rootnames[j] : ""); - (void) printf("\n\n"); - } -} - -/* - * count_security(opts) - * - * Count the number of security types (flavors). The optionset has - * been populated with the security flavors as a holding mechanism. - * We later use this number to allocate data structures. - */ - -static int -count_security(sa_optionset_t opts) -{ - int count = 0; - sa_property_t prop; - if (opts != NULL) { - for (prop = sa_get_property(opts, NULL); prop != NULL; - prop = sa_get_next_property(prop)) { - count++; - } - } - return (count); -} - -/* - * nfs_sprint_option(rbuff, rbuffsize, incr, prop, sep) - * - * provides a mechanism to format NFS properties into legacy output - * format. If the buffer would overflow, it is reallocated and grown - * as appropriate. Special cases of converting internal form of values - * to those used by "share" are done. this function does one property - * at a time. - */ - -static void -nfs_sprint_option(char **rbuff, size_t *rbuffsize, size_t incr, - sa_property_t prop, int sep) -{ - char *name; - char *value; - int curlen; - char *buff = *rbuff; - size_t buffsize = *rbuffsize; - - name = sa_get_property_attr(prop, "type"); - value = sa_get_property_attr(prop, "value"); - if (buff != NULL) - curlen = strlen(buff); - else - curlen = 0; - if (name != NULL) { - int len; - len = strlen(name) + sep; - - /* - * A future RFE would be to replace this with more - * generic code and to possibly handle more types. - */ - switch (gettype(name)) { - case OPT_TYPE_BOOLEAN: - if (value != NULL && strcasecmp(value, "false") == 0) { - *name = '\0'; - } - if (value != NULL) - sa_free_attr_string(value); - value = NULL; - break; - case OPT_TYPE_ACCLIST: - if (value != NULL && strcmp(value, "*") == 0) { - sa_free_attr_string(value); - value = NULL; - } else { - if (value != NULL) - len += 1 + strlen(value); - } - break; - case OPT_TYPE_LOGTAG: - if (value != NULL && strlen(value) == 0) { - sa_free_attr_string(value); - value = NULL; - } else { - if (value != NULL) - len += 1 + strlen(value); - } - break; - default: - if (value != NULL) - len += 1 + strlen(value); - break; - } - while (buffsize <= (curlen + len)) { - /* need more room */ - buffsize += incr; - buff = realloc(buff, buffsize); - if (buff == NULL) { - /* realloc failed so free everything */ - if (*rbuff != NULL) - free(*rbuff); - } - *rbuff = buff; - *rbuffsize = buffsize; - if (buff == NULL) { - return; - } - } - if (buff == NULL) - return; - if (value == NULL) - (void) snprintf(buff + curlen, buffsize - curlen, - "%s%s", sep ? "," : "", - name, value != NULL ? value : ""); - else - (void) snprintf(buff + curlen, buffsize - curlen, - "%s%s=%s", sep ? "," : "", - name, value != NULL ? value : ""); - } - if (name != NULL) - sa_free_attr_string(name); - if (value != NULL) - sa_free_attr_string(value); -} - -/* - * nfs_format_options(group, hier) - * - * format all the options on the group into an old-style option - * string. If hier is non-zero, walk up the tree to get inherited - * options. - */ - -static char * -nfs_format_options(sa_group_t group, int hier) -{ - sa_optionset_t options = NULL; - sa_optionset_t secoptions; - sa_property_t prop, secprop; - sa_security_t security; - char *buff; - size_t buffsize; - - options = sa_get_derived_optionset(group, "nfs", hier); - - /* - * have a an optionset relative to this item, if any. format - * these then add any security definitions. - */ - buff = malloc(OPT_CHUNK); - if (buff != NULL) { - int sep = 0; - buff[0] = '\0'; - buffsize = OPT_CHUNK; - /* - * do the default set first but skip any option that is also - * in the protocol specific optionset. - */ - if (options != NULL) { - for (prop = sa_get_property(options, NULL); prop != NULL; - prop = sa_get_next_property(prop)) { - /* - * use this one since we skipped any of these that - * were also in optdefault - */ - nfs_sprint_option(&buff, &buffsize, OPT_CHUNK, prop, sep); - if (buff == NULL) { - /* - * buff could become NULL if there isn't - * enough memory for nfs_sprint_option to - * realloc() as necessary. We can't really do - * anything about it at this point so we - * return NULL. The caller should handle the - * failure. Note that this - */ - return (buff); - } - sep = 1; - } - } - secoptions = (sa_optionset_t)sa_get_all_security_types(group, - "nfs", hier); - if (secoptions != NULL) { - for (secprop = sa_get_property(secoptions, NULL); - secprop != NULL; secprop = sa_get_next_property(secprop)) { - char *sectype; - - sectype = sa_get_property_attr(secprop, "type"); - security = (sa_security_t)sa_get_derived_security(group, - sectype, - "nfs", hier); - if (security != NULL) { - if (sectype != NULL) { - prop = sa_create_property("sec", sectype); - nfs_sprint_option(&buff, &buffsize, OPT_CHUNK, - prop, sep); - (void) sa_remove_property(prop); - sep = 1; - } - for (prop = sa_get_property(security, NULL); - prop != NULL; - prop = sa_get_next_property(prop)) { - - nfs_sprint_option(&buff, &buffsize, OPT_CHUNK, - prop, sep); - if (buff == NULL) { - /* catastrophic memory failure */ - sa_free_derived_optionset(secoptions); - if (security != NULL) - sa_free_derived_optionset(security); - if (sectype != NULL) - sa_free_attr_string(sectype); - if (options != NULL) - sa_free_derived_optionset(options); - return (buff); - } - sep = 1; - } - sa_free_derived_optionset(security); - } - if (sectype != NULL) - sa_free_attr_string(sectype); - } - sa_free_derived_optionset(secoptions); - } - } - if (options != NULL) - sa_free_derived_optionset(options); - return (buff); -} -/* - * Append an entry to the nfslogtab file - */ -static int -nfslogtab_add(dir, buffer, tag) - char *dir, *buffer, *tag; -{ - FILE *f; - struct logtab_ent lep; - int error = 0; - - /* - * Open the file for update and create it if necessary. - * This may leave the I/O offset at the end of the file, - * so rewind back to the beginning of the file. - */ - f = fopen(NFSLOGTAB, "a+"); - if (f == NULL) { - error = errno; - goto out; - } - rewind(f); - - if (lockf(fileno(f), F_LOCK, 0L) < 0) { - (void) fprintf(stderr, gettext( - "share complete, however failed to lock %s " - "for update: %s\n"), NFSLOGTAB, strerror(errno)); - error = -1; - goto out; - } - - if (logtab_deactivate_after_boot(f) == -1) { - (void) fprintf(stderr, gettext( - "share complete, however could not deactivate " - "entries in %s\n"), NFSLOGTAB); - error = -1; - goto out; - } - - /* - * Remove entries matching buffer and sharepoint since we're - * going to replace it with perhaps an entry with a new tag. - */ - if (logtab_rement(f, buffer, dir, NULL, -1)) { - (void) fprintf(stderr, gettext( - "share complete, however could not remove matching " - "entries in %s\n"), NFSLOGTAB); - error = -1; - goto out; - } - - /* - * Deactivate all active entries matching this sharepoint - */ - if (logtab_deactivate(f, NULL, dir, NULL)) { - (void) fprintf(stderr, gettext( - "share complete, however could not deactivate matching " - "entries in %s\n"), NFSLOGTAB); - error = -1; - goto out; - } - - lep.le_buffer = buffer; - lep.le_path = dir; - lep.le_tag = tag; - lep.le_state = LES_ACTIVE; - - /* - * Add new sharepoint / buffer location to nfslogtab - */ - if (logtab_putent(f, &lep) < 0) { - (void) fprintf(stderr, gettext( - "share complete, however could not add %s to %s\n"), - dir, NFSLOGTAB); - error = -1; - } - -out: - if (f != NULL) - (void) fclose(f); - return (error); -} - -/* - * Deactivate an entry from the nfslogtab file - */ -static int -nfslogtab_deactivate(path) - char *path; -{ - FILE *f; - int error = 0; - - f = fopen(NFSLOGTAB, "r+"); - if (f == NULL) { - error = errno; - goto out; - } - if (lockf(fileno(f), F_LOCK, 0L) < 0) { - error = errno; - (void) fprintf(stderr, gettext( - "share complete, however could not lock %s for " - "update: %s\n"), NFSLOGTAB, strerror(error)); - goto out; - } - if (logtab_deactivate(f, NULL, path, NULL) == -1) { - error = -1; - (void) fprintf(stderr, - gettext("share complete, however could not " - "deactivate %s in %s\n"), path, NFSLOGTAB); - goto out; - } - -out: if (f != NULL) - (void) fclose(f); - - return (error); -} - -/* - * public_exists(share) - * - * check to see if public option is set on any other share than the - * one specified. - */ -static int -public_exists(sa_share_t skipshare) -{ - sa_share_t share; - sa_group_t group; - sa_optionset_t opt; - sa_property_t prop; - int exists = 0; - - for (group = sa_get_group(NULL); group != NULL; - group = sa_get_next_group(group)) { - for (share = sa_get_share(group, NULL); share != NULL; - share = sa_get_next_share(share)) { - if (share == skipshare) - continue; - opt = sa_get_optionset(share, "nfs"); - if (opt != NULL) { - prop = sa_get_property(opt, "public"); - if (prop != NULL) { - char *shared; - shared = sa_get_share_attr(share, "shared"); - if (shared != NULL) { - exists = strcmp(shared, "true") == 0; - sa_free_attr_string(shared); - goto out; - } - } - } - } - } -out: - return (exists); -} - -/* - * sa_enable_share at the protocol level, enable_share must tell the - * implementation that it is to enable the share. This entails - * converting the path and options into the appropriate ioctl - * calls. It is assumed that all error checking of paths, etc. were - * done earlier. - */ -static int -nfs_enable_share(sa_share_t share) -{ - struct exportdata export; - sa_optionset_t secoptlist; - struct secinfo *sp; - int num_secinfo; - sa_optionset_t opt; - sa_security_t sec; - sa_property_t prop; - char *path; - int err = SA_OK; - - /* Don't drop core if the NFS module isn't loaded. */ - (void) signal(SIGSYS, SIG_IGN); - - /* get the path since it is important in several places */ - path = sa_get_share_attr(share, "path"); - if (path == NULL) - return (SA_NO_SUCH_PATH); - - /* - * find the optionsets and security sets. There may not be - * any or there could be one or two for each of optionset and - * security may have multiple, one per security type per - * protocol type. - */ - opt = sa_get_derived_optionset(share, "nfs", 1); - secoptlist = (sa_optionset_t)sa_get_all_security_types(share, "nfs", 1); - if (secoptlist != NULL) - num_secinfo = MAX(1, count_security(secoptlist)); - else - num_secinfo = 1; - - /* - * walk through the options and fill in the structure - * appropriately. - */ - - (void) memset(&export, '\0', sizeof (export)); - - /* - * do non-security options first since there is only one after - * the derived group is constructed. - */ - export.ex_version = EX_CURRENT_VERSION; - export.ex_anon = UID_NOBODY; /* this is our default value */ - export.ex_index = NULL; - export.ex_path = path; - export.ex_pathlen = strlen(path) + 1; - - sp = calloc(num_secinfo, sizeof (struct secinfo)); - - if (opt != NULL) - err = fill_export_from_optionset(&export, opt); - - /* - * check to see if "public" is set. If it is, then make sure - * no other share has it set. If it is already used, fail. - */ - - if (export.ex_flags & EX_PUBLIC && public_exists(share)) { - (void) printf(gettext("NFS: Cannot share more than one file " - "system with 'public' property\n")); - err = SA_NOT_ALLOWED; - goto out; - } - - if (sp == NULL) { - /* failed to alloc memory */ - (void) printf("NFS: no memory for security\n"); - err = SA_NO_MEMORY; - } else { - int i; - export.ex_secinfo = sp; - /* get default secinfo */ - export.ex_seccnt = num_secinfo; - /* - * since we must have one security option defined, we - * init to the default and then override as we find - * defined security options. This handles the case - * where we have no defined options but we need to set - * up one. - */ - sp[0].s_window = DEF_WIN; - sp[0].s_rootnames = NULL; - /* setup a default in case no properties defined */ - if (nfs_getseconfig_default(&sp[0].s_secinfo)) { - (void) printf(gettext("NFS: nfs_getseconfig_default: failed to " - "get default security mode\n")); - err = SA_CONFIG_ERR; - } - if (secoptlist != NULL) { - for (i = 0, prop = sa_get_property(secoptlist, NULL); - prop != NULL && i < num_secinfo; - prop = sa_get_next_property(prop), i++) { - char *sectype; - - sectype = sa_get_property_attr(prop, "type"); - /* if sectype is NULL, we can't do anything so skip */ - if (sectype == NULL) - continue; - sec = (sa_security_t)sa_get_derived_security(share, - sectype, - "nfs", 1); - sp[i].s_window = DEF_WIN; - sp[i].s_rootcnt = 0; - sp[i].s_rootnames = NULL; - - (void) fill_security_from_secopts(&sp[i], sec); - if (sec != NULL) - sa_free_derived_security(sec); - if (sectype != NULL) - sa_free_attr_string(sectype); - } - } - /* - * when we get here, we can do the exportfs system call and - * initiate thinsg. We probably want to enable the nfs.server - * service first if it isn't running within SMF. - */ - /* check nfs.server status and start if needed */ - - /* now add the share to the internal tables */ - printarg(path, &export); - /* - * call the exportfs system call which is implemented - * via the nfssys() call as the EXPORTFS subfunction. - */ - if ((err = exportfs(path, &export)) < 0) { - err = SA_SYSTEM_ERR; - switch (errno) { - case EREMOTE: - (void) printf(gettext("NFS: Cannot share remote file" - "system: %s\n"), - path); - break; - case EPERM: - if (getzoneid() != GLOBAL_ZONEID) { - (void) printf(gettext("NFS: Cannot share file systems " - "in non-global zones: %s\n"), path); - err = SA_NOT_SUPPORTED; - break; - } - err = SA_NO_PERMISSION; - /* FALLTHROUGH */ - default: - break; - } - } else { - /* update sharetab with an add/modify */ - (void) sa_update_sharetab(share, "nfs"); - } - } - - if (err == SA_OK) { - /* - * enable services as needed. This should probably be - * done elsewhere in order to minimize the calls to - * check services. - */ - /* - * check to see if logging and other services need to - * be triggered, but only if there wasn't an - * error. This is probably where sharetab should be - * updated with the NFS specific entry. - */ - if (export.ex_flags & EX_LOG) { - /* enable logging */ - if (nfslogtab_add(path, export.ex_log_buffer, - export.ex_tag) != 0) { - (void) fprintf(stderr, - gettext("Could not enable logging for %s\n"), - path); - } - _check_services(service_list_logging); - } else { - /* - * don't have logging so remove it from file. It might - * not be thre, but that doesn't matter. - */ - (void) nfslogtab_deactivate(path); - _check_services(service_list_default); - } - } - -out: - if (path != NULL) - free(path); - - cleanup_export(&export); - if (opt != NULL) - sa_free_derived_optionset(opt); - if (secoptlist != NULL) - (void) sa_destroy_optionset(secoptlist); - return (err); -} - -/* - * nfs_disable_share(share) - * - * Unshare the specified share. How much error checking should be - * done? We only do basic errors for now. - */ -static int -nfs_disable_share(char *share) -{ - int err; - int ret = SA_OK; - - if (share != NULL) { - err = exportfs(share, NULL); - if (err < 0) { - /* TBD: only an error in some cases - need better analysis */ - switch (errno) { - case EPERM: - case EACCES: - ret = SA_NO_PERMISSION; - if (getzoneid() != GLOBAL_ZONEID) { - ret = SA_NOT_SUPPORTED; - } - break; - case EINVAL: - case ENOENT: - ret = SA_NO_SUCH_PATH; - break; - default: - ret = SA_SYSTEM_ERR; - break; - } - } - if (ret == SA_OK || ret == SA_NO_SUCH_PATH) { - (void) sa_delete_sharetab(share, "nfs"); - /* just in case it was logged */ - (void) nfslogtab_deactivate(share); - } - } - return (ret); -} - -/* - * check ro vs rw values. Over time this may get beefed up. - * for now it just does simple checks. - */ - -static int -check_rorw(char *v1, char *v2) -{ - int ret = SA_OK; - if (strcmp(v1, v2) == 0) - ret = SA_VALUE_CONFLICT; - return (ret); -} - -/* - * nfs_validate_property(property, parent) - * - * Check that the property has a legitimate value for its type. - */ - -static int -nfs_validate_property(sa_property_t property, sa_optionset_t parent) -{ - int ret = SA_OK; - char *propname; - char *other; - int optindex; - nfsl_config_t *configlist; - sa_group_t parent_group; - char *value; - - propname = sa_get_property_attr(property, "type"); - - if ((optindex = findopt(propname)) < 0) - ret = SA_NO_SUCH_PROP; - - /* need to validate value range here as well */ - - if (ret == SA_OK) { - parent_group = sa_get_parent_group((sa_share_t)parent); - if (optdefs[optindex].share && !sa_is_share(parent_group)) { - ret = SA_PROP_SHARE_ONLY; - } - } - if (ret == SA_OK) { - value = sa_get_property_attr(property, "value"); - if (value != NULL) { - /* first basic type checking */ - switch (optdefs[optindex].type) { - case OPT_TYPE_NUMBER: - /* check that the value is all digits */ - if (!is_a_number(value)) - ret = SA_BAD_VALUE; - break; - case OPT_TYPE_BOOLEAN: - if (strlen(value) == 0 || - strcasecmp(value, "true") == 0 || - strcmp(value, "1") == 0 || - strcasecmp(value, "false") == 0 || - strcmp(value, "0") == 0) { - ret = SA_OK; - } else { - ret = SA_BAD_VALUE; - } - break; - case OPT_TYPE_USER: - if (!is_a_number(value)) { - struct passwd *pw; - /* in this case it would have to be a user name */ - pw = getpwnam(value); - if (pw == NULL) - ret = SA_BAD_VALUE; - endpwent(); - } else { - uint64_t intval; - intval = strtoull(value, NULL, 0); - if (intval > UID_MAX && intval != ~0) - ret = SA_BAD_VALUE; - } - break; - case OPT_TYPE_FILE: - if (strcmp(value, "..") == 0 || - strchr(value, '/') != NULL) { - ret = SA_BAD_VALUE; - } - break; - case OPT_TYPE_ACCLIST: - /* - * access list handling. Should eventually - * validate that all the values make sense. - * Also, ro and rw may have cross value - * conflicts. - */ - if (strcmp(propname, SHOPT_RO) == 0) - other = SHOPT_RW; - else if (strcmp(propname, SHOPT_RW) == 0) - other = SHOPT_RO; - else - other = NULL; - if (other != NULL && parent != NULL) { - /* compare rw(ro) with ro(rw) */ - sa_property_t oprop; - oprop = sa_get_property(parent, other); - if (oprop != NULL) { - /* only potential confusion if other exists */ - char *ovalue; - ovalue = sa_get_property_attr(oprop, "value"); - if (ovalue != NULL) { - ret = check_rorw(value, ovalue); - sa_free_attr_string(ovalue); - } - } - } - break; - case OPT_TYPE_LOGTAG: - if (nfsl_getconfig_list(&configlist) == 0) { - int error; - if (value == NULL || strlen(value) == 0) { - if (value != NULL) - sa_free_attr_string(value); - value = strdup("global"); - } - if (nfsl_findconfig(configlist, value, &error) == NULL) - ret = SA_BAD_VALUE; - nfsl_freeconfig_list(&configlist); - } else { - ret = SA_CONFIG_ERR; - } - break; - case OPT_TYPE_STRING: - /* whatever is here should be ok */ - break; - case OPT_TYPE_SECURITY: - /* - * The "sec" property isn't used in the - * non-legacy parts of sharemgr. We need to - * reject it here. For legacy, it is pulled - * out well before we get here. - */ - ret = SA_NO_SUCH_PROP; - break; - default: - break; - } - sa_free_attr_string(value); - if (ret == SA_OK && optdefs[optindex].check != NULL) { - /* do the property specific check */ - ret = optdefs[optindex].check(property); - } - } - } - - if (propname != NULL) - sa_free_attr_string(propname); - return (ret); -} - -/* - * Protocol management functions - * - * Properties defined in the default files are defined in - * proto_option_defs for parsing and validation. If "other" and - * "compare" are set, then the value for this property should be - * compared against the property specified in "other" using the - * "compare" check (either <= or >=) in order to ensure that the - * values are in the correct range. E.g. setting server_versmin - * higher than server_versmax should not be allowed. - */ - -struct proto_option_defs { - char *tag; - char *name; /* display name -- remove protocol identifier */ - int index; - int type; - union { - int intval; - char *string; - } defvalue; - uint32_t svcs; - int32_t minval; - int32_t maxval; - char *file; - char *other; - int compare; -#define OPT_CMP_GE 0 -#define OPT_CMP_LE 1 - int (*check)(char *); -} proto_options[] = { -#define PROTO_OPT_NFSD_SERVERS 0 - {"nfsd_servers", - "servers", PROTO_OPT_NFSD_SERVERS, OPT_TYPE_NUMBER, 16, SVC_NFSD, - 1, INT32_MAX, NFSADMIN}, -#define PROTO_OPT_LOCKD_LISTEN_BACKLOG 1 - {"lockd_listen_backlog", - "lockd_listen_backlog", PROTO_OPT_LOCKD_LISTEN_BACKLOG, - OPT_TYPE_NUMBER, 32, SVC_LOCKD, 32, INT32_MAX, NFSADMIN}, -#define PROTO_OPT_LOCKD_SERVERS 2 - {"lockd_servers", - "lockd_servers", PROTO_OPT_LOCKD_SERVERS, OPT_TYPE_NUMBER, 20, - SVC_LOCKD, 1, INT32_MAX, NFSADMIN}, -#define PROTO_OPT_LOCKD_RETRANSMIT_TIMEOUT 3 - {"lockd_retransmit_timeout", - "lockd_retransmit_timeout", PROTO_OPT_LOCKD_RETRANSMIT_TIMEOUT, - OPT_TYPE_NUMBER, 5, SVC_LOCKD, 0, INT32_MAX, NFSADMIN}, -#define PROTO_OPT_GRACE_PERIOD 4 - {"grace_period", - "grace_period", PROTO_OPT_GRACE_PERIOD, OPT_TYPE_NUMBER, 90, - SVC_LOCKD, 0, INT32_MAX, NFSADMIN}, -#define PROTO_OPT_NFS_SERVER_VERSMIN 5 - {"nfs_server_versmin", - "server_versmin", PROTO_OPT_NFS_SERVER_VERSMIN, OPT_TYPE_NUMBER, - (int)NFS_VERSMIN_DEFAULT, SVC_NFSD|SVC_MOUNTD, NFS_VERSMIN, - NFS_VERSMAX, NFSADMIN, "server_versmax", OPT_CMP_LE}, -#define PROTO_OPT_NFS_SERVER_VERSMAX 6 - {"nfs_server_versmax", - "server_versmax", PROTO_OPT_NFS_SERVER_VERSMAX, OPT_TYPE_NUMBER, - (int)NFS_VERSMAX_DEFAULT, SVC_NFSD|SVC_MOUNTD, NFS_VERSMIN, - NFS_VERSMAX, NFSADMIN, "server_versmin", OPT_CMP_GE}, -#define PROTO_OPT_NFS_CLIENT_VERSMIN 7 - {"nfs_client_versmin", - "client_versmin", PROTO_OPT_NFS_CLIENT_VERSMIN, OPT_TYPE_NUMBER, - (int)NFS_VERSMIN_DEFAULT, NULL, NFS_VERSMIN, NFS_VERSMAX, - NFSADMIN, "client_versmax", OPT_CMP_LE}, -#define PROTO_OPT_NFS_CLIENT_VERSMAX 8 - {"nfs_client_versmax", - "client_versmax", PROTO_OPT_NFS_CLIENT_VERSMAX, OPT_TYPE_NUMBER, - (int)NFS_VERSMAX_DEFAULT, NULL, NFS_VERSMIN, NFS_VERSMAX, - NFSADMIN, "client_versmin", OPT_CMP_GE}, -#define PROTO_OPT_NFS_SERVER_DELEGATION 9 - {"nfs_server_delegation", - "server_delegation", PROTO_OPT_NFS_SERVER_DELEGATION, - OPT_TYPE_ONOFF, NFS_SERVER_DELEGATION_DEFAULT, SVC_NFSD, 0, 0, - NFSADMIN}, -#define PROTO_OPT_NFSMAPID_DOMAIN 10 - {"nfsmapid_domain", - "nfsmapid_domain", PROTO_OPT_NFSMAPID_DOMAIN, OPT_TYPE_DOMAIN, - NULL, SVC_NFSMAPID, 0, 0, NFSADMIN}, -#define PROTO_OPT_NFSD_MAX_CONNECTIONS 11 - {"nfsd_max_connections", - "max_connections", PROTO_OPT_NFSD_MAX_CONNECTIONS, - OPT_TYPE_NUMBER, -1, SVC_NFSD, -1, INT32_MAX, NFSADMIN}, -#define PROTO_OPT_NFSD_PROTOCOL 12 - {"nfsd_protocol", - "protocol", PROTO_OPT_NFSD_PROTOCOL, OPT_TYPE_PROTOCOL, 0, - SVC_NFSD, 0, 0, NFSADMIN}, -#define PROTO_OPT_NFSD_LISTEN_BACKLOG 13 - {"nfsd_listen_backlog", - "listen_backlog", PROTO_OPT_NFSD_LISTEN_BACKLOG, - OPT_TYPE_NUMBER, 0, - SVC_LOCKD, 0, INT32_MAX, NFSADMIN}, - {NULL} -}; - -/* - * the protoset holds the defined options so we don't have to read - * them multiple times - */ -sa_protocol_properties_t protoset; - -static int -findprotoopt(char *name, int whichname) -{ - int i; - for (i = 0; proto_options[i].tag != NULL; i++) { - if (whichname == 1) { - if (strcasecmp(proto_options[i].name, name) == 0) - return (i); - } else { - if (strcasecmp(proto_options[i].tag, name) == 0) - return (i); - } - } - return (-1); -} - -/* - * fixcaselower(str) - * - * convert a string to lower case (inplace). - */ - -static void -fixcaselower(char *str) -{ - while (*str) { - *str = tolower(*str); - str++; - } -} - -/* - * fixcaseupper(str) - * - * convert a string to upper case (inplace). - */ - -static void -fixcaseupper(char *str) -{ - while (*str) { - *str = toupper(*str); - str++; - } -} - -/* - * initprotofromdefault() - * - * read the default file(s) and add the defined values to the - * protoset. Note that default values are known from the built in - * table in case the file doesn't have a definition. - */ - -static int -initprotofromdefault() -{ - FILE *nfs; - char buff[BUFSIZ]; - char *name; - char *value; - sa_property_t prop; - int index; - - protoset = sa_create_protocol_properties("nfs"); - - if (protoset != NULL) { - nfs = fopen(NFSADMIN, "r"); - if (nfs != NULL) { - while (fgets(buff, sizeof (buff), nfs) != NULL) { - switch (buff[0]) { - case '\n': - case '#': - /* skip */ - break; - default: - name = buff; - buff[strlen(buff) - 1] = '\0'; - value = strchr(name, '='); - if (value != NULL) { - *value++ = '\0'; - if ((index = findprotoopt(name, 0)) >= 0) { - fixcaselower(name); - prop = sa_create_property( - proto_options[index].name, - value); - (void) sa_add_protocol_property(protoset, prop); - } - } - } - } - if (nfs != NULL) - (void) fclose(nfs); - } - } - if (protoset == NULL) - return (SA_NO_MEMORY); - return (SA_OK); -} - -/* - * add_default() - * - * Add the default values for any property not defined in the parsing - * of the default files. Values are set according to their defined - * types. - */ - -static void -add_defaults() -{ - int i; - char number[MAXDIGITS]; - - for (i = 0; proto_options[i].tag != NULL; i++) { - sa_property_t prop; - prop = sa_get_protocol_property(protoset, proto_options[i].name); - if (prop == NULL) { - /* add the default value */ - switch (proto_options[i].type) { - case OPT_TYPE_NUMBER: - (void) snprintf(number, sizeof (number), "%d", - proto_options[i].defvalue.intval); - prop = sa_create_property(proto_options[i].name, number); - break; - - case OPT_TYPE_BOOLEAN: - prop = sa_create_property(proto_options[i].name, - proto_options[i].defvalue.intval ? - "true" : "false"); - break; - - case OPT_TYPE_ONOFF: - prop = sa_create_property(proto_options[i].name, - proto_options[i].defvalue.intval ? - "on" : "off"); - break; - - default: - /* treat as strings of zero length */ - prop = sa_create_property(proto_options[i].name, ""); - break; - } - if (prop != NULL) - (void) sa_add_protocol_property(protoset, prop); - } - } -} - -static void -free_protoprops() -{ - xmlFreeNode(protoset); -} - -/* - * nfs_init() - * - * Initialize the NFS plugin. - */ - -static int -nfs_init() -{ - int ret = SA_OK; - - if (sa_plugin_ops.sa_init != nfs_init) - (void) printf(gettext("NFS plugin not properly initialized\n")); - - ret = initprotofromdefault(); - add_defaults(); - - return (ret); -} - -/* - * nfs_fini() - * - * uninitialize the NFS plugin. Want to avoid memory leaks. - */ - -static void -nfs_fini() -{ - free_protoprops(); -} - -/* - * nfs_get_proto_set() - * - * Return an optionset with all the protocol specific properties in - * it. - */ - -static sa_protocol_properties_t -nfs_get_proto_set() -{ - return (protoset); -} - -struct deffile { - struct deffile *next; - char *line; -}; - -/* - * read_default_file(fname) - * - * Read the specified default file. We return a list of entries. This - * get used for adding or removing values. - */ - -static struct deffile * -read_default_file(char *fname) -{ - FILE *file; - struct deffile *defs = NULL; - struct deffile *newdef; - struct deffile *prevdef = NULL; - char buff[BUFSIZ * 2]; - - file = fopen(fname, "r"); - if (file != NULL) { - while (fgets(buff, sizeof (buff), file) != NULL) { - newdef = (struct deffile *)calloc(1, sizeof (struct deffile)); - if (newdef != NULL) { - newdef->line = strdup(buff); - if (defs == NULL) { - prevdef = defs = newdef; - } else { - prevdef->next = newdef; - prevdef = newdef; - } - } - } - } - (void) fclose(file); - return (defs); -} - -static void -free_default_file(struct deffile *defs) -{ - struct deffile *curdefs = NULL; - - while (defs != NULL) { - curdefs = defs; - defs = defs->next; - if (curdefs->line != NULL) - free(curdefs->line); - free(curdefs); - } -} - -/* - * write_default_file(fname, defs) - * - * Write the default file back. - */ - -static int -write_default_file(char *fname, struct deffile *defs) -{ - FILE *file; - int ret = SA_OK; - sigset_t old, new; - - file = fopen(fname, "w+"); - if (file != NULL) { - (void) sigprocmask(SIG_BLOCK, NULL, &new); - (void) sigaddset(&new, SIGHUP); - (void) sigaddset(&new, SIGINT); - (void) sigaddset(&new, SIGQUIT); - (void) sigaddset(&new, SIGTSTP); - (void) sigprocmask(SIG_SETMASK, &new, &old); - while (defs != NULL) { - (void) fputs(defs->line, file); - defs = defs->next; - } - (void) fsync(fileno(file)); - (void) sigprocmask(SIG_SETMASK, &old, NULL); - (void) fclose(file); - } else { - switch (errno) { - case EPERM: - case EACCES: - ret = SA_NO_PERMISSION; - break; - default: - ret = SA_SYSTEM_ERR; - } - } - return (ret); -} - - -/* - * set_default_file_value(tag, value) - * - * Set the default file value for tag to value. Then rewrite the file. - * tag and value are always set. The caller must ensure this. - */ - -#define MAX_STRING_LENGTH 256 -static int -set_default_file_value(char *tag, char *value) -{ - int ret = SA_OK; - struct deffile *root; - struct deffile *defs; - struct deffile *prev; - char string[MAX_STRING_LENGTH]; - int len; - int update = 0; - - (void) snprintf(string, MAX_STRING_LENGTH, "%s=", tag); - len = strlen(string); - - root = defs = read_default_file(NFSADMIN); - if (root == NULL) { - if (errno == EPERM || errno == EACCES) - ret = SA_NO_PERMISSION; - else - ret = SA_SYSTEM_ERR; - } else { - while (defs != NULL) { - if (defs->line != NULL && - strncasecmp(defs->line, string, len) == 0) { - /* replace with the new value */ - free(defs->line); - fixcaseupper(tag); - (void) snprintf(string, sizeof (string), "%s=%s\n", - tag, value); - string[MAX_STRING_LENGTH - 1] = '\0'; - defs->line = strdup(string); - update = 1; - break; - } - defs = defs->next; - } - if (!update) { - defs = root; - /* didn't find, so see if it is a comment */ - (void) snprintf(string, MAX_STRING_LENGTH, "#%s=", tag); - len = strlen(string); - while (defs != NULL) { - if (strncasecmp(defs->line, string, len) == 0) { - /* replace with the new value */ - free(defs->line); - fixcaseupper(tag); - (void) snprintf(string, sizeof (string), - "%s=%s\n", tag, value); - string[MAX_STRING_LENGTH - 1] = '\0'; - defs->line = strdup(string); - update = 1; - break; - } - defs = defs->next; - } - } - if (!update) { - fixcaseupper(tag); - (void) snprintf(string, sizeof (string), "%s=%s\n", - tag, value); - prev = root; - while (prev->next != NULL) - prev = prev->next; - defs = malloc(sizeof (struct deffile)); - prev->next = defs; - if (defs != NULL) { - defs->next = NULL; - defs->line = strdup(string); - } - } - if (update) { - ret = write_default_file(NFSADMIN, root); - } - free_default_file(root); - } - return (ret); -} - -/* - * service_in_state(service, chkstate) - * - * Want to know if the specified service is in the desired state - * (chkstate) or not. Return true (1) if it is and false (0) if it - * isn't. - */ -static int -service_in_state(char *service, const char *chkstate) -{ - char *state; - int ret = B_FALSE; - - state = smf_get_state(service); - if (state != NULL) { - /* got the state so get the equality for the return value */ - ret = strcmp(state, chkstate) == 0 ? B_TRUE : B_FALSE; - free(state); - } - return (ret); -} - -/* - * restart_service(svcs) - * - * Walk through the bit mask of services that need to be restarted in - * order to use the new property values. Some properties affect - * multiple daemons. Should only restart a service if it is currently - * enabled (online). - */ - -static void -restart_service(uint32_t svcs) -{ - uint32_t mask; - int ret; - char *service; - - for (mask = 1; svcs != 0; mask <<= 1) { - switch (svcs & mask) { - case SVC_LOCKD: - service = LOCKD; - break; - case SVC_STATD: - service = STATD; - break; - case SVC_NFSD: - service = NFSD; - break; - case SVC_MOUNTD: - service = MOUNTD; - break; - case SVC_NFS4CBD: - service = NFS4CBD; - break; - case SVC_NFSMAPID: - service = NFSMAPID; - break; - case SVC_RQUOTAD: - service = RQUOTAD; - break; - case SVC_NFSLOGD: - service = NFSLOGD; - break; - default: - continue; - } - - /* - * Only attempt to restart the service if it is - * currently running. In the future, it may be - * desirable to use smf_refresh_instance if the NFS - * services ever implement the refresh method. - */ - if (service_in_state(service, SCF_STATE_STRING_ONLINE)) { - ret = smf_restart_instance(service); - /* - * There are only a few SMF errors at this point, but - * it is also possible that a bad value may have put - * the service into maintenance if there wasn't an - * SMF level error. - */ - if (ret != 0) { - (void) fprintf(stderr, - gettext("%s failed to restart: %s\n"), - scf_strerror(scf_error())); - } else { - /* - * Check whether it has gone to "maintenance" - * mode or not. Maintenance implies something - * went wrong. - */ - if (service_in_state(service, SCF_STATE_STRING_MAINT)) { - (void) fprintf(stderr, - gettext("%s failed to restart\n"), - service); - } - } - } - svcs &= ~mask; - } -} - -/* - * nfs_minmax_check(name, value) - * - * Verify that the value for the property specified by index is valid - * relative to the opposite value in the case of a min/max variable. - * Currently, server_minvers/server_maxvers and - * client_minvers/client_maxvers are the only ones to check. - */ - -static int -nfs_minmax_check(int index, int value) -{ - int val; - char *pval; - sa_property_t prop; - sa_optionset_t opts; - int ret = B_TRUE; - - if (proto_options[index].other != NULL) { - /* have a property to compare against */ - opts = nfs_get_proto_set(); - prop = sa_get_property(opts, proto_options[index].other); - /* - * If we don't find the property, assume default - * values which will work since the max will be at the - * max and the min at the min. - */ - if (prop != NULL) { - pval = sa_get_property_attr(prop, "value"); - if (pval != NULL) { - val = strtoul(pval, NULL, 0); - if (proto_options[index].compare == OPT_CMP_LE) { - ret = value <= val ? B_TRUE : B_FALSE; - } else if (proto_options[index].compare == OPT_CMP_GE) { - ret = value >= val ? B_TRUE : B_FALSE; - } - } - } - } - return (ret); -} - -/* - * nfs_validate_proto_prop(index, name, value) - * - * Verify that the property specifed by name can take the new - * value. This is a sanity check to prevent bad values getting into - * the default files. All values need to be checked against what is - * allowed by their defined type. If a type isn't explicitly defined - * here, it is treated as a string. - * - * Note that OPT_TYPE_NUMBER will additionally check that the value is - * within the range specified and potentially against another property - * value as well as specified in the proto_options members other and - * compare. - */ - -static int -nfs_validate_proto_prop(int index, char *name, char *value) -{ - int ret = SA_OK; - char *cp; -#ifdef lint - name = name; -#endif - - switch (proto_options[index].type) { - case OPT_TYPE_NUMBER: - if (!is_a_number(value)) - ret = SA_BAD_VALUE; - else { - int val; - val = strtoul(value, NULL, 0); - if (val < proto_options[index].minval || - val > proto_options[index].maxval) - ret = SA_BAD_VALUE; - /* - * For server_versmin/server_versmax and - * client_versmin/client_versmax, the value of the - * min(max) should be checked to be correct relative - * to the current max(min). - */ - if (!nfs_minmax_check(index, val)) { - ret = SA_BAD_VALUE; - } - } - break; - - case OPT_TYPE_DOMAIN: - /* - * needs to be a qualified domain so will have at - * least one period and other characters on either - * side of it. A zero length string is also allowed - * and is the way to turn off the override. - */ - if (strlen(value) == 0) - break; - cp = strchr(value, '.'); - if (cp == NULL || cp == value || strchr(value, '@') != NULL) - ret = SA_BAD_VALUE; - break; - - case OPT_TYPE_BOOLEAN: - if (strlen(value) == 0 || - strcasecmp(value, "true") == 0 || - strcmp(value, "1") == 0 || - strcasecmp(value, "false") == 0 || - strcmp(value, "0") == 0) { - ret = SA_OK; - } else { - ret = SA_BAD_VALUE; - } - break; - - case OPT_TYPE_ONOFF: - if (strcasecmp(value, "on") != 0 && - strcasecmp(value, "off") != 0) { - ret = SA_BAD_VALUE; - } - break; - - case OPT_TYPE_PROTOCOL: - if (strcasecmp(value, "all") != 0 && - strcasecmp(value, "tcp") != 0 && - strcasecmp(value, "udp") != 0) - ret = SA_BAD_VALUE; - break; - - default: - /* treat as a string */ - break; - } - return (ret); -} - -/* - * nfs_set_proto_prop(prop) - * - * check that prop is valid. - */ - -static int -nfs_set_proto_prop(sa_property_t prop) -{ - int ret = SA_OK; - char *name; - char *value; - - name = sa_get_property_attr(prop, "type"); - value = sa_get_property_attr(prop, "value"); - if (name != NULL && value != NULL) { - int index = findprotoopt(name, 1); - if (index >= 0) { - /* should test for valid value */ - ret = nfs_validate_proto_prop(index, name, value); - if (ret == SA_OK) - ret = set_default_file_value(proto_options[index].tag, - value); - if (ret == SA_OK) - restart_service(proto_options[index].svcs); - } - } - if (name != NULL) - sa_free_attr_string(name); - if (value != NULL) - sa_free_attr_string(value); - return (ret); -} - -/* - * nfs_get_status() - * - * What is the current status of the nfsd? We use the SMF state here. - * Caller must free the returned value. - */ - -static char * -nfs_get_status() -{ - char *state; - state = smf_get_state(NFSD); - return (state != NULL ? state : strdup("-")); -} - -/* - * nfs_space_alias(alias) - * - * Lookup the space (security) name. If it is default, convert to the - * real name. - */ - -static char * -nfs_space_alias(char *space) -{ - char *name = space; - seconfig_t secconf; - - /* - * Only the space named "default" is special. If it is used, - * the default needs to be looked up and the real name used. - * This is normally "sys" but could be changed. We always - * change defautl to the real name. - */ - if (strcmp(space, "default") == 0 && - nfs_getseconfig_default(&secconf) == 0) { - if (nfs_getseconfig_bynumber(secconf.sc_nfsnum, &secconf) == 0) - name = secconf.sc_name; - } - return (strdup(name)); -} diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/plugins/libshare_nfs.h --- a/usr/src/cmd/dfs.cmds/sharemgr/plugins/libshare_nfs.h Wed Mar 28 07:55:32 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * basic API declarations for share management - */ - -#ifndef _LIBSHARE_NFS_H -#define _LIBSHARE_NFS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* property names used by NFS */ -#define SHOPT_RO "ro" -#define SHOPT_RW "rw" - -#define SHOPT_SEC "sec" -#define SHOPT_SECURE "secure" -#define SHOPT_ROOT "root" -#define SHOPT_ANON "anon" -#define SHOPT_WINDOW "window" -#define SHOPT_NOSUB "nosub" -#define SHOPT_NOSUID "nosuid" -#define SHOPT_ACLOK "aclok" -#define SHOPT_PUBLIC "public" -#define SHOPT_INDEX "index" -#define SHOPT_LOG "log" -#define SHOPT_CKSUM "cksum" - -/* - * defined options types. These should be in a file rather than - * compiled in. Until there is a plugin mechanism to add new types, - * this is sufficient. - */ -#define OPT_TYPE_ANY 0 -#define OPT_TYPE_STRING 1 -#define OPT_TYPE_BOOLEAN 2 -#define OPT_TYPE_NUMBER 3 -#define OPT_TYPE_RANGE 4 -#define OPT_TYPE_USER 5 -#define OPT_TYPE_ACCLIST 6 -#define OPT_TYPE_DEPRECATED 7 -#define OPT_TYPE_SECURITY 8 -#define OPT_TYPE_PATH 9 -#define OPT_TYPE_FILE 10 -#define OPT_TYPE_LOGTAG 11 -#define OPT_TYPE_STRINGSET 12 -#define OPT_TYPE_DOMAIN 13 -#define OPT_TYPE_ONOFF 14 -#define OPT_TYPE_PROTOCOL 15 - -#define OPT_SHARE_ONLY 1 - -struct option_defs { - char *tag; - int index; - int type; - int share; /* share only option */ - int (*check)(char *); -}; - -/* - * service bit mask values - */ -#define SVC_LOCKD 0x0001 -#define SVC_STATD 0x0002 -#define SVC_NFSD 0x0004 -#define SVC_MOUNTD 0x0008 -#define SVC_NFS4CBD 0x0010 -#define SVC_NFSMAPID 0x0020 -#define SVC_RQUOTAD 0x0040 -#define SVC_NFSLOGD 0x0080 - -/* - * place holder for future service -- will move to daemon_utils.h when - * fully implemented. - */ -#define NFSLOGD "svc:/network/nfs/log:default" - -/* The NFS export structure flags for read/write modes */ -#define NFS_RWMODES (M_RO|M_ROL|M_RW|M_RWL) - -/* other values */ -/* max size of 64-bit integer in digits plus a bit extra */ -#define MAXDIGITS 32 - -/* external variable */ -extern boolean_t nfsl_errs_to_syslog; - -/* imported functions */ -extern int exportfs(char *, struct exportdata *); -extern void _check_services(char **); -extern int nfs_getseconfig_default(seconfig_t *); -extern int nfs_getseconfig_byname(char *, seconfig_t *); -extern bool_t nfs_get_root_principal(seconfig_t *, char *, caddr_t *); -extern int nfsl_getconfig_list(nfsl_config_t **); -extern void nfsl_freeconfig_list(nfsl_config_t **); -extern nfsl_config_t *nfsl_findconfig(nfsl_config_t *, char *, int *); - -#ifdef __cplusplus -} -#endif - -#endif /* _LIBSHARE_NFS_H */ diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/plugins/sparc/Makefile --- a/usr/src/cmd/dfs.cmds/sharemgr/plugins/sparc/Makefile Wed Mar 28 07:55:32 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include ../Makefile.com - -install: all diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/sharemgr.h --- a/usr/src/cmd/dfs.cmds/sharemgr/sharemgr.h Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/cmd/dfs.cmds/sharemgr/sharemgr.h Wed Mar 28 08:50:43 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,6 +32,7 @@ #ifdef __cplusplus extern "C" { #endif +#include /* * shareadm internal interfaces @@ -68,7 +69,7 @@ typedef struct sa_command { char *cmdname; int flags; - int (*cmdfunc)(int, int, char **); + int (*cmdfunc)(sa_handle_t, int, int, char **); int cmdidx; int priv; /* requires RBAC authorizations */ } sa_command_t; @@ -107,7 +108,7 @@ }; /* shareutil entry points */ - extern int add_opt(struct options **, char *, int); +extern int add_opt(struct options **, char *, int); #ifdef __cplusplus diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/sharemgr_main.c --- a/usr/src/cmd/dfs.cmds/sharemgr/sharemgr_main.c Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/cmd/dfs.cmds/sharemgr/sharemgr_main.c Wed Mar 28 08:50:43 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,7 +42,7 @@ char *protocol = NULL; static int help = 0; -static int run_command(char *, int, char **, char *); +static int run_command(char *, int, char **, char *, sa_handle_t); extern sa_command_t *sa_lookup(char *, char *); extern void sub_command_help(char *proto); @@ -59,6 +59,7 @@ int c; int rval; char *command = NULL; + sa_handle_t handle; /* * make sure locale and gettext domain is setup @@ -109,21 +110,22 @@ */ optind = 1; - sa_init(SA_INIT_SHARE_API); + handle = sa_init(SA_INIT_SHARE_API); /* * reset optind again since we will start parsing all over in * the sub-commands. */ optind = 1; - rval = run_command(command, argc, argv, protocol); + rval = run_command(command, argc, argv, protocol, handle); - sa_fini(); + sa_fini(handle); return (rval); } static int -run_command(char *command, int argc, char *argv[], char *proto) +run_command(char *command, int argc, char *argv[], char *proto, + sa_handle_t handle) { sa_command_t *cmdvec; int ret; @@ -154,6 +156,6 @@ * based on least priviledge and sub-command so pass this in * as a flag. */ - ret = cmdvec->cmdfunc(cmdvec->priv, argc, argv); + ret = cmdvec->cmdfunc(handle, cmdvec->priv, argc, argv); return (ret); } diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/sparc/Makefile --- a/usr/src/cmd/dfs.cmds/sharemgr/sparc/Makefile Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/cmd/dfs.cmds/sharemgr/sparc/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -21,10 +21,10 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../Makefile.com -install: all +install: all $(ROOTUSRSBINPROG32) $(ROOTLINKS) diff -r 9f4024db0edf -r 00586900e34c usr/src/cmd/dfs.cmds/sharemgr/sparcv9/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/dfs.cmds/sharemgr/sparcv9/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../../Makefile.cmd.64 + +install: all $(ROOTUSRSBINPROG64) diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/Makefile --- a/usr/src/lib/libshare/Makefile Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -27,9 +27,18 @@ include ../Makefile.lib -HDRS = libshare.h +HDRS = libshare.h libshare_impl.h scfutil.h HDRDIR = common -SUBDIRS = $(MACH) + +MACHS = $(MACH) +$(BUILD64)MACHS += $(MACH64) + +# Add plugin module directories here. They need to build after the libshare +# objects are built. +PLUGINS = nfs +$(PLUGINS): $(MACHS) + +SUBDIRS = $(MACHS) $(PLUGINS) MSGFILES= common/libshare.c common/libsharecore.c common/scfutil.c \ common/plugin.c common/parser.c common/libshare_zfs.c diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/Makefile.com --- a/usr/src/lib/libshare/Makefile.com Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/Makefile.com Wed Mar 28 08:50:43 2007 -0700 @@ -47,8 +47,7 @@ #add nfs/lib directory as part of the include path CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT -I$(NFSLIB_DIR) -I/usr/include/libxml2 \ - -I$(SRCDIR) +CPPFLAGS += -D_REENTRANT -I$(NFSLIB_DIR) -I/usr/include/libxml2 .KEEP_STATE: diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/amd64/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/amd64/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/libshare.c --- a/usr/src/lib/libshare/common/libshare.c Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/libshare.c Wed Mar 28 08:50:43 2007 -0700 @@ -44,6 +44,8 @@ #include "scfutil.h" #include #include +#include +#include #if _NOT_SMF #define CONFIG_FILE "/var/tmp/share.cfg" @@ -58,14 +60,11 @@ * internal data structures */ -static xmlNodePtr sa_config_tree; /* the current config */ -static xmlDocPtr sa_config_doc = NULL; /* current config document */ extern struct sa_proto_plugin *sap_proto_list; /* current SMF/SVC repository handle */ -static scfutilhandle_t *scf_handle = NULL; -extern void getlegacyconfig(char *, xmlNodePtr *); -extern int gettransients(xmlNodePtr *); +extern void getlegacyconfig(sa_handle_t, char *, xmlNodePtr *); +extern int gettransients(sa_handle_impl_t, xmlNodePtr *); extern int sa_valid_property(void *, char *, sa_property_t); extern char *sa_fstype(char *); extern int sa_is_share(void *); @@ -73,17 +72,37 @@ extern int sa_group_is_zfs(sa_group_t); extern int sa_path_is_zfs(char *); extern int sa_zfs_set_sharenfs(sa_group_t, char *, int); -extern void update_legacy_config(void); +extern void update_legacy_config(sa_handle_t); extern int issubdir(char *, char *); -extern void sa_zfs_init(void); -extern void sa_zfs_fini(void); +extern void sa_zfs_init(sa_handle_impl_t); +extern void sa_zfs_fini(sa_handle_impl_t); extern void sablocksigs(sigset_t *); extern void saunblocksigs(sigset_t *); -static int sa_initialized = 0; +/* + * Data structures for finding/managing the document root to access + * handle mapping. The list isn't expected to grow very large so a + * simple list is acceptable. The purpose is to provide a way to start + * with a group or share and find the library handle needed for + * various operations. + */ +mutex_t sa_global_lock; +struct doc2handle { + struct doc2handle *next; + xmlNodePtr root; + sa_handle_impl_t handle; +}; + +static struct doc2handle *sa_global_handles = NULL; /* helper functions */ +/* + * sa_errorstr(err) + * + * convert an error value to an error string + */ + char * sa_errorstr(int err) { @@ -172,6 +191,102 @@ } /* + * Document root to active handle mapping functions. These are only + * used internally. A mutex is used to prevent access while the list + * is changing. In general, the list will be relatively short - one + * item per thread that has called sa_init(). + */ + +sa_handle_impl_t +get_handle_for_root(xmlNodePtr root) +{ + struct doc2handle *item; + + (void) mutex_lock(&sa_global_lock); + for (item = sa_global_handles; item != NULL; item = item->next) { + if (item->root == root) + break; + } + (void) mutex_unlock(&sa_global_lock); + if (item != NULL) + return (item->handle); + return (NULL); +} + +static int +add_handle_for_root(xmlNodePtr root, sa_handle_impl_t handle) +{ + struct doc2handle *item; + int ret = SA_NO_MEMORY; + + item = (struct doc2handle *)calloc(sizeof (struct doc2handle), 1); + if (item != NULL) { + item->root = root; + item->handle = handle; + (void) mutex_lock(&sa_global_lock); + item->next = sa_global_handles; + sa_global_handles = item; + (void) mutex_unlock(&sa_global_lock); + ret = SA_OK; + } + return (ret); +} + +/* + * remove_handle_for_root(root) + * + * Walks the list of handles and removes the one for this "root" from + * the list. It is up to the caller to free the data. + */ + +static void +remove_handle_for_root(xmlNodePtr root) +{ + struct doc2handle *item, *prev; + + (void) mutex_lock(&sa_global_lock); + for (prev = NULL, item = sa_global_handles; item != NULL; + item = item->next) { + if (item->root == root) { + if (prev == NULL) { + /* first in the list */ + sa_global_handles = sa_global_handles->next; + } else { + prev->next = item->next; + } + /* Item is out of the list so free the list structure */ + free(item); + break; + } + prev = item; + } + (void) mutex_unlock(&sa_global_lock); +} + +/* + * sa_find_group_handle(sa_group_t group) + * + * Find the sa_handle_t for the configuration associated with this + * group. + */ +sa_handle_t +sa_find_group_handle(sa_group_t group) +{ + xmlNodePtr node = (xmlNodePtr)group; + sa_handle_t handle; + + while (node != NULL) { + if (strcmp((char *)(node->name), "sharecfg") == 0) { + /* have the root so get the handle */ + handle = (sa_handle_t)get_handle_for_root(node); + return (handle); + } + node = node->parent; + } + return (NULL); +} + +/* * set_legacy_timestamp(root, path, timevalue) * * add the current timestamp value to the configuration for use in @@ -184,6 +299,12 @@ { xmlNodePtr node; xmlChar *lpath = NULL; + sa_handle_impl_t handle; + + /* Have to have a handle or else we weren't initialized. */ + handle = get_handle_for_root(root); + if (handle == NULL) + return; for (node = root->xmlChildrenNode; node != NULL; node = node->next) { @@ -210,16 +331,16 @@ xmlSetProp(node, (xmlChar *)"timestamp", (xmlChar *)tstring); xmlSetProp(node, (xmlChar *)"path", (xmlChar *)path); /* now commit to SMF */ - ret = sa_get_instance(scf_handle, "default"); + ret = sa_get_instance(handle->scfhandle, "default"); if (ret == SA_OK) { - ret = sa_start_transaction(scf_handle, "operation"); + ret = sa_start_transaction(handle->scfhandle, "operation"); if (ret == SA_OK) { - ret = sa_set_property(scf_handle, "legacy-timestamp", + ret = sa_set_property(handle->scfhandle, "legacy-timestamp", tstring); if (ret == SA_OK) { - (void) sa_end_transaction(scf_handle); + (void) sa_end_transaction(handle->scfhandle); } else { - sa_abort_transaction(scf_handle); + sa_abort_transaction(handle->scfhandle); } } } @@ -314,13 +435,13 @@ * and those * stored in the repository */ static int -checksubdir(char *newpath, int strictness) +checksubdir(sa_handle_t handle, char *newpath, int strictness) { sa_group_t group; int issub; char *path = NULL; - for (issub = 0, group = sa_get_group(NULL); + for (issub = 0, group = sa_get_group(handle, NULL); group != NULL && !issub; group = sa_get_next_group(group)) { if (sa_group_is_zfs(group)) { @@ -345,7 +466,7 @@ * share path. */ static int -validpath(char *path, int strictness) +validpath(sa_handle_t handle, char *path, int strictness) { int error = SA_OK; struct stat st; @@ -358,7 +479,7 @@ if (stat(path, &st) < 0) { error = SA_NO_SUCH_PATH; } else { - share = sa_find_share(path); + share = sa_find_share(handle, path); if (share != NULL) { error = SA_DUPLICATE_NAME; } @@ -373,14 +494,14 @@ */ fstype = sa_fstype(path); if (fstype != NULL && strcmp(fstype, "zfs") == 0) { - if (sa_zfs_is_shared(path)) + if (sa_zfs_is_shared(handle, path)) error = SA_INVALID_NAME; } if (fstype != NULL) sa_free_fstype(fstype); } if (error == SA_OK) { - error = checksubdir(path, strictness); + error = checksubdir(handle, path, strictness); } } return (error); @@ -531,7 +652,7 @@ * read in the current configuration */ -void +sa_handle_t sa_init(int init_service) { struct stat st; @@ -541,8 +662,12 @@ sigset_t old; int updatelegacy = B_FALSE; scf_simple_prop_t *prop; + sa_handle_impl_t handle; + int err; - if (!sa_initialized) { + handle = calloc(sizeof (struct sa_handle_impl), 1); + + if (handle != NULL) { /* get protocol specific structures */ (void) proto_plugin_init(); if (init_service & SA_INIT_SHARE_API) { @@ -550,13 +675,13 @@ * initialize access into libzfs. We use this when * collecting info about ZFS datasets and shares. */ - sa_zfs_init(); + sa_zfs_init(handle); /* * since we want to use SMF, initialize an svc handle * and find out what is there. */ - scf_handle = sa_scf_init(); - if (scf_handle != NULL) { + handle->scfhandle = sa_scf_init(handle); + if (handle->scfhandle != NULL) { /* * Need to lock the extraction of the * configuration if the dfstab file has @@ -585,7 +710,7 @@ * lock will make any changes before the * others can read the repository. */ - prop = scf_simple_prop_get(scf_handle->handle, + prop = scf_simple_prop_get(handle->scfhandle->handle, (const char *) SA_SVC_FMRI_BASE ":default", "operation", @@ -610,14 +735,28 @@ (void) lockf(lockfd, F_ULOCK, 0); (void) close(lockfd); } - (void) sa_get_config(scf_handle, &sa_config_tree, - &sa_config_doc); + (void) sa_get_config(handle->scfhandle, &handle->tree, + &handle->doc, handle); + /* need to setup for later searchs when using group/share */ + err = add_handle_for_root(handle->tree, handle); saunblocksigs(&old); + + if (err != SA_OK) { + /* + * If we couldn't add the tree handle to the + * list, then things are going to fail + * badly. Might as well undo everything now + * and fail the sa_init(). + */ + sa_fini(handle); + return (NULL); + } + if (tval == 0) { /* first time so make sure default is setup */ sa_group_t defgrp; sa_optionset_t opt; - defgrp = sa_get_group("default"); + defgrp = sa_get_group(handle, "default"); if (defgrp != NULL) { opt = sa_get_optionset(defgrp, NULL); if (opt == NULL) @@ -627,9 +766,10 @@ } if (updatelegacy == B_TRUE) { sablocksigs(&old); - getlegacyconfig(SA_LEGACY_DFSTAB, &sa_config_tree); + getlegacyconfig((sa_handle_t)handle, + SA_LEGACY_DFSTAB, &handle->tree); if (stat(SA_LEGACY_DFSTAB, &st) >= 0) - set_legacy_timestamp(sa_config_tree, + set_legacy_timestamp(handle->tree, SA_LEGACY_DFSTAB, TSTAMP(st.st_ctim)); saunblocksigs(&old); @@ -637,32 +777,48 @@ (void) lockf(lockfd, F_ULOCK, 0); (void) close(lockfd); } - legacy |= sa_get_zfs_shares("zfs"); - legacy |= gettransients(&sa_config_tree); + legacy |= sa_get_zfs_shares(handle, "zfs"); + legacy |= gettransients(handle, &handle->tree); } } } + return ((sa_handle_t)handle); } /* - * sa_fini() + * sa_fini(handle) * Uninitialize the API structures including the configuration * data structures and ZFS related data. */ void -sa_fini() +sa_fini(sa_handle_t handle) { - if (sa_initialized) { - /* free the config trees */ - sa_initialized = 0; - if (sa_config_doc != NULL) - xmlFreeDoc(sa_config_doc); - sa_config_tree = NULL; - sa_config_doc = NULL; - sa_scf_fini(scf_handle); - sa_zfs_fini(); - (void) proto_plugin_init(); + sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle; + + if (impl_handle != NULL) { + /* + * Free the config trees and any other data structures + * used in the handle. + */ + if (impl_handle->doc != NULL) + xmlFreeDoc(impl_handle->doc); + sa_scf_fini(impl_handle->scfhandle); + sa_zfs_fini(impl_handle); + + /* Remove and free the entry in the global list. */ + remove_handle_for_root(impl_handle->tree); + + /* Make sure we free the handle */ + free(impl_handle); + + /* + * If this was the last handle to release, unload the + * plugins that were loaded. + */ + if (sa_global_handles == NULL) + (void) proto_plugin_fini(); + } } @@ -744,27 +900,28 @@ * return the first group of the list of groups. */ sa_group_t -sa_get_group(char *groupname) +sa_get_group(sa_handle_t handle, char *groupname) { xmlNodePtr node = NULL; char *subgroup = NULL; char *group = NULL; + sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle; - if (sa_config_tree != NULL) { + if (impl_handle != NULL && impl_handle->tree != NULL) { if (groupname != NULL) { group = strdup(groupname); subgroup = strchr(group, '/'); if (subgroup != NULL) *subgroup++ = '\0'; } - node = find_group_by_name(sa_config_tree, (xmlChar *)group); + node = find_group_by_name(impl_handle->tree, (xmlChar *)group); /* if a subgroup, find it before returning */ if (subgroup != NULL && node != NULL) { node = find_group_by_name(node, (xmlChar *)subgroup); } } if (node != NULL && (char *)group != NULL) - (void) sa_get_instance(scf_handle, (char *)group); + (void) sa_get_instance(impl_handle->scfhandle, (char *)group); if (group != NULL) free(group); return ((sa_group_t)(node)); @@ -918,14 +1075,14 @@ * resource names comes into being. */ sa_share_t -sa_find_share(char *sharepath) +sa_find_share(sa_handle_t handle, char *sharepath) { sa_group_t group; sa_group_t zgroup; sa_share_t share = NULL; int done = 0; - for (group = sa_get_group(NULL); group != NULL && !done; + for (group = sa_get_group(handle, NULL); group != NULL && !done; group = sa_get_next_group(group)) { if (is_zfs_group(group)) { for (zgroup = (sa_group_t)_sa_get_child_node((xmlNodePtr)group, @@ -959,10 +1116,10 @@ int sa_check_path(sa_group_t group, char *path, int strictness) { -#ifdef lint - group = group; -#endif - return (validpath(path, strictness)); + sa_handle_t handle; + + handle = sa_find_group_handle(group); + return (validpath(handle, path, strictness)); } /* @@ -998,8 +1155,13 @@ if (sa_group_is_zfs(group) && sa_path_is_zfs(sharepath)) { err = sa_zfs_set_sharenfs(group, sharepath, 1); } else { - err = sa_commit_share(scf_handle, group, + sa_handle_impl_t impl_handle; + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) + err = sa_commit_share(impl_handle->scfhandle, group, (sa_share_t)node); + else + err = SA_SYSTEM_ERR; } } if (err == SA_NO_PERMISSION && persist & SA_SHARE_PARSER) { @@ -1038,6 +1200,7 @@ xmlNodePtr node = NULL; sa_share_t dup; int strictness = SA_CHECK_NORMAL; + sa_handle_t handle; /* * If the share is to be permanent, use strict checking so a @@ -1052,7 +1215,9 @@ if (persist & SA_SHARE_PARSER || persist == SA_SHARE_PERMANENT) strictness = SA_CHECK_STRICT; - if ((dup = sa_find_share(sharepath)) == NULL && + handle = sa_find_group_handle(group); + + if ((dup = sa_find_share(handle, sharepath)) == NULL && (*error = sa_check_path(group, sharepath, strictness)) == SA_OK) { node = _sa_add_share(group, sharepath, persist, error); @@ -1163,7 +1328,13 @@ ret = sa_delete_legacy(share); if (ret == SA_OK) { if (!sa_group_is_zfs(group)) { - ret = sa_delete_share(scf_handle, group, share); + sa_handle_impl_t impl_handle; + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) + ret = sa_delete_share(impl_handle->scfhandle, + group, share); + else + ret = SA_SYSTEM_ERR; } else { char *sharepath = sa_get_share_attr(share, "path"); if (sharepath != NULL) { @@ -1200,20 +1371,25 @@ oldgroup = sa_get_parent_group(share); if (oldgroup != group) { + sa_handle_impl_t impl_handle; xmlUnlinkNode((xmlNodePtr)share); /* now that the share isn't in its old group, add to the new one */ xmlAddChild((xmlNodePtr)group, (xmlNodePtr)share); /* need to deal with SMF */ - if (ret == SA_OK) { + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) { /* * need to remove from old group first and then add to * new group. Ideally, we would do the other order but * need to avoid having the share in two groups at the * same time. */ - ret = sa_delete_share(scf_handle, oldgroup, share); + ret = sa_delete_share(impl_handle->scfhandle, oldgroup, share); + if (ret == SA_OK) + ret = sa_commit_share(impl_handle->scfhandle, group, share); + } else { + ret = SA_SYSTEM_ERR; } - ret = sa_commit_share(scf_handle, group, share); } return (ret); } @@ -1244,19 +1420,19 @@ } /* - * _sa_create_group(groupname) + * _sa_create_group(impl_handle, groupname) * * Create a group in the document. The caller will need to deal with * configuration store and activation. */ sa_group_t -_sa_create_group(char *groupname) +_sa_create_group(sa_handle_impl_t impl_handle, char *groupname) { xmlNodePtr node = NULL; if (sa_valid_group_name(groupname)) { - node = xmlNewChild(sa_config_tree, NULL, + node = xmlNewChild(impl_handle->tree, NULL, (xmlChar *)"group", NULL); if (node != NULL) { xmlSetProp(node, (xmlChar *)"name", (xmlChar *)groupname); @@ -1298,64 +1474,68 @@ * (via the SMF transaction model). */ sa_group_t -sa_create_group(char *groupname, int *error) +sa_create_group(sa_handle_t handle, char *groupname, int *error) { xmlNodePtr node = NULL; sa_group_t group; int ret; char rbacstr[256]; + sa_handle_impl_t impl_handle = (sa_handle_impl_t)handle; ret = SA_OK; - if (scf_handle == NULL) { + if (impl_handle == NULL || impl_handle->scfhandle == NULL) { ret = SA_SYSTEM_ERR; goto err; } - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group != NULL) { ret = SA_DUPLICATE_NAME; } else { if (sa_valid_group_name(groupname)) { - node = xmlNewChild(sa_config_tree, NULL, + node = xmlNewChild(impl_handle->tree, NULL, (xmlChar *)"group", NULL); if (node != NULL) { xmlSetProp(node, (xmlChar *)"name", (xmlChar *)groupname); /* default to the group being enabled */ xmlSetProp(node, (xmlChar *)"state", (xmlChar *)"enabled"); - ret = sa_create_instance(scf_handle, groupname); + ret = sa_create_instance(impl_handle->scfhandle, groupname); if (ret == SA_OK) { - ret = sa_start_transaction(scf_handle, "operation"); + ret = sa_start_transaction(impl_handle->scfhandle, + "operation"); } if (ret == SA_OK) { - ret = sa_set_property(scf_handle, "state", "enabled"); + ret = sa_set_property(impl_handle->scfhandle, + "state", "enabled"); if (ret == SA_OK) { - ret = sa_end_transaction(scf_handle); + ret = sa_end_transaction(impl_handle->scfhandle); } else { - sa_abort_transaction(scf_handle); + sa_abort_transaction(impl_handle->scfhandle); } } if (ret == SA_OK) { /* initialize the RBAC strings */ - ret = sa_start_transaction(scf_handle, "general"); + ret = sa_start_transaction(impl_handle->scfhandle, + "general"); if (ret == SA_OK) { (void) snprintf(rbacstr, sizeof (rbacstr), "%s.%s", SA_RBAC_MANAGE, groupname); - ret = sa_set_property(scf_handle, + ret = sa_set_property(impl_handle->scfhandle, "action_authorization", rbacstr); } if (ret == SA_OK) { (void) snprintf(rbacstr, sizeof (rbacstr), "%s.%s", SA_RBAC_VALUE, groupname); - ret = sa_set_property(scf_handle, + ret = sa_set_property(impl_handle->scfhandle, "value_authorization", rbacstr); } if (ret == SA_OK) { - ret = sa_end_transaction(scf_handle); + ret = sa_end_transaction(impl_handle->scfhandle); } else { - sa_abort_transaction(scf_handle); + sa_abort_transaction(impl_handle->scfhandle); } } if (ret != SA_OK) { @@ -1392,14 +1572,20 @@ { char *name; int ret = SA_OK; + sa_handle_impl_t impl_handle; - name = sa_get_group_attr(group, "name"); - if (name != NULL) { - ret = sa_delete_instance(scf_handle, name); - sa_free_attr_string(name); + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) { + name = sa_get_group_attr(group, "name"); + if (name != NULL) { + ret = sa_delete_instance(impl_handle->scfhandle, name); + sa_free_attr_string(name); + } + xmlUnlinkNode((xmlNodePtr)group); /* make sure unlinked */ + xmlFreeNode((xmlNodePtr)group); /* now it is gone */ + } else { + ret = SA_SYSTEM_ERR; } - xmlUnlinkNode((xmlNodePtr)group); /* make sure unlinked */ - xmlFreeNode((xmlNodePtr)group); /* now it is gone */ return (ret); } @@ -1412,14 +1598,14 @@ */ int -sa_update_config() +sa_update_config(sa_handle_t handle) { /* * do legacy files first so we can tell when they change. * This will go away when we start updating individual records * rather than the whole file. */ - update_legacy_config(); + update_legacy_config(handle); return (SA_OK); } @@ -1490,23 +1676,29 @@ { int ret; char *groupname; + sa_handle_impl_t impl_handle; - groupname = sa_get_group_attr(group, "name"); - ret = sa_get_instance(scf_handle, groupname); - if (ret == SA_OK) { - set_node_attr((void *)group, tag, value); - ret = sa_start_transaction(scf_handle, "operation"); + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) { + groupname = sa_get_group_attr(group, "name"); + ret = sa_get_instance(impl_handle->scfhandle, groupname); if (ret == SA_OK) { - ret = sa_set_property(scf_handle, tag, value); - if (ret == SA_OK) - (void) sa_end_transaction(scf_handle); - else { - sa_abort_transaction(scf_handle); + set_node_attr((void *)group, tag, value); + ret = sa_start_transaction(impl_handle->scfhandle, "operation"); + if (ret == SA_OK) { + ret = sa_set_property(impl_handle->scfhandle, tag, value); + if (ret == SA_OK) + (void) sa_end_transaction(impl_handle->scfhandle); + else { + sa_abort_transaction(impl_handle->scfhandle); + } } } + if (groupname != NULL) + sa_free_attr_string(groupname); + } else { + ret = SA_SYSTEM_ERR; } - if (groupname != NULL) - sa_free_attr_string(groupname); return (ret); } @@ -1609,8 +1801,15 @@ char *type; /* we can probably optimize this some */ type = sa_get_share_attr(share, "type"); - if (type == NULL || strcmp(type, "transient") != 0) - ret = sa_commit_share(scf_handle, group, share); + if (type == NULL || strcmp(type, "transient") != 0) { + sa_handle_impl_t impl_handle; + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) + ret = sa_commit_share(impl_handle->scfhandle, + group, share); + else + ret = SA_SYSTEM_ERR; + } if (type != NULL) sa_free_attr_string(type); } @@ -1894,8 +2093,14 @@ xmlUnlinkNode(node); xmlFreeNode(node); } - if (group != NULL && is_persistent((sa_group_t)share)) - ret = sa_commit_share(scf_handle, group, share); + if (group != NULL && is_persistent((sa_group_t)share)) { + sa_handle_impl_t impl_handle; + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) + ret = sa_commit_share(impl_handle->scfhandle, group, share); + else + ret = SA_SYSTEM_ERR; + } return (ret); } @@ -1998,10 +2203,17 @@ sizeof (oname), id); groupname = sa_get_group_attr(parent, "name"); if (groupname != NULL && is_persistent(group)) { - (void) sa_get_instance(scf_handle, groupname); - sa_free_attr_string(groupname); - (void) sa_create_pgroup(scf_handle, oname); + sa_handle_impl_t impl_handle; + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + assert(impl_handle != NULL); + if (impl_handle != NULL) { + (void) sa_get_instance(impl_handle->scfhandle, + groupname); + (void) sa_create_pgroup(impl_handle->scfhandle, oname); + } } + if (groupname != NULL) + sa_free_attr_string(groupname); if (id != NULL) sa_free_attr_string(id); } @@ -2097,6 +2309,7 @@ int zfs = 0; int needsupdate = 0; int ret = SA_OK; + sa_handle_impl_t impl_handle; group = sa_get_optionset_parent(optionset); if (group != NULL && (sa_is_share(group) || is_zfs_group(group))) { @@ -2113,10 +2326,15 @@ if (!clear && needsupdate) ret = sa_zfs_update((sa_share_t)group); } else { - if (clear) - (void) sa_abort_transaction(scf_handle); - else - ret = sa_end_transaction(scf_handle); + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) { + if (clear) + (void) sa_abort_transaction(impl_handle->scfhandle); + else + ret = sa_end_transaction(impl_handle->scfhandle); + } else { + ret = SA_SYSTEM_ERR; + } } return (ret); } @@ -2145,9 +2363,15 @@ id = sa_get_share_attr((sa_share_t)group, "id"); } if (ispersist) { + sa_handle_impl_t impl_handle; len = sa_optionset_name(optionset, name, sizeof (name), id); - if (len > 0) { - ret = sa_delete_pgroup(scf_handle, name); + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) { + if (len > 0) { + ret = sa_delete_pgroup(impl_handle->scfhandle, name); + } + } else { + ret = SA_SYSTEM_ERR; } } xmlUnlinkNode((xmlNodePtr)optionset); @@ -2209,8 +2433,15 @@ (void) sa_security_name(security, oname, sizeof (oname), id); if (groupname != NULL && is_persistent(group)) { - (void) sa_get_instance(scf_handle, groupname); - (void) sa_create_pgroup(scf_handle, oname); + sa_handle_impl_t impl_handle; + impl_handle = + (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) { + (void) sa_get_instance(impl_handle->scfhandle, + groupname); + (void) sa_create_pgroup(impl_handle->scfhandle, + oname); + } } } } @@ -2250,7 +2481,13 @@ if (ispersist) { len = sa_security_name(security, name, sizeof (name), id); if (!iszfs && len > 0) { - ret = sa_delete_pgroup(scf_handle, name); + sa_handle_impl_t impl_handle; + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) { + ret = sa_delete_pgroup(impl_handle->scfhandle, name); + } else { + ret = SA_SYSTEM_ERR; + } } } xmlUnlinkNode((xmlNodePtr)security); @@ -2326,6 +2563,8 @@ int iszfs = 0; int isshare = 0; sa_group_t parent = NULL; + sa_handle_impl_t impl_handle; + scfutilhandle_t *scf_handle; if (!is_persistent(group)) { /* @@ -2334,6 +2573,11 @@ */ return (SA_OK); } + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle == NULL || impl_handle->scfhandle == NULL) { + return (SA_SYSTEM_ERR); + } + scf_handle = impl_handle->scfhandle; name = sa_get_property_attr(prop, "type"); valstr = sa_get_property_attr(prop, "value"); entry = scf_entry_create(scf_handle->handle); @@ -2350,68 +2594,68 @@ iszfs = is_zfs_group(group); } if (!iszfs) { - if (scf_handle->trans == NULL) { - char oname[256]; - char *groupname = NULL; - if (isshare) { - if (parent != NULL) { - groupname = sa_get_group_attr(parent, "name"); + if (scf_handle->trans == NULL) { + char oname[256]; + char *groupname = NULL; + if (isshare) { + if (parent != NULL) { + groupname = sa_get_group_attr(parent, "name"); + } + id = sa_get_share_attr((sa_share_t)group, "id"); + } else { + groupname = sa_get_group_attr(group, "name"); } - id = sa_get_share_attr((sa_share_t)group, "id"); - } else { - groupname = sa_get_group_attr(group, "name"); - } - if (groupname != NULL) { - ret = sa_get_instance(scf_handle, groupname); - sa_free_attr_string(groupname); - } - if (opttype) - (void) sa_optionset_name(optionset, oname, + if (groupname != NULL) { + ret = sa_get_instance(scf_handle, groupname); + sa_free_attr_string(groupname); + } + if (opttype) + (void) sa_optionset_name(optionset, oname, sizeof (oname), id); - else - (void) sa_security_name(optionset, oname, + else + (void) sa_security_name(optionset, oname, sizeof (oname), id); - ret = sa_start_transaction(scf_handle, oname); - } - if (ret == SA_OK) { - switch (type) { - case SA_PROP_OP_REMOVE: - ret = scf_transaction_property_delete(scf_handle->trans, - entry, - name); - break; - case SA_PROP_OP_ADD: - case SA_PROP_OP_UPDATE: - value = scf_value_create(scf_handle->handle); - if (value != NULL) { - if (type == SA_PROP_OP_ADD) - ret = scf_transaction_property_new( - scf_handle->trans, - entry, - name, - SCF_TYPE_ASTRING); - else - ret = scf_transaction_property_change( - scf_handle->trans, - entry, - name, - SCF_TYPE_ASTRING); - if (ret == 0) { - ret = scf_value_set_astring(value, valstr); - if (ret == 0) - ret = scf_entry_add_value(entry, value); - if (ret != 0) { - scf_value_destroy(value); + ret = sa_start_transaction(scf_handle, oname); + } + if (ret == SA_OK) { + switch (type) { + case SA_PROP_OP_REMOVE: + ret = scf_transaction_property_delete( + scf_handle->trans, + entry, name); + break; + case SA_PROP_OP_ADD: + case SA_PROP_OP_UPDATE: + value = scf_value_create(scf_handle->handle); + if (value != NULL) { + if (type == SA_PROP_OP_ADD) + ret = scf_transaction_property_new( + scf_handle->trans, + entry, + name, + SCF_TYPE_ASTRING); + else + ret = scf_transaction_property_change( + scf_handle->trans, + entry, + name, + SCF_TYPE_ASTRING); + if (ret == 0) { + ret = scf_value_set_astring(value, valstr); + if (ret == 0) + ret = scf_entry_add_value(entry, value); + if (ret != 0) { + scf_value_destroy(value); + ret = SA_SYSTEM_ERR; + } + } else { + scf_entry_destroy(entry); ret = SA_SYSTEM_ERR; } - } else { - scf_entry_destroy(entry); - ret = SA_SYSTEM_ERR; + break; } - break; } } - } } else { /* * ZFS update. The calling function would have updated @@ -2501,35 +2745,44 @@ if (!is_zfs_group(group)) { char *id = NULL; - if (sa_is_share((sa_group_t)parent)) { - id = sa_get_share_attr((sa_share_t)parent, "id"); - } - if (scf_handle->trans == NULL) { - if (is_nodetype(object, "optionset")) - (void) sa_optionset_name((sa_optionset_t)object, - oname, sizeof (oname), id); - else - (void) sa_security_name((sa_optionset_t)object, - oname, sizeof (oname), id); - ret = sa_start_transaction(scf_handle, oname); - } + sa_handle_impl_t impl_handle; + scfutilhandle_t *scf_handle; + + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle == NULL || impl_handle->scfhandle == NULL) + ret = SA_SYSTEM_ERR; if (ret == SA_OK) { - char *name; - char *value; - name = sa_get_property_attr(property, "type"); - value = sa_get_property_attr(property, "value"); - if (name != NULL && value != NULL) { - if (scf_handle->scf_state == SCH_STATE_INIT) - ret = sa_set_property(scf_handle, name, value); - } else - ret = SA_CONFIG_ERR; - if (name != NULL) - sa_free_attr_string(name); - if (value != NULL) - sa_free_attr_string(value); + scf_handle = impl_handle->scfhandle; + if (sa_is_share((sa_group_t)parent)) { + id = sa_get_share_attr((sa_share_t)parent, "id"); + } + if (scf_handle->trans == NULL) { + if (is_nodetype(object, "optionset")) + (void) sa_optionset_name((sa_optionset_t)object, + oname, sizeof (oname), id); + else + (void) sa_security_name((sa_optionset_t)object, + oname, sizeof (oname), id); + ret = sa_start_transaction(scf_handle, oname); + } + if (ret == SA_OK) { + char *name; + char *value; + name = sa_get_property_attr(property, "type"); + value = sa_get_property_attr(property, "value"); + if (name != NULL && value != NULL) { + if (scf_handle->scf_state == SCH_STATE_INIT) + ret = sa_set_property(scf_handle, name, value); + } else + ret = SA_CONFIG_ERR; + if (name != NULL) + sa_free_attr_string(name); + if (value != NULL) + sa_free_attr_string(value); + } + if (id != NULL) + sa_free_attr_string(id); } - if (id != NULL) - sa_free_attr_string(id); } else { /* * ZFS is a special case. We do want to allow editing @@ -2610,31 +2863,6 @@ } /* - * _sa_get_next_error(node) - * - * Get the next (first if node==NULL) error node in the - * document. "error" nodes are added if there were syntax errors - * during parsing of the /etc/dfs/dfstab file. They are preserved in - * comments and recreated in the doc on the next parse. - */ - -xmlNodePtr -_sa_get_next_error(xmlNodePtr node) -{ - if (node == NULL) { - for (node = sa_config_tree->xmlChildrenNode; - node != NULL; node = node->next) - if (xmlStrcmp(node->name, (xmlChar *)"error") == 0) - return (node); - } else { - for (node = node->next; node != NULL; node = node->next) - if (xmlStrcmp(node->name, (xmlChar *)"error") == 0) - return (node); - } - return (node); -} - -/* * sa_get_protocol_property(propset, prop) * * Get the specified protocol specific property. These are global to diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/libshare.h --- a/usr/src/lib/libshare/common/libshare.h Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/libshare.h Wed Mar 28 08:50:43 2007 -0700 @@ -118,9 +118,9 @@ #define SA_SVC_FMRI_BASE "svc:/network/shares/group" /* initialization */ -extern void sa_init(int); -extern void sa_fini(void); -extern int sa_update_config(void); +extern sa_handle_t sa_init(int); +extern void sa_fini(sa_handle_t); +extern int sa_update_config(sa_handle_t); extern char *sa_errorstr(int); /* protocol names */ @@ -128,9 +128,9 @@ extern int sa_valid_protocol(char *); /* group control (create, remove, etc) */ -extern sa_group_t sa_create_group(char *, int *); +extern sa_group_t sa_create_group(sa_handle_t, char *, int *); extern int sa_remove_group(sa_group_t); -extern sa_group_t sa_get_group(char *); +extern sa_group_t sa_get_group(sa_handle_t, char *); extern sa_group_t sa_get_next_group(sa_group_t); extern char *sa_get_group_attr(sa_group_t, char *); extern int sa_set_group_attr(sa_group_t, char *, char *); @@ -144,7 +144,7 @@ extern int sa_remove_share(sa_share_t); extern sa_share_t sa_get_share(sa_group_t, char *); extern sa_share_t sa_get_resource(sa_group_t, char *); -extern sa_share_t sa_find_share(char *); +extern sa_share_t sa_find_share(sa_handle_t, char *); extern sa_share_t sa_get_next_share(sa_share_t); extern char *sa_get_share_attr(sa_share_t, char *); extern char *sa_get_share_description(sa_share_t); @@ -214,8 +214,13 @@ extern int sa_delete_sharetab(char *, char *); /* ZFS functions */ -extern int sa_zfs_is_shared(char *); +extern int sa_zfs_is_shared(sa_handle_t, char *); extern int sa_group_is_zfs(sa_group_t); + + +/* SA Handle specific functions */ +extern sa_handle_t sa_find_group_handle(sa_group_t); + #ifdef __cplusplus } #endif diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/libshare_impl.h --- a/usr/src/lib/libshare/common/libshare_impl.h Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/libshare_impl.h Wed Mar 28 08:50:43 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -114,11 +115,12 @@ extern int sa_delete_pgroup(scfutilhandle_t *, char *); /* ZFS functions */ -extern int sa_get_zfs_shares(char *); +extern int sa_get_zfs_shares(sa_handle_t, char *); extern int sa_zfs_update(sa_share_t); /* plugin specific functions */ extern int proto_plugin_init(); +extern void proto_plugin_fini(); extern int sa_proto_set_property(char *, sa_property_t); extern int sa_proto_delete_legacy(char *, sa_share_t); extern int sa_proto_update_legacy(char *, sa_share_t); @@ -136,6 +138,17 @@ void *plugin_handle; }; +/* internal version of sa_handle_t */ +typedef struct sa_handle_impl { + uint64_t flags; + scfutilhandle_t *scfhandle; + libzfs_handle_t *zfs_libhandle; + zfs_handle_t **zfs_list; + size_t zfs_list_count; + xmlNodePtr tree; + xmlDocPtr doc; +} *sa_handle_impl_t; + #ifdef __cplusplus } #endif diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/libshare_zfs.c --- a/usr/src/lib/libshare/common/libshare_zfs.c Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/libshare_zfs.c Wed Mar 28 08:50:43 2007 -0700 @@ -50,43 +50,42 @@ size_t cb_used; } get_all_cbdata_t; -static libzfs_handle_t *zfs_libhandle = NULL; -static zfs_handle_t **zfs_list = NULL; -static size_t zfs_list_count = 0; - /* - * sa_zfs_init() + * sa_zfs_init(impl_handle) * - * initialize an access handle into libzfs + * Initialize an access handle into libzfs. The handle needs to stay + * around until sa_zfs_fini() in order to maintain the cache of + * mounts. */ void -sa_zfs_init() +sa_zfs_init(sa_handle_impl_t impl_handle) { - zfs_libhandle = libzfs_init(); - libzfs_print_on_error(zfs_libhandle, B_TRUE); + impl_handle->zfs_libhandle = libzfs_init(); + libzfs_print_on_error(impl_handle->zfs_libhandle, B_TRUE); } /* - * sa_zfs_fini() + * sa_zfs_fini(impl_handle) * * cleanup data structures and the libzfs handle used for accessing * zfs file share info. */ void -sa_zfs_fini() +sa_zfs_fini(sa_handle_impl_t impl_handle) { - if (zfs_libhandle != NULL) { - libzfs_fini(zfs_libhandle); - zfs_libhandle = NULL; - if (zfs_list != NULL) { + if (impl_handle->zfs_libhandle != NULL) { + libzfs_fini(impl_handle->zfs_libhandle); + impl_handle->zfs_libhandle = NULL; + if (impl_handle->zfs_list != NULL) { /* * contents of zfs_list were already freed by the call to * libzfs_fini(). */ - free(zfs_list); - zfs_list = NULL; + free(impl_handle->zfs_list); + impl_handle->zfs_list = NULL; + impl_handle->zfs_list_count = 0; } } } @@ -149,20 +148,22 @@ */ static void -get_all_filesystems(zfs_handle_t ***fslist, size_t *count) +get_all_filesystems(sa_handle_impl_t impl_handle, + zfs_handle_t ***fslist, size_t *count) { get_all_cbdata_t cb = { 0 }; - if (zfs_list != NULL) { - *fslist = zfs_list; - *count = zfs_list_count; + if (impl_handle->zfs_list != NULL) { + *fslist = impl_handle->zfs_list; + *count = impl_handle->zfs_list_count; return; } - (void) zfs_iter_root(zfs_libhandle, get_one_filesystem, &cb); + (void) zfs_iter_root(impl_handle->zfs_libhandle, + get_one_filesystem, &cb); - zfs_list = *fslist = cb.cb_handles; - zfs_list_count = *count = cb.cb_used; + impl_handle->zfs_list = *fslist = cb.cb_handles; + impl_handle->zfs_list_count = *count = cb.cb_used; } /* @@ -189,7 +190,7 @@ } /* - * get_zfs_dataset(path) + * get_zfs_dataset(impl_handle, path) * * get the name of the ZFS dataset the path is equivalent to. The * dataset name is used for get/set of ZFS properties since libzfs @@ -197,14 +198,14 @@ */ static char * -get_zfs_dataset(char *path) +get_zfs_dataset(sa_handle_impl_t impl_handle, char *path) { size_t i, count = 0; char *dataset = NULL; zfs_handle_t **zlist; char mountpoint[ZFS_MAXPROPLEN]; - get_all_filesystems(&zlist, &count); + get_all_filesystems(impl_handle, &zlist, &count); qsort(zlist, count, sizeof (void *), mountpoint_compare); for (i = 0; i < count; i++) { /* must have a mountpoint */ @@ -272,14 +273,14 @@ } /* - * sa_zfs_is_shared(path) + * sa_zfs_is_shared(handle, path) * * Check to see if the ZFS path provided has the sharenfs option set * or not. */ int -sa_zfs_is_shared(char *path) +sa_zfs_is_shared(sa_handle_t sahandle, char *path) { int ret = 0; char *dataset; @@ -287,7 +288,7 @@ char shareopts[ZFS_MAXPROPLEN]; libzfs_handle_t *libhandle; - dataset = get_zfs_dataset(path); + dataset = get_zfs_dataset((sa_handle_t)sahandle, path); if (dataset != NULL) { libhandle = libzfs_init(); if (libhandle != NULL) { @@ -319,7 +320,7 @@ */ static sa_group_t -find_or_create_group(char *groupname, char *proto, int *err) +find_or_create_group(sa_handle_t handle, char *groupname, char *proto, int *err) { sa_group_t group; sa_optionset_t optionset; @@ -331,9 +332,9 @@ * parent. This is to make sure the zfs group has been created * and to created if it hasn't been. */ - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group == NULL) { - group = sa_create_group(groupname, &ret); + group = sa_create_group(handle, groupname, &ret); /* make sure this is flagged as a ZFS group */ if (group != NULL) @@ -374,7 +375,8 @@ */ static sa_group_t -find_or_create_zfs_subgroup(char *groupname, char *optstring, int *err) +find_or_create_zfs_subgroup(sa_handle_t handle, char *groupname, + char *optstring, int *err) { sa_group_t group = NULL; sa_group_t zfs; @@ -382,7 +384,7 @@ char *options; /* start with the top-level "zfs" group */ - zfs = sa_get_group("zfs"); + zfs = sa_get_group(handle, "zfs"); *err = SA_OK; if (zfs != NULL) { for (group = sa_get_sub_group(zfs); group != NULL; @@ -420,7 +422,7 @@ } /* - * sa_get_zfs_shares(groupname) + * sa_get_zfs_shares(handle, groupname) * * Walk the mnttab for all zfs mounts and determine which are * shared. Find or create the appropriate group/sub-group to contain @@ -431,7 +433,7 @@ */ int -sa_get_zfs_shares(char *groupname) +sa_get_zfs_shares(sa_handle_t handle, char *groupname) { sa_group_t group; sa_group_t zfsgroup; @@ -445,20 +447,22 @@ char mountpoint[ZFS_MAXPROPLEN]; char *options; size_t count = 0, i; + libzfs_handle_t *zfs_libhandle; /* - * if we can't access libzfs, don't bother doing anything. + * If we can't access libzfs, don't bother doing anything. */ + zfs_libhandle = ((sa_handle_impl_t)handle)->zfs_libhandle; if (zfs_libhandle == NULL) return (SA_SYSTEM_ERR); - zfsgroup = find_or_create_group(groupname, "nfs", &err); + zfsgroup = find_or_create_group(handle, groupname, "nfs", &err); if (zfsgroup != NULL) { /* * need to walk the mounted ZFS pools and datasets to * find shares that are possible. */ - get_all_filesystems(&zlist, &count); + get_all_filesystems((sa_handle_impl_t)handle, &zlist, &count); qsort(zlist, count, sizeof (void *), mountpoint_compare); group = zfsgroup; @@ -494,7 +498,7 @@ B_FALSE) == 0 && strcmp(shareopts, "off") != 0) { /* it is shared so add to list */ - share = sa_find_share(mountpoint); + share = sa_find_share(handle, mountpoint); err = SA_OK; if (share != NULL) { /* @@ -520,7 +524,8 @@ * variable. The real parent not mounted can * occur if "canmount=off and sharenfs=on". */ - group = find_or_create_zfs_subgroup(sourcestr, + group = find_or_create_zfs_subgroup(handle, + sourcestr, shareopts, &doshopt); if (group != NULL) { share = _sa_add_share(group, mountpoint, @@ -633,8 +638,9 @@ command = malloc(ZFS_MAXPROPLEN * 2); if (command != NULL) { char *opts = NULL; - char *dataset; + char *dataset = NULL; FILE *pfile; + sa_handle_impl_t impl_handle; /* for now, NFS is always available for "zfs" */ if (on) { opts = sa_proto_legacy_format("nfs", group, 1); @@ -643,7 +649,13 @@ opts = strdup("on"); } } - dataset = get_zfs_dataset(path); + + impl_handle = (sa_handle_impl_t)sa_find_group_handle(group); + if (impl_handle != NULL) + dataset = get_zfs_dataset(impl_handle, path); + else + ret = SA_SYSTEM_ERR; + if (dataset != NULL) { (void) snprintf(command, ZFS_MAXPROPLEN * 2, "%s set sharenfs=\"%s\" %s", COMMAND, @@ -704,7 +716,14 @@ if (sa_is_share(group)) { path = sa_get_share_attr((sa_share_t)group, "path"); if (path != NULL) { - dataset = get_zfs_dataset(path); + sa_handle_impl_t impl_handle; + + impl_handle = sa_find_group_handle(group); + if (impl_handle != NULL) + dataset = get_zfs_dataset(impl_handle, path); + else + ret = SA_SYSTEM_ERR; + sa_free_attr_string(path); } } else { diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/libsharecore.c --- a/usr/src/lib/libshare/common/libsharecore.c Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/libsharecore.c Wed Mar 28 08:50:43 2007 -0700 @@ -82,14 +82,13 @@ char *origline; int lineno; } xfs_sharelist_t; -static void parse_dfstab(char *, xmlNodePtr); +static void parse_dfstab(sa_handle_t, char *, xmlNodePtr); extern char *get_token(char *); static void dfs_free_list(xfs_sharelist_t *); /* prototypes */ -void getlegacyconfig(char *, xmlNodePtr *); +void getlegacyconfig(sa_handle_t, char *, xmlNodePtr *); extern sa_share_t _sa_add_share(sa_group_t, char *, int, int *); -extern xmlNodePtr _sa_get_next_error(xmlNodePtr); -extern sa_group_t _sa_create_group(char *); +extern sa_group_t _sa_create_group(sa_handle_impl_t, char *); static void outdfstab(FILE *, xfs_sharelist_t *); extern int _sa_remove_optionset(sa_optionset_t); extern int set_node_share(void *, char *, char *); @@ -915,7 +914,7 @@ */ static void -parse_dfstab(char *dfstab, xmlNodePtr root) +parse_dfstab(sa_handle_t handle, char *dfstab, xmlNodePtr root) { sa_share_t share; sa_group_t group; @@ -934,7 +933,7 @@ return; } - defgroup = sa_get_group("default"); + defgroup = sa_get_group(handle, "default"); for (head = list = getdfstab(dfs); list != NULL; @@ -974,8 +973,8 @@ continue; } if (list->path != NULL && strlen(list->path) > 0 && - *list->path == '/') { - share = sa_find_share(list->path); + *list->path == '/') { + share = sa_find_share(handle, list->path); if (share != NULL) sgroup = sa_get_parent_group(share); else @@ -991,7 +990,7 @@ continue; } if (list->group != NULL && strlen(list->group) > 0) { - group = sa_get_group(list->group); + group = sa_get_group(handle, list->group); defined_group = 1; } else { group = defgroup; @@ -1141,7 +1140,7 @@ */ void -getlegacyconfig(char *path, xmlNodePtr *root) +getlegacyconfig(sa_handle_t handle, char *path, xmlNodePtr *root) { sa_group_t defgroup; @@ -1157,12 +1156,12 @@ * code add/del via dfstab and we need to * cleanup SMF. */ - defgroup = sa_get_group("default"); + defgroup = sa_get_group(handle, "default"); if (defgroup != NULL) { legacy_removes(defgroup, path); } /* parse the dfstab and add anything new */ - parse_dfstab(path, *root); + parse_dfstab(handle, path, *root); } } } @@ -1244,7 +1243,7 @@ } /* - * parse_sharetab(void) + * parse_sharetab(handle) * * Read the /etc/dfs/sharetab file and see which entries don't exist * in the repository. These shares are marked transient. We also need @@ -1253,7 +1252,7 @@ */ int -parse_sharetab(void) +parse_sharetab(sa_handle_t handle) { xfs_sharelist_t *list, *tmplist; int err = 0; @@ -1267,11 +1266,11 @@ if (list == NULL) return (legacy); - lgroup = sa_get_group("default"); + lgroup = sa_get_group(handle, "default"); for (tmplist = list; tmplist != NULL; tmplist = tmplist->next) { group = NULL; - share = sa_find_share(tmplist->path); + share = sa_find_share(handle, tmplist->path); if (share == NULL) { /* * this share is transient so needs to be @@ -1283,7 +1282,7 @@ (groupname = strchr(tmplist->resource, '@')) != NULL) { /* there is a defined group */ *groupname++ = '\0'; - group = sa_get_group(groupname); + group = sa_get_group(handle, groupname); if (group != NULL) { share = _sa_add_share(group, tmplist->path, SA_SHARE_TRANSIENT, &err); @@ -1302,12 +1301,14 @@ SA_SHARE_TRANSIENT, &err); } } else { - if (sa_zfs_is_shared(tmplist->path)) { - group = sa_get_group("zfs"); + if (sa_zfs_is_shared(handle, tmplist->path)) { + group = sa_get_group(handle, "zfs"); if (group == NULL) { - group = sa_create_group("zfs", &err); + group = sa_create_group(handle, "zfs", &err); if (group == NULL && err == SA_NO_PERMISSION) { - group = _sa_create_group("zfs"); + group = _sa_create_group( + (sa_handle_impl_t)handle, + "zfs"); } if (group != NULL) { (void) sa_create_optionset(group, @@ -1371,7 +1372,7 @@ * in a repository. */ int -gettransients(xmlNodePtr *root) +gettransients(sa_handle_impl_t ihandle, xmlNodePtr *root) { int legacy = 0; @@ -1379,7 +1380,7 @@ if (*root == NULL) *root = xmlNewNode(NULL, (xmlChar *)"sharecfg"); if (*root != NULL) { - legacy = parse_sharetab(); + legacy = parse_sharetab(ihandle); } } return (legacy); @@ -1418,12 +1419,15 @@ */ void -update_legacy_config(void) +update_legacy_config(sa_handle_t handle) { /* * no longer used -- this is a placeholder in case we need to * add it back later. */ +#ifdef lint + handle = handle; +#endif } /* diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/mapfile-vers --- a/usr/src/lib/libshare/common/mapfile-vers Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/mapfile-vers Wed Mar 28 08:50:43 2007 -0700 @@ -19,13 +19,13 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # -SUNWprivate_1.1 { +SUNWprivate { global: sa_get_optionset; sa_create_property; @@ -104,6 +104,7 @@ sa_enable_share; sa_create_group; sa_valid_protocol; + sa_find_group_handle; local: *; }; diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/plugin.c --- a/usr/src/lib/libshare/common/plugin.c Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/plugin.c Wed Mar 28 08:50:43 2007 -0700 @@ -38,6 +38,9 @@ #include #include #include +#include + +#define MAXISALEN 257 /* based on sysinfo(2) man page */ /* * protocol plugin interface @@ -85,14 +88,25 @@ if (dir != NULL) { while (ret == SA_OK && (dent = readdir(dir)) != NULL) { char path[MAXPATHLEN]; + char isa[MAXISALEN]; + +#if defined(_LP64) + if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1) + isa[0] = '\0'; +#else + isa[0] = '\0'; +#endif (void) snprintf(path, MAXPATHLEN, - "%s/%s/libshare_%s.so", SA_LIB_DIR, - dent->d_name, dent->d_name); - if (stat(path, &st) < 0) { + "%s/%s/%s/libshare_%s.so.1", + SA_LIB_DIR, + dent->d_name, + isa, + dent->d_name); + if (stat(path, &st) < 0) { /* file doesn't exist, so don't try to map it */ continue; } - dlhandle = dlopen(path, RTLD_NOW|RTLD_GLOBAL|RTLD_WORLD); + dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY); if (dlhandle != NULL) { plugin_ops = (struct sa_plugin_ops *) dlsym(dlhandle, "sa_plugin_ops"); diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/scfutil.c --- a/usr/src/lib/libshare/common/scfutil.c Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/scfutil.c Wed Mar 28 08:50:43 2007 -0700 @@ -42,6 +42,7 @@ ssize_t scf_max_name_len; extern struct sa_proto_plugin *sap_proto_list; +extern sa_handle_impl_t get_handle_for_root(xmlNodePtr); /* * The SMF facility uses some properties that must exist. We want to @@ -93,7 +94,7 @@ */ scfutilhandle_t * -sa_scf_init() +sa_scf_init(sa_handle_impl_t ihandle) { scfutilhandle_t *handle; @@ -103,6 +104,7 @@ handle = calloc(1, sizeof (scfutilhandle_t)); if (handle != NULL) { + ihandle->scfhandle = handle; handle->scf_state = SCH_STATE_INITIALIZING; handle->handle = scf_handle_create(SCF_VERSION); if (handle->handle != NULL) { @@ -123,7 +125,8 @@ char **protolist; int numprotos, i; sa_group_t defgrp; - defgrp = sa_create_group("default", NULL); + defgrp = sa_create_group((sa_handle_t)ihandle, + "default", NULL); if (defgrp != NULL) { numprotos = sa_get_protocols(&protolist); for (i = 0; i < numprotos; i++) { @@ -539,14 +542,14 @@ */ static sa_share_t -find_share_by_id(char *shareid) +find_share_by_id(sa_handle_t handle, char *shareid) { sa_group_t group; sa_share_t share = NULL; char *id = NULL; int done = 0; - for (group = sa_get_group(NULL); group != NULL && !done; + for (group = sa_get_group(handle, NULL); group != NULL && !done; group = sa_get_next_group(group)) { for (share = sa_get_share(group, NULL); share != NULL; share = sa_get_next_share(share)) { @@ -577,7 +580,7 @@ static int sa_share_props_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle, - scf_propertygroup_t *pg, char *id) + scf_propertygroup_t *pg, char *id, sa_handle_t sahandle) { xmlNodePtr node; char *name; @@ -638,7 +641,7 @@ * match. */ - share = find_share_by_id(id); + share = find_share_by_id(sahandle, id); if (share == NULL) return (SA_BAD_PATH); @@ -717,7 +720,7 @@ static int sa_extract_group(xmlNodePtr root, scfutilhandle_t *handle, - scf_instance_t *instance) + scf_instance_t *instance, sa_handle_t sahandle) { char *buff; xmlNodePtr node; @@ -857,7 +860,7 @@ ret = sa_share_props_from_pgroup(node, handle, handle->pg, - buff); + buff, sahandle); } } } @@ -924,14 +927,15 @@ /* - * sa_get_config(handle, root, doc) + * sa_get_config(handle, root, doc, sahandlec) * * walk the SMF repository for /network/shares/group and find all the * instances. These become group names. Then add the XML structure * below the groups based on property groups and properties. */ int -sa_get_config(scfutilhandle_t *handle, xmlNodePtr *root, xmlDocPtr *doc) +sa_get_config(scfutilhandle_t *handle, xmlNodePtr *root, xmlDocPtr *doc, + sa_handle_t sahandle) { int ret = SA_OK; scf_instance_t *instance; @@ -952,7 +956,8 @@ sizeof (buff)) > 0) { if (strcmp(buff, "default") == 0) sa_extract_defaults(*root, handle, instance); - ret = sa_extract_group(*root, handle, instance); + ret = sa_extract_group(*root, handle, instance, + sahandle); } } } diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/common/scfutil.h --- a/usr/src/lib/libshare/common/scfutil.h Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/lib/libshare/common/scfutil.h Wed Mar 28 08:50:43 2007 -0700 @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -55,7 +55,8 @@ extern void sa_scf_fini(scfutilhandle_t *); extern scfutilhandle_t *sa_scf_init(); -extern int sa_get_config(scfutilhandle_t *, xmlNodePtr *, xmlDocPtr *); +extern int sa_get_config(scfutilhandle_t *, xmlNodePtr *, xmlDocPtr *, + sa_handle_t); extern int sa_get_instance(scfutilhandle_t *, char *); extern int sa_create_instance(scfutilhandle_t *, char *); diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,57 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../../Makefile.lib + +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +MSGFILES = libshare_nfs.c +POFILE = libshare_nfs.po + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +lint := TARGET= lint + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +$(POFILE): $(MSGFILES) + $(BUILDPO.msgfiles) + +_msg: $(MSGDOMAINPOFILE) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../../Makefile.targ +include ../../../Makefile.msg.targ diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/Makefile.com --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/Makefile.com Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,67 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +LIBRARY = libshare_nfs.a +VERS = .1 +NFSLIB_DIR = $(SRC)/cmd/fs.d/nfs/lib + +LIBOBJS = libshare_nfs.o +OTHOBJS = nfs_sec.o nfslog_config.o nfslogtab.o +OBJECTS = $(LIBOBJS) $(OTHOBJS) + +include ../../../Makefile.lib + +ROOTLIBDIR = $(ROOT)/usr/lib/fs/nfs +ROOTLIBDIR64 = $(ROOT)/usr/lib/fs/nfs/$(MACH64) + +LIBSRCS = $(LIBOBJS:%.o=$(SRCDIR)/%.c) +# we don't want to lint the sources for OTHOBJS since they are pre-existing files +# that are not lint free. +lintcheck := SRCS = $(LIBSRCS) + +LIBS = $(DYNLIB) +LDLIBS += -lshare -lnsl -lscf -lumem -lc +all install := LDLIBS += -lxml2 + +#add nfs/lib directory as part of the include path +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -I$(NFSLIB_DIR) -I/usr/include/libxml2 \ + -I$(SRCDIR)/../common + +.KEEP_STATE: + +all: $(LIBS) + +install: all + +lint: lintcheck + +pics/%.o: $(NFSLIB_DIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +include ../../../Makefile.targ diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/amd64/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/amd64/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/i386/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/i386/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/inc.flg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/inc.flg Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +echo_file usr/src/cmd/fs.d/nfs/lib/nfs_sec.c +echo_file usr/src/cmd/fs.d/nfs/lib/nfslog_config.c +echo_file usr/src/cmd/fs.d/nfs/lib/nfslogtab.c diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/libshare_nfs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/libshare_nfs.c Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,2722 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * NFS specific functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libshare.h" +#include "libshare_impl.h" +#include +#include +#include +#include +#include "nfslog_config.h" +#include "nfslogtab.h" +#include "libshare_nfs.h" +#include +#include + +/* should really be in some global place */ +#define DEF_WIN 30000 +#define OPT_CHUNK 1024 + +int debug = 0; + + +/* internal functions */ +static int nfs_init(); +static void nfs_fini(); +static int nfs_enable_share(sa_share_t); +static int nfs_disable_share(char *); +static int nfs_validate_property(sa_property_t, sa_optionset_t); +static int nfs_validate_security_mode(char *); +static int nfs_is_security_opt(char *); +static int nfs_parse_legacy_options(sa_group_t, char *); +static char *nfs_format_options(sa_group_t, int); +static int nfs_set_proto_prop(sa_property_t); +static sa_protocol_properties_t nfs_get_proto_set(); +static char *nfs_get_status(); +static char *nfs_space_alias(char *); + +/* + * ops vector that provides the protocol specific info and operations + * for share management. + */ + +struct sa_plugin_ops sa_plugin_ops = { + SA_PLUGIN_VERSION, + "nfs", + nfs_init, + nfs_fini, + nfs_enable_share, + nfs_disable_share, + nfs_validate_property, + nfs_validate_security_mode, + nfs_is_security_opt, + nfs_parse_legacy_options, + nfs_format_options, + nfs_set_proto_prop, + nfs_get_proto_set, + nfs_get_status, + nfs_space_alias, + NULL, + NULL +}; + +/* + * list of support services needed + * defines should come from head/rpcsvc/daemon_utils.h + */ + +static char *service_list_default[] = + { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, NULL }; +static char *service_list_logging[] = + { STATD, LOCKD, MOUNTD, NFSD, NFSMAPID, RQUOTAD, NFSLOGD, NULL }; + +/* + * option definitions. Make sure to keep the #define for the option + * index just before the entry it is the index for. Changing the order + * can cause breakage. E.g OPT_RW is index 1 and must precede the + * line that includes the SHOPT_RW and OPT_RW entries. + */ + +struct option_defs optdefs[] = { +#define OPT_RO 0 + {SHOPT_RO, OPT_RO, OPT_TYPE_ACCLIST}, +#define OPT_RW 1 + {SHOPT_RW, OPT_RW, OPT_TYPE_ACCLIST}, +#define OPT_ROOT 2 + {SHOPT_ROOT, OPT_ROOT, OPT_TYPE_ACCLIST}, +#define OPT_SECURE 3 + {SHOPT_SECURE, OPT_SECURE, OPT_TYPE_DEPRECATED}, +#define OPT_ANON 4 + {SHOPT_ANON, OPT_ANON, OPT_TYPE_USER}, +#define OPT_WINDOW 5 + {SHOPT_WINDOW, OPT_WINDOW, OPT_TYPE_NUMBER}, +#define OPT_NOSUID 6 + {SHOPT_NOSUID, OPT_NOSUID, OPT_TYPE_BOOLEAN}, +#define OPT_ACLOK 7 + {SHOPT_ACLOK, OPT_ACLOK, OPT_TYPE_BOOLEAN}, +#define OPT_NOSUB 8 + {SHOPT_NOSUB, OPT_NOSUB, OPT_TYPE_BOOLEAN}, +#define OPT_SEC 9 + {SHOPT_SEC, OPT_SEC, OPT_TYPE_SECURITY}, +#define OPT_PUBLIC 10 + {SHOPT_PUBLIC, OPT_PUBLIC, OPT_TYPE_BOOLEAN, OPT_SHARE_ONLY}, +#define OPT_INDEX 11 + {SHOPT_INDEX, OPT_INDEX, OPT_TYPE_FILE}, +#define OPT_LOG 12 + {SHOPT_LOG, OPT_LOG, OPT_TYPE_LOGTAG}, +#define OPT_CKSUM 13 + {SHOPT_CKSUM, OPT_CKSUM, OPT_TYPE_STRINGSET}, +#ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */ +#define OPT_VOLFH 14 + {SHOPT_VOLFH, OPT_VOLFH}, +#endif /* VOLATILE_FH_TEST */ + NULL +}; + +/* + * list of properties that are related to security flavors. + */ +static char *seclist[] = { + SHOPT_RO, + SHOPT_RW, + SHOPT_ROOT, + SHOPT_WINDOW, + NULL +}; + +/* structure for list of securities */ +struct securities { + sa_security_t security; + struct securities *next; +}; + +/* + * findopt(name) + * + * Lookup option "name" in the option table and return the table + * index. + */ + +static int +findopt(char *name) +{ + int i; + if (name != NULL) { + for (i = 0; optdefs[i].tag != NULL; i++) { + if (strcmp(optdefs[i].tag, name) == 0) + return (i); + } + } + return (-1); +} + +/* + * gettype(name) + * + * Return the type of option "name". + */ + +static int +gettype(char *name) +{ + int optdef; + + optdef = findopt(name); + if (optdef != -1) + return (optdefs[optdef].type); + return (OPT_TYPE_ANY); +} + +/* + * nfs_validate_security_mode(mode) + * + * is the specified mode string a valid one for use with NFS? + */ + +static int +nfs_validate_security_mode(char *mode) +{ + seconfig_t secinfo; + int err; + + (void) memset(&secinfo, '\0', sizeof (secinfo)); + err = nfs_getseconfig_byname(mode, &secinfo); + if (err == SC_NOERROR) + return (1); + return (0); +} + +/* + * nfs_is_security_opt(tok) + * + * check to see if tok represents an option that is only valid in some + * security flavor. + */ + +static int +nfs_is_security_opt(char *tok) +{ + int i; + + for (i = 0; seclist[i] != NULL; i++) { + if (strcmp(tok, seclist[i]) == 0) + return (1); + } + return (0); +} + +/* + * find_security(seclist, sec) + * + * Walk the current list of security flavors and return true if it is + * present, else return false. + */ + +static int +find_security(struct securities *seclist, sa_security_t sec) +{ + while (seclist != NULL) { + if (seclist->security == sec) + return (1); + seclist = seclist->next; + } + return (0); +} + +/* + * make_security_list(group, securitymodes, proto) + * go through the list of securitymodes and add them to the + * group's list of security optionsets. We also keep a list of + * those optionsets so we don't have to find them later. All of + * these will get copies of the same properties. + */ + +static struct securities * +make_security_list(sa_group_t group, char *securitymodes, char *proto) +{ + char *tok, *next = NULL; + struct securities *curp, *headp = NULL, *prev; + sa_security_t check; + int freetok = 0; + + for (tok = securitymodes; tok != NULL; tok = next) { + next = strchr(tok, ':'); + if (next != NULL) + *next++ = '\0'; + if (strcmp(tok, "default") == 0) { + /* resolve default into the real type */ + tok = nfs_space_alias(tok); + freetok = 1; + } + check = sa_get_security(group, tok, proto); + + /* add to the security list if it isn't there already */ + if (check == NULL || !find_security(headp, check)) { + curp = (struct securities *)calloc(1, + sizeof (struct securities)); + if (curp != NULL) { + if (check == NULL) { + curp->security = sa_create_security(group, tok, + proto); + } else { + curp->security = check; + } + /* + * note that the first time through the loop, + * headp will be NULL and prev will be + * undefined. Since headp is NULL, we set + * both it and prev to the curp (first + * structure to be allocated). + * + * later passes through the loop will have + * headp not being NULL and prev will be used + * to allocate at the end of the list. + */ + if (headp == NULL) { + headp = curp; + prev = curp; + } else { + prev->next = curp; + prev = curp; + } + } + } + + if (freetok) { + freetok = 0; + sa_free_attr_string(tok); + } + } + return (headp); +} + +static void +free_security_list(struct securities *sec) +{ + struct securities *next; + if (sec != NULL) { + for (next = sec->next; sec != NULL; sec = next) { + next = sec->next; + free(sec); + } + } +} + +/* + * nfs_alistcat(str1, str2, sep) + * + * concatenate str1 and str2 into a new string using sep as a separate + * character. If memory allocation fails, return NULL; + */ + +static char * +nfs_alistcat(char *str1, char *str2, char sep) +{ + char *newstr; + size_t len; + + len = strlen(str1) + strlen(str2) + 2; + newstr = (char *)malloc(len); + if (newstr != NULL) + (void) snprintf(newstr, len, "%s%c%s", str1, sep, str2); + return (newstr); +} + +/* + * add_security_prop(sec, name, value, persist) + * + * Add the property to the securities structure. This accumulates + * properties for as part of parsing legacy options. + */ + +static int +add_security_prop(struct securities *sec, char *name, char *value, + int persist, int iszfs) +{ + sa_property_t prop; + int ret = SA_OK; + + for (; sec != NULL; sec = sec->next) { + if (value == NULL) { + if (strcmp(name, SHOPT_RW) == 0 || strcmp(name, SHOPT_RO) == 0) + value = "*"; + else + value = "true"; + } + + /* + * Get the existing property, if it exists, so we can + * determine what to do with it. The ro/rw/root + * properties can be merged if multiple instances of + * these properies are given. For example, if "rw" + * exists with a value "host1" and a later token of + * rw="host2" is seen, the values are merged into a + * single rw="host1:host2". + */ + prop = sa_get_property(sec->security, name); + + if (prop != NULL) { + char *oldvalue; + char *newvalue; + + /* + * The security options of ro/rw/root might appear + * multiple times. If they do, the values need to be + * merged into an access list. If it was previously + * empty, the new value alone is added. + */ + oldvalue = sa_get_property_attr(prop, "value"); + if (oldvalue != NULL) { + /* + * The general case is to concatenate the new + * value onto the old value for multiple + * rw(ro/root) properties. A special case + * exists when either the old or new is the + * "all" case. In the special case, if both + * are "all", then it is "all", else if one is + * an access-list, that replaces the "all". + */ + if (strcmp(oldvalue, "*") == 0) { + /* Replace old value with new value. */ + newvalue = strdup(value); + } else if (strcmp(value, "*") == 0) { + /* Keep old value and ignore the new value. */ + newvalue = NULL; + } else { + /* Make a new list of old plus new access-list. */ + newvalue = nfs_alistcat(oldvalue, value, ':'); + } + + if (newvalue != NULL) { + (void) sa_remove_property(prop); + prop = sa_create_property(name, newvalue); + ret = sa_add_property(sec->security, prop); + free(newvalue); + } + if (oldvalue != NULL) + sa_free_attr_string(oldvalue); + } + } else { + prop = sa_create_property(name, value); + ret = sa_add_property(sec->security, prop); + } + if (ret == SA_OK && !iszfs) { + ret = sa_commit_properties(sec->security, !persist); + } + } + return (ret); +} + +/* + * check to see if group/share is persistent. + */ +static int +is_persistent(sa_group_t group) +{ + char *type; + int persist = 1; + + type = sa_get_group_attr(group, "type"); + if (type != NULL && strcmp(type, "persist") != 0) + persist = 0; + if (type != NULL) + sa_free_attr_string(type); + return (persist); +} + +/* + * invalid_security(options) + * + * search option string for any invalid sec= type. + * return true (1) if any are not valid else false (0) + */ +static int +invalid_security(char *options) +{ + char *copy, *base, *token, *value; + int ret = 0; + + copy = strdup(options); + token = base = copy; + while (token != NULL && ret == 0) { + token = strtok(base, ","); + base = NULL; + if (token != NULL) { + value = strchr(token, '='); + if (value != NULL) + *value++ = '\0'; + if (strcmp(token, "sec") == 0) { + /* have security flavors so check them */ + char *tok, *next; + for (next = NULL, tok = value; tok != NULL; tok = next) { + next = strchr(tok, ':'); + if (next != NULL) + *next++ = '\0'; + ret = !nfs_validate_security_mode(tok); + if (ret) + break; + } + } + } + } + if (copy != NULL) + free(copy); + return (ret); +} + +/* + * nfs_parse_legacy_options(group, options) + * + * Parse the old style options into internal format and store on the + * specified group. Group could be a share for full legacy support. + */ + +static int +nfs_parse_legacy_options(sa_group_t group, char *options) +{ + char *dup = strdup(options); + char *base; + char *token; + sa_optionset_t optionset; + struct securities *security_list = NULL; + sa_property_t prop; + int ret = SA_OK; + int iszfs = 0; + sa_group_t parent; + int persist = 0; + char *lasts; + + /* do we have an existing optionset? */ + optionset = sa_get_optionset(group, "nfs"); + if (optionset == NULL) { + /* didn't find existing optionset so create one */ + optionset = sa_create_optionset(group, "nfs"); + } else { + /* + * have an existing optionset so we need to compare + * options in order to detect errors. For now, we + * assume that the first optionset is the correct one + * and the others will be the same. This needs to be + * fixed before the final code is ready. + */ + return (ret); + } + + if (strcmp(options, SHOPT_RW) == 0) { + /* + * there is a special case of only the option "rw" + * being the default option. We don't have to do + * anything. + */ + return (ret); + } + + /* + * check if security types are present and validate them. If + * any are not legal, fail. + */ + + if (invalid_security(options)) { + return (SA_INVALID_SECURITY); + } + + /* + * in order to not attempt to change ZFS properties unless + * absolutely necessary, we never do it in the legacy parsing. + */ + if (sa_is_share(group)) { + char *zfs; + parent = sa_get_parent_group(group); + if (parent != NULL) { + zfs = sa_get_group_attr(parent, "zfs"); + if (zfs != NULL) { + sa_free_attr_string(zfs); + iszfs++; + } + } + } else { + iszfs = sa_group_is_zfs(group); + } + + /* + * we need to step through each option in the string and then + * add either the option or the security option as needed. If + * this is not a persistent share, don't commit to the + * repository. If there is an error, we also want to abort the + * processing and report it. + */ + persist = is_persistent(group); + base = dup; + token = dup; + lasts = NULL; + while (token != NULL && ret == SA_OK) { + ret = SA_OK; + token = strtok_r(base, ",", &lasts); + base = NULL; + if (token != NULL) { + char *value; + /* + * if the option has a value, it will have an '=' to + * separate the name from the value. The following + * code will result in value != NULL and token + * pointing to just the name if there is a value. + */ + value = strchr(token, '='); + if (value != NULL) { + *value++ = '\0'; + } + if (strcmp(token, "sec") == 0 || strcmp(token, "secure") == 0) { + /* + * Once in security parsing, we only + * do security. We do need to move + * between the security node and the + * toplevel. The security tag goes on + * the root while the following ones + * go on the security. + */ + if (security_list != NULL) { + /* have an old list so close it and start the new */ + free_security_list(security_list); + } + if (strcmp(token, "secure") == 0) { + value = "dh"; + } else { + if (value == NULL) { + ret = SA_SYNTAX_ERR; + break; + } + } + security_list = make_security_list(group, value, "nfs"); + } else { + /* + * Note that the "old" syntax allowed a + * default security model This must be + * accounted for and internally converted to + * "standard" security structure. + */ + if (nfs_is_security_opt(token)) { + if (security_list == NULL) { + /* + * need to have a security option. This + * will be "closed" when a defined "sec=" + * option is seen. This is technically an + * error but will be allowed with warning. + */ + security_list = make_security_list(group, + "default", + "nfs"); + } + if (security_list != NULL) { + ret = add_security_prop(security_list, token, + value, persist, + iszfs); + } else { + ret = SA_NO_MEMORY; + } + } else { + /* regular options */ + if (value == NULL) { + if (strcmp(token, SHOPT_RW) == 0 || + strcmp(token, SHOPT_RO) == 0) + value = "*"; + else if (strcmp(token, SHOPT_LOG) == 0) + value = "global"; + else + value = "true"; + } + prop = sa_create_property(token, value); + ret = sa_add_property(optionset, prop); + if (ret != SA_OK) { + break; + } + if (!iszfs) { + ret = sa_commit_properties(optionset, !persist); + } + } + } + } + } + if (security_list != NULL) + free_security_list(security_list); + if (dup != NULL) + free(dup); + return (ret); +} + +/* + * is_a_number(number) + * + * is the string a number in one of the forms we want to use? + */ + +static int +is_a_number(char *number) +{ + int ret = 1; + int hex = 0; + + if (strncmp(number, "0x", 2) == 0) { + number += 2; + hex = 1; + } else if (*number == '-') + number++; /* skip the minus */ + + while (ret == 1 && *number != '\0') { + if (hex) { + ret = isxdigit(*number++); + } else { + ret = isdigit(*number++); + } + } + return (ret); +} + +/* + * Look for the specified tag in the configuration file. If it is found, + * enable logging and set the logging configuration information for exp. + */ +static void +configlog(struct exportdata *exp, char *tag) +{ + nfsl_config_t *configlist = NULL, *configp; + int error = 0; + char globaltag[] = DEFAULTTAG; + + /* + * Sends config errors to stderr + */ + nfsl_errs_to_syslog = B_FALSE; + + /* + * get the list of configuration settings + */ + error = nfsl_getconfig_list(&configlist); + if (error) { + (void) fprintf(stderr, + dgettext(TEXT_DOMAIN, + "Cannot get log configuration: %s\n"), + strerror(error)); + } + + if (tag == NULL) + tag = globaltag; + if ((configp = nfsl_findconfig(configlist, tag, &error)) == NULL) { + nfsl_freeconfig_list(&configlist); + (void) fprintf(stderr, + dgettext(TEXT_DOMAIN, + "No tags matching \"%s\"\n"), tag); + /* bad configuration */ + error = ENOENT; + goto err; + } + + if ((exp->ex_tag = strdup(tag)) == NULL) { + error = ENOMEM; + goto out; + } + if ((exp->ex_log_buffer = strdup(configp->nc_bufferpath)) == NULL) { + error = ENOMEM; + goto out; + } + exp->ex_flags |= EX_LOG; + if (configp->nc_rpclogpath != NULL) + exp->ex_flags |= EX_LOG_ALLOPS; +out: + if (configlist != NULL) + nfsl_freeconfig_list(&configlist); + +err: + if (error != 0) { + if (exp->ex_flags != NULL) + free(exp->ex_tag); + if (exp->ex_log_buffer != NULL) + free(exp->ex_log_buffer); + (void) fprintf(stderr, + dgettext(TEXT_DOMAIN, + "Cannot set log configuration: %s\n"), + strerror(error)); + } +} + +/* + * fill_export_from_optionset(export, optionset) + * + * In order to share, we need to set all the possible general options + * into the export structure. Share info will be filled in by the + * caller. Various property values get turned into structure specific + * values. + */ + +static int +fill_export_from_optionset(struct exportdata *export, sa_optionset_t optionset) +{ + sa_property_t option; + int ret = SA_OK; + + for (option = sa_get_property(optionset, NULL); + option != NULL; option = sa_get_next_property(option)) { + char *name; + char *value; + uint32_t val; + + /* + * since options may be set/reset multiple times, always do an + * explicit set or clear of the option. This allows defaults + * to be set and then the protocol specifici to override. + */ + + name = sa_get_property_attr(option, "type"); + value = sa_get_property_attr(option, "value"); + switch (findopt(name)) { + case OPT_ANON: + if (value != NULL && is_a_number(value)) { + val = strtoul(value, NULL, 0); + } else { + struct passwd *pw; + pw = getpwnam(value != NULL ? value : "nobody"); + if (pw != NULL) { + val = pw->pw_uid; + } else { + val = UID_NOBODY; + } + endpwent(); + } + export->ex_anon = val; + break; + case OPT_NOSUID: + if (value != NULL && + (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0)) + export->ex_flags |= EX_NOSUID; + else + export->ex_flags &= ~EX_NOSUID; + break; + case OPT_ACLOK: + if (value != NULL && + (strcasecmp(value, "true") == 0 || + strcmp(value, "1") == 0)) + export->ex_flags |= EX_ACLOK; + else + export->ex_flags &= ~EX_ACLOK; + break; + case OPT_NOSUB: + if (value != NULL && + (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0)) + export->ex_flags |= EX_NOSUB; + else + export->ex_flags &= ~EX_NOSUB; + break; + case OPT_PUBLIC: + if (value != NULL && + (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0)) + export->ex_flags |= EX_PUBLIC; + else + export->ex_flags &= ~EX_PUBLIC; + break; + case OPT_INDEX: + if (value != NULL && + (strcmp(value, "..") == 0 || strchr(value, '/') != NULL)) { + /* this is an error */ + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: index=\"%s\" not valid;" + "must be a filename.\n"), + value); + break; + } + if (value != NULL && *value != '\0' && + strcmp(value, ".") != 0) { + /* valid index file string */ + if (export->ex_index != NULL) { + /* left over from "default" */ + free(export->ex_index); + } + export->ex_index = strdup(value); /* remember to free */ + if (export->ex_index == NULL) { + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: out of memory setting " + "index property\n")); + break; + } + export->ex_flags |= EX_INDEX; + } + break; + case OPT_LOG: + if (value == NULL) + value = strdup("global"); + if (value != NULL) + configlog(export, strlen(value) ? value : "global"); + break; + case OPT_CKSUM: + /* TBD: not ready yet */ + break; + default: + /* have a syntactic error */ + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: unrecognized option %s=%s\n"), + name, value != NULL ? value : ""); + break; + } + if (name != NULL) + sa_free_attr_string(name); + if (value != NULL) + sa_free_attr_string(value); + } + return (ret); +} + +/* + * cleanup_export(export) + * + * Cleanup the allocated areas so we don't leak memory + */ + +static void +cleanup_export(struct exportdata *export) +{ + int i; + + if (export->ex_index != NULL) + free(export->ex_index); + if (export->ex_secinfo != NULL) { + for (i = 0; i < export->ex_seccnt; i++) + if (export->ex_secinfo[i].s_rootnames != NULL) { + free(export->ex_secinfo[i].s_rootnames); + } + free(export->ex_secinfo); + } +} + +/* + * Given a seconfig entry and a colon-separated + * list of names, allocate an array big enough + * to hold the root list, then convert each name to + * a principal name according to the security + * info and assign it to an array element. + * Return the array and its size. + */ +static caddr_t * +get_rootnames(seconfig_t *sec, char *list, int *count) +{ + caddr_t *a; + int c, i; + char *host, *p; + + /* + * Count the number of strings in the list. + * This is the number of colon separators + 1. + */ + c = 1; + for (p = list; *p; p++) + if (*p == ':') + c++; + *count = c; + + a = (caddr_t *)malloc(c * sizeof (char *)); + if (a == NULL) { + (void) printf(dgettext(TEXT_DOMAIN, + "get_rootnames: no memory\n")); + } else { + for (i = 0; i < c; i++) { + host = strtok(list, ":"); + if (!nfs_get_root_principal(sec, host, &a[i])) { + free(a); + a = NULL; + break; + } + list = NULL; + } + } + + return (a); +} + +/* + * fill_security_from_secopts(sp, secopts) + * + * Fill the secinfo structure from the secopts optionset. + */ + +static int +fill_security_from_secopts(struct secinfo *sp, sa_security_t secopts) +{ + sa_property_t prop; + char *type; + int longform; + int err = SC_NOERROR; + + type = sa_get_security_attr(secopts, "sectype"); + if (type != NULL) { + /* named security type needs secinfo to be filled in */ + err = nfs_getseconfig_byname(type, &sp->s_secinfo); + sa_free_attr_string(type); + if (err != SC_NOERROR) + return (err); + } else { + /* default case */ + err = nfs_getseconfig_default(&sp->s_secinfo); + if (err != SC_NOERROR) + return (err); + } + + err = SA_OK; + for (prop = sa_get_property(secopts, NULL); + prop != NULL && err == SA_OK; + prop = sa_get_next_property(prop)) { + char *name; + char *value; + + name = sa_get_property_attr(prop, "type"); + value = sa_get_property_attr(prop, "value"); + + longform = value != NULL && strcmp(value, "*") != 0; + + switch (findopt(name)) { + case OPT_RO: + sp->s_flags |= longform ? M_ROL : M_RO; + break; + case OPT_RW: + sp->s_flags |= longform ? M_RWL : M_RW; + break; + case OPT_ROOT: + sp->s_flags |= M_ROOT; + /* + * if we are using AUTH_UNIX, handle like other things + * such as RO/RW + */ + if (sp->s_secinfo.sc_rpcnum == AUTH_UNIX) + continue; + /* not AUTH_UNIX */ + if (value != NULL) { + sp->s_rootnames = get_rootnames(&sp->s_secinfo, value, + &sp->s_rootcnt); + if (sp->s_rootnames == NULL) { + err = SA_BAD_VALUE; + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "Bad root list\n")); + } + } + break; + case OPT_WINDOW: + if (value != NULL) { + sp->s_window = atoi(value); + if (sp->s_window < 0) + sp->s_window = DEF_WIN; /* just in case */ + } + break; + default: + break; + } + if (name != NULL) + sa_free_attr_string(name); + if (value != NULL) + sa_free_attr_string(value); + } + /* if rw/ro options not set, use default of RW */ + if ((sp->s_flags & NFS_RWMODES) == 0) + sp->s_flags |= M_RW; + return (err); +} + +/* + * This is for testing only + * It displays the export structure that + * goes into the kernel. + */ +static void +printarg(char *path, struct exportdata *ep) +{ + int i, j; + struct secinfo *sp; + + if (debug == 0) + return; + + (void) printf("%s:\n", path); + (void) printf("\tex_version = %d\n", ep->ex_version); + (void) printf("\tex_path = %s\n", ep->ex_path); + (void) printf("\tex_pathlen = %ld\n", (ulong_t)ep->ex_pathlen); + (void) printf("\tex_flags: (0x%02x) ", ep->ex_flags); + if (ep->ex_flags & EX_NOSUID) + (void) printf("NOSUID "); + if (ep->ex_flags & EX_ACLOK) + (void) printf("ACLOK "); + if (ep->ex_flags & EX_PUBLIC) + (void) printf("PUBLIC "); + if (ep->ex_flags & EX_NOSUB) + (void) printf("NOSUB "); + if (ep->ex_flags & EX_LOG) + (void) printf("LOG "); + if (ep->ex_flags & EX_LOG_ALLOPS) + (void) printf("LOG_ALLOPS "); + if (ep->ex_flags == 0) + (void) printf("(none)"); + (void) printf("\n"); + if (ep->ex_flags & EX_LOG) { + (void) printf("\tex_log_buffer = %s\n", + (ep->ex_log_buffer ? ep->ex_log_buffer : "(NULL)")); + (void) printf("\tex_tag = %s\n", + (ep->ex_tag ? ep->ex_tag : "(NULL)")); + } + (void) printf("\tex_anon = %d\n", ep->ex_anon); + (void) printf("\tex_seccnt = %d\n", ep->ex_seccnt); + (void) printf("\n"); + for (i = 0; i < ep->ex_seccnt; i++) { + sp = &ep->ex_secinfo[i]; + (void) printf("\t\ts_secinfo = %s\n", sp->s_secinfo.sc_name); + (void) printf("\t\ts_flags: (0x%02x) ", sp->s_flags); + if (sp->s_flags & M_ROOT) (void) printf("M_ROOT "); + if (sp->s_flags & M_RO) (void) printf("M_RO "); + if (sp->s_flags & M_ROL) (void) printf("M_ROL "); + if (sp->s_flags & M_RW) (void) printf("M_RW "); + if (sp->s_flags & M_RWL) (void) printf("M_RWL "); + if (sp->s_flags == 0) (void) printf("(none)"); + (void) printf("\n"); + (void) printf("\t\ts_window = %d\n", sp->s_window); + (void) printf("\t\ts_rootcnt = %d ", sp->s_rootcnt); + (void) fflush(stdout); + for (j = 0; j < sp->s_rootcnt; j++) + (void) printf("%s ", sp->s_rootnames[j] ? + sp->s_rootnames[j] : ""); + (void) printf("\n\n"); + } +} + +/* + * count_security(opts) + * + * Count the number of security types (flavors). The optionset has + * been populated with the security flavors as a holding mechanism. + * We later use this number to allocate data structures. + */ + +static int +count_security(sa_optionset_t opts) +{ + int count = 0; + sa_property_t prop; + if (opts != NULL) { + for (prop = sa_get_property(opts, NULL); prop != NULL; + prop = sa_get_next_property(prop)) { + count++; + } + } + return (count); +} + +/* + * nfs_sprint_option(rbuff, rbuffsize, incr, prop, sep) + * + * provides a mechanism to format NFS properties into legacy output + * format. If the buffer would overflow, it is reallocated and grown + * as appropriate. Special cases of converting internal form of values + * to those used by "share" are done. this function does one property + * at a time. + */ + +static void +nfs_sprint_option(char **rbuff, size_t *rbuffsize, size_t incr, + sa_property_t prop, int sep) +{ + char *name; + char *value; + int curlen; + char *buff = *rbuff; + size_t buffsize = *rbuffsize; + + name = sa_get_property_attr(prop, "type"); + value = sa_get_property_attr(prop, "value"); + if (buff != NULL) + curlen = strlen(buff); + else + curlen = 0; + if (name != NULL) { + int len; + len = strlen(name) + sep; + + /* + * A future RFE would be to replace this with more + * generic code and to possibly handle more types. + */ + switch (gettype(name)) { + case OPT_TYPE_BOOLEAN: + if (value != NULL && strcasecmp(value, "false") == 0) { + *name = '\0'; + } + if (value != NULL) + sa_free_attr_string(value); + value = NULL; + break; + case OPT_TYPE_ACCLIST: + if (value != NULL && strcmp(value, "*") == 0) { + sa_free_attr_string(value); + value = NULL; + } else { + if (value != NULL) + len += 1 + strlen(value); + } + break; + case OPT_TYPE_LOGTAG: + if (value != NULL && strlen(value) == 0) { + sa_free_attr_string(value); + value = NULL; + } else { + if (value != NULL) + len += 1 + strlen(value); + } + break; + default: + if (value != NULL) + len += 1 + strlen(value); + break; + } + while (buffsize <= (curlen + len)) { + /* need more room */ + buffsize += incr; + buff = realloc(buff, buffsize); + if (buff == NULL) { + /* realloc failed so free everything */ + if (*rbuff != NULL) + free(*rbuff); + } + *rbuff = buff; + *rbuffsize = buffsize; + if (buff == NULL) { + return; + } + } + if (buff == NULL) + return; + if (value == NULL) + (void) snprintf(buff + curlen, buffsize - curlen, + "%s%s", sep ? "," : "", + name, value != NULL ? value : ""); + else + (void) snprintf(buff + curlen, buffsize - curlen, + "%s%s=%s", sep ? "," : "", + name, value != NULL ? value : ""); + } + if (name != NULL) + sa_free_attr_string(name); + if (value != NULL) + sa_free_attr_string(value); +} + +/* + * nfs_format_options(group, hier) + * + * format all the options on the group into an old-style option + * string. If hier is non-zero, walk up the tree to get inherited + * options. + */ + +static char * +nfs_format_options(sa_group_t group, int hier) +{ + sa_optionset_t options = NULL; + sa_optionset_t secoptions; + sa_property_t prop, secprop; + sa_security_t security; + char *buff; + size_t buffsize; + + options = sa_get_derived_optionset(group, "nfs", hier); + + /* + * have a an optionset relative to this item, if any. format + * these then add any security definitions. + */ + buff = malloc(OPT_CHUNK); + if (buff != NULL) { + int sep = 0; + buff[0] = '\0'; + buffsize = OPT_CHUNK; + /* + * do the default set first but skip any option that is also + * in the protocol specific optionset. + */ + if (options != NULL) { + for (prop = sa_get_property(options, NULL); prop != NULL; + prop = sa_get_next_property(prop)) { + /* + * use this one since we skipped any of these that + * were also in optdefault + */ + nfs_sprint_option(&buff, &buffsize, OPT_CHUNK, prop, sep); + if (buff == NULL) { + /* + * buff could become NULL if there isn't + * enough memory for nfs_sprint_option to + * realloc() as necessary. We can't really do + * anything about it at this point so we + * return NULL. The caller should handle the + * failure. Note that this + */ + return (buff); + } + sep = 1; + } + } + secoptions = (sa_optionset_t)sa_get_all_security_types(group, + "nfs", hier); + if (secoptions != NULL) { + for (secprop = sa_get_property(secoptions, NULL); + secprop != NULL; secprop = sa_get_next_property(secprop)) { + char *sectype; + + sectype = sa_get_property_attr(secprop, "type"); + security = (sa_security_t)sa_get_derived_security(group, + sectype, + "nfs", hier); + if (security != NULL) { + if (sectype != NULL) { + prop = sa_create_property("sec", sectype); + nfs_sprint_option(&buff, &buffsize, OPT_CHUNK, + prop, sep); + (void) sa_remove_property(prop); + sep = 1; + } + for (prop = sa_get_property(security, NULL); + prop != NULL; + prop = sa_get_next_property(prop)) { + + nfs_sprint_option(&buff, &buffsize, OPT_CHUNK, + prop, sep); + if (buff == NULL) { + /* catastrophic memory failure */ + sa_free_derived_optionset(secoptions); + if (security != NULL) + sa_free_derived_optionset(security); + if (sectype != NULL) + sa_free_attr_string(sectype); + if (options != NULL) + sa_free_derived_optionset(options); + return (buff); + } + sep = 1; + } + sa_free_derived_optionset(security); + } + if (sectype != NULL) + sa_free_attr_string(sectype); + } + sa_free_derived_optionset(secoptions); + } + } + if (options != NULL) + sa_free_derived_optionset(options); + return (buff); +} +/* + * Append an entry to the nfslogtab file + */ +static int +nfslogtab_add(dir, buffer, tag) + char *dir, *buffer, *tag; +{ + FILE *f; + struct logtab_ent lep; + int error = 0; + + /* + * Open the file for update and create it if necessary. + * This may leave the I/O offset at the end of the file, + * so rewind back to the beginning of the file. + */ + f = fopen(NFSLOGTAB, "a+"); + if (f == NULL) { + error = errno; + goto out; + } + rewind(f); + + if (lockf(fileno(f), F_LOCK, 0L) < 0) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "share complete, however failed to lock %s " + "for update: %s\n"), NFSLOGTAB, strerror(errno)); + error = -1; + goto out; + } + + if (logtab_deactivate_after_boot(f) == -1) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "share complete, however could not deactivate " + "entries in %s\n"), NFSLOGTAB); + error = -1; + goto out; + } + + /* + * Remove entries matching buffer and sharepoint since we're + * going to replace it with perhaps an entry with a new tag. + */ + if (logtab_rement(f, buffer, dir, NULL, -1)) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "share complete, however could not remove matching " + "entries in %s\n"), NFSLOGTAB); + error = -1; + goto out; + } + + /* + * Deactivate all active entries matching this sharepoint + */ + if (logtab_deactivate(f, NULL, dir, NULL)) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "share complete, however could not deactivate matching " + "entries in %s\n"), NFSLOGTAB); + error = -1; + goto out; + } + + lep.le_buffer = buffer; + lep.le_path = dir; + lep.le_tag = tag; + lep.le_state = LES_ACTIVE; + + /* + * Add new sharepoint / buffer location to nfslogtab + */ + if (logtab_putent(f, &lep) < 0) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "share complete, however could not add %s to %s\n"), + dir, NFSLOGTAB); + error = -1; + } + +out: + if (f != NULL) + (void) fclose(f); + return (error); +} + +/* + * Deactivate an entry from the nfslogtab file + */ +static int +nfslogtab_deactivate(path) + char *path; +{ + FILE *f; + int error = 0; + + f = fopen(NFSLOGTAB, "r+"); + if (f == NULL) { + error = errno; + goto out; + } + if (lockf(fileno(f), F_LOCK, 0L) < 0) { + error = errno; + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "share complete, however could not lock %s for " + "update: %s\n"), NFSLOGTAB, strerror(error)); + goto out; + } + if (logtab_deactivate(f, NULL, path, NULL) == -1) { + error = -1; + (void) fprintf(stderr, + dgettext(TEXT_DOMAIN, + "share complete, however could not " + "deactivate %s in %s\n"), path, NFSLOGTAB); + goto out; + } + +out: if (f != NULL) + (void) fclose(f); + + return (error); +} + +/* + * public_exists(share) + * + * check to see if public option is set on any other share than the + * one specified. + */ +static int +public_exists(sa_share_t skipshare) +{ + sa_share_t share; + sa_group_t group; + sa_optionset_t opt; + sa_property_t prop; + int exists = 0; + sa_handle_t handle; + + group = sa_get_parent_group(skipshare); + if (group == NULL) + return (SA_NO_SUCH_GROUP); + + handle = sa_find_group_handle(group); + if (handle == NULL) + return (SA_SYSTEM_ERR); + + for (group = sa_get_group(handle, NULL); group != NULL; + group = sa_get_next_group(group)) { + for (share = sa_get_share(group, NULL); share != NULL; + share = sa_get_next_share(share)) { + if (share == skipshare) + continue; + opt = sa_get_optionset(share, "nfs"); + if (opt != NULL) { + prop = sa_get_property(opt, "public"); + if (prop != NULL) { + char *shared; + shared = sa_get_share_attr(share, "shared"); + if (shared != NULL) { + exists = strcmp(shared, "true") == 0; + sa_free_attr_string(shared); + goto out; + } + } + } + } + } +out: + return (exists); +} + +/* + * sa_enable_share at the protocol level, enable_share must tell the + * implementation that it is to enable the share. This entails + * converting the path and options into the appropriate ioctl + * calls. It is assumed that all error checking of paths, etc. were + * done earlier. + */ +static int +nfs_enable_share(sa_share_t share) +{ + struct exportdata export; + sa_optionset_t secoptlist; + struct secinfo *sp; + int num_secinfo; + sa_optionset_t opt; + sa_security_t sec; + sa_property_t prop; + char *path; + int err = SA_OK; + + /* Don't drop core if the NFS module isn't loaded. */ + (void) signal(SIGSYS, SIG_IGN); + + /* get the path since it is important in several places */ + path = sa_get_share_attr(share, "path"); + if (path == NULL) + return (SA_NO_SUCH_PATH); + + /* + * find the optionsets and security sets. There may not be + * any or there could be one or two for each of optionset and + * security may have multiple, one per security type per + * protocol type. + */ + opt = sa_get_derived_optionset(share, "nfs", 1); + secoptlist = (sa_optionset_t)sa_get_all_security_types(share, "nfs", 1); + if (secoptlist != NULL) + num_secinfo = MAX(1, count_security(secoptlist)); + else + num_secinfo = 1; + + /* + * walk through the options and fill in the structure + * appropriately. + */ + + (void) memset(&export, '\0', sizeof (export)); + + /* + * do non-security options first since there is only one after + * the derived group is constructed. + */ + export.ex_version = EX_CURRENT_VERSION; + export.ex_anon = UID_NOBODY; /* this is our default value */ + export.ex_index = NULL; + export.ex_path = path; + export.ex_pathlen = strlen(path) + 1; + + sp = calloc(num_secinfo, sizeof (struct secinfo)); + + if (opt != NULL) + err = fill_export_from_optionset(&export, opt); + + /* + * check to see if "public" is set. If it is, then make sure + * no other share has it set. If it is already used, fail. + */ + + if (export.ex_flags & EX_PUBLIC && public_exists(share)) { + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: Cannot share more than one file " + "system with 'public' property\n")); + err = SA_NOT_ALLOWED; + goto out; + } + + if (sp == NULL) { + /* failed to alloc memory */ + (void) printf("NFS: no memory for security\n"); + err = SA_NO_MEMORY; + } else { + int i; + export.ex_secinfo = sp; + /* get default secinfo */ + export.ex_seccnt = num_secinfo; + /* + * since we must have one security option defined, we + * init to the default and then override as we find + * defined security options. This handles the case + * where we have no defined options but we need to set + * up one. + */ + sp[0].s_window = DEF_WIN; + sp[0].s_rootnames = NULL; + /* setup a default in case no properties defined */ + if (nfs_getseconfig_default(&sp[0].s_secinfo)) { + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: nfs_getseconfig_default: failed to " + "get default security mode\n")); + err = SA_CONFIG_ERR; + } + if (secoptlist != NULL) { + for (i = 0, prop = sa_get_property(secoptlist, NULL); + prop != NULL && i < num_secinfo; + prop = sa_get_next_property(prop), i++) { + char *sectype; + + sectype = sa_get_property_attr(prop, "type"); + /* if sectype is NULL, we can't do anything so skip */ + if (sectype == NULL) + continue; + sec = (sa_security_t)sa_get_derived_security(share, + sectype, + "nfs", 1); + sp[i].s_window = DEF_WIN; + sp[i].s_rootcnt = 0; + sp[i].s_rootnames = NULL; + + (void) fill_security_from_secopts(&sp[i], sec); + if (sec != NULL) + sa_free_derived_security(sec); + if (sectype != NULL) + sa_free_attr_string(sectype); + } + } + /* + * when we get here, we can do the exportfs system call and + * initiate thinsg. We probably want to enable the nfs.server + * service first if it isn't running within SMF. + */ + /* check nfs.server status and start if needed */ + + /* now add the share to the internal tables */ + printarg(path, &export); + /* + * call the exportfs system call which is implemented + * via the nfssys() call as the EXPORTFS subfunction. + */ + if ((err = exportfs(path, &export)) < 0) { + err = SA_SYSTEM_ERR; + switch (errno) { + case EREMOTE: + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: Cannot share remote file" + "system: %s\n"), + path); + break; + case EPERM: + if (getzoneid() != GLOBAL_ZONEID) { + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: Cannot share file systems " + "in non-global zones: %s\n"), path); + err = SA_NOT_SUPPORTED; + break; + } + err = SA_NO_PERMISSION; + /* FALLTHROUGH */ + default: + break; + } + } else { + /* update sharetab with an add/modify */ + (void) sa_update_sharetab(share, "nfs"); + } + } + + if (err == SA_OK) { + /* + * enable services as needed. This should probably be + * done elsewhere in order to minimize the calls to + * check services. + */ + /* + * check to see if logging and other services need to + * be triggered, but only if there wasn't an + * error. This is probably where sharetab should be + * updated with the NFS specific entry. + */ + if (export.ex_flags & EX_LOG) { + /* enable logging */ + if (nfslogtab_add(path, export.ex_log_buffer, + export.ex_tag) != 0) { + (void) fprintf(stderr, + dgettext(TEXT_DOMAIN, + "Could not enable logging for %s\n"), + path); + } + _check_services(service_list_logging); + } else { + /* + * don't have logging so remove it from file. It might + * not be thre, but that doesn't matter. + */ + (void) nfslogtab_deactivate(path); + _check_services(service_list_default); + } + } + +out: + if (path != NULL) + free(path); + + cleanup_export(&export); + if (opt != NULL) + sa_free_derived_optionset(opt); + if (secoptlist != NULL) + (void) sa_destroy_optionset(secoptlist); + return (err); +} + +/* + * nfs_disable_share(share) + * + * Unshare the specified share. How much error checking should be + * done? We only do basic errors for now. + */ +static int +nfs_disable_share(char *share) +{ + int err; + int ret = SA_OK; + + if (share != NULL) { + err = exportfs(share, NULL); + if (err < 0) { + /* TBD: only an error in some cases - need better analysis */ + switch (errno) { + case EPERM: + case EACCES: + ret = SA_NO_PERMISSION; + if (getzoneid() != GLOBAL_ZONEID) { + ret = SA_NOT_SUPPORTED; + } + break; + case EINVAL: + case ENOENT: + ret = SA_NO_SUCH_PATH; + break; + default: + ret = SA_SYSTEM_ERR; + break; + } + } + if (ret == SA_OK || ret == SA_NO_SUCH_PATH) { + (void) sa_delete_sharetab(share, "nfs"); + /* just in case it was logged */ + (void) nfslogtab_deactivate(share); + } + } + return (ret); +} + +/* + * check ro vs rw values. Over time this may get beefed up. + * for now it just does simple checks. + */ + +static int +check_rorw(char *v1, char *v2) +{ + int ret = SA_OK; + if (strcmp(v1, v2) == 0) + ret = SA_VALUE_CONFLICT; + return (ret); +} + +/* + * nfs_validate_property(property, parent) + * + * Check that the property has a legitimate value for its type. + */ + +static int +nfs_validate_property(sa_property_t property, sa_optionset_t parent) +{ + int ret = SA_OK; + char *propname; + char *other; + int optindex; + nfsl_config_t *configlist; + sa_group_t parent_group; + char *value; + + propname = sa_get_property_attr(property, "type"); + + if ((optindex = findopt(propname)) < 0) + ret = SA_NO_SUCH_PROP; + + /* need to validate value range here as well */ + + if (ret == SA_OK) { + parent_group = sa_get_parent_group((sa_share_t)parent); + if (optdefs[optindex].share && !sa_is_share(parent_group)) { + ret = SA_PROP_SHARE_ONLY; + } + } + if (ret == SA_OK) { + value = sa_get_property_attr(property, "value"); + if (value != NULL) { + /* first basic type checking */ + switch (optdefs[optindex].type) { + case OPT_TYPE_NUMBER: + /* check that the value is all digits */ + if (!is_a_number(value)) + ret = SA_BAD_VALUE; + break; + case OPT_TYPE_BOOLEAN: + if (strlen(value) == 0 || + strcasecmp(value, "true") == 0 || + strcmp(value, "1") == 0 || + strcasecmp(value, "false") == 0 || + strcmp(value, "0") == 0) { + ret = SA_OK; + } else { + ret = SA_BAD_VALUE; + } + break; + case OPT_TYPE_USER: + if (!is_a_number(value)) { + struct passwd *pw; + /* in this case it would have to be a user name */ + pw = getpwnam(value); + if (pw == NULL) + ret = SA_BAD_VALUE; + endpwent(); + } else { + uint64_t intval; + intval = strtoull(value, NULL, 0); + if (intval > UID_MAX && intval != ~0) + ret = SA_BAD_VALUE; + } + break; + case OPT_TYPE_FILE: + if (strcmp(value, "..") == 0 || + strchr(value, '/') != NULL) { + ret = SA_BAD_VALUE; + } + break; + case OPT_TYPE_ACCLIST: + /* + * access list handling. Should eventually + * validate that all the values make sense. + * Also, ro and rw may have cross value + * conflicts. + */ + if (strcmp(propname, SHOPT_RO) == 0) + other = SHOPT_RW; + else if (strcmp(propname, SHOPT_RW) == 0) + other = SHOPT_RO; + else + other = NULL; + if (other != NULL && parent != NULL) { + /* compare rw(ro) with ro(rw) */ + sa_property_t oprop; + oprop = sa_get_property(parent, other); + if (oprop != NULL) { + /* only potential confusion if other exists */ + char *ovalue; + ovalue = sa_get_property_attr(oprop, "value"); + if (ovalue != NULL) { + ret = check_rorw(value, ovalue); + sa_free_attr_string(ovalue); + } + } + } + break; + case OPT_TYPE_LOGTAG: + if (nfsl_getconfig_list(&configlist) == 0) { + int error; + if (value == NULL || strlen(value) == 0) { + if (value != NULL) + sa_free_attr_string(value); + value = strdup("global"); + } + if (nfsl_findconfig(configlist, value, &error) == NULL) + ret = SA_BAD_VALUE; + nfsl_freeconfig_list(&configlist); + } else { + ret = SA_CONFIG_ERR; + } + break; + case OPT_TYPE_STRING: + /* whatever is here should be ok */ + break; + case OPT_TYPE_SECURITY: + /* + * The "sec" property isn't used in the + * non-legacy parts of sharemgr. We need to + * reject it here. For legacy, it is pulled + * out well before we get here. + */ + ret = SA_NO_SUCH_PROP; + break; + default: + break; + } + sa_free_attr_string(value); + if (ret == SA_OK && optdefs[optindex].check != NULL) { + /* do the property specific check */ + ret = optdefs[optindex].check(property); + } + } + } + + if (propname != NULL) + sa_free_attr_string(propname); + return (ret); +} + +/* + * Protocol management functions + * + * Properties defined in the default files are defined in + * proto_option_defs for parsing and validation. If "other" and + * "compare" are set, then the value for this property should be + * compared against the property specified in "other" using the + * "compare" check (either <= or >=) in order to ensure that the + * values are in the correct range. E.g. setting server_versmin + * higher than server_versmax should not be allowed. + */ + +struct proto_option_defs { + char *tag; + char *name; /* display name -- remove protocol identifier */ + int index; + int type; + union { + int intval; + char *string; + } defvalue; + uint32_t svcs; + int32_t minval; + int32_t maxval; + char *file; + char *other; + int compare; +#define OPT_CMP_GE 0 +#define OPT_CMP_LE 1 + int (*check)(char *); +} proto_options[] = { +#define PROTO_OPT_NFSD_SERVERS 0 + {"nfsd_servers", + "servers", PROTO_OPT_NFSD_SERVERS, OPT_TYPE_NUMBER, 16, SVC_NFSD, + 1, INT32_MAX, NFSADMIN}, +#define PROTO_OPT_LOCKD_LISTEN_BACKLOG 1 + {"lockd_listen_backlog", + "lockd_listen_backlog", PROTO_OPT_LOCKD_LISTEN_BACKLOG, + OPT_TYPE_NUMBER, 32, SVC_LOCKD, 32, INT32_MAX, NFSADMIN}, +#define PROTO_OPT_LOCKD_SERVERS 2 + {"lockd_servers", + "lockd_servers", PROTO_OPT_LOCKD_SERVERS, OPT_TYPE_NUMBER, 20, + SVC_LOCKD, 1, INT32_MAX, NFSADMIN}, +#define PROTO_OPT_LOCKD_RETRANSMIT_TIMEOUT 3 + {"lockd_retransmit_timeout", + "lockd_retransmit_timeout", PROTO_OPT_LOCKD_RETRANSMIT_TIMEOUT, + OPT_TYPE_NUMBER, 5, SVC_LOCKD, 0, INT32_MAX, NFSADMIN}, +#define PROTO_OPT_GRACE_PERIOD 4 + {"grace_period", + "grace_period", PROTO_OPT_GRACE_PERIOD, OPT_TYPE_NUMBER, 90, + SVC_LOCKD, 0, INT32_MAX, NFSADMIN}, +#define PROTO_OPT_NFS_SERVER_VERSMIN 5 + {"nfs_server_versmin", + "server_versmin", PROTO_OPT_NFS_SERVER_VERSMIN, OPT_TYPE_NUMBER, + (int)NFS_VERSMIN_DEFAULT, SVC_NFSD|SVC_MOUNTD, NFS_VERSMIN, + NFS_VERSMAX, NFSADMIN, "server_versmax", OPT_CMP_LE}, +#define PROTO_OPT_NFS_SERVER_VERSMAX 6 + {"nfs_server_versmax", + "server_versmax", PROTO_OPT_NFS_SERVER_VERSMAX, OPT_TYPE_NUMBER, + (int)NFS_VERSMAX_DEFAULT, SVC_NFSD|SVC_MOUNTD, NFS_VERSMIN, + NFS_VERSMAX, NFSADMIN, "server_versmin", OPT_CMP_GE}, +#define PROTO_OPT_NFS_CLIENT_VERSMIN 7 + {"nfs_client_versmin", + "client_versmin", PROTO_OPT_NFS_CLIENT_VERSMIN, OPT_TYPE_NUMBER, + (int)NFS_VERSMIN_DEFAULT, NULL, NFS_VERSMIN, NFS_VERSMAX, + NFSADMIN, "client_versmax", OPT_CMP_LE}, +#define PROTO_OPT_NFS_CLIENT_VERSMAX 8 + {"nfs_client_versmax", + "client_versmax", PROTO_OPT_NFS_CLIENT_VERSMAX, OPT_TYPE_NUMBER, + (int)NFS_VERSMAX_DEFAULT, NULL, NFS_VERSMIN, NFS_VERSMAX, + NFSADMIN, "client_versmin", OPT_CMP_GE}, +#define PROTO_OPT_NFS_SERVER_DELEGATION 9 + {"nfs_server_delegation", + "server_delegation", PROTO_OPT_NFS_SERVER_DELEGATION, + OPT_TYPE_ONOFF, NFS_SERVER_DELEGATION_DEFAULT, SVC_NFSD, 0, 0, + NFSADMIN}, +#define PROTO_OPT_NFSMAPID_DOMAIN 10 + {"nfsmapid_domain", + "nfsmapid_domain", PROTO_OPT_NFSMAPID_DOMAIN, OPT_TYPE_DOMAIN, + NULL, SVC_NFSMAPID, 0, 0, NFSADMIN}, +#define PROTO_OPT_NFSD_MAX_CONNECTIONS 11 + {"nfsd_max_connections", + "max_connections", PROTO_OPT_NFSD_MAX_CONNECTIONS, + OPT_TYPE_NUMBER, -1, SVC_NFSD, -1, INT32_MAX, NFSADMIN}, +#define PROTO_OPT_NFSD_PROTOCOL 12 + {"nfsd_protocol", + "protocol", PROTO_OPT_NFSD_PROTOCOL, OPT_TYPE_PROTOCOL, 0, + SVC_NFSD, 0, 0, NFSADMIN}, +#define PROTO_OPT_NFSD_LISTEN_BACKLOG 13 + {"nfsd_listen_backlog", + "listen_backlog", PROTO_OPT_NFSD_LISTEN_BACKLOG, + OPT_TYPE_NUMBER, 0, + SVC_LOCKD, 0, INT32_MAX, NFSADMIN}, + {NULL} +}; + +/* + * the protoset holds the defined options so we don't have to read + * them multiple times + */ +sa_protocol_properties_t protoset; + +static int +findprotoopt(char *name, int whichname) +{ + int i; + for (i = 0; proto_options[i].tag != NULL; i++) { + if (whichname == 1) { + if (strcasecmp(proto_options[i].name, name) == 0) + return (i); + } else { + if (strcasecmp(proto_options[i].tag, name) == 0) + return (i); + } + } + return (-1); +} + +/* + * fixcaselower(str) + * + * convert a string to lower case (inplace). + */ + +static void +fixcaselower(char *str) +{ + while (*str) { + *str = tolower(*str); + str++; + } +} + +/* + * fixcaseupper(str) + * + * convert a string to upper case (inplace). + */ + +static void +fixcaseupper(char *str) +{ + while (*str) { + *str = toupper(*str); + str++; + } +} + +/* + * initprotofromdefault() + * + * read the default file(s) and add the defined values to the + * protoset. Note that default values are known from the built in + * table in case the file doesn't have a definition. + */ + +static int +initprotofromdefault() +{ + FILE *nfs; + char buff[BUFSIZ]; + char *name; + char *value; + sa_property_t prop; + int index; + + protoset = sa_create_protocol_properties("nfs"); + + if (protoset != NULL) { + nfs = fopen(NFSADMIN, "r"); + if (nfs != NULL) { + while (fgets(buff, sizeof (buff), nfs) != NULL) { + switch (buff[0]) { + case '\n': + case '#': + /* skip */ + break; + default: + name = buff; + buff[strlen(buff) - 1] = '\0'; + value = strchr(name, '='); + if (value != NULL) { + *value++ = '\0'; + if ((index = findprotoopt(name, 0)) >= 0) { + fixcaselower(name); + prop = sa_create_property( + proto_options[index].name, + value); + (void) sa_add_protocol_property(protoset, prop); + } + } + } + } + if (nfs != NULL) + (void) fclose(nfs); + } + } + if (protoset == NULL) + return (SA_NO_MEMORY); + return (SA_OK); +} + +/* + * add_default() + * + * Add the default values for any property not defined in the parsing + * of the default files. Values are set according to their defined + * types. + */ + +static void +add_defaults() +{ + int i; + char number[MAXDIGITS]; + + for (i = 0; proto_options[i].tag != NULL; i++) { + sa_property_t prop; + prop = sa_get_protocol_property(protoset, proto_options[i].name); + if (prop == NULL) { + /* add the default value */ + switch (proto_options[i].type) { + case OPT_TYPE_NUMBER: + (void) snprintf(number, sizeof (number), "%d", + proto_options[i].defvalue.intval); + prop = sa_create_property(proto_options[i].name, number); + break; + + case OPT_TYPE_BOOLEAN: + prop = sa_create_property(proto_options[i].name, + proto_options[i].defvalue.intval ? + "true" : "false"); + break; + + case OPT_TYPE_ONOFF: + prop = sa_create_property(proto_options[i].name, + proto_options[i].defvalue.intval ? + "on" : "off"); + break; + + default: + /* treat as strings of zero length */ + prop = sa_create_property(proto_options[i].name, ""); + break; + } + if (prop != NULL) + (void) sa_add_protocol_property(protoset, prop); + } + } +} + +static void +free_protoprops() +{ + xmlFreeNode(protoset); +} + +/* + * nfs_init() + * + * Initialize the NFS plugin. + */ + +static int +nfs_init() +{ + int ret = SA_OK; + + if (sa_plugin_ops.sa_init != nfs_init) + (void) printf(dgettext(TEXT_DOMAIN, + "NFS plugin not properly initialized\n")); + + ret = initprotofromdefault(); + add_defaults(); + + return (ret); +} + +/* + * nfs_fini() + * + * uninitialize the NFS plugin. Want to avoid memory leaks. + */ + +static void +nfs_fini() +{ + free_protoprops(); +} + +/* + * nfs_get_proto_set() + * + * Return an optionset with all the protocol specific properties in + * it. + */ + +static sa_protocol_properties_t +nfs_get_proto_set() +{ + return (protoset); +} + +struct deffile { + struct deffile *next; + char *line; +}; + +/* + * read_default_file(fname) + * + * Read the specified default file. We return a list of entries. This + * get used for adding or removing values. + */ + +static struct deffile * +read_default_file(char *fname) +{ + FILE *file; + struct deffile *defs = NULL; + struct deffile *newdef; + struct deffile *prevdef = NULL; + char buff[BUFSIZ * 2]; + + file = fopen(fname, "r"); + if (file != NULL) { + while (fgets(buff, sizeof (buff), file) != NULL) { + newdef = (struct deffile *)calloc(1, sizeof (struct deffile)); + if (newdef != NULL) { + newdef->line = strdup(buff); + if (defs == NULL) { + prevdef = defs = newdef; + } else { + prevdef->next = newdef; + prevdef = newdef; + } + } + } + } + (void) fclose(file); + return (defs); +} + +static void +free_default_file(struct deffile *defs) +{ + struct deffile *curdefs = NULL; + + while (defs != NULL) { + curdefs = defs; + defs = defs->next; + if (curdefs->line != NULL) + free(curdefs->line); + free(curdefs); + } +} + +/* + * write_default_file(fname, defs) + * + * Write the default file back. + */ + +static int +write_default_file(char *fname, struct deffile *defs) +{ + FILE *file; + int ret = SA_OK; + sigset_t old, new; + + file = fopen(fname, "w+"); + if (file != NULL) { + (void) sigprocmask(SIG_BLOCK, NULL, &new); + (void) sigaddset(&new, SIGHUP); + (void) sigaddset(&new, SIGINT); + (void) sigaddset(&new, SIGQUIT); + (void) sigaddset(&new, SIGTSTP); + (void) sigprocmask(SIG_SETMASK, &new, &old); + while (defs != NULL) { + (void) fputs(defs->line, file); + defs = defs->next; + } + (void) fsync(fileno(file)); + (void) sigprocmask(SIG_SETMASK, &old, NULL); + (void) fclose(file); + } else { + switch (errno) { + case EPERM: + case EACCES: + ret = SA_NO_PERMISSION; + break; + default: + ret = SA_SYSTEM_ERR; + } + } + return (ret); +} + + +/* + * set_default_file_value(tag, value) + * + * Set the default file value for tag to value. Then rewrite the file. + * tag and value are always set. The caller must ensure this. + */ + +#define MAX_STRING_LENGTH 256 +static int +set_default_file_value(char *tag, char *value) +{ + int ret = SA_OK; + struct deffile *root; + struct deffile *defs; + struct deffile *prev; + char string[MAX_STRING_LENGTH]; + int len; + int update = 0; + + (void) snprintf(string, MAX_STRING_LENGTH, "%s=", tag); + len = strlen(string); + + root = defs = read_default_file(NFSADMIN); + if (root == NULL) { + if (errno == EPERM || errno == EACCES) + ret = SA_NO_PERMISSION; + else + ret = SA_SYSTEM_ERR; + } else { + while (defs != NULL) { + if (defs->line != NULL && + strncasecmp(defs->line, string, len) == 0) { + /* replace with the new value */ + free(defs->line); + fixcaseupper(tag); + (void) snprintf(string, sizeof (string), "%s=%s\n", + tag, value); + string[MAX_STRING_LENGTH - 1] = '\0'; + defs->line = strdup(string); + update = 1; + break; + } + defs = defs->next; + } + if (!update) { + defs = root; + /* didn't find, so see if it is a comment */ + (void) snprintf(string, MAX_STRING_LENGTH, "#%s=", tag); + len = strlen(string); + while (defs != NULL) { + if (strncasecmp(defs->line, string, len) == 0) { + /* replace with the new value */ + free(defs->line); + fixcaseupper(tag); + (void) snprintf(string, sizeof (string), + "%s=%s\n", tag, value); + string[MAX_STRING_LENGTH - 1] = '\0'; + defs->line = strdup(string); + update = 1; + break; + } + defs = defs->next; + } + } + if (!update) { + fixcaseupper(tag); + (void) snprintf(string, sizeof (string), "%s=%s\n", + tag, value); + prev = root; + while (prev->next != NULL) + prev = prev->next; + defs = malloc(sizeof (struct deffile)); + prev->next = defs; + if (defs != NULL) { + defs->next = NULL; + defs->line = strdup(string); + } + } + if (update) { + ret = write_default_file(NFSADMIN, root); + } + free_default_file(root); + } + return (ret); +} + +/* + * service_in_state(service, chkstate) + * + * Want to know if the specified service is in the desired state + * (chkstate) or not. Return true (1) if it is and false (0) if it + * isn't. + */ +static int +service_in_state(char *service, const char *chkstate) +{ + char *state; + int ret = B_FALSE; + + state = smf_get_state(service); + if (state != NULL) { + /* got the state so get the equality for the return value */ + ret = strcmp(state, chkstate) == 0 ? B_TRUE : B_FALSE; + free(state); + } + return (ret); +} + +/* + * restart_service(svcs) + * + * Walk through the bit mask of services that need to be restarted in + * order to use the new property values. Some properties affect + * multiple daemons. Should only restart a service if it is currently + * enabled (online). + */ + +static void +restart_service(uint32_t svcs) +{ + uint32_t mask; + int ret; + char *service; + + for (mask = 1; svcs != 0; mask <<= 1) { + switch (svcs & mask) { + case SVC_LOCKD: + service = LOCKD; + break; + case SVC_STATD: + service = STATD; + break; + case SVC_NFSD: + service = NFSD; + break; + case SVC_MOUNTD: + service = MOUNTD; + break; + case SVC_NFS4CBD: + service = NFS4CBD; + break; + case SVC_NFSMAPID: + service = NFSMAPID; + break; + case SVC_RQUOTAD: + service = RQUOTAD; + break; + case SVC_NFSLOGD: + service = NFSLOGD; + break; + default: + continue; + } + + /* + * Only attempt to restart the service if it is + * currently running. In the future, it may be + * desirable to use smf_refresh_instance if the NFS + * services ever implement the refresh method. + */ + if (service_in_state(service, SCF_STATE_STRING_ONLINE)) { + ret = smf_restart_instance(service); + /* + * There are only a few SMF errors at this point, but + * it is also possible that a bad value may have put + * the service into maintenance if there wasn't an + * SMF level error. + */ + if (ret != 0) { + (void) fprintf(stderr, + dgettext(TEXT_DOMAIN, + "%s failed to restart: %s\n"), + scf_strerror(scf_error())); + } else { + /* + * Check whether it has gone to "maintenance" + * mode or not. Maintenance implies something + * went wrong. + */ + if (service_in_state(service, SCF_STATE_STRING_MAINT)) { + (void) fprintf(stderr, + dgettext(TEXT_DOMAIN, + "%s failed to restart\n"), + service); + } + } + } + svcs &= ~mask; + } +} + +/* + * nfs_minmax_check(name, value) + * + * Verify that the value for the property specified by index is valid + * relative to the opposite value in the case of a min/max variable. + * Currently, server_minvers/server_maxvers and + * client_minvers/client_maxvers are the only ones to check. + */ + +static int +nfs_minmax_check(int index, int value) +{ + int val; + char *pval; + sa_property_t prop; + sa_optionset_t opts; + int ret = B_TRUE; + + if (proto_options[index].other != NULL) { + /* have a property to compare against */ + opts = nfs_get_proto_set(); + prop = sa_get_property(opts, proto_options[index].other); + /* + * If we don't find the property, assume default + * values which will work since the max will be at the + * max and the min at the min. + */ + if (prop != NULL) { + pval = sa_get_property_attr(prop, "value"); + if (pval != NULL) { + val = strtoul(pval, NULL, 0); + if (proto_options[index].compare == OPT_CMP_LE) { + ret = value <= val ? B_TRUE : B_FALSE; + } else if (proto_options[index].compare == OPT_CMP_GE) { + ret = value >= val ? B_TRUE : B_FALSE; + } + } + } + } + return (ret); +} + +/* + * nfs_validate_proto_prop(index, name, value) + * + * Verify that the property specifed by name can take the new + * value. This is a sanity check to prevent bad values getting into + * the default files. All values need to be checked against what is + * allowed by their defined type. If a type isn't explicitly defined + * here, it is treated as a string. + * + * Note that OPT_TYPE_NUMBER will additionally check that the value is + * within the range specified and potentially against another property + * value as well as specified in the proto_options members other and + * compare. + */ + +static int +nfs_validate_proto_prop(int index, char *name, char *value) +{ + int ret = SA_OK; + char *cp; +#ifdef lint + name = name; +#endif + + switch (proto_options[index].type) { + case OPT_TYPE_NUMBER: + if (!is_a_number(value)) + ret = SA_BAD_VALUE; + else { + int val; + val = strtoul(value, NULL, 0); + if (val < proto_options[index].minval || + val > proto_options[index].maxval) + ret = SA_BAD_VALUE; + /* + * For server_versmin/server_versmax and + * client_versmin/client_versmax, the value of the + * min(max) should be checked to be correct relative + * to the current max(min). + */ + if (!nfs_minmax_check(index, val)) { + ret = SA_BAD_VALUE; + } + } + break; + + case OPT_TYPE_DOMAIN: + /* + * needs to be a qualified domain so will have at + * least one period and other characters on either + * side of it. A zero length string is also allowed + * and is the way to turn off the override. + */ + if (strlen(value) == 0) + break; + cp = strchr(value, '.'); + if (cp == NULL || cp == value || strchr(value, '@') != NULL) + ret = SA_BAD_VALUE; + break; + + case OPT_TYPE_BOOLEAN: + if (strlen(value) == 0 || + strcasecmp(value, "true") == 0 || + strcmp(value, "1") == 0 || + strcasecmp(value, "false") == 0 || + strcmp(value, "0") == 0) { + ret = SA_OK; + } else { + ret = SA_BAD_VALUE; + } + break; + + case OPT_TYPE_ONOFF: + if (strcasecmp(value, "on") != 0 && + strcasecmp(value, "off") != 0) { + ret = SA_BAD_VALUE; + } + break; + + case OPT_TYPE_PROTOCOL: + if (strcasecmp(value, "all") != 0 && + strcasecmp(value, "tcp") != 0 && + strcasecmp(value, "udp") != 0) + ret = SA_BAD_VALUE; + break; + + default: + /* treat as a string */ + break; + } + return (ret); +} + +/* + * nfs_set_proto_prop(prop) + * + * check that prop is valid. + */ + +static int +nfs_set_proto_prop(sa_property_t prop) +{ + int ret = SA_OK; + char *name; + char *value; + + name = sa_get_property_attr(prop, "type"); + value = sa_get_property_attr(prop, "value"); + if (name != NULL && value != NULL) { + int index = findprotoopt(name, 1); + if (index >= 0) { + /* should test for valid value */ + ret = nfs_validate_proto_prop(index, name, value); + if (ret == SA_OK) + ret = set_default_file_value(proto_options[index].tag, + value); + if (ret == SA_OK) + restart_service(proto_options[index].svcs); + } + } + if (name != NULL) + sa_free_attr_string(name); + if (value != NULL) + sa_free_attr_string(value); + return (ret); +} + +/* + * nfs_get_status() + * + * What is the current status of the nfsd? We use the SMF state here. + * Caller must free the returned value. + */ + +static char * +nfs_get_status() +{ + char *state; + state = smf_get_state(NFSD); + return (state != NULL ? state : strdup("-")); +} + +/* + * nfs_space_alias(alias) + * + * Lookup the space (security) name. If it is default, convert to the + * real name. + */ + +static char * +nfs_space_alias(char *space) +{ + char *name = space; + seconfig_t secconf; + + /* + * Only the space named "default" is special. If it is used, + * the default needs to be looked up and the real name used. + * This is normally "sys" but could be changed. We always + * change defautl to the real name. + */ + if (strcmp(space, "default") == 0 && + nfs_getseconfig_default(&secconf) == 0) { + if (nfs_getseconfig_bynumber(secconf.sc_nfsnum, &secconf) == 0) + name = secconf.sc_name; + } + return (strdup(name)); +} diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/libshare_nfs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/libshare_nfs.h Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,131 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * basic API declarations for share management + */ + +#ifndef _LIBSHARE_NFS_H +#define _LIBSHARE_NFS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* property names used by NFS */ +#define SHOPT_RO "ro" +#define SHOPT_RW "rw" + +#define SHOPT_SEC "sec" +#define SHOPT_SECURE "secure" +#define SHOPT_ROOT "root" +#define SHOPT_ANON "anon" +#define SHOPT_WINDOW "window" +#define SHOPT_NOSUB "nosub" +#define SHOPT_NOSUID "nosuid" +#define SHOPT_ACLOK "aclok" +#define SHOPT_PUBLIC "public" +#define SHOPT_INDEX "index" +#define SHOPT_LOG "log" +#define SHOPT_CKSUM "cksum" + +/* + * defined options types. These should be in a file rather than + * compiled in. Until there is a plugin mechanism to add new types, + * this is sufficient. + */ +#define OPT_TYPE_ANY 0 +#define OPT_TYPE_STRING 1 +#define OPT_TYPE_BOOLEAN 2 +#define OPT_TYPE_NUMBER 3 +#define OPT_TYPE_RANGE 4 +#define OPT_TYPE_USER 5 +#define OPT_TYPE_ACCLIST 6 +#define OPT_TYPE_DEPRECATED 7 +#define OPT_TYPE_SECURITY 8 +#define OPT_TYPE_PATH 9 +#define OPT_TYPE_FILE 10 +#define OPT_TYPE_LOGTAG 11 +#define OPT_TYPE_STRINGSET 12 +#define OPT_TYPE_DOMAIN 13 +#define OPT_TYPE_ONOFF 14 +#define OPT_TYPE_PROTOCOL 15 + +#define OPT_SHARE_ONLY 1 + +struct option_defs { + char *tag; + int index; + int type; + int share; /* share only option */ + int (*check)(char *); +}; + +/* + * service bit mask values + */ +#define SVC_LOCKD 0x0001 +#define SVC_STATD 0x0002 +#define SVC_NFSD 0x0004 +#define SVC_MOUNTD 0x0008 +#define SVC_NFS4CBD 0x0010 +#define SVC_NFSMAPID 0x0020 +#define SVC_RQUOTAD 0x0040 +#define SVC_NFSLOGD 0x0080 + +/* + * place holder for future service -- will move to daemon_utils.h when + * fully implemented. + */ +#define NFSLOGD "svc:/network/nfs/log:default" + +/* The NFS export structure flags for read/write modes */ +#define NFS_RWMODES (M_RO|M_ROL|M_RW|M_RWL) + +/* other values */ +/* max size of 64-bit integer in digits plus a bit extra */ +#define MAXDIGITS 32 + +/* external variable */ +extern boolean_t nfsl_errs_to_syslog; + +/* imported functions */ +extern int exportfs(char *, struct exportdata *); +extern void _check_services(char **); +extern int nfs_getseconfig_default(seconfig_t *); +extern int nfs_getseconfig_byname(char *, seconfig_t *); +extern bool_t nfs_get_root_principal(seconfig_t *, char *, caddr_t *); +extern int nfsl_getconfig_list(nfsl_config_t **); +extern void nfsl_freeconfig_list(nfsl_config_t **); +extern nfsl_config_t *nfsl_findconfig(nfsl_config_t *, char *, int *); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBSHARE_NFS_H */ diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/mapfile-vers --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/mapfile-vers Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +SUNWprivate_1.1 { + global: + sa_plugin_ops; + local: + *; +}; + diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/sparc/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/sparc/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/nfs/sparcv9/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/nfs/sparcv9/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff -r 9f4024db0edf -r 00586900e34c usr/src/lib/libshare/sparcv9/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libshare/sparcv9/Makefile Wed Mar 28 08:50:43 2007 -0700 @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/SUNWarc/prototype_i386 --- a/usr/src/pkgdefs/SUNWarc/prototype_i386 Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/SUNWarc/prototype_i386 Wed Mar 28 08:50:43 2007 -0700 @@ -129,6 +129,7 @@ s none usr/lib/amd64/llib-lsec.ln=../../../lib/amd64/llib-lsec.ln s none usr/lib/amd64/llib-lsecdb.ln=../../../lib/amd64/llib-lsecdb.ln s none usr/lib/amd64/llib-lsendfile.ln=../../../lib/amd64/llib-lsendfile.ln +f none usr/lib/amd64/llib-lshare.ln 644 root bin f none usr/lib/amd64/llib-lsip.ln 644 root bin f none usr/lib/amd64/llib-lsldap.ln 644 root bin f none usr/lib/amd64/llib-lsmbios.ln 644 root bin diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/SUNWarc/prototype_sparc --- a/usr/src/pkgdefs/SUNWarc/prototype_sparc Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/SUNWarc/prototype_sparc Wed Mar 28 08:50:43 2007 -0700 @@ -124,6 +124,7 @@ s none usr/lib/sparcv9/llib-lsec.ln=../../../lib/sparcv9/llib-lsec.ln s none usr/lib/sparcv9/llib-lsecdb.ln=../../../lib/sparcv9/llib-lsecdb.ln s none usr/lib/sparcv9/llib-lsendfile.ln=../../../lib/sparcv9/llib-lsendfile.ln +f none usr/lib/sparcv9/llib-lshare.ln 644 root bin f none usr/lib/sparcv9/llib-lsip.ln 644 root bin f none usr/lib/sparcv9/llib-lsldap.ln 644 root bin f none usr/lib/sparcv9/llib-lsmbios.ln 644 root bin diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/SUNWcsu/prototype_com --- a/usr/src/pkgdefs/SUNWcsu/prototype_com Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/SUNWcsu/prototype_com Wed Mar 28 08:50:43 2007 -0700 @@ -861,7 +861,6 @@ f none usr/sbin/sharectl 555 root bin f none usr/sbin/sharemgr 555 root bin f none usr/lib/libshare.so.1 755 root bin -s none usr/lib/libshare.so=./libshare.so.1 l none usr/sbin/share=../../usr/sbin/sharemgr l none usr/sbin/unshare=../../usr/sbin/sharemgr f none usr/sbin/unshareall 555 root bin diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/SUNWcsu/prototype_i386 --- a/usr/src/pkgdefs/SUNWcsu/prototype_i386 Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/SUNWcsu/prototype_i386 Wed Mar 28 08:50:43 2007 -0700 @@ -144,6 +144,9 @@ s none usr/lib/secure/64=amd64 d none usr/lib/amd64 755 root bin s none usr/lib/amd64/ld.so.1=../../../lib/amd64/ld.so.1 +f none usr/lib/amd64/libshare.so.1 755 root bin +d none usr/lib/fs/nfs 755 root sys +d none usr/lib/fs/nfs/amd64 755 root sys d none usr/sbin/amd64 755 root bin f none usr/sbin/amd64/add_drv 555 root sys f none usr/sbin/amd64/modinfo 555 root sys diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/SUNWcsu/prototype_sparc --- a/usr/src/pkgdefs/SUNWcsu/prototype_sparc Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/SUNWcsu/prototype_sparc Wed Mar 28 08:50:43 2007 -0700 @@ -98,6 +98,9 @@ s none usr/lib/secure/64=sparcv9 d none usr/lib/sparcv9 755 root bin s none usr/lib/sparcv9/ld.so.1=../../../lib/sparcv9/ld.so.1 +f none usr/lib/sparcv9/libshare.so.1 755 root bin +d none usr/lib/fs/nfs 755 root sys +d none usr/lib/fs/nfs/sparcv9 755 root sys l none usr/sbin/prtdiag=../../usr/lib/platexec d none usr/sbin/sparcv9 755 root bin f none usr/sbin/sparcv9/add_drv 555 root sys diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/SUNWnfssu/prototype_com --- a/usr/src/pkgdefs/SUNWnfssu/prototype_com Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/SUNWnfssu/prototype_com Wed Mar 28 08:50:43 2007 -0700 @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -47,7 +47,7 @@ d none usr/lib 755 root bin d none usr/lib/fs 755 root sys d none usr/lib/fs/nfs 755 root sys -f none usr/lib/fs/nfs/libshare_nfs.so 555 root bin +f none usr/lib/fs/nfs/libshare_nfs.so.1 755 root bin d none usr/lib/nfs 755 root sys f none usr/lib/nfs/mountd 555 root bin f none usr/lib/nfs/nfsd 555 root bin diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/SUNWnfssu/prototype_i386 --- a/usr/src/pkgdefs/SUNWnfssu/prototype_i386 Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/SUNWnfssu/prototype_i386 Wed Mar 28 08:50:43 2007 -0700 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,9 +18,8 @@ # # CDDL HEADER END # -# -# Copyright (c) 2000 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # @@ -47,3 +45,5 @@ # # SUNWnfssu # +d none usr/lib/fs/nfs/amd64 755 root sys +f none usr/lib/fs/nfs/amd64/libshare_nfs.so.1 755 root bin diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/SUNWnfssu/prototype_sparc --- a/usr/src/pkgdefs/SUNWnfssu/prototype_sparc Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/SUNWnfssu/prototype_sparc Wed Mar 28 08:50:43 2007 -0700 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,9 +18,8 @@ # # CDDL HEADER END # -# -# Copyright (c) 2000 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # @@ -46,3 +44,5 @@ # # SUNWnfssu # +d none usr/lib/fs/nfs/sparcv9 755 root sys +f none usr/lib/fs/nfs/sparcv9/libshare_nfs.so.1 755 root bin diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/etc/exception_list_i386 --- a/usr/src/pkgdefs/etc/exception_list_i386 Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/etc/exception_list_i386 Wed Mar 28 08:50:43 2007 -0700 @@ -816,3 +816,14 @@ lib/llib-liscsitgt.ln i386 lib/amd64/libiscsitgt.so i386 lib/amd64/llib-liscsitgt.ln i386 +# +# libshare is private and the 64-bit sharemgr is not delivered. +# +usr/lib/libshare.so i386 +usr/lib/amd64/libshare.so i386 +usr/lib/fs/nfs/libshare_nfs.so i386 +usr/lib/fs/nfs/amd64/libshare_nfs.so i386 +usr/include/libshare_impl.h i386 +usr/include/scfutil.h i386 +usr/sbin/i86/sharemgr i386 +usr/sbin/amd64/sharemgr i386 diff -r 9f4024db0edf -r 00586900e34c usr/src/pkgdefs/etc/exception_list_sparc --- a/usr/src/pkgdefs/etc/exception_list_sparc Wed Mar 28 07:55:32 2007 -0700 +++ b/usr/src/pkgdefs/etc/exception_list_sparc Wed Mar 28 08:50:43 2007 -0700 @@ -885,6 +885,17 @@ lib/sparcv9/libiscsitgt.so sparc lib/sparcv9/llib-liscsitgt.ln sparc # +# libshare is private and the 64-bit sharemg is not delivered. +# +usr/lib/libshare.so sparc +usr/lib/sparcv9/libshare.so sparc +usr/lib/fs/nfs/libshare_nfs.so sparc +usr/lib/fs/nfs/sparcv9/libshare_nfs.so sparc +usr/include/libshare_impl.h sparc +usr/include/scfutil.h sparc +usr/sbin/sparcv9/sharemgr sparc +usr/sbin/sparcv7/sharemgr sparc +# # These files are installed in the proto area by the build of libpri for # the benefit of the builds of FMA libldom, Zeus, picld plugins, and/or # other libpri consumers. However, the libpri interfaces are private to