diff options
author | Dai Ngo <dai.ngo@sun.com> | 2009-10-14 11:15:07 -0500 |
---|---|---|
committer | Dai Ngo <dai.ngo@sun.com> | 2009-10-14 11:15:07 -0500 |
commit | 7a286c471efbab8562f7655a82931904703fffe0 (patch) | |
tree | bbd1ea3af4176ce7e295afaa9eb7cb86b95010c0 /usr/src | |
parent | 635216b673cf196ac523ff2a7ab715717e553292 (diff) | |
download | illumos-gate-7a286c471efbab8562f7655a82931904703fffe0.tar.gz |
6886081 Solaris needs reparse point support (PSARC 2009/387)
PSARC 2009/387 Pathname Reparse Points
Diffstat (limited to 'usr/src')
53 files changed, 2192 insertions, 22 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint index e9f7a30667..873460b38d 100644 --- a/usr/src/Makefile.lint +++ b/usr/src/Makefile.lint @@ -405,6 +405,7 @@ COMMON_SUBDIRS = \ lib/libraidcfg \ lib/librcm \ lib/librdc \ + lib/libreparse \ lib/librestart \ lib/librstp \ lib/librt \ diff --git a/usr/src/cmd/fs.d/Makefile b/usr/src/cmd/fs.d/Makefile index 20ffc9f17c..a2e02bba6a 100644 --- a/usr/src/cmd/fs.d/Makefile +++ b/usr/src/cmd/fs.d/Makefile @@ -43,7 +43,7 @@ include ../Makefile.cmd SUBDIR1= lofs zfs SUBDIR2= dev fd pcfs nfs hsfs proc ctfs udfs ufs tmpfs cachefs \ - autofs mntfs objfs sharefs smbclnt + autofs mntfs objfs sharefs smbclnt reparsed SUBDIRS= $(SUBDIR1) $(SUBDIR2) I18NDIRS= $(SUBDIR2) diff --git a/usr/src/cmd/fs.d/reparsed/Makefile b/usr/src/cmd/fs.d/reparsed/Makefile new file mode 100644 index 0000000000..9df265a3c9 --- /dev/null +++ b/usr/src/cmd/fs.d/reparsed/Makefile @@ -0,0 +1,60 @@ +# +# 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 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# +include $(SRC)/Makefile.master + +FSTYPE= reparse +TYPEPROG= reparsed + +include ../Makefile.fstype + +OBJS= $(TYPEPROG).o +SRCS= $(TYPEPROG).c +POFILE= $(TYPEPROG).po + +CLOBBERFILES += $(TYPEPROG) + +CFLAGS += $(CCVERBOSE) +C99MODE= $(C99_ENABLE) + +LDLIBS += -lreparse -lnsl + +CPPFLAGS += -I$(SRC)/uts/common + +all: $(TYPEPROG) + +catalog: $(POFILE) + +lint: lint_SRCS + +clean: + $(RM) $(OBJS) $(POFILE) + +MANIFEST= reparsed.xml +ROOTMANIFESTDIR= $(ROOTSVCNETWORKSHARES) +$(ROOTMANIFEST) := FILEMODE = 0444 +install: $(ROOTMANIFEST) + +.KEEP_STATE: diff --git a/usr/src/cmd/fs.d/reparsed/reparsed.c b/usr/src/cmd/fs.d/reparsed/reparsed.c new file mode 100644 index 0000000000..17027b0c78 --- /dev/null +++ b/usr/src/cmd/fs.d/reparsed/reparsed.c @@ -0,0 +1,358 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Reparsed daemon + */ + +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <memory.h> +#include <alloca.h> +#include <ucontext.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <strings.h> +#include <door.h> +#include <wait.h> +#include <libintl.h> +#include <locale.h> +#include <sys/param.h> +#include <sys/systeminfo.h> +#include <sys/thread.h> +#include <rpc/xdr.h> +#include <priv.h> +#include <sys/fs_reparse.h> +#include <priv_utils.h> +#include <rpcsvc/daemon_utils.h> + +#define REPARSED_CMD_OPTS "v" +#define DOOR_RESULT_BUFSZ (MAXPATHLEN + sizeof (reparsed_door_res_t)) +#define SAFETY_BUFFER 8*1024 + +static char *MyName; +static int verbose = 0; + +static int start_reparsed_svcs(); +static void daemonize(void); +static void reparsed_door_call_error(int error, int buflen); +static void reparsed_doorfunc(void *cookie, char *argp, size_t arg_size, + door_desc_t *dp, uint_t n_desc); + +static void +usage() +{ + syslog(LOG_ERR, "Usage: %s", MyName); + syslog(LOG_ERR, "\t[-v]\t\tverbose error messages)"); + exit(1); +} + +static void +warn_hup(int i) +{ + syslog(LOG_ERR, "SIGHUP received: ignored"); + (void) signal(SIGHUP, warn_hup); +} + +/* + * Processing for daemonization + */ +static void +daemonize(void) +{ + switch (fork()) { + case -1: + syslog(LOG_ERR, "reparsed: can't fork - errno %d", errno); + exit(2); + /* NOTREACHED */ + case 0: /* child */ + break; + + default: /* parent */ + _exit(0); + } + (void) chdir("/"); + + /* + * Close stdin, stdout, and stderr. + * Open again to redirect input+output + */ + (void) close(0); + (void) close(1); + (void) close(2); + (void) open("/dev/null", O_RDONLY); + (void) open("/dev/null", O_WRONLY); + (void) dup(1); + (void) setsid(); +} + +int +main(int argc, char *argv[]) +{ + pid_t pid; + int c, error; + struct rlimit rlset; + char *defval; + + /* + * There is no check for non-global zone and Trusted Extensions. + * Reparsed works in both of these environments as long as the + * services that use reparsed are supported. + */ + + MyName = argv[0]; + if (geteuid() != 0) { + syslog(LOG_ERR, "%s must be run as root", MyName); + exit(1); + } + + while ((c = getopt(argc, argv, REPARSED_CMD_OPTS)) != EOF) { + switch (c) { + case 'v': + verbose++; + break; + default: + usage(); + } + } + + daemonize(); + openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON); + + (void) _create_daemon_lock(REPARSED, DAEMON_UID, DAEMON_GID); + (void) enable_extended_FILE_stdio(-1, -1); + switch (_enter_daemon_lock(REPARSED)) { + case 0: + break; + case -1: + syslog(LOG_ERR, "Error locking for %s", REPARSED); + exit(2); + default: + /* daemon was already running */ + exit(0); + } + + (void) signal(SIGHUP, warn_hup); + + /* + * Make the process a privilege aware daemon. + * Only "basic" privileges are required. + * + */ + if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, 0, 0, + (char *)NULL) == -1) { + syslog(LOG_ERR, "should be run with sufficient privileges"); + exit(3); + } + + /* + * Clear basic privileges not required by reparsed. + */ + __fini_daemon_priv(PRIV_PROC_FORK, PRIV_PROC_EXEC, PRIV_PROC_SESSION, + PRIV_FILE_LINK_ANY, PRIV_PROC_INFO, (char *)NULL); + + return (start_reparsed_svcs()); +} + +static void +reparsed_door_call_error(int error, int buflen) +{ + reparsed_door_res_t rpd_res; + + memset(&rpd_res, 0, sizeof (reparsed_door_res_t)); + rpd_res.res_status = error; + rpd_res.res_len = buflen; + door_return((char *)&rpd_res, sizeof (reparsed_door_res_t), NULL, 0); + + (void) door_return(NULL, 0, NULL, 0); + /* NOTREACHED */ +} + +/* + * reparsed_doorfunc + * + * argp: "service_type:service_data" string + * dp & n_desc: not used. + */ +static void +reparsed_doorfunc(void *cookie, char *argp, size_t arg_size, + door_desc_t *dp, uint_t n_desc) +{ + int err; + size_t bufsz; + char *svc_type, *svc_data; + char *cp, *buf, *sbuf, res_buf[DOOR_RESULT_BUFSZ]; + reparsed_door_res_t *resp; + + if ((argp == NULL) || (arg_size == 0)) { + reparsed_door_call_error(EINVAL, 0); + /* NOTREACHED */ + } + + if (verbose) + syslog(LOG_NOTICE, "reparsed_door: [%s, %d]", argp, arg_size); + + if ((svc_type = strdup(argp)) == NULL) { + reparsed_door_call_error(ENOMEM, 0); + /* NOTREACHED */ + } + + /* + * Door argument string comes in "service_type:service_data" format. + * Need to break it into separate "service_type" and "service_data" + * string before passing them to reparse_deref() to process them. + */ + if ((cp = strchr(svc_type, ':')) == NULL) { + free(svc_type); + reparsed_door_call_error(EINVAL, 0); + /* NOTREACHED */ + } + *cp++ = '\0'; + svc_data = cp; + + /* + * Setup buffer for reparse_deref(). 'bufsz' is the actual + * buffer size to hold the result returned by reparse_deref(). + */ + resp = (reparsed_door_res_t *)res_buf; + buf = resp->res_data; + bufsz = sizeof (res_buf) - sizeof (reparsed_door_res_t); + + /* + * reparse_deref() calls the service type plugin library to process + * the service data. The plugin library function should understand + * the context of the service data and should be the one to XDR the + * results before returning it to the caller. + */ + err = reparse_deref(svc_type, svc_data, buf, &bufsz); + + if (verbose) + syslog(LOG_NOTICE, + "reparsed_deref(svc_type: %s, data: %s, size: %d) -> %d", + svc_type, svc_data, bufsz, err); + + switch (err) { + case 0: + break; + + case EOVERFLOW: + /* + * bufsz was returned with size needed by reparse_deref(). + * + * We cannot use malloc() here because door_return() never + * returns, and memory allocated by malloc() would get leaked. + */ + sbuf = alloca(bufsz + sizeof (reparsed_door_res_t)); + if (sbuf == NULL || stack_inbounds(buf) == 0 || + stack_inbounds(buf + sizeof (reparsed_door_res_t) + + SAFETY_BUFFER - 1) == 0) { + free(svc_type); + reparsed_door_call_error(ENOMEM, 0); + /* NOTREACHED */ + } + + resp = (reparsed_door_res_t *)sbuf; + if ((err = reparse_deref(svc_type, svc_data, resp->res_data, + &bufsz)) == 0) + break; + + /* fall through */ + + default: + free(svc_type); + reparsed_door_call_error(err, 0); + /* NOTREACHED */ + } + + free(svc_type); + + if (verbose) + syslog(LOG_NOTICE, "reparsed_door_return <buf=%s> size=%d", + buf, bufsz); + + resp->res_status = 0; + resp->res_len = bufsz; + (void) door_return((char *)resp, bufsz + sizeof (reparsed_door_res_t), + NULL, 0); + + (void) door_return(NULL, 0, NULL, 0); + /* NOTREACHED */ +} + +static int +start_reparsed_svcs() +{ + int doorfd; + int dfd; + + if ((doorfd = door_create(reparsed_doorfunc, NULL, + DOOR_REFUSE_DESC|DOOR_NO_CANCEL)) == -1) { + syslog(LOG_ERR, "Unable to create door"); + return (1); + } + + /* + * Create a file system path for the door + */ + if ((dfd = open(REPARSED_DOOR, O_RDWR|O_CREAT|O_TRUNC, + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) { + syslog(LOG_ERR, "unable to open %s", REPARSED_DOOR); + (void) close(doorfd); + return (1); + } + + /* + * Clean up any stale associations + */ + (void) fdetach(REPARSED_DOOR); + + /* + * Register in the kernel namespace for door_ki_open(). + */ + if (fattach(doorfd, REPARSED_DOOR) == -1) { + syslog(LOG_ERR, "Unable to fattach door %s", REPARSED_DOOR); + (void) close(doorfd); + (void) close(dfd); + return (1); + } + (void) close(dfd); + + /* + * Wait for incoming calls + */ + /*CONSTCOND*/ + while (1) + (void) pause(); + + syslog(LOG_ERR, "Door server exited"); + return (10); +} diff --git a/usr/src/cmd/fs.d/reparsed/reparsed.xml b/usr/src/cmd/fs.d/reparsed/reparsed.xml new file mode 100644 index 0000000000..62f5e5cb21 --- /dev/null +++ b/usr/src/cmd/fs.d/reparsed/reparsed.xml @@ -0,0 +1,108 @@ +<?xml version="1.0"?> +<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> +<!-- + Copyright 2009 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + 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 + + NOTE: This service manifest is not editable; its contents will + be overwritten by package or patch operations, including + operating system upgrade. Make customizations in a different + file. + + Note: if this service is modified to consist of anything other + than a single instance named 'default', you must make changes to + $SRC/head/rpcsvc/daemon_utils.h and libnsl:open_daemon_lock(). +--> + +<service_bundle type='manifest' name='SUNWcsr:reparse'> + +<service + name='system/filesystem/reparse' + type='service' + version='1'> + + <create_default_instance enabled='false' /> + + <single_instance /> + + <dependency name='network' + grouping='require_any' + restart_on='error' + type='service'> + <service_fmri value='svc:/milestone/network' /> + </dependency> + + <dependency name='name-services' + grouping='require_all' + restart_on='refresh' + type='service'> + <service_fmri value='svc:/milestone/name-services' /> + </dependency> + + <dependency name='filesystem-minimal' + grouping='require_all' + restart_on='error' + type='service'> + <service_fmri value='svc:/system/filesystem/minimal' /> + </dependency> + + <exec_method + type='method' + name='start' + exec='/usr/lib/reparse/reparsed' + timeout_seconds='60' /> + + <exec_method + type='method' + name='stop' + exec=':kill' + timeout_seconds='60' /> + + <property_group name='general' type='framework'> + <!-- to start stop reparse service --> + <propval name='action_authorization' type='astring' + value='solaris.smf.manage.reparse' /> + <propval name='value_authorization' type='astring' + value='solaris.smf.manage.reparse' /> + </property_group> + + <property_group name='application' type='framework'> + <stability value='Evolving' /> + <propval name='auto_enable' type='boolean' value='true' /> + </property_group> + + <stability value='Stable' /> + + <template> + <common_name> + <loctext xml:lang='C'> + Reparse Point daemon + </loctext> + </common_name> + <documentation> + <manpage title='reparsed' section='1M' + manpath='/usr/share/man' /> + </documentation> + </template> +</service> + +</service_bundle> diff --git a/usr/src/common/fsreparse/fs_reparse.c b/usr/src/common/fsreparse/fs_reparse.c new file mode 100644 index 0000000000..82da0349fd --- /dev/null +++ b/usr/src/common/fsreparse/fs_reparse.c @@ -0,0 +1,328 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> + +#ifdef _KERNEL +#include <sys/sunddi.h> +#include <fs/fs_reparse.h> +#else +#include <string.h> +#include <limits.h> +#include <sys/fs_reparse.h> + +#define strfree(str) free((str)) +#endif + +static char *reparse_skipspace(char *cp); +static int reparse_create_nvlist(const char *string, nvlist_t *nvl); +static int reparse_add_nvpair(char *token, nvlist_t *nvl); +static boolean_t reparse_validate_svctype(char *svc_str); +static int reparse_validate_create_nvlist(const char *string, nvlist_t *nvl); + +/* array of characters not allowed in service type string */ +static char svctype_invalid_chars[] = { '{', '}', 0 }; + +/* + * reparse_init() + * + * Function to allocate a new name-value pair list. + * Caller needs to call reparse_free() to free memory + * used by the list when done. + * + * Return pointer to new list else return NULL. + */ +nvlist_t * +reparse_init(void) +{ + nvlist_t *nvl; + + /* + * Service type is unique, only one entry + * of each service type is allowed + */ + if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) + return (NULL); + + return (nvl); +} + +/* + * reparse_free() + * + * Function to free memory of a nvlist allocated previously + * by reparse_init(). + */ +void +reparse_free(nvlist_t *nvl) +{ + if (nvl) + nvlist_free(nvl); +} + +/* + * reparse_parse() + * + * Parse the specified string and populate the nvlist with the svc_types + * and data from the 'string'. The string could be read from the reparse + * point symlink body. This routine will allocate memory that must be + * freed by reparse_free(). + * + * If ok return 0 and the nvlist is populated, otherwise return error code. + */ +int +reparse_parse(const char *string, nvlist_t *nvl) +{ + int err; + + if (string == NULL || nvl == NULL) + return (EINVAL); + + if ((err = reparse_validate(string)) != 0) + return (err); + + if ((err = reparse_create_nvlist(string, nvl)) != 0) + return (err); + + return (0); +} + +static char * +reparse_skipspace(char *cp) +{ + while ((*cp) && (*cp == ' ' || *cp == '\t')) + cp++; + return (cp); +} + +static boolean_t +reparse_validate_svctype(char *svc_str) +{ + int nx, ix, len; + + if (svc_str == NULL) + return (B_FALSE); + + len = strlen(svc_str); + for (ix = 0; ix < len; ix++) { + for (nx = 0; nx < sizeof (svctype_invalid_chars); nx++) { + if (svc_str[ix] == svctype_invalid_chars[nx]) + return (B_FALSE); + } + } + return (B_TRUE); +} + +static boolean_t +reparse_validate_svc_token(char *svc_token) +{ + char save_c, *cp; + + if (svc_token == NULL) + return (B_FALSE); + if ((cp = strchr(svc_token, ':')) == NULL) + return (B_FALSE); + + save_c = *cp; + *cp = '\0'; + + /* + * make sure service type and service data are non-empty string. + */ + if (strlen(svc_token) == 0 || strlen(cp + 1) == 0) { + *cp = save_c; + return (B_FALSE); + } + + *cp = save_c; + return (B_TRUE); +} + +/* + * Format of reparse data: + * @{REPARSE@{servicetype:data} [@{servicetype:data}] ...} + * REPARSE_TAG_STR@{REPARSE_TOKEN} [@{REPARSE_TOKEN}] ... REPARSE_TAG_END + * + * Validating reparse data: + * . check for valid length of reparse data + * . check for valid reparse data format + * Return 0 if OK else return error code. + */ +int +reparse_validate(const char *string) +{ + return (reparse_validate_create_nvlist(string, NULL)); +} + +/* + * reparse_validate_create_nvlist + * + * dual-purpose function: + * . Validate a reparse data string. + * . Validate a reparse data string and parse the data + * into a nvlist. + */ +static int +reparse_validate_create_nvlist(const char *string, nvlist_t *nvl) +{ + int err, tcnt; + char *reparse_data, save_c, save_e, *save_e_ptr, *cp, *s_str, *e_str; + + if (string == NULL) + return (EINVAL); + + if (strlen(string) >= MAXREPARSELEN) + return (ENAMETOOLONG); + + if ((reparse_data = strdup(string)) == NULL) + return (ENOMEM); + + /* check FS_REPARSE_TAG_STR */ + if (strncmp(reparse_data, FS_REPARSE_TAG_STR, + strlen(FS_REPARSE_TAG_STR))) { + strfree(reparse_data); + return (EINVAL); + } + + /* locate FS_REPARSE_TAG_END_CHAR */ + if ((cp = strrchr(reparse_data, FS_REPARSE_TAG_END_CHAR)) == NULL) { + strfree(reparse_data); + return (EINVAL); + } + save_e = *cp; + save_e_ptr = cp; + *cp = '\0'; + + e_str = cp; + cp++; /* should point to NULL, or spaces */ + + cp = reparse_skipspace(cp); + if (*cp) { + *save_e_ptr = save_e; + strfree(reparse_data); + return (EINVAL); + } + + /* skip FS_REPARSE_TAG_STR */ + s_str = reparse_data + strlen(FS_REPARSE_TAG_STR); + + /* skip spaces after FS_REPARSE_TAG_STR */ + s_str = reparse_skipspace(s_str); + + tcnt = 0; + while (s_str < e_str) { + /* check FS_TOKEN_START_STR */ + if (strncmp(s_str, FS_TOKEN_START_STR, + strlen(FS_TOKEN_START_STR))) { + *save_e_ptr = save_e; + strfree(reparse_data); + return (EINVAL); + } + + /* skip over FS_TOKEN_START_STR */ + s_str += strlen(FS_TOKEN_START_STR); + + /* locate FS_TOKEN_END_STR */ + if ((cp = strstr(s_str, FS_TOKEN_END_STR)) == NULL) { + *save_e_ptr = save_e; + strfree(reparse_data); + return (EINVAL); + } + + tcnt++; + save_c = *cp; + *cp = '\0'; + + /* check for valid characters in service type */ + if (reparse_validate_svctype(s_str) == B_FALSE) { + *cp = save_c; + *save_e_ptr = save_e; + strfree(reparse_data); + return (EINVAL); + } + + if (strlen(s_str) == 0) { + *cp = save_c; + *save_e_ptr = save_e; + strfree(reparse_data); + return (EINVAL); + } + + if (reparse_validate_svc_token(s_str) == B_FALSE) { + *cp = save_c; + *save_e_ptr = save_e; + strfree(reparse_data); + return (EINVAL); + } + + /* create a nvpair entry */ + if (nvl != NULL && + (err = reparse_add_nvpair(s_str, nvl)) != 0) { + *cp = save_c; + *save_e_ptr = save_e; + strfree(reparse_data); + return (err); + } + + *cp = save_c; + + /* skip over FS_TOKEN_END_STR */ + cp += strlen(FS_TOKEN_END_STR); + cp = reparse_skipspace(cp); + s_str = cp; + } + *save_e_ptr = save_e; + strfree(reparse_data); + + return (tcnt ? 0 : EINVAL); +} + +static int +reparse_add_nvpair(char *token, nvlist_t *nvl) +{ + int err; + char save_c, *cp; + + if ((cp = strchr(token, ':')) == NULL) + return (EINVAL); + + save_c = *cp; + *cp = '\0'; + err = nvlist_add_string(nvl, token, cp + 1); + *cp = save_c; + + return (err); +} + +static int +reparse_create_nvlist(const char *string, nvlist_t *nvl) +{ + if (nvl == NULL) + return (EINVAL); + + return (reparse_validate_create_nvlist(string, nvl)); +} diff --git a/usr/src/common/xattr/xattr_common.c b/usr/src/common/xattr/xattr_common.c index d20eaf6a61..efe782c5f9 100644 --- a/usr/src/common/xattr/xattr_common.c +++ b/usr/src/common/xattr/xattr_common.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/attr.h> #if defined(_KERNEL) #include <sys/systm.h> @@ -63,6 +61,8 @@ static xattr_entry_t xattrs[F_ATTR_ALL] = { { A_OWNERSID, O_NONE, XATTR_VIEW_READWRITE, DATA_TYPE_NVLIST }, { A_GROUPSID, O_NONE, XATTR_VIEW_READWRITE, DATA_TYPE_NVLIST }, { A_FSID, O_NONE, XATTR_VIEW_READONLY, DATA_TYPE_UINT64 }, + { A_REPARSE_POINT, O_REPARSE_POINT, XATTR_VIEW_READONLY, + DATA_TYPE_BOOLEAN_VALUE }, }; const char * diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 9c364883a7..b535355b13 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -261,6 +261,7 @@ SUBDIRS += \ libsun_ima \ mpapi \ librstp \ + libreparse \ $($(MACH)_SUBDIRS) i386_SUBDIRS= \ @@ -359,7 +360,8 @@ MSGSUBDIRS= \ mpss \ pam_modules \ pyzfs \ - rpcsec_gss + rpcsec_gss \ + libreparse MSGSUBDIRS += \ $($(MACH)_MSGSUBDIRS) @@ -491,6 +493,7 @@ HDRSUBDIRS= \ libsun_ima \ mpapi \ mms \ + libreparse \ $($(MACH)_HDRSUBDIRS) $(CLOSED_BUILD)HDRSUBDIRS += \ @@ -637,6 +640,7 @@ scsi: libnvpair mpapi: libpthread libdevinfo libsysevent libnvpair libgrubmgmt: libdevinfo libzfs libfstyp pyzfs: libnvpair libsec libidmap libzfs +libreparse: libnvpair # # The reason this rule checks for the existence of the diff --git a/usr/src/lib/libreparse/Makefile b/usr/src/lib/libreparse/Makefile new file mode 100644 index 0000000000..1f0e0b4647 --- /dev/null +++ b/usr/src/lib/libreparse/Makefile @@ -0,0 +1,60 @@ +# +# 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 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.lib + +HDRS= rp_plugin.h +HDRDIR= common + +SUBDIRS= $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) +POFILE= libreparse.po +MSGFILES= common/fs_reparse_lib.c + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(POFILE): pofile_MSGFILES + +_msg: $(MSGDOMAINPOFILE) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/lib/Makefile.targ +include $(SRC)/Makefile.msg.targ diff --git a/usr/src/lib/libreparse/Makefile.com b/usr/src/lib/libreparse/Makefile.com new file mode 100644 index 0000000000..ca913755fe --- /dev/null +++ b/usr/src/lib/libreparse/Makefile.com @@ -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 +# +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +LIBRARY= libreparse.a +VERS= .1 + +LOCOBJS = fs_reparse_lib.o +COMOBJS = fs_reparse.o +OBJECTS = $(LOCOBJS) $(COMOBJS) +COMDIR = $(SRC)/common/fsreparse + +include ../../Makefile.lib + +SRCDIR = ../common +SRCS = $(LOCOBJS:%.o=$(SRCDIR)/%.c) $(COMOBJS:%.o=$(COMDIR)/%.c) + +LIBS = $(DYNLIB) $(LINTLIB) +LDLIBS += -lc -lnvpair + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -I$(COMDIR) -D_FILE_OFFSET_BITS=64 + +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ + +pics/%.o: $(COMDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) diff --git a/usr/src/lib/libreparse/amd64/Makefile b/usr/src/lib/libreparse/amd64/Makefile new file mode 100644 index 0000000000..036c13779e --- /dev/null +++ b/usr/src/lib/libreparse/amd64/Makefile @@ -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 +# +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/libreparse/common/fs_reparse_lib.c b/usr/src/lib/libreparse/common/fs_reparse_lib.c new file mode 100644 index 0000000000..b1ac809e63 --- /dev/null +++ b/usr/src/lib/libreparse/common/fs_reparse_lib.c @@ -0,0 +1,437 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <strings.h> +#include <string.h> +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <limits.h> +#include <libnvpair.h> +#include <dlfcn.h> +#include <libintl.h> +#include <sys/systeminfo.h> +#include <sys/fs_reparse.h> +#include "rp_plugin.h" + +#define MAXISALEN 257 /* based on sysinfo(2) man page */ + +static rp_proto_handle_t rp_proto_handle; +static rp_proto_plugin_t *rp_proto_list; + +int rp_plugin_init(void); +static void proto_plugin_fini(void); +static rp_plugin_ops_t *rp_find_protocol(const char *svctype); + +extern int errno; +static int rp_plugin_inited = 0; + +/* + * reparse_create() + * + * Create a symlink at the specified 'path' as a reparse point. + * This function will fail if path refers to an existing file system + * object or an object named string already exists at the given path. + * + * return 0 if ok else return error code. + */ +int +reparse_create(const char *path, const char *string) +{ + int err; + struct stat sbuf; + + if (path == NULL || string == NULL) + return (EINVAL); + + if ((err = reparse_validate(string)) != 0) + return (err); + + /* check if object exists */ + if (lstat(path, &sbuf) == 0) + return (EEXIST); + + return (symlink(string, path) ? errno : 0); +} + +/* + * reparse_unparse() + * + * Convert an nvlist back to a string format suitable to write + * to the reparse point symlink body. The string returned is in + * allocated memory and must be freed by the caller. + * + * return 0 if ok else return error code. + */ +int +reparse_unparse(nvlist_t *nvl, char **stringp) +{ + int err, buflen; + char *buf, *stype, *val; + nvpair_t *curr; + + if (nvl == NULL || stringp == NULL || + ((curr = nvlist_next_nvpair(nvl, NULL)) == NULL)) + return (EINVAL); + + buflen = SYMLINK_MAX; + if ((buf = malloc(buflen)) == NULL) + return (ENOMEM); + + err = 0; + (void) snprintf(buf, buflen, "%s", FS_REPARSE_TAG_STR); + while (curr != NULL) { + if (!(stype = nvpair_name(curr))) { + err = EINVAL; + break; + } + if ((strlcat(buf, FS_TOKEN_START_STR, buflen) >= buflen) || + (strlcat(buf, stype, buflen) >= buflen) || + (strlcat(buf, ":", buflen) >= buflen) || + (nvpair_value_string(curr, &val) != 0) || + (strlcat(buf, val, buflen) >= buflen) || + (strlcat(buf, FS_TOKEN_END_STR, buflen) >= buflen)) { + err = E2BIG; + break; + } + curr = nvlist_next_nvpair(nvl, curr); + } + if (err != 0) { + free(buf); + return (err); + } + if (strlcat(buf, FS_REPARSE_TAG_END_STR, buflen) >= buflen) { + free(buf); + return (E2BIG); + } + + *stringp = buf; + return (0); +} + +/* + * reparse_deref() + * + * Accepts the service-specific item from the reparse point and returns + * the service-specific data requested. The caller specifies the size + * of the buffer provided via *bufsz. + * + * if ok return 0 and *bufsz is updated to contain the actual length of + * the returned results, else return error code. If the error code is + * EOVERFLOW; results do not fit in the buffer, *bufsz will be updated + * to contain the number of bytes needed to hold the results. + */ +int +reparse_deref(const char *svc_type, const char *svc_data, char *buf, + size_t *bufsz) +{ + rp_plugin_ops_t *ops; + + if ((svc_type == NULL) || (svc_data == NULL) || (buf == NULL) || + (bufsz == NULL)) + return (EINVAL); + + ops = rp_find_protocol(svc_type); + if ((ops != NULL) && (ops->rpo_deref != NULL)) + return (ops->rpo_deref(svc_type, svc_data, buf, bufsz)); + + /* no plugin, return error */ + return (ENOTSUP); +} + +/* + * reparse_delete() + * + * Delete a reparse point at a given pathname. It will fail if + * a reparse point does not exist at the given path or the pathname + * is not a symlink. + * + * return 0 if ok else return error code. + */ +int +reparse_delete(const char *path) +{ + struct stat sbuf; + + if (path == NULL) + return (EINVAL); + + /* check if object exists */ + if (lstat(path, &sbuf) != 0) + return (errno); + + if ((sbuf.st_mode & S_IFLNK) != S_IFLNK) + return (EINVAL); + + return (unlink(path) ? errno : 0); +} + +/* + * reparse_add() + * + * Add a service type entry to a nvlist with a copy of svc_data, + * replacing one of the same type if already present. + * + * return 0 if ok else return error code. + */ +int +reparse_add(nvlist_t *nvl, const char *svc_type, const char *svc_data) +{ + int err; + char *buf; + size_t bufsz; + rp_plugin_ops_t *ops; + + if ((nvl == NULL) || (svc_type == NULL) || (svc_data == NULL)) + return (EINVAL); + + bufsz = SYMLINK_MAX; /* no need to mess around */ + if ((buf = malloc(bufsz)) == NULL) + return (ENOMEM); + + ops = rp_find_protocol(svc_type); + if ((ops != NULL) && (ops->rpo_form != NULL)) + err = ops->rpo_form(svc_type, svc_data, buf, &bufsz); + else + err = ENOTSUP; /* no plugin */ + + if (err != 0) { + free(buf); + return (err); + } + + err = nvlist_add_string(nvl, svc_type, buf); + free(buf); + return (err); +} + +/* + * reparse_remove() + * + * Remove a service type entry from the nvlist, if present. + * + * return 0 if ok else return error code. + */ +int +reparse_remove(nvlist_t *nvl, const char *svc_type) +{ + if ((nvl == NULL) || (svc_type == NULL)) + return (EINVAL); + + return (nvlist_remove_all(nvl, svc_type)); +} + +/* + * Returns true if name is "." or "..", otherwise returns false. + */ +static boolean_t +rp_is_dot_or_dotdot(const char *name) +{ + if (*name != '.') + return (B_FALSE); + + if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) + return (B_TRUE); + + return (B_FALSE); +} + +static void +proto_plugin_fini() +{ + rp_proto_plugin_t *p; + + /* + * Protocols may call this framework during _fini + */ + for (p = rp_proto_list; p != NULL; p = p->plugin_next) { + if (p->plugin_ops->rpo_fini) + p->plugin_ops->rpo_fini(); + } + while ((p = rp_proto_list) != NULL) { + rp_proto_list = p->plugin_next; + if (p->plugin_handle != NULL) + (void) dlclose(p->plugin_handle); + free(p); + } + + if (rp_proto_handle.rp_ops != NULL) { + free(rp_proto_handle.rp_ops); + rp_proto_handle.rp_ops = NULL; + } + rp_proto_handle.rp_num_proto = 0; +} + +/* + * rp_plugin_init() + * + * Initialize the service type specific plugin modules. + * For each reparse service type, there should be a plugin library for it. + * This function walks /usr/lib/reparse directory for plugin libraries. + * For each plugin library found, initialize it and add it to the internal + * list of service type plugin. These are used for service type specific + * operations. + */ +int +rp_plugin_init() +{ + int err, ret = RP_OK; + char isa[MAXISALEN], dirpath[MAXPATHLEN], path[MAXPATHLEN]; + int num_protos = 0; + rp_proto_handle_t *rp_hdl; + rp_proto_plugin_t *proto, *tmp; + rp_plugin_ops_t *plugin_ops; + struct stat st; + void *dlhandle; + DIR *dir; + struct dirent *dent; + +#if defined(_LP64) + if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1) + isa[0] = '\0'; +#else + isa[0] = '\0'; +#endif + + (void) snprintf(dirpath, MAXPATHLEN, + "%s/%s", RP_LIB_DIR, isa); + + if ((dir = opendir(dirpath)) == NULL) + return (RP_NO_PLUGIN_DIR); + + while ((dent = readdir(dir)) != NULL) { + if (rp_is_dot_or_dotdot(dent->d_name)) + continue; + + (void) snprintf(path, MAXPATHLEN, + "%s/%s", dirpath, dent->d_name); + + /* + * If file doesn't exist, don't try to map it + */ + if (stat(path, &st) < 0) + continue; + if ((dlhandle = dlopen(path, RTLD_FIRST|RTLD_LAZY)) == NULL) + continue; + + plugin_ops = (rp_plugin_ops_t *) + dlsym(dlhandle, "rp_plugin_ops"); + if (plugin_ops == NULL) { + (void) fprintf(stderr, dgettext(TEXT_DOMAIN, + "Error in plugin ops for service type %s\n%s\n"), + dent->d_name, dlerror()); + (void) dlclose(dlhandle); + continue; + } + proto = (rp_proto_plugin_t *) + calloc(1, sizeof (rp_proto_plugin_t)); + if (proto == NULL) { + (void) dlclose(dlhandle); + (void) fprintf(stderr, + dgettext(TEXT_DOMAIN, "No memory for plugin %s\n"), + dent->d_name); + ret = RP_NO_MEMORY; + break; + } + + proto->plugin_ops = plugin_ops; + proto->plugin_handle = dlhandle; + num_protos++; + proto->plugin_next = rp_proto_list; + rp_proto_list = proto; + } + + (void) closedir(dir); + + if ((num_protos == 0) && (ret == 0)) + ret = RP_NO_PLUGIN; + /* + * There was an error, so cleanup prior to return of failure. + */ + if (ret != RP_OK) { + proto_plugin_fini(); + return (ret); + } + + rp_proto_handle.rp_ops = (rp_plugin_ops_t **)calloc(num_protos, + sizeof (rp_plugin_ops_t *)); + if (!rp_proto_handle.rp_ops) { + proto_plugin_fini(); + return (RP_NO_MEMORY); + } + + rp_hdl = &rp_proto_handle; + rp_hdl->rp_num_proto = 0; + for (tmp = rp_proto_list; rp_hdl->rp_num_proto < num_protos && + tmp != NULL; tmp = tmp->plugin_next) { + + err = RP_OK; + if (tmp->plugin_ops->rpo_init != NULL) + err = tmp->plugin_ops->rpo_init(); + if (err != RP_OK) + continue; + rp_hdl->rp_ops[rp_hdl->rp_num_proto++] = tmp->plugin_ops; + } + + return (rp_hdl->rp_num_proto > 0 ? RP_OK : RP_NO_PLUGIN); +} + + +/* + * find_protocol() + * + * Search the plugin list for the specified protocol and return the + * ops vector. return NULL if protocol is not defined. + */ +static rp_plugin_ops_t * +rp_find_protocol(const char *svc_type) +{ + int i; + rp_plugin_ops_t *ops = NULL; + + if (svc_type == NULL) + return (NULL); + + if (rp_plugin_inited == 0) { + if (rp_plugin_init() == RP_OK) + rp_plugin_inited = 1; + else + return (NULL); + } + + for (i = 0; i < rp_proto_handle.rp_num_proto; i++) { + ops = rp_proto_handle.rp_ops[i]; + if (ops->rpo_supports_svc(svc_type)) + return (ops); + + } + return (NULL); +} diff --git a/usr/src/lib/libreparse/common/llib-lreparse b/usr/src/lib/libreparse/common/llib-lreparse new file mode 100644 index 0000000000..082aa4032d --- /dev/null +++ b/usr/src/lib/libreparse/common/llib-lreparse @@ -0,0 +1,46 @@ +/* + * 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 + */ +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/fs_reparse.h> +#include "rp_plugin.h" + +/* + * usr/src/lib/libreparse + */ +int reparse_add(nvlist_t *, const char *, const char *); +int reparse_create(const char *, const char *); +int reparse_delete(const char *); +int reparse_deref(const char *, const char *, char *, size_t *); +void reparse_free(nvlist_t *); +nvlist_t *reparse_init(void); +int reparse_parse(const char *, nvlist_t *); +int reparse_remove(nvlist_t *, const char *); +int reparse_remove(nvlist_t *, const char *); +int reparse_unparse(nvlist_t *, char **); +int reparse_validate(const char *); +int rp_plugin_init(); diff --git a/usr/src/lib/libreparse/common/mapfile-vers b/usr/src/lib/libreparse/common/mapfile-vers new file mode 100644 index 0000000000..94bfba08ec --- /dev/null +++ b/usr/src/lib/libreparse/common/mapfile-vers @@ -0,0 +1,54 @@ +# +# 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 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +SUNWprivate { + global: + reparse_add; + reparse_create; + reparse_delete; + reparse_deref; + reparse_free; + reparse_init; + reparse_parse; + reparse_remove; + reparse_unparse; + reparse_validate; + rp_plugin_init; + local: + *; +}; diff --git a/usr/src/lib/libreparse/common/rp_plugin.h b/usr/src/lib/libreparse/common/rp_plugin.h new file mode 100644 index 0000000000..a12b45776c --- /dev/null +++ b/usr/src/lib/libreparse/common/rp_plugin.h @@ -0,0 +1,75 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _RP_PLUGIN_H +#define _RP_PLUGIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> + +#define RP_LIB_DIR "/usr/lib/reparse" +#define RP_PLUGIN_V1 1 + +/* + * some error codes + */ +#define RP_OK 0 +#define RP_NO_PLUGIN ENOENT +#define RP_NO_MEMORY ENOMEM +#define RP_NO_PLUGIN_DIR ENOTDIR +#define RP_INVALID_PROTOCOL EINVAL + +extern int rp_plugin_init(); + +typedef struct rp_plugin_ops { + int rpo_version; + int (*rpo_init)(void); + int (*rpo_fini)(void); + char *(*rpo_svc_types)(void); + boolean_t (*rpo_supports_svc)(const char *); + int (*rpo_form)(const char *, const char *, char *, size_t *); + int (*rpo_deref)(const char *, const char *, char *, size_t *); +} rp_plugin_ops_t; + +typedef struct rp_proto_plugin { + struct rp_proto_plugin *plugin_next; + rp_plugin_ops_t *plugin_ops; + void *plugin_handle; +} rp_proto_plugin_t; + +typedef struct rp_proto_handle { + int rp_num_proto; + rp_plugin_ops_t **rp_ops; +} rp_proto_handle_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _RP_PLUGIN_H */ diff --git a/usr/src/lib/libreparse/i386/Makefile b/usr/src/lib/libreparse/i386/Makefile new file mode 100644 index 0000000000..c86be4377c --- /dev/null +++ b/usr/src/lib/libreparse/i386/Makefile @@ -0,0 +1,28 @@ +# +# 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 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libreparse/sparc/Makefile b/usr/src/lib/libreparse/sparc/Makefile new file mode 100644 index 0000000000..c86be4377c --- /dev/null +++ b/usr/src/lib/libreparse/sparc/Makefile @@ -0,0 +1,28 @@ +# +# 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 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libreparse/sparcv9/Makefile b/usr/src/lib/libreparse/sparcv9/Makefile new file mode 100644 index 0000000000..036c13779e --- /dev/null +++ b/usr/src/lib/libreparse/sparcv9/Makefile @@ -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 +# +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/libsecdb/auth_attr.txt b/usr/src/lib/libsecdb/auth_attr.txt index f3df01c4f7..b09d1f7a1e 100644 --- a/usr/src/lib/libsecdb/auth_attr.txt +++ b/usr/src/lib/libsecdb/auth_attr.txt @@ -139,6 +139,7 @@ solaris.smf.manage.nwam:::Manage Network Auto-Magic Service States::help=SmfNWAM solaris.smf.manage.power:::Manage Power Management Service States::help=SmfPowerStates.html solaris.smf.manage.smb:::Manage SMB Service States::help=SmfSMBStates.html solaris.smf.manage.smbfs:::Manage SMB Client States::help=SmfSMBFSStates.html +solaris.smf.manage.reparse:::Manage Reparse Service States::help=SmfReparseStates.html solaris.smf.manage.rmvolmgr:::Manage Rmvolmgr Service States::help=SmfRmvolmgrStates.html solaris.smf.manage.routing:::Manage Routing Service States::help=SmfRoutingStates.html solaris.smf.manage.rpc.bind:::Manage RPC Program number mapper::help=SmfRPCBind.html diff --git a/usr/src/lib/libsecdb/help/auths/Makefile b/usr/src/lib/libsecdb/help/auths/Makefile index b18c017f5c..e5611950f5 100644 --- a/usr/src/lib/libsecdb/help/auths/Makefile +++ b/usr/src/lib/libsecdb/help/auths/Makefile @@ -86,6 +86,7 @@ HTMLENTS = \ SmfNDMPStates.html \ SmfNWAMStates.html \ SmfPowerStates.html \ + SmfReparseStates.html \ SmfRoutingStates.html \ SmfSendmailStates.html \ SmfSshStates.html \ diff --git a/usr/src/lib/libsecdb/help/auths/SmfReparseStates.html b/usr/src/lib/libsecdb/help/auths/SmfReparseStates.html new file mode 100644 index 0000000000..c4c0d406e5 --- /dev/null +++ b/usr/src/lib/libsecdb/help/auths/SmfReparseStates.html @@ -0,0 +1,37 @@ +<HTML> +<!-- + 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 2009 Sun Microsystems, Inc. All rights reserved. +Use is subject to license terms. +--> +<!-- + <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> +--> +<BODY> +When Manage Reparse Service States is in the Authorizations Include +column, it grants the authorization to enable, disable, or restart +the Reparse service. +<p> +If Manage Reparse Service States is grayed, then you are not entitled +to Add or Remove this authorization. +<BR> +</BODY> +</HTML> diff --git a/usr/src/lib/libsecdb/help/profiles/Makefile b/usr/src/lib/libsecdb/help/profiles/Makefile index 153d1eae39..cb36914f91 100644 --- a/usr/src/lib/libsecdb/help/profiles/Makefile +++ b/usr/src/lib/libsecdb/help/profiles/Makefile @@ -69,6 +69,7 @@ HTMLENTS = \ RtObAccessMngmnt.html \ RtPrntAdmin.html \ RtProcManagement.html \ + RtReparseMngmnt.html \ RtRightsDelegate.html \ RtSMBMngmnt.html \ RtSMBFSMngmnt.html \ diff --git a/usr/src/lib/libsecdb/help/profiles/RtReparseMngmnt.html b/usr/src/lib/libsecdb/help/profiles/RtReparseMngmnt.html new file mode 100644 index 0000000000..c4c0d406e5 --- /dev/null +++ b/usr/src/lib/libsecdb/help/profiles/RtReparseMngmnt.html @@ -0,0 +1,37 @@ +<HTML> +<!-- + 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 2009 Sun Microsystems, Inc. All rights reserved. +Use is subject to license terms. +--> +<!-- + <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> +--> +<BODY> +When Manage Reparse Service States is in the Authorizations Include +column, it grants the authorization to enable, disable, or restart +the Reparse service. +<p> +If Manage Reparse Service States is grayed, then you are not entitled +to Add or Remove this authorization. +<BR> +</BODY> +</HTML> diff --git a/usr/src/lib/libsecdb/prof_attr.txt b/usr/src/lib/libsecdb/prof_attr.txt index 1bb782d6d3..96bfbfc5c9 100644 --- a/usr/src/lib/libsecdb/prof_attr.txt +++ b/usr/src/lib/libsecdb/prof_attr.txt @@ -72,6 +72,7 @@ Name Service Management:::Non-security name service scripts/commands:help=RtName Name Service Security:::Security related name service scripts/commands:help=RtNameServiceSecure.html Object Access Management:::Change ownership and permission on files:help=RtObAccessMngmnt.html Process Management:::Manage current processes and processors:auths=solaris.smf.manage.cron,solaris.smf.manage.power;help=RtProcManagement.html +Reparse Management:::Manage the reparse service:auths=solaris.smf.manage.reparse:help=RtReparseMngmnt.html Rights Delegation:::Delegate ability to assign rights to users and roles:auths=solaris.role.delegate,solaris.profmgr.delegate,solaris.grant;help=RtRightsDelegate.html Rmvolmgr Management:::Manage Removable Volume Manager SMF service:auths=solaris.smf.manage.rmvolmgr;help=RtRmvolmgrMngmnt.html Service Management:::Manage services:auths=solaris.smf.manage,solaris.smf.modify diff --git a/usr/src/lib/libzpool/common/sys/zfs_context.h b/usr/src/lib/libzpool/common/sys/zfs_context.h index 2c02170556..b4707ce9ee 100644 --- a/usr/src/lib/libzpool/common/sys/zfs_context.h +++ b/usr/src/lib/libzpool/common/sys/zfs_context.h @@ -346,6 +346,7 @@ typedef struct vnode { char *v_path; } vnode_t; +#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */ typedef struct xoptattr { timestruc_t xoa_createtime; /* Create time of file */ @@ -361,6 +362,8 @@ typedef struct xoptattr { uint8_t xoa_opaque; uint8_t xoa_av_quarantined; uint8_t xoa_av_modified; + uint8_t xoa_av_scanstamp[AV_SCANSTAMP_SZ]; + uint8_t xoa_reparse; } xoptattr_t; typedef struct vattr { diff --git a/usr/src/pkgdefs/SUNW0on/prototype_com b/usr/src/pkgdefs/SUNW0on/prototype_com index 0466324e8b..59d362abea 100644 --- a/usr/src/pkgdefs/SUNW0on/prototype_com +++ b/usr/src/pkgdefs/SUNW0on/prototype_com @@ -259,6 +259,7 @@ f none usr/lib/help/auths/locale/SmfNscdStates.html 444 root bin f none usr/lib/help/auths/locale/SmfNADDStates.html 444 root bin f none usr/lib/help/auths/locale/SmfNWAMStates.html 444 root bin f none usr/lib/help/auths/locale/SmfPowerStates.html 444 root bin +f none usr/lib/help/auths/locale/SmfReparseStates.html 444 root bin f none usr/lib/help/auths/locale/SmfRoutingStates.html 444 root bin f none usr/lib/help/auths/locale/SmfSendmailStates.html 444 root bin f none usr/lib/help/auths/locale/SmfSMBFSStates.html 444 root bin @@ -380,6 +381,7 @@ f none usr/lib/help/profiles/locale/RtNetWifiSecure.html 444 root bin f none usr/lib/help/profiles/locale/RtNetLinkSecure.html 444 root bin f none usr/lib/help/profiles/locale/RtObAccessMngmnt.html 444 root bin f none usr/lib/help/profiles/locale/RtProcManagement.html 444 root bin +f none usr/lib/help/profiles/locale/RtReparseMngmnt.html 444 root bin f none usr/lib/help/profiles/locale/RtRightsDelegate.html 444 root bin f none usr/lib/help/profiles/locale/RtSoftwareInstall.html 444 root bin f none usr/lib/help/profiles/locale/RtSMBFSMngmnt.html 444 root bin diff --git a/usr/src/pkgdefs/SUNWarc/prototype_com b/usr/src/pkgdefs/SUNWarc/prototype_com index 57a3212f7a..75cd755017 100644 --- a/usr/src/pkgdefs/SUNWarc/prototype_com +++ b/usr/src/pkgdefs/SUNWarc/prototype_com @@ -150,6 +150,8 @@ s none usr/lib/llib-lposix4=../../lib/llib-lrt s none usr/lib/llib-lposix4.ln=../../lib/llib-lrt.ln f none usr/lib/llib-lproject 644 root bin f none usr/lib/llib-lproject.ln 644 root bin +f none usr/lib/llib-lreparse 644 root bin +f none usr/lib/llib-lreparse.ln 644 root bin s none usr/lib/llib-lresolv=../../lib/llib-lresolv s none usr/lib/llib-lresolv.ln=../../lib/llib-lresolv.ln s none usr/lib/llib-lrpcsvc=../../lib/llib-lrpcsvc diff --git a/usr/src/pkgdefs/SUNWarc/prototype_i386 b/usr/src/pkgdefs/SUNWarc/prototype_i386 index 3ed9cf42d8..ac0c40de89 100644 --- a/usr/src/pkgdefs/SUNWarc/prototype_i386 +++ b/usr/src/pkgdefs/SUNWarc/prototype_i386 @@ -114,6 +114,7 @@ f none usr/lib/amd64/llib-l300s.ln 644 root bin f none usr/lib/amd64/llib-l4014.ln 644 root bin f none usr/lib/amd64/llib-l450.ln 644 root bin s none usr/lib/amd64/llib-lpthread.ln=../../../lib/amd64/llib-lpthread.ln +f none usr/lib/amd64/llib-lreparse.ln 644 root bin s none usr/lib/amd64/llib-lresolv.ln=../../../lib/amd64/llib-lresolv.ln s none usr/lib/amd64/llib-lrpcsvc.ln=../../../lib/amd64/llib-lrpcsvc.ln s none usr/lib/amd64/llib-lrt.ln=../../../lib/amd64/llib-lrt.ln diff --git a/usr/src/pkgdefs/SUNWarc/prototype_sparc b/usr/src/pkgdefs/SUNWarc/prototype_sparc index 46af1deb3d..9315cb47a8 100644 --- a/usr/src/pkgdefs/SUNWarc/prototype_sparc +++ b/usr/src/pkgdefs/SUNWarc/prototype_sparc @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -110,6 +110,7 @@ f none usr/lib/sparcv9/llib-l300s.ln 644 root bin f none usr/lib/sparcv9/llib-l4014.ln 644 root bin f none usr/lib/sparcv9/llib-l450.ln 644 root bin s none usr/lib/sparcv9/llib-lpthread.ln=../../../lib/sparcv9/llib-lpthread.ln +f none usr/lib/sparcv9/llib-lreparse.ln 644 root bin s none usr/lib/sparcv9/llib-lresolv.ln=../../../lib/sparcv9/llib-lresolv.ln s none usr/lib/sparcv9/llib-lrpcsvc.ln=../../../lib/sparcv9/llib-lrpcsvc.ln s none usr/lib/sparcv9/llib-lrt.ln=../../../lib/sparcv9/llib-lrt.ln diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_com b/usr/src/pkgdefs/SUNWcsl/prototype_com index 8132fc38a3..13001f6c96 100644 --- a/usr/src/pkgdefs/SUNWcsl/prototype_com +++ b/usr/src/pkgdefs/SUNWcsl/prototype_com @@ -210,6 +210,8 @@ s none usr/lib/libpthread.so=../../lib/libpthread.so.1 s none usr/lib/libpthread.so.1=../../lib/libpthread.so.1 s none usr/lib/librcm.so=../../lib/librcm.so.1 s none usr/lib/librcm.so.1=../../lib/librcm.so.1 +f none usr/lib/libreparse.so.1 755 root bin +s none usr/lib/libreparse.so=./libreparse.so.1 s none usr/lib/libresolv.so=../../lib/libresolv.so.2 s none usr/lib/libresolv.so.1=../../lib/libresolv.so.1 s none usr/lib/libresolv.so.2=../../lib/libresolv.so.2 diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_i386 b/usr/src/pkgdefs/SUNWcsl/prototype_i386 index 5998608f6d..d7a759507d 100644 --- a/usr/src/pkgdefs/SUNWcsl/prototype_i386 +++ b/usr/src/pkgdefs/SUNWcsl/prototype_i386 @@ -298,6 +298,8 @@ s none usr/lib/amd64/libpthread.so.1=../../../lib/amd64/libpthread.so.1 s none usr/lib/amd64/libpthread.so=../../../lib/amd64/libpthread.so.1 s none usr/lib/amd64/librcm.so.1=../../../lib/amd64/librcm.so.1 s none usr/lib/amd64/librcm.so=../../../lib/amd64/librcm.so.1 +f none usr/lib/amd64/libreparse.so.1 755 root bin +s none usr/lib/amd64/libreparse.so=libreparse.so.1 s none usr/lib/amd64/libresolv.so.2=../../../lib/amd64/libresolv.so.2 s none usr/lib/amd64/libresolv.so=../../../lib/amd64/libresolv.so.2 s none usr/lib/amd64/librpcsvc.so.1=../../../lib/amd64/librpcsvc.so.1 diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_sparc b/usr/src/pkgdefs/SUNWcsl/prototype_sparc index bbf2f51dda..2eb58e5d50 100644 --- a/usr/src/pkgdefs/SUNWcsl/prototype_sparc +++ b/usr/src/pkgdefs/SUNWcsl/prototype_sparc @@ -288,6 +288,8 @@ s none usr/lib/sparcv9/libpthread.so.1=../../../lib/sparcv9/libpthread.so.1 s none usr/lib/sparcv9/libpthread.so=../../../lib/sparcv9/libpthread.so.1 s none usr/lib/sparcv9/librcm.so.1=../../../lib/sparcv9/librcm.so.1 s none usr/lib/sparcv9/librcm.so=../../../lib/sparcv9/librcm.so.1 +f none usr/lib/sparcv9/libreparse.so.1 755 root bin +s none usr/lib/sparcv9/libreparse.so=libreparse.so.1 s none usr/lib/sparcv9/libresolv.so.2=../../../lib/sparcv9/libresolv.so.2 s none usr/lib/sparcv9/libresolv.so=../../../lib/sparcv9/libresolv.so.2 s none usr/lib/sparcv9/librestart.so.1=../../../lib/sparcv9/librestart.so.1 diff --git a/usr/src/pkgdefs/SUNWcsr/prototype_com b/usr/src/pkgdefs/SUNWcsr/prototype_com index 52640a47a3..168304edec 100644 --- a/usr/src/pkgdefs/SUNWcsr/prototype_com +++ b/usr/src/pkgdefs/SUNWcsr/prototype_com @@ -531,6 +531,7 @@ d none var/svc/manifest/network/ssl 0755 root sys f manifest var/svc/manifest/network/ssl/kssl-proxy.xml 0444 root sys d none var/svc/manifest/network/shares 0755 root sys f manifest var/svc/manifest/network/shares/group.xml 0444 root sys +f manifest var/svc/manifest/network/shares/reparsed.xml 0444 root sys d none var/svc/manifest/platform 755 root sys d none var/svc/manifest/site 755 root sys d none var/svc/manifest/system 755 root sys diff --git a/usr/src/pkgdefs/SUNWcsu/prototype_com b/usr/src/pkgdefs/SUNWcsu/prototype_com index 2e310f335d..4bf58d60f4 100644 --- a/usr/src/pkgdefs/SUNWcsu/prototype_com +++ b/usr/src/pkgdefs/SUNWcsu/prototype_com @@ -501,6 +501,7 @@ f none usr/lib/help/auths/locale/C/SmfNscdStates.html 444 root bin f none usr/lib/help/auths/locale/C/SmfNADDStates.html 444 root bin f none usr/lib/help/auths/locale/C/SmfNWAMStates.html 444 root bin f none usr/lib/help/auths/locale/C/SmfPowerStates.html 444 root bin +f none usr/lib/help/auths/locale/C/SmfReparseStates.html 444 root bin f none usr/lib/help/auths/locale/C/SmfRoutingStates.html 444 root bin f none usr/lib/help/auths/locale/C/SmfSendmailStates.html 444 root bin f none usr/lib/help/auths/locale/C/SmfSMBFSStates.html 444 root bin @@ -604,6 +605,7 @@ f none usr/lib/help/profiles/locale/C/RtNetLinkSecure.html 444 root bin f none usr/lib/help/profiles/locale/C/RtObAccessMngmnt.html 444 root bin f none usr/lib/help/profiles/locale/C/RtPrntAdmin.html 444 root bin f none usr/lib/help/profiles/locale/C/RtProcManagement.html 444 root bin +f none usr/lib/help/profiles/locale/C/RtReparseMngmnt.html 444 root bin f none usr/lib/help/profiles/locale/C/RtRightsDelegate.html 444 root bin f none usr/lib/help/profiles/locale/C/RtSoftwareInstall.html 444 root bin f none usr/lib/help/profiles/locale/C/RtSMBFSMngmnt.html 444 root bin @@ -697,6 +699,8 @@ f none usr/lib/rcm/modules/SUNW_aggr_rcm.so 555 root bin f none usr/lib/rcm/modules/SUNW_swap_rcm.so 555 root bin f none usr/lib/rcm/rcm_daemon 555 root bin d none usr/lib/rcm/scripts 755 root bin +d none usr/lib/reparse 755 root bin +f none usr/lib/reparse/reparsed 555 root sys s none usr/lib/rsh=../../sbin/sh d none usr/lib/saf 755 root bin f none usr/lib/saf/listen 755 root sys diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com index 4e1d00c89b..03cfc436a0 100644 --- a/usr/src/pkgdefs/SUNWhea/prototype_com +++ b/usr/src/pkgdefs/SUNWhea/prototype_com @@ -470,6 +470,7 @@ f none usr/include/regexp.h 644 root bin f none usr/include/regexpr.h 644 root bin f none usr/include/resolv.h 644 root bin f none usr/include/rje.h 644 root bin +f none usr/include/rp_plugin.h 644 root bin d none usr/include/iso 755 root bin s none usr/include/iso/assert_iso.h=../assert.h f none usr/include/iso/ctype_c99.h 644 root bin @@ -913,6 +914,7 @@ f none usr/include/sys/fs/ufs_quota.h 644 root bin f none usr/include/sys/fs/ufs_snap.h 644 root bin f none usr/include/sys/fs/ufs_trans.h 644 root bin f none usr/include/sys/fs/zfs.h 644 root bin +f none usr/include/sys/fs_reparse.h 644 root bin f none usr/include/sys/fs_subr.h 644 root bin f none usr/include/sys/fsid.h 644 root bin f none usr/include/sys/fssnap.h 644 root bin diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 2c0777fc54..7d8ed8dac1 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -162,6 +162,7 @@ GENUNIX_OBJS += \ fork.o \ vpm.o \ fsat.o \ + fs_reparse.o \ fs_subr.o \ fsflush.o \ ftrace.o \ diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules index 75354e4c62..01a28db0be 100644 --- a/usr/src/uts/common/Makefile.rules +++ b/usr/src/uts/common/Makefile.rules @@ -340,6 +340,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/io/scsi/adapters/pmcs/%.bin $(COMPILE.b) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(COMMONBASE)/fsreparse/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + KMECHKRB5_BASE=$(UTSBASE)/common/gssapi/mechs/krb5 KGSSDFLAGS=-I $(UTSBASE)/common/gssapi/include @@ -2530,3 +2534,6 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/vr/%.c $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/yge/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(COMMONBASE)/fsreparse/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) diff --git a/usr/src/uts/common/fs/Makefile b/usr/src/uts/common/fs/Makefile index 28ad019955..53660e655d 100644 --- a/usr/src/uts/common/fs/Makefile +++ b/usr/src/uts/common/fs/Makefile @@ -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,17 +18,16 @@ # # CDDL HEADER END # -# -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1989 by Sun Microsystems, Inc. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. # # uts/common/fs/Makefile # # include global definitions include ../../../Makefile.master -HDRS= fs_subr.h +HDRS= fs_subr.h \ + fs_reparse.h PROCHDRS= prdata.h diff --git a/usr/src/uts/common/fs/fs_reparse.h b/usr/src/uts/common/fs/fs_reparse.h new file mode 100644 index 0000000000..ec44484117 --- /dev/null +++ b/usr/src/uts/common/fs/fs_reparse.h @@ -0,0 +1,88 @@ +/* + * 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 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _FS_REPARSE_H +#define _FS_REPARSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#include <sys/param.h> +#ifdef _KERNEL +#include <sys/time.h> +#include <sys/nvpair.h> +#else +#include <libnvpair.h> +#endif + +#define FS_REPARSE_TAG_STR "@{REPARSE" +#define FS_REPARSE_TAG_END_CHAR '}' +#define FS_REPARSE_TAG_END_STR "}" +#define FS_TOKEN_START_STR "@{" +#define FS_TOKEN_END_STR "}" + +#define REPARSED "svc:/system/filesystem/reparse:default" +#define MAXREPARSELEN MAXPATHLEN +#define REPARSED_DOOR "/var/run/reparsed_door" +#define REPARSED_DOORCALL_MAX_RETRY 4 + +/* + * This structure is shared between kernel code and user reparsed daemon. + * The 'res_len' must be defined as int, and not size_t, for 32-bit reparsed + * binary and 64-bit kernel code to work together. + */ +typedef struct reparsed_door_res { + int res_status; + int res_len; + char res_data[1]; +} reparsed_door_res_t; + +extern nvlist_t *reparse_init(void); +extern void reparse_free(nvlist_t *nvl); +extern int reparse_parse(const char *reparse_data, nvlist_t *nvl); +extern int reparse_validate(const char *reparse_data); + +#ifdef _KERNEL +extern int reparse_kderef(const char *svc_type, const char *svc_data, + char *buf, size_t *bufsz); +extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl); +#else +extern int reparse_add(nvlist_t *nvl, const char *svc_type, + const char *svc_data); +extern int reparse_remove(nvlist_t *nvl, const char *svc_type); +extern int reparse_unparse(nvlist_t *nvl, char **stringp); +extern int reparse_create(const char *path, const char *string); +extern int reparse_delete(const char *path); +extern int reparse_deref(const char *svc_type, const char *svc_data, + char *buf, size_t *bufsz); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FS_REPARSE_H */ diff --git a/usr/src/uts/common/fs/fs_subr.c b/usr/src/uts/common/fs/fs_subr.c index 5187ecf327..a465a97043 100644 --- a/usr/src/uts/common/fs/fs_subr.c +++ b/usr/src/uts/common/fs/fs_subr.c @@ -48,6 +48,8 @@ #include <sys/cmn_err.h> #include <sys/stream.h> #include <fs/fs_subr.h> +#include <fs/fs_reparse.h> +#include <sys/door.h> #include <sys/acl.h> #include <sys/share.h> #include <sys/file.h> @@ -55,6 +57,7 @@ #include <sys/file.h> #include <sys/nbmlock.h> #include <acl/acl_common.h> +#include <sys/pathname.h> static callb_cpr_t *frlock_serialize_blocked(flk_cb_when_t, void *); @@ -64,6 +67,12 @@ static callb_cpr_t *frlock_serialize_blocked(flk_cb_when_t, void *); int fs_estale_retry = 5; /* + * supports for reparse point door upcall + */ +static door_handle_t reparsed_door; +static kmutex_t reparsed_door_lock; + +/* * The associated operation is not supported by the file system. */ int @@ -838,3 +847,175 @@ fs_vscan(vnode_t *vp, cred_t *cr, int async) return (ret); } + +/* + * support functions for reparse point + */ +/* + * reparse_vnode_parse + * + * Read the symlink data of a reparse point specified by the vnode + * and return the reparse data as name-value pair in the nvlist. + */ +int +reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl) +{ + int err; + char *lkdata; + struct uio uio; + struct iovec iov; + + if (vp == NULL || nvl == NULL) + return (EINVAL); + + lkdata = kmem_alloc(MAXREPARSELEN, KM_SLEEP); + + /* + * Set up io vector to read sym link data + */ + iov.iov_base = lkdata; + iov.iov_len = MAXREPARSELEN; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_extflg = UIO_COPY_CACHED; + uio.uio_loffset = (offset_t)0; + uio.uio_resid = MAXREPARSELEN; + + if ((err = VOP_READLINK(vp, &uio, kcred, NULL)) == 0) { + *(lkdata + MAXREPARSELEN - uio.uio_resid) = '\0'; + err = reparse_parse(lkdata, nvl); + } + kmem_free(lkdata, MAXREPARSELEN); /* done with lkdata */ + + return (err); +} + +void +reparse_point_init() +{ + mutex_init(&reparsed_door_lock, NULL, MUTEX_DEFAULT, NULL); +} + +static door_handle_t +reparse_door_get_handle() +{ + door_handle_t dh; + + mutex_enter(&reparsed_door_lock); + if ((dh = reparsed_door) == NULL) { + if (door_ki_open(REPARSED_DOOR, &reparsed_door) != 0) { + reparsed_door = NULL; + dh = NULL; + } else + dh = reparsed_door; + } + mutex_exit(&reparsed_door_lock); + return (dh); +} + +static void +reparse_door_reset_handle() +{ + mutex_enter(&reparsed_door_lock); + reparsed_door = NULL; + mutex_exit(&reparsed_door_lock); +} + +/* + * reparse_kderef + * + * Accepts the service-specific item from the reparse point and returns + * the service-specific data requested. The caller specifies the size of + * the buffer provided via *bufsz; the routine will fail with EOVERFLOW + * if the results will not fit in the buffer, in which case, *bufsz will + * contain the number of bytes needed to hold the results. + * + * if ok return 0 and update *bufsize with length of actual result + * else return error code. + */ +int +reparse_kderef(const char *svc_type, const char *svc_data, char *buf, + size_t *bufsize) +{ + int err, retries, need_free; + size_t dlen, res_len; + char *darg; + door_arg_t door_args; + reparsed_door_res_t *resp; + door_handle_t rp_door; + + if (svc_type == NULL || svc_data == NULL || buf == NULL || + bufsize == NULL) + return (EINVAL); + + /* get reparsed's door handle */ + if ((rp_door = reparse_door_get_handle()) == NULL) + return (EBADF); + + /* setup buffer for door_call args and results */ + dlen = strlen(svc_type) + strlen(svc_data) + 2; + if (*bufsize < dlen) { + darg = kmem_alloc(dlen, KM_SLEEP); + need_free = 1; + } else { + darg = buf; /* use same buffer for door's args & results */ + need_free = 0; + } + + /* build argument string of door call */ + (void) snprintf(darg, dlen, "%s:%s", svc_type, svc_data); + + /* setup args for door call */ + door_args.data_ptr = darg; + door_args.data_size = dlen; + door_args.desc_ptr = NULL; + door_args.desc_num = 0; + door_args.rbuf = buf; + door_args.rsize = *bufsize; + + /* do the door_call */ + retries = 0; + door_ki_hold(rp_door); + while ((err = door_ki_upcall_limited(rp_door, &door_args, + NULL, SIZE_MAX, 0)) != 0) { + if (err == EAGAIN || err == EINTR) { + if (++retries < REPARSED_DOORCALL_MAX_RETRY) { + delay(SEC_TO_TICK(1)); + continue; + } + } else if (err == EBADF) { + /* door server goes away... */ + reparse_door_reset_handle(); + } + break; + } + door_ki_rele(rp_door); + if (need_free) + kmem_free(darg, dlen); /* done with args buffer */ + + if (err != 0) + return (err); + + resp = (reparsed_door_res_t *)door_args.rbuf; + if ((err = resp->res_status) == 0) { + /* + * have to save the length of the results before the + * bcopy below since it's can be an overlap copy that + * overwrites the reparsed_door_res_t structure at + * the beginning of the buffer. + */ + res_len = (size_t)resp->res_len; + + /* deref call is ok */ + if (res_len > *bufsize) + err = EOVERFLOW; + else + bcopy(resp->res_data, buf, res_len); + *bufsize = res_len; + } + if (door_args.rbuf != buf) + kmem_free(door_args.rbuf, door_args.rsize); + + return (err); +} diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c index bf9d325048..0d750e00ed 100644 --- a/usr/src/uts/common/fs/vfs.c +++ b/usr/src/uts/common/fs/vfs.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -4252,6 +4252,8 @@ vfsinit(void) } xattr_init(); + + reparse_point_init(); } vfs_t * diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c index 09a011fc87..a42259df93 100644 --- a/usr/src/uts/common/fs/vnode.c +++ b/usr/src/uts/common/fs/vnode.c @@ -64,6 +64,7 @@ #include <sys/fcntl.h> #include <fs/fs_subr.h> #include <sys/taskq.h> +#include <fs/fs_reparse.h> /* Determine if this vnode is a file that is read-only */ #define ISROFILE(vp) \ @@ -106,6 +107,11 @@ int vopstats_enabled = 1; static void *vsd_realloc(void *, size_t, size_t); /* + * forward declarations for reparse point functions + */ +static int fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr); + +/* * VSD -- VNODE SPECIFIC DATA * The v_data pointer is typically used by a file system to store a * pointer to the file system's private node (e.g. ufs inode, nfs rnode). @@ -3604,6 +3610,7 @@ fop_symlink( int flags) { int err; + xvattr_t xvattr; /* * If this file system doesn't support case-insensitive access @@ -3616,6 +3623,14 @@ fop_symlink( VOPXID_MAP_CR(dvp, cr); + /* check for reparse point */ + if ((vfs_has_feature(dvp->v_vfsp, VFSFT_REPARSE)) && + (strncmp(target, FS_REPARSE_TAG_STR, + strlen(FS_REPARSE_TAG_STR)) == 0)) { + if (!fs_reparse_mark(target, vap, &xvattr)) + vap = (vattr_t *)&xvattr; + } + err = (*(dvp)->v_op->vop_symlink) (dvp, linkname, vap, target, cr, ct, flags); VOPSTATS_UPDATE(dvp, symlink); @@ -4395,3 +4410,34 @@ vsd_realloc(void *old, size_t osize, size_t nsize) } return (new); } + +/* + * Setup the extensible system attribute for creating a reparse point. + * The symlink data 'target' is validated for proper format of a reparse + * string and a check also made to make sure the symlink data does not + * point to an existing file. + * + * return 0 if ok else -1. + */ +static int +fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr) +{ + xoptattr_t *xoap; + + if ((!target) || (!vap) || (!xvattr)) + return (-1); + + /* validate reparse string */ + if (reparse_validate((const char *)target)) + return (-1); + + xva_init(xvattr); + xvattr->xva_vattr = *vap; + xvattr->xva_vattr.va_mask |= AT_XVATTR; + xoap = xva_getxoptattr(xvattr); + ASSERT(xoap); + XVA_SET_REQ(xvattr, XAT_REPARSE); + xoap->xoa_reparse = 1; + + return (0); +} diff --git a/usr/src/uts/common/fs/xattr.c b/usr/src/uts/common/fs/xattr.c index 274c57869c..137379ecc3 100644 --- a/usr/src/uts/common/fs/xattr.c +++ b/usr/src/uts/common/fs/xattr.c @@ -212,6 +212,9 @@ xattr_fill_nvlist(vnode_t *vp, xattr_view_t xattr_view, nvlist_t *nvlp, VERIFY(nvlist_add_uint64(nvlp, attr_to_name(attr), fsid) == 0); break; + case F_REPARSE: + XVA_SET_REQ(&xvattr, XAT_REPARSE); + break; default: break; } @@ -294,6 +297,11 @@ xattr_fill_nvlist(vnode_t *vp, xattr_view_t xattr_view, nvlist_t *nvlp, sizeof (xoap->xoa_createtime) / sizeof (uint64_t)) == 0); } + if (XVA_ISSET_RTN(&xvattr, XAT_REPARSE)) { + VERIFY(nvlist_add_boolean_value(nvlp, + attr_to_name(F_REPARSE), + xoap->xoa_reparse) == 0); + } } /* * Check for optional ownersid/groupsid @@ -667,6 +675,10 @@ xattr_file_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, return (EINVAL); } break; + case F_REPARSE: + XVA_SET_REQ(&xvattr, XAT_REPARSE); + xoap->xoa_reparse = value; + break; default: break; } @@ -807,6 +819,7 @@ xattr_copy(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, XVA_SET_REQ(&xvattr, XAT_AV_MODIFIED); XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED); XVA_SET_REQ(&xvattr, XAT_CREATETIME); + XVA_SET_REQ(&xvattr, XAT_REPARSE); pdvp = gfs_file_parent(sdvp); error = VOP_GETATTR(pdvp, &xvattr.xva_vattr, 0, cr, ct); diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h index 5db5b8d518..ca826abbac 100644 --- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h +++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h @@ -57,6 +57,7 @@ extern "C" { #define ZFS_OPAQUE 0x0000010000000000 #define ZFS_AV_QUARANTINED 0x0000020000000000 #define ZFS_AV_MODIFIED 0x0000040000000000 +#define ZFS_REPARSE 0x0000080000000000 #define ZFS_ATTR_SET(zp, attr, value) \ { \ diff --git a/usr/src/uts/common/fs/zfs/zfs_log.c b/usr/src/uts/common/fs/zfs/zfs_log.c index 4df7115f58..f0a713ed94 100644 --- a/usr/src/uts/common/fs/zfs/zfs_log.c +++ b/usr/src/uts/common/fs/zfs/zfs_log.c @@ -175,6 +175,9 @@ zfs_log_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) ZFS_TIME_ENCODE(&xoap->xoa_createtime, crtime); if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) bcopy(xoap->xoa_av_scanstamp, scanstamp, AV_SCANSTAMP_SZ); + if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) + *attrs |= (xoap->xoa_reparse == 0) ? 0 : + XAT0_REPARSE; } static void * diff --git a/usr/src/uts/common/fs/zfs/zfs_replay.c b/usr/src/uts/common/fs/zfs/zfs_replay.c index 85b79703a7..232422b0f8 100644 --- a/usr/src/uts/common/fs/zfs/zfs_replay.c +++ b/usr/src/uts/common/fs/zfs/zfs_replay.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> @@ -129,6 +127,8 @@ zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) ZFS_TIME_DECODE(&xoap->xoa_createtime, crtime); if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ); + if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) + xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0); } static int diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c index 8f51a0dbf2..7a6b850d1c 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c @@ -1049,6 +1049,7 @@ zfs_set_fuid_feature(zfsvfs_t *zfsvfs) vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS); vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE); vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER); + vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE); } } diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c index 644b2dba9a..6513640437 100644 --- a/usr/src/uts/common/fs/zfs/zfs_vnops.c +++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c @@ -2370,6 +2370,12 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, ZFS_TIME_DECODE(&xoap->xoa_createtime, pzp->zp_crtime); XVA_SET_RTN(xvap, XAT_CREATETIME); } + + if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { + xoap->xoa_reparse = + ((pzp->zp_flags & ZFS_REPARSE) != 0); + XVA_SET_RTN(xvap, XAT_REPARSE); + } } ZFS_TIME_DECODE(&vap->va_atime, pzp->zp_atime); @@ -2671,6 +2677,12 @@ top: } } + if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { + mutex_exit(&zp->z_lock); + ZFS_EXIT(zfsvfs); + return (EPERM); + } + if (need_policy == FALSE && (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) || XVA_ISSET_REQ(xvap, XAT_OPAQUE))) { diff --git a/usr/src/uts/common/fs/zfs/zfs_znode.c b/usr/src/uts/common/fs/zfs/zfs_znode.c index 62156fb4f6..c861bd9936 100644 --- a/usr/src/uts/common/fs/zfs/zfs_znode.c +++ b/usr/src/uts/common/fs/zfs/zfs_znode.c @@ -909,6 +909,10 @@ zfs_xvattr_set(znode_t *zp, xvattr_t *xvap) zp->z_phys->zp_flags |= ZFS_BONUS_SCANSTAMP; XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP); } + if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { + ZFS_ATTR_SET(zp, ZFS_REPARSE, xoap->xoa_reparse); + XVA_SET_RTN(xvap, XAT_REPARSE); + } } int diff --git a/usr/src/uts/common/fs/zut/zut.c b/usr/src/uts/common/fs/zut/zut.c index 9381b69aea..c655585968 100644 --- a/usr/src/uts/common/fs/zut/zut.c +++ b/usr/src/uts/common/fs/zut/zut.c @@ -217,6 +217,7 @@ zut_stat64(vnode_t *vp, struct stat64 *sb, uint64_t *xvs, int flag, cred_t *cr) XVA_SET_REQ(&xv, XAT_OPAQUE); XVA_SET_REQ(&xv, XAT_AV_QUARANTINED); XVA_SET_REQ(&xv, XAT_AV_MODIFIED); + XVA_SET_REQ(&xv, XAT_REPARSE); xv.xva_vattr.va_mask |= AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE; if (error = VOP_GETATTR(vp, &xv.xva_vattr, flag, cr, NULL)) @@ -263,6 +264,8 @@ zut_stat64(vnode_t *vp, struct stat64 *sb, uint64_t *xvs, int flag, cred_t *cr) *xvs |= (1 << F_AV_QUARANTINED); if (XVA_ISSET_RTN(&xv, XAT_AV_MODIFIED) && xoap->xoa_av_modified) *xvs |= (1 << F_AV_MODIFIED); + if (XVA_ISSET_RTN(&xv, XAT_REPARSE) && xoap->xoa_reparse) + *xvs |= (1 << F_REPARSE); return (0); } diff --git a/usr/src/uts/common/sys/attr.h b/usr/src/uts/common/sys/attr.h index 86c4cd5d6c..b312b5a429 100644 --- a/usr/src/uts/common/sys/attr.h +++ b/usr/src/uts/common/sys/attr.h @@ -19,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_ATTR_H #define _SYS_ATTR_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -56,6 +54,7 @@ extern "C" { #define A_AV_SCANSTAMP "av_scanstamp" #define A_OWNERSID "ownersid" #define A_GROUPSID "groupsid" +#define A_REPARSE_POINT "reparse" /* Attribute option for utilities */ #define O_HIDDEN "H" @@ -68,6 +67,7 @@ extern "C" { #define O_NODUMP "d" #define O_AV_QUARANTINED "q" #define O_AV_MODIFIED "m" +#define O_REPARSE_POINT "r" #define O_NONE "" /* ownersid and groupsid are composed of two nvpairs */ @@ -92,6 +92,7 @@ typedef enum { F_OWNERSID, F_GROUPSID, F_FSID, + F_REPARSE, F_ATTR_ALL } f_attr_t; diff --git a/usr/src/uts/common/sys/vfs.h b/usr/src/uts/common/sys/vfs.h index 17ee536024..4d0d6d1257 100644 --- a/usr/src/uts/common/sys/vfs.h +++ b/usr/src/uts/common/sys/vfs.h @@ -297,6 +297,7 @@ typedef uint64_t vfs_feature_t; #define VFSFT_ACEMASKONACCESS 0x100000020 /* Can use ACEMASK for access */ #define VFSFT_SYSATTR_VIEWS 0x100000040 /* Supports sysattr view i/f */ #define VFSFT_ACCESS_FILTER 0x100000080 /* dirents filtered by access */ +#define VFSFT_REPARSE 0x100000100 /* Supports reparse point */ /* * Argument structure for mount(2). diff --git a/usr/src/uts/common/sys/vnode.h b/usr/src/uts/common/sys/vnode.h index f3e3fe6879..a060c30434 100644 --- a/usr/src/uts/common/sys/vnode.h +++ b/usr/src/uts/common/sys/vnode.h @@ -387,6 +387,7 @@ typedef struct xoptattr { uint8_t xoa_av_quarantined; uint8_t xoa_av_modified; uint8_t xoa_av_scanstamp[AV_SCANSTAMP_SZ]; + uint8_t xoa_reparse; } xoptattr_t; /* @@ -565,11 +566,12 @@ typedef vattr_t vattr32_t; #define XAT0_AV_QUARANTINED 0x00000400 /* anti-virus quarantine */ #define XAT0_AV_MODIFIED 0x00000800 /* anti-virus modified */ #define XAT0_AV_SCANSTAMP 0x00001000 /* anti-virus scanstamp */ +#define XAT0_REPARSE 0x00002000 /* FS reparse point */ #define XAT0_ALL_ATTRS (XAT0_CREATETIME|XAT0_ARCHIVE|XAT0_SYSTEM| \ XAT0_READONLY|XAT0_HIDDEN|XAT0_NOUNLINK|XAT0_IMMUTABLE|XAT0_APPENDONLY| \ XAT0_NODUMP|XAT0_OPAQUE|XAT0_AV_QUARANTINED| \ - XAT0_AV_MODIFIED|XAT0_AV_SCANSTAMP) + XAT0_AV_MODIFIED|XAT0_AV_SCANSTAMP|XAT0_REPARSE) /* Support for XAT_* optional attributes */ #define XVA_MASK 0xffffffff /* Used to mask off 32 bits */ @@ -602,6 +604,7 @@ typedef vattr_t vattr32_t; #define XAT_AV_QUARANTINED ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_QUARANTINED) #define XAT_AV_MODIFIED ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_MODIFIED) #define XAT_AV_SCANSTAMP ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_SCANSTAMP) +#define XAT_REPARSE ((XAT0_INDEX << XVA_SHFT) | XAT0_REPARSE) /* * The returned attribute map array (xva_rtnattrmap[]) is located past the @@ -1274,6 +1277,9 @@ void xattr_init(void); /* Initialize vnodeops for xattrs */ /* GFS tunnel for xattrs */ int xattr_dir_lookup(vnode_t *, vnode_t **, int, cred_t *); +/* Reparse Point */ +void reparse_point_init(void); + /* Context identification */ u_longlong_t fs_new_caller_id(); |