/* * 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 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include int smb_fem_fcn_create(femarg_t *, char *, vattr_t *, vcexcl_t, int, vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *); int smb_fem_fcn_remove(femarg_t *, char *, cred_t *, caller_context_t *, int); int smb_fem_fcn_rename(femarg_t *, char *, vnode_t *, char *, cred_t *, caller_context_t *, int); int smb_fem_fcn_mkdir(femarg_t *, char *, vattr_t *, vnode_t **, cred_t *, caller_context_t *, int, vsecattr_t *); int smb_fem_fcn_rmdir(femarg_t *, char *, vnode_t *, cred_t *, caller_context_t *, int); int smb_fem_fcn_link(femarg_t *, vnode_t *, char *, cred_t *, caller_context_t *, int); int smb_fem_fcn_symlink(femarg_t *, char *, vattr_t *, char *, cred_t *, caller_context_t *, int); static const fs_operation_def_t smb_fcn_tmpl[] = { VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create }, VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove}, VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename}, VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir}, VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir}, VOPNAME_LINK, {.femop_link = smb_fem_fcn_link}, VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink}, NULL, NULL }; static boolean_t smb_fem_initialized = B_FALSE; static fem_t *smb_fcn_ops = NULL; /* * smb_fem_init * * This function is not multi-thread safe. The caller must make sure only one * thread makes the call. */ int smb_fem_init(void) { int rc = 0; if (smb_fem_initialized) return (0); rc = fem_create("smb_fcn_ops", smb_fcn_tmpl, &smb_fcn_ops); if (rc) return (rc); smb_fem_initialized = B_TRUE; return (0); } /* * smb_fem_fini * * This function is not multi-thread safe. The caller must make sure only one * thread makes the call. */ void smb_fem_fini(void) { if (!smb_fem_initialized) return; fem_free(smb_fcn_ops); smb_fcn_ops = NULL; smb_fem_initialized = B_FALSE; } void smb_fem_fcn_install(smb_node_t *node) { (void) fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ, (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release); } void smb_fem_fcn_uninstall(smb_node_t *node) { (void) fem_uninstall(node->vp, smb_fcn_ops, (void *)node); } /* * smb_fem_fcn_create() * * This monitor will catch only changes to VREG files and not to extended * attribute files. This is fine because, for CIFS files, stream creates * should not trigger any file change notification on the VDIR directory * being monitored. Creates of any other kind of extended attribute in * the directory will also not trigger any file change notification on the * VDIR directory being monitored. */ int smb_fem_fcn_create( femarg_t *arg, char *name, vattr_t *vap, vcexcl_t excl, int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct, vsecattr_t *vsecp) { smb_node_t *dnode; int error; dnode = (smb_node_t *)arg->fa_fnode->fn_available; ASSERT(dnode); error = vnext_create(arg, name, vap, excl, mode, vpp, cr, flag, ct, vsecp); if (error == 0) smb_process_node_notify_change_queue(dnode); return (error); } /* * smb_fem_fcn_remove() * * This monitor will catch only changes to VREG files and to not extended * attribute files. This is fine because, for CIFS files, stream deletes * should not trigger any file change notification on the VDIR directory * being monitored. Deletes of any other kind of extended attribute in * the directory will also not trigger any file change notification on the * VDIR directory being monitored. */ int smb_fem_fcn_remove( femarg_t *arg, char *name, cred_t *cr, caller_context_t *ct, int flags) { smb_node_t *dnode; int error; dnode = (smb_node_t *)arg->fa_fnode->fn_available; ASSERT(dnode); error = vnext_remove(arg, name, cr, ct, flags); if (error == 0) smb_process_node_notify_change_queue(dnode); return (error); } int smb_fem_fcn_rename( femarg_t *arg, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr, caller_context_t *ct, int flags) { smb_node_t *dnode; int error; dnode = (smb_node_t *)arg->fa_fnode->fn_available; ASSERT(dnode); error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags); if (error == 0) smb_process_node_notify_change_queue(dnode); return (error); } int smb_fem_fcn_mkdir( femarg_t *arg, char *name, vattr_t *vap, vnode_t **vpp, cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp) { smb_node_t *dnode; int error; dnode = (smb_node_t *)arg->fa_fnode->fn_available; ASSERT(dnode); error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp); if (error == 0) smb_process_node_notify_change_queue(dnode); return (error); } int smb_fem_fcn_rmdir( femarg_t *arg, char *name, vnode_t *cdir, cred_t *cr, caller_context_t *ct, int flags) { smb_node_t *dnode; int error; dnode = (smb_node_t *)arg->fa_fnode->fn_available; ASSERT(dnode); error = vnext_rmdir(arg, name, cdir, cr, ct, flags); if (error == 0) smb_process_node_notify_change_queue(dnode); return (error); } int smb_fem_fcn_link( femarg_t *arg, vnode_t *svp, char *tnm, cred_t *cr, caller_context_t *ct, int flags) { smb_node_t *dnode; int error; dnode = (smb_node_t *)arg->fa_fnode->fn_available; ASSERT(dnode); error = vnext_link(arg, svp, tnm, cr, ct, flags); if (error == 0) smb_process_node_notify_change_queue(dnode); return (error); } int smb_fem_fcn_symlink( femarg_t *arg, char *linkname, vattr_t *vap, char *target, cred_t *cr, caller_context_t *ct, int flags) { smb_node_t *dnode; int error; dnode = (smb_node_t *)arg->fa_fnode->fn_available; ASSERT(dnode); error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags); if (error == 0) smb_process_node_notify_change_queue(dnode); return (error); }