4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
27 * AUTOMOUNT specific functions
38 #include <sys/types.h>
42 #include "libshare_impl.h"
51 static int autofs_init();
52 static void autofs_fini();
53 static int autofs_validate_property(sa_handle_t
, sa_property_t
, sa_optionset_t
);
54 static int autofs_set_proto_prop(sa_property_t
);
55 static sa_protocol_properties_t
autofs_get_proto_set();
56 static char *autofs_get_status();
57 static uint64_t autofs_features();
59 static int initautofsprotofromsmf();
60 static int true_false_validator(int index
, char *value
);
61 static int strlen_validator(int index
, char *value
);
62 static int range_check_validator(int index
, char *value
);
65 * ops vector that provides the protocol specific info and operations
66 * for share management.
68 struct sa_plugin_ops sa_plugin_ops
= {
71 autofs_init
, /* Init autofs */
72 autofs_fini
, /* Fini autofs */
73 NULL
, /* Start Sharing */
74 NULL
, /* stop sharing */
75 autofs_validate_property
,
76 NULL
, /* valid_space */
77 NULL
, /* security_prop */
78 NULL
, /* parse optstring */
79 NULL
, /* format optstring */
80 autofs_set_proto_prop
, /* Set properties */
81 autofs_get_proto_set
, /* get properties */
82 autofs_get_status
, /* get status */
83 NULL
, /* space_alias */
84 NULL
, /* update_legacy */
85 NULL
, /* delete_legacy */
86 NULL
, /* change notify */
87 NULL
, /* enable resource */
88 NULL
, /* disable resource */
89 autofs_features
, /* features */
90 NULL
, /* transient shares */
91 NULL
, /* notify resource */
92 NULL
, /* rename resource */
93 NULL
, /* run_command */
94 NULL
, /* command_help */
95 NULL
/* delete_proto_section */
99 static sa_protocol_properties_t protoset
;
101 #define AUTOMOUNT_VERBOSE_DEFAULT 0
102 #define AUTOMOUNTD_VERBOSE_DEFAULT 0
103 #define AUTOMOUNT_NOBROWSE_DEFAULT 0
104 #define AUTOMOUNT_TIMEOUT_DEFAULT 600
105 #define AUTOMOUNT_TRACE_DEFAULT 0
107 * Protocol Management functions
109 struct proto_option_defs
{
111 char *name
; /* display name -- remove protocol identifier */
120 int (*check
)(int, char *);
121 } proto_options
[] = {
122 #define PROTO_OPT_AUTOMOUNT_TIMEOUT 0
124 "timeout", PROTO_OPT_AUTOMOUNT_TIMEOUT
,
125 SCF_TYPE_INTEGER
, AUTOMOUNT_TIMEOUT_DEFAULT
,
126 1, INT32_MAX
, range_check_validator
},
127 #define PROTO_OPT_AUTOMOUNT_VERBOSE 1
128 { "automount_verbose",
129 "automount_verbose", PROTO_OPT_AUTOMOUNT_VERBOSE
,
130 SCF_TYPE_BOOLEAN
, AUTOMOUNT_VERBOSE_DEFAULT
, 0, 1,
131 true_false_validator
},
132 #define PROTO_OPT_AUTOMOUNTD_VERBOSE 2
133 { "automountd_verbose",
134 "automountd_verbose", PROTO_OPT_AUTOMOUNTD_VERBOSE
,
135 SCF_TYPE_BOOLEAN
, AUTOMOUNTD_VERBOSE_DEFAULT
, 0, 1,
136 true_false_validator
},
137 #define PROTO_OPT_AUTOMOUNTD_NOBROWSE 3
139 "nobrowse", PROTO_OPT_AUTOMOUNTD_NOBROWSE
, SCF_TYPE_BOOLEAN
,
140 AUTOMOUNT_NOBROWSE_DEFAULT
, 0, 1, true_false_validator
},
141 #define PROTO_OPT_AUTOMOUNTD_TRACE 4
143 "trace", PROTO_OPT_AUTOMOUNTD_TRACE
,
144 SCF_TYPE_INTEGER
, AUTOMOUNT_TRACE_DEFAULT
,
145 0, 20, range_check_validator
},
146 #define PROTO_OPT_AUTOMOUNTD_ENV 5
148 "environment", PROTO_OPT_AUTOMOUNTD_ENV
, SCF_TYPE_ASTRING
,
149 0, 0, 1024, strlen_validator
},
150 {NULL
, NULL
, 0, 0, 0, 0, 0, NULL
}
153 #define AUTOFS_PROP_MAX (sizeof (proto_options) / sizeof (proto_options[0]))
159 char number
[MAXDIGITS
];
161 for (i
= 0; proto_options
[i
].tag
!= NULL
; i
++) {
163 prop
= sa_get_protocol_property(protoset
,
164 proto_options
[i
].name
);
166 /* add the default value */
167 switch (proto_options
[i
].type
) {
168 case SCF_TYPE_INTEGER
:
169 (void) snprintf(number
, sizeof (number
), "%d",
170 proto_options
[i
].defvalue
.intval
);
171 prop
= sa_create_property(proto_options
[i
].name
,
175 case SCF_TYPE_BOOLEAN
:
176 prop
= sa_create_property(proto_options
[i
].name
,
177 proto_options
[i
].defvalue
.intval
?
182 /* treat as strings of zero length */
183 prop
= sa_create_property(proto_options
[i
].name
,
188 (void) sa_add_protocol_property(protoset
, prop
);
198 if (sa_plugin_ops
.sa_init
!= autofs_init
) {
199 (void) printf(dgettext(TEXT_DOMAIN
,
200 "AUTOFS plugin not installed properly\n"));
201 return (SA_CONFIG_ERR
);
204 ret
= initautofsprotofromsmf();
206 (void) printf(dgettext(TEXT_DOMAIN
,
207 "AUTOFS plugin problem with SMF properties: %s\n"),
218 if (protoset
!= NULL
) {
219 xmlFreeNode(protoset
);
231 findprotoopt(char *propname
)
235 for (i
= 0; proto_options
[i
].tag
!= NULL
; i
++)
236 if (strcmp(proto_options
[i
].name
, propname
) == 0)
242 autofs_validate_property(sa_handle_t handle
, sa_property_t property
,
243 sa_optionset_t parent
)
250 propname
= sa_get_property(property
, "type");
251 if (propname
== NULL
)
252 return (SA_NO_SUCH_PROP
);
254 if ((optionindex
= findprotoopt(propname
)) < 0)
255 ret
= SA_NO_SUCH_PROP
;
258 if (propname
!= NULL
)
259 sa_free_attr_string(propname
);
263 value
= sa_get_property_attr(property
, "value");
266 * If any property is added to AUTOFS, which is a different
267 * type than the below list, a case needs to be added for that
268 * to check the values. For now AUTOFS type are just integers,
269 * string and boolean properties. Just taking care of them.
271 switch (proto_options
[optionindex
].type
) {
272 case SCF_TYPE_INTEGER
:
273 case SCF_TYPE_BOOLEAN
:
274 case SCF_TYPE_ASTRING
:
275 ret
= proto_options
[optionindex
].check(optionindex
,
285 sa_free_attr_string(value
);
286 if (propname
!= NULL
)
287 sa_free_attr_string(propname
);
292 * service_in_state(service, chkstate)
294 * Want to know if the specified service is in the desired state
295 * (chkstate) or not. Return true (1) if it is and false (0) if it
299 service_in_state(char *service
, const char *chkstate
)
304 state
= smf_get_state(service
);
306 /* got the state so get the equality for the return value */
307 ret
= strcmp(state
, chkstate
) == 0 ? B_TRUE
: B_FALSE
;
314 restart_service(char *service
)
319 * Only attempt to restart the service if it is
320 * currently running. In the future, it may be
321 * desirable to use smf_refresh_instance if the AUTOFS
322 * services ever implement the refresh method.
324 if (service_in_state(service
, SCF_STATE_STRING_ONLINE
)) {
325 ret
= smf_restart_instance(service
);
327 * There are only a few SMF errors at this point, but
328 * it is also possible that a bad value may have put
329 * the service into maintenance if there wasn't an
333 (void) fprintf(stderr
,
334 dgettext(TEXT_DOMAIN
,
335 "%s failed to restart: %s\n"),
336 scf_strerror(scf_error()));
339 * Check whether it has gone to "maintenance"
340 * mode or not. Maintenance implies something
343 if (service_in_state(service
,
344 SCF_STATE_STRING_MAINT
)) {
345 (void) fprintf(stderr
,
346 dgettext(TEXT_DOMAIN
,
347 "%s failed to restart\n"),
355 is_a_number(char *number
)
360 if (strncmp(number
, "0x", 2) == 0) {
363 } else if (*number
== '-') {
364 number
++; /* skip the minus */
366 while (ret
== 1 && *number
!= '\0') {
368 ret
= isxdigit(*number
++);
370 ret
= isdigit(*number
++);
379 * convert a string to lower case (inplace).
383 fixcaselower(char *str
)
386 *str
= tolower(*str
);
392 * skipwhitespace(str)
394 * Skip leading white space. It is assumed that it is called with a
398 skipwhitespace(char *str
)
400 while (*str
&& isspace(*str
))
409 * Extract the property and value out of the line and create the
410 * property in the optionset.
413 extractprop(char *name
, char *value
)
422 name
= skipwhitespace(name
);
424 index
= findprotoopt(name
);
427 prop
= sa_create_property(proto_options
[index
].name
, value
);
429 ret
= sa_add_protocol_property(protoset
, prop
);
437 initautofsprotofromsmf(void)
440 char value
[PATH_MAX
];
441 int ret
= SA_OK
, bufsz
= 0, i
;
442 char *instance
= NULL
;
445 protoset
= sa_create_protocol_properties("autofs");
446 if (protoset
!= NULL
) {
447 for (i
= 0; proto_options
[i
].tag
!= NULL
; i
++) {
448 bzero(value
, PATH_MAX
);
449 (void) strncpy(name
, proto_options
[i
].name
, PATH_MAX
);
450 sctype
= proto_options
[i
].type
;
452 ret
= autofs_smf_get_prop(name
, value
,
453 instance
, sctype
, AUTOFS_FMRI
, &bufsz
);
455 ret
= extractprop(name
, value
);
465 range_check_validator(int index
, char *value
)
468 if (!is_a_number(value
)) {
473 val
= strtoul(value
, NULL
, 0);
475 return (SA_BAD_VALUE
);
477 if (val
< proto_options
[index
].minval
||
478 val
> proto_options
[index
].maxval
)
485 true_false_validator(int index
, char *value
)
488 if ((strcasecmp(value
, "true") == 0) ||
489 (strcasecmp(value
, "on") == 0) ||
490 (strcasecmp(value
, "yes") == 0) ||
491 (strcmp(value
, "1") == 0) ||
492 (strcasecmp(value
, "false") == 0) ||
493 (strcasecmp(value
, "off") == 0) ||
494 (strcasecmp(value
, "no") == 0) ||
495 (strcmp(value
, "0") == 0)) {
498 return (SA_BAD_VALUE
);
502 strlen_validator(int index
, char *value
)
506 if (proto_options
[index
].minval
== 0) {
509 return (SA_BAD_VALUE
);
512 if (strlen(value
) > proto_options
[index
].maxval
||
513 strlen(value
) < proto_options
[index
].minval
)
519 autofs_validate_proto_prop(int index
, char *name
, char *value
)
521 return (proto_options
[index
].check(index
, value
));
525 autofs_set_proto_prop(sa_property_t prop
)
529 char *value
, *instance
= NULL
;
532 name
= sa_get_property_attr(prop
, "type");
533 value
= sa_get_property_attr(prop
, "value");
534 if (name
!= NULL
&& value
!= NULL
) {
535 int index
= findprotoopt(name
);
537 ret
= autofs_validate_proto_prop(index
, name
, value
);
539 sctype
= proto_options
[index
].type
;
540 if (sctype
== SCF_TYPE_BOOLEAN
) {
542 sa_free_attr_string(value
);
543 if (string_to_boolean(value
) == 0)
548 ret
= autofs_smf_set_prop(name
, value
,
549 instance
, sctype
, AUTOFS_FMRI
);
551 * Make an instance based FMRI.
552 * For now its DEFAULT_AUTOFS_FMRI.
555 restart_service(AUTOFS_DEFAULT_FMRI
);
558 ret
= SA_NO_SUCH_PROP
;
565 sa_free_attr_string(name
);
567 sa_free_attr_string(value
);
572 static sa_protocol_properties_t
573 autofs_get_proto_set(void)
579 autofs_features(void)
585 autofs_get_status(void)
587 return (smf_get_state(AUTOFS_DEFAULT_FMRI
));