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
|