Print this page
3484 enhance and document tail follow support
Reviewed by: Joshua M. Clulow <jmc@joyent.com>


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 




  27 #include <sys/types.h>
  28 #include <sys/param.h>
  29 #include <sys/t_lock.h>
  30 #include <sys/systm.h>
  31 #include <sys/sysmacros.h>
  32 #include <sys/user.h>
  33 #include <sys/time.h>
  34 #include <sys/vfs.h>
  35 #include <sys/vfs_opreg.h>
  36 #include <sys/vnode.h>
  37 #include <sys/file.h>
  38 #include <sys/fcntl.h>
  39 #include <sys/flock.h>
  40 #include <sys/kmem.h>
  41 #include <sys/uio.h>
  42 #include <sys/errno.h>
  43 #include <sys/stat.h>
  44 #include <sys/cred.h>
  45 #include <sys/dirent.h>
  46 #include <sys/pathname.h>


 961 
 962         if (vap->va_type == VREG && (vap->va_mode & VSVTX)) {
 963                 /* Must be privileged to set sticky bit */
 964                 if (secpolicy_vnode_stky_modify(cred))
 965                         vap->va_mode &= ~VSVTX;
 966         } else if (vap->va_type == VNON) {
 967                 return (EINVAL);
 968         }
 969 
 970         /*
 971          * Null component name is a synonym for directory being searched.
 972          */
 973         if (*nm == '\0') {
 974                 VN_HOLD(dvp);
 975                 oldtp = parent;
 976         } else {
 977                 error = tdirlookup(parent, nm, &oldtp, cred);
 978         }
 979 
 980         if (error == 0) {       /* name found */


 981                 ASSERT(oldtp);
 982 
 983                 rw_enter(&oldtp->tn_rwlock, RW_WRITER);
 984 
 985                 /*
 986                  * if create/read-only an existing
 987                  * directory, allow it
 988                  */
 989                 if (exclusive == EXCL)
 990                         error = EEXIST;
 991                 else if ((oldtp->tn_type == VDIR) && (mode & VWRITE))
 992                         error = EISDIR;
 993                 else {
 994                         error = tmp_taccess(oldtp, mode, cred);
 995                 }
 996 
 997                 if (error) {
 998                         rw_exit(&oldtp->tn_rwlock);
 999                         tmpnode_rele(oldtp);
1000                         return (error);
1001                 }
1002                 *vpp = TNTOV(oldtp);
1003                 if ((*vpp)->v_type == VREG && (vap->va_mask & AT_SIZE) &&
1004                     vap->va_size == 0) {
1005                         rw_enter(&oldtp->tn_contents, RW_WRITER);
1006                         (void) tmpnode_trunc(tm, oldtp, 0);
1007                         rw_exit(&oldtp->tn_contents);

1008                 }
1009                 rw_exit(&oldtp->tn_rwlock);
1010                 if (IS_DEVVP(*vpp)) {
1011                         struct vnode *newvp;
1012 
1013                         newvp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type,
1014                             cred);
1015                         VN_RELE(*vpp);
1016                         if (newvp == NULL) {
1017                                 return (ENOSYS);
1018                         }
1019                         *vpp = newvp;
1020                 }
1021 
1022                 if (error == 0) {
1023                         vnevent_create(*vpp, ct);
1024                 }
1025                 return (0);
1026         }
1027 
1028         if (error != ENOENT)
1029                 return (error);
1030 
1031         rw_enter(&parent->tn_rwlock, RW_WRITER);
1032         error = tdirenter(tm, parent, nm, DE_CREATE,
1033             (struct tmpnode *)NULL, (struct tmpnode *)NULL,
1034             vap, &self, cred, ct);
1035         rw_exit(&parent->tn_rwlock);
1036 
1037         if (error) {
1038                 if (self)
1039                         tmpnode_rele(self);
1040 
1041                 if (error == EEXIST) {
1042                         /*
1043                          * This means that the file was created sometime
1044                          * after we checked and did not find it and when




   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/param.h>
  33 #include <sys/t_lock.h>
  34 #include <sys/systm.h>
  35 #include <sys/sysmacros.h>
  36 #include <sys/user.h>
  37 #include <sys/time.h>
  38 #include <sys/vfs.h>
  39 #include <sys/vfs_opreg.h>
  40 #include <sys/vnode.h>
  41 #include <sys/file.h>
  42 #include <sys/fcntl.h>
  43 #include <sys/flock.h>
  44 #include <sys/kmem.h>
  45 #include <sys/uio.h>
  46 #include <sys/errno.h>
  47 #include <sys/stat.h>
  48 #include <sys/cred.h>
  49 #include <sys/dirent.h>
  50 #include <sys/pathname.h>


 965 
 966         if (vap->va_type == VREG && (vap->va_mode & VSVTX)) {
 967                 /* Must be privileged to set sticky bit */
 968                 if (secpolicy_vnode_stky_modify(cred))
 969                         vap->va_mode &= ~VSVTX;
 970         } else if (vap->va_type == VNON) {
 971                 return (EINVAL);
 972         }
 973 
 974         /*
 975          * Null component name is a synonym for directory being searched.
 976          */
 977         if (*nm == '\0') {
 978                 VN_HOLD(dvp);
 979                 oldtp = parent;
 980         } else {
 981                 error = tdirlookup(parent, nm, &oldtp, cred);
 982         }
 983 
 984         if (error == 0) {       /* name found */
 985                 boolean_t trunc = B_FALSE;
 986 
 987                 ASSERT(oldtp);
 988 
 989                 rw_enter(&oldtp->tn_rwlock, RW_WRITER);
 990 
 991                 /*
 992                  * if create/read-only an existing
 993                  * directory, allow it
 994                  */
 995                 if (exclusive == EXCL)
 996                         error = EEXIST;
 997                 else if ((oldtp->tn_type == VDIR) && (mode & VWRITE))
 998                         error = EISDIR;
 999                 else {
1000                         error = tmp_taccess(oldtp, mode, cred);
1001                 }
1002 
1003                 if (error) {
1004                         rw_exit(&oldtp->tn_rwlock);
1005                         tmpnode_rele(oldtp);
1006                         return (error);
1007                 }
1008                 *vpp = TNTOV(oldtp);
1009                 if ((*vpp)->v_type == VREG && (vap->va_mask & AT_SIZE) &&
1010                     vap->va_size == 0) {
1011                         rw_enter(&oldtp->tn_contents, RW_WRITER);
1012                         (void) tmpnode_trunc(tm, oldtp, 0);
1013                         rw_exit(&oldtp->tn_contents);
1014                         trunc = B_TRUE;
1015                 }
1016                 rw_exit(&oldtp->tn_rwlock);
1017                 if (IS_DEVVP(*vpp)) {
1018                         struct vnode *newvp;
1019 
1020                         newvp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type,
1021                             cred);
1022                         VN_RELE(*vpp);
1023                         if (newvp == NULL) {
1024                                 return (ENOSYS);
1025                         }
1026                         *vpp = newvp;
1027                 }
1028 
1029                 if (trunc)
1030                         vnevent_create(*vpp, ct);
1031 
1032                 return (0);
1033         }
1034 
1035         if (error != ENOENT)
1036                 return (error);
1037 
1038         rw_enter(&parent->tn_rwlock, RW_WRITER);
1039         error = tdirenter(tm, parent, nm, DE_CREATE,
1040             (struct tmpnode *)NULL, (struct tmpnode *)NULL,
1041             vap, &self, cred, ct);
1042         rw_exit(&parent->tn_rwlock);
1043 
1044         if (error) {
1045                 if (self)
1046                         tmpnode_rele(self);
1047 
1048                 if (error == EEXIST) {
1049                         /*
1050                          * This means that the file was created sometime
1051                          * after we checked and did not find it and when