xref: /titanic_50/usr/src/uts/common/syscall/fcntl.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
23*7c478bd9Sstevel@tonic-gate /*
24*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
25*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
26*7c478bd9Sstevel@tonic-gate  */
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
29*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*
32*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
33*7c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
34*7c478bd9Sstevel@tonic-gate  */
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
37*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
46*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
47*7c478bd9Sstevel@tonic-gate #include <sys/flock.h>
48*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
49*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/mode.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/filio.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/share.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/rctl.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/nbmlock.h>
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
60*7c478bd9Sstevel@tonic-gate static int flock_check(vnode_t *, flock64_t *, offset_t, offset_t);
61*7c478bd9Sstevel@tonic-gate static int flock_get_start(vnode_t *, flock64_t *, offset_t, u_offset_t *);
62*7c478bd9Sstevel@tonic-gate static void fd_too_big(proc_t *);
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /*
65*7c478bd9Sstevel@tonic-gate  * File control.
66*7c478bd9Sstevel@tonic-gate  */
67*7c478bd9Sstevel@tonic-gate int
68*7c478bd9Sstevel@tonic-gate fcntl(int fdes, int cmd, intptr_t arg)
69*7c478bd9Sstevel@tonic-gate {
70*7c478bd9Sstevel@tonic-gate 	int iarg;
71*7c478bd9Sstevel@tonic-gate 	int error = 0;
72*7c478bd9Sstevel@tonic-gate 	int retval;
73*7c478bd9Sstevel@tonic-gate 	proc_t *p;
74*7c478bd9Sstevel@tonic-gate 	file_t *fp;
75*7c478bd9Sstevel@tonic-gate 	vnode_t *vp;
76*7c478bd9Sstevel@tonic-gate 	u_offset_t offset;
77*7c478bd9Sstevel@tonic-gate 	u_offset_t start;
78*7c478bd9Sstevel@tonic-gate 	struct vattr vattr;
79*7c478bd9Sstevel@tonic-gate 	int in_crit;
80*7c478bd9Sstevel@tonic-gate 	int flag;
81*7c478bd9Sstevel@tonic-gate 	struct flock sbf;
82*7c478bd9Sstevel@tonic-gate 	struct flock64 bf;
83*7c478bd9Sstevel@tonic-gate 	struct o_flock obf;
84*7c478bd9Sstevel@tonic-gate 	struct flock64_32 bf64_32;
85*7c478bd9Sstevel@tonic-gate 	struct fshare fsh;
86*7c478bd9Sstevel@tonic-gate 	struct shrlock shr;
87*7c478bd9Sstevel@tonic-gate 	struct shr_locowner shr_own;
88*7c478bd9Sstevel@tonic-gate 	offset_t maxoffset;
89*7c478bd9Sstevel@tonic-gate 	model_t datamodel;
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate #if defined(_ILP32) && !defined(lint) && defined(_SYSCALL32)
92*7c478bd9Sstevel@tonic-gate 	ASSERT(sizeof (struct flock) == sizeof (struct flock32));
93*7c478bd9Sstevel@tonic-gate 	ASSERT(sizeof (struct flock64) == sizeof (struct flock64_32));
94*7c478bd9Sstevel@tonic-gate #endif
95*7c478bd9Sstevel@tonic-gate #if defined(_LP64) && !defined(lint) && defined(_SYSCALL32)
96*7c478bd9Sstevel@tonic-gate 	ASSERT(sizeof (struct flock) == sizeof (struct flock64_64));
97*7c478bd9Sstevel@tonic-gate 	ASSERT(sizeof (struct flock64) == sizeof (struct flock64_64));
98*7c478bd9Sstevel@tonic-gate #endif
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	/*
101*7c478bd9Sstevel@tonic-gate 	 * First, for speed, deal with the subset of cases
102*7c478bd9Sstevel@tonic-gate 	 * that do not require getf() / releasef().
103*7c478bd9Sstevel@tonic-gate 	 */
104*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
105*7c478bd9Sstevel@tonic-gate 	case F_GETFD:
106*7c478bd9Sstevel@tonic-gate 		if ((error = f_getfd_error(fdes, &flag)) == 0)
107*7c478bd9Sstevel@tonic-gate 			retval = flag;
108*7c478bd9Sstevel@tonic-gate 		goto out;
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate 	case F_SETFD:
111*7c478bd9Sstevel@tonic-gate 		error = f_setfd_error(fdes, (int)arg);
112*7c478bd9Sstevel@tonic-gate 		retval = 0;
113*7c478bd9Sstevel@tonic-gate 		goto out;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	case F_GETFL:
116*7c478bd9Sstevel@tonic-gate 		if ((error = f_getfl(fdes, &flag)) == 0)
117*7c478bd9Sstevel@tonic-gate 			retval = (flag & (FMASK | FASYNC)) + FOPEN;
118*7c478bd9Sstevel@tonic-gate 		goto out;
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 	case F_GETXFL:
121*7c478bd9Sstevel@tonic-gate 		if ((error = f_getfl(fdes, &flag)) == 0)
122*7c478bd9Sstevel@tonic-gate 			retval = flag + FOPEN;
123*7c478bd9Sstevel@tonic-gate 		goto out;
124*7c478bd9Sstevel@tonic-gate 	}
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	/*
127*7c478bd9Sstevel@tonic-gate 	 * Second, for speed, deal with the subset of cases that
128*7c478bd9Sstevel@tonic-gate 	 * require getf() / releasef() but do not require copyin.
129*7c478bd9Sstevel@tonic-gate 	 */
130*7c478bd9Sstevel@tonic-gate 	if ((fp = getf(fdes)) == NULL) {
131*7c478bd9Sstevel@tonic-gate 		error = EBADF;
132*7c478bd9Sstevel@tonic-gate 		goto out;
133*7c478bd9Sstevel@tonic-gate 	}
134*7c478bd9Sstevel@tonic-gate 	iarg = (int)arg;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
137*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate 	case F_DUPFD:
140*7c478bd9Sstevel@tonic-gate 		p = curproc;
141*7c478bd9Sstevel@tonic-gate 		if ((uint_t)iarg >= p->p_fno_ctl) {
142*7c478bd9Sstevel@tonic-gate 			if (iarg >= 0)
143*7c478bd9Sstevel@tonic-gate 				fd_too_big(p);
144*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
145*7c478bd9Sstevel@tonic-gate 		} else if ((retval = ufalloc_file(iarg, fp)) == -1) {
146*7c478bd9Sstevel@tonic-gate 			error = EMFILE;
147*7c478bd9Sstevel@tonic-gate 		} else {
148*7c478bd9Sstevel@tonic-gate 			mutex_enter(&fp->f_tlock);
149*7c478bd9Sstevel@tonic-gate 			fp->f_count++;
150*7c478bd9Sstevel@tonic-gate 			mutex_exit(&fp->f_tlock);
151*7c478bd9Sstevel@tonic-gate 		}
152*7c478bd9Sstevel@tonic-gate 		goto done;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	case F_DUP2FD:
155*7c478bd9Sstevel@tonic-gate 		p = curproc;
156*7c478bd9Sstevel@tonic-gate 		if (fdes == iarg) {
157*7c478bd9Sstevel@tonic-gate 			retval = iarg;
158*7c478bd9Sstevel@tonic-gate 		} else if ((uint_t)iarg >= p->p_fno_ctl) {
159*7c478bd9Sstevel@tonic-gate 			if (iarg >= 0)
160*7c478bd9Sstevel@tonic-gate 				fd_too_big(p);
161*7c478bd9Sstevel@tonic-gate 			error = EBADF;
162*7c478bd9Sstevel@tonic-gate 		} else {
163*7c478bd9Sstevel@tonic-gate 			/*
164*7c478bd9Sstevel@tonic-gate 			 * We can't hold our getf(fdes) across the call to
165*7c478bd9Sstevel@tonic-gate 			 * closeandsetf() because it creates a window for
166*7c478bd9Sstevel@tonic-gate 			 * deadlock: if one thread is doing dup2(a, b) while
167*7c478bd9Sstevel@tonic-gate 			 * another is doing dup2(b, a), each one will block
168*7c478bd9Sstevel@tonic-gate 			 * waiting for the other to call releasef().  The
169*7c478bd9Sstevel@tonic-gate 			 * solution is to increment the file reference count
170*7c478bd9Sstevel@tonic-gate 			 * (which we have to do anyway), then releasef(fdes),
171*7c478bd9Sstevel@tonic-gate 			 * then closeandsetf().  Incrementing f_count ensures
172*7c478bd9Sstevel@tonic-gate 			 * that fp won't disappear after we call releasef().
173*7c478bd9Sstevel@tonic-gate 			 */
174*7c478bd9Sstevel@tonic-gate 			mutex_enter(&fp->f_tlock);
175*7c478bd9Sstevel@tonic-gate 			fp->f_count++;
176*7c478bd9Sstevel@tonic-gate 			mutex_exit(&fp->f_tlock);
177*7c478bd9Sstevel@tonic-gate 			releasef(fdes);
178*7c478bd9Sstevel@tonic-gate 			(void) closeandsetf(iarg, fp);
179*7c478bd9Sstevel@tonic-gate 			retval = iarg;
180*7c478bd9Sstevel@tonic-gate 			goto out;
181*7c478bd9Sstevel@tonic-gate 		}
182*7c478bd9Sstevel@tonic-gate 		goto done;
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 	case F_SETFL:
185*7c478bd9Sstevel@tonic-gate 		vp = fp->f_vnode;
186*7c478bd9Sstevel@tonic-gate 		flag = fp->f_flag;
187*7c478bd9Sstevel@tonic-gate 		if ((iarg & (FNONBLOCK|FNDELAY)) == (FNONBLOCK|FNDELAY))
188*7c478bd9Sstevel@tonic-gate 			iarg &= ~FNDELAY;
189*7c478bd9Sstevel@tonic-gate 		if ((error = VOP_SETFL(vp, flag, iarg, fp->f_cred)) == 0) {
190*7c478bd9Sstevel@tonic-gate 			iarg &= FMASK;
191*7c478bd9Sstevel@tonic-gate 			mutex_enter(&fp->f_tlock);
192*7c478bd9Sstevel@tonic-gate 			fp->f_flag &= ~FMASK | (FREAD|FWRITE);
193*7c478bd9Sstevel@tonic-gate 			fp->f_flag |= (iarg - FOPEN) & ~(FREAD|FWRITE);
194*7c478bd9Sstevel@tonic-gate 			mutex_exit(&fp->f_tlock);
195*7c478bd9Sstevel@tonic-gate 		}
196*7c478bd9Sstevel@tonic-gate 		retval = 0;
197*7c478bd9Sstevel@tonic-gate 		goto done;
198*7c478bd9Sstevel@tonic-gate 	}
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 	/*
201*7c478bd9Sstevel@tonic-gate 	 * Finally, deal with the expensive cases.
202*7c478bd9Sstevel@tonic-gate 	 */
203*7c478bd9Sstevel@tonic-gate 	retval = 0;
204*7c478bd9Sstevel@tonic-gate 	in_crit = 0;
205*7c478bd9Sstevel@tonic-gate 	maxoffset = MAXOFF_T;
206*7c478bd9Sstevel@tonic-gate 	datamodel = DATAMODEL_NATIVE;
207*7c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL)
208*7c478bd9Sstevel@tonic-gate 	if ((datamodel = get_udatamodel()) == DATAMODEL_ILP32)
209*7c478bd9Sstevel@tonic-gate 		maxoffset = MAXOFF32_T;
210*7c478bd9Sstevel@tonic-gate #endif
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 	vp = fp->f_vnode;
213*7c478bd9Sstevel@tonic-gate 	flag = fp->f_flag;
214*7c478bd9Sstevel@tonic-gate 	offset = fp->f_offset;
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
217*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
218*7c478bd9Sstevel@tonic-gate 	/*
219*7c478bd9Sstevel@tonic-gate 	 * The file system and vnode layers understand and implement
220*7c478bd9Sstevel@tonic-gate 	 * locking with flock64 structures. So here once we pass through
221*7c478bd9Sstevel@tonic-gate 	 * the test for compatibility as defined by LFS API, (for F_SETLK,
222*7c478bd9Sstevel@tonic-gate 	 * F_SETLKW, F_GETLK, F_GETLKW, F_FREESP) we transform
223*7c478bd9Sstevel@tonic-gate 	 * the flock structure to a flock64 structure and send it to the
224*7c478bd9Sstevel@tonic-gate 	 * lower layers. Similarly in case of GETLK the returned flock64
225*7c478bd9Sstevel@tonic-gate 	 * structure is transformed to a flock structure if everything fits
226*7c478bd9Sstevel@tonic-gate 	 * in nicely, otherwise we return EOVERFLOW.
227*7c478bd9Sstevel@tonic-gate 	 */
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	case F_GETLK:
230*7c478bd9Sstevel@tonic-gate 	case F_O_GETLK:
231*7c478bd9Sstevel@tonic-gate 	case F_SETLK:
232*7c478bd9Sstevel@tonic-gate 	case F_SETLKW:
233*7c478bd9Sstevel@tonic-gate 	case F_SETLK_NBMAND:
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 		/*
236*7c478bd9Sstevel@tonic-gate 		 * Copy in input fields only.
237*7c478bd9Sstevel@tonic-gate 		 */
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 		if (cmd == F_O_GETLK) {
240*7c478bd9Sstevel@tonic-gate 			if (datamodel != DATAMODEL_ILP32) {
241*7c478bd9Sstevel@tonic-gate 				error = EINVAL;
242*7c478bd9Sstevel@tonic-gate 				break;
243*7c478bd9Sstevel@tonic-gate 			}
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 			if (copyin((void *)arg, &obf, sizeof (obf))) {
246*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
247*7c478bd9Sstevel@tonic-gate 				break;
248*7c478bd9Sstevel@tonic-gate 			}
249*7c478bd9Sstevel@tonic-gate 			bf.l_type = obf.l_type;
250*7c478bd9Sstevel@tonic-gate 			bf.l_whence = obf.l_whence;
251*7c478bd9Sstevel@tonic-gate 			bf.l_start = (off64_t)obf.l_start;
252*7c478bd9Sstevel@tonic-gate 			bf.l_len = (off64_t)obf.l_len;
253*7c478bd9Sstevel@tonic-gate 			bf.l_sysid = (int)obf.l_sysid;
254*7c478bd9Sstevel@tonic-gate 			bf.l_pid = obf.l_pid;
255*7c478bd9Sstevel@tonic-gate 		} else if (datamodel == DATAMODEL_NATIVE) {
256*7c478bd9Sstevel@tonic-gate 			if (copyin((void *)arg, &sbf, sizeof (sbf))) {
257*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
258*7c478bd9Sstevel@tonic-gate 				break;
259*7c478bd9Sstevel@tonic-gate 			}
260*7c478bd9Sstevel@tonic-gate 			/*
261*7c478bd9Sstevel@tonic-gate 			 * XXX	In an LP64 kernel with an LP64 application
262*7c478bd9Sstevel@tonic-gate 			 *	there's no need to do a structure copy here
263*7c478bd9Sstevel@tonic-gate 			 *	struct flock == struct flock64. However,
264*7c478bd9Sstevel@tonic-gate 			 *	we did it this way to avoid more conditional
265*7c478bd9Sstevel@tonic-gate 			 *	compilation.
266*7c478bd9Sstevel@tonic-gate 			 */
267*7c478bd9Sstevel@tonic-gate 			bf.l_type = sbf.l_type;
268*7c478bd9Sstevel@tonic-gate 			bf.l_whence = sbf.l_whence;
269*7c478bd9Sstevel@tonic-gate 			bf.l_start = (off64_t)sbf.l_start;
270*7c478bd9Sstevel@tonic-gate 			bf.l_len = (off64_t)sbf.l_len;
271*7c478bd9Sstevel@tonic-gate 			bf.l_sysid = sbf.l_sysid;
272*7c478bd9Sstevel@tonic-gate 			bf.l_pid = sbf.l_pid;
273*7c478bd9Sstevel@tonic-gate 		}
274*7c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL)
275*7c478bd9Sstevel@tonic-gate 		else {
276*7c478bd9Sstevel@tonic-gate 			struct flock32 sbf32;
277*7c478bd9Sstevel@tonic-gate 			if (copyin((void *)arg, &sbf32, sizeof (sbf32))) {
278*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
279*7c478bd9Sstevel@tonic-gate 				break;
280*7c478bd9Sstevel@tonic-gate 			}
281*7c478bd9Sstevel@tonic-gate 			bf.l_type = sbf32.l_type;
282*7c478bd9Sstevel@tonic-gate 			bf.l_whence = sbf32.l_whence;
283*7c478bd9Sstevel@tonic-gate 			bf.l_start = (off64_t)sbf32.l_start;
284*7c478bd9Sstevel@tonic-gate 			bf.l_len = (off64_t)sbf32.l_len;
285*7c478bd9Sstevel@tonic-gate 			bf.l_sysid = sbf32.l_sysid;
286*7c478bd9Sstevel@tonic-gate 			bf.l_pid = sbf32.l_pid;
287*7c478bd9Sstevel@tonic-gate 		}
288*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 		/*
291*7c478bd9Sstevel@tonic-gate 		 * 64-bit support: check for overflow for 32-bit lock ops
292*7c478bd9Sstevel@tonic-gate 		 */
293*7c478bd9Sstevel@tonic-gate 		if ((error = flock_check(vp, &bf, offset, maxoffset)) != 0)
294*7c478bd9Sstevel@tonic-gate 			break;
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 		/*
297*7c478bd9Sstevel@tonic-gate 		 * Not all of the filesystems understand F_O_GETLK, and
298*7c478bd9Sstevel@tonic-gate 		 * there's no need for them to know.  Map it to F_GETLK.
299*7c478bd9Sstevel@tonic-gate 		 */
300*7c478bd9Sstevel@tonic-gate 		if ((error = VOP_FRLOCK(vp, (cmd == F_O_GETLK) ? F_GETLK : cmd,
301*7c478bd9Sstevel@tonic-gate 		    &bf, flag, offset, NULL, fp->f_cred)) != 0)
302*7c478bd9Sstevel@tonic-gate 			break;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 		/*
305*7c478bd9Sstevel@tonic-gate 		 * If command is GETLK and no lock is found, only
306*7c478bd9Sstevel@tonic-gate 		 * the type field is changed.
307*7c478bd9Sstevel@tonic-gate 		 */
308*7c478bd9Sstevel@tonic-gate 		if ((cmd == F_O_GETLK || cmd == F_GETLK) &&
309*7c478bd9Sstevel@tonic-gate 		    bf.l_type == F_UNLCK) {
310*7c478bd9Sstevel@tonic-gate 			/* l_type always first entry, always a short */
311*7c478bd9Sstevel@tonic-gate 			if (copyout(&bf.l_type, &((struct flock *)arg)->l_type,
312*7c478bd9Sstevel@tonic-gate 			    sizeof (bf.l_type)))
313*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
314*7c478bd9Sstevel@tonic-gate 			break;
315*7c478bd9Sstevel@tonic-gate 		}
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 		if (cmd == F_O_GETLK) {
318*7c478bd9Sstevel@tonic-gate 			/*
319*7c478bd9Sstevel@tonic-gate 			 * Return an SVR3 flock structure to the user.
320*7c478bd9Sstevel@tonic-gate 			 */
321*7c478bd9Sstevel@tonic-gate 			obf.l_type = (int16_t)bf.l_type;
322*7c478bd9Sstevel@tonic-gate 			obf.l_whence = (int16_t)bf.l_whence;
323*7c478bd9Sstevel@tonic-gate 			obf.l_start = (int32_t)bf.l_start;
324*7c478bd9Sstevel@tonic-gate 			obf.l_len = (int32_t)bf.l_len;
325*7c478bd9Sstevel@tonic-gate 			if (bf.l_sysid > SHRT_MAX || bf.l_pid > SHRT_MAX) {
326*7c478bd9Sstevel@tonic-gate 				/*
327*7c478bd9Sstevel@tonic-gate 				 * One or both values for the above fields
328*7c478bd9Sstevel@tonic-gate 				 * is too large to store in an SVR3 flock
329*7c478bd9Sstevel@tonic-gate 				 * structure.
330*7c478bd9Sstevel@tonic-gate 				 */
331*7c478bd9Sstevel@tonic-gate 				error = EOVERFLOW;
332*7c478bd9Sstevel@tonic-gate 				break;
333*7c478bd9Sstevel@tonic-gate 			}
334*7c478bd9Sstevel@tonic-gate 			obf.l_sysid = (int16_t)bf.l_sysid;
335*7c478bd9Sstevel@tonic-gate 			obf.l_pid = (int16_t)bf.l_pid;
336*7c478bd9Sstevel@tonic-gate 			if (copyout(&obf, (void *)arg, sizeof (obf)))
337*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
338*7c478bd9Sstevel@tonic-gate 		} else if (cmd == F_GETLK) {
339*7c478bd9Sstevel@tonic-gate 			/*
340*7c478bd9Sstevel@tonic-gate 			 * Copy out SVR4 flock.
341*7c478bd9Sstevel@tonic-gate 			 */
342*7c478bd9Sstevel@tonic-gate 			int i;
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 			if (bf.l_start > maxoffset || bf.l_len > maxoffset) {
345*7c478bd9Sstevel@tonic-gate 				error = EOVERFLOW;
346*7c478bd9Sstevel@tonic-gate 				break;
347*7c478bd9Sstevel@tonic-gate 			}
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate 			if (datamodel == DATAMODEL_NATIVE) {
350*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < 4; i++)
351*7c478bd9Sstevel@tonic-gate 					sbf.l_pad[i] = 0;
352*7c478bd9Sstevel@tonic-gate 				/*
353*7c478bd9Sstevel@tonic-gate 				 * XXX	In an LP64 kernel with an LP64
354*7c478bd9Sstevel@tonic-gate 				 *	application there's no need to do a
355*7c478bd9Sstevel@tonic-gate 				 *	structure copy here as currently
356*7c478bd9Sstevel@tonic-gate 				 *	struct flock == struct flock64.
357*7c478bd9Sstevel@tonic-gate 				 *	We did it this way to avoid more
358*7c478bd9Sstevel@tonic-gate 				 *	conditional compilation.
359*7c478bd9Sstevel@tonic-gate 				 */
360*7c478bd9Sstevel@tonic-gate 				sbf.l_type = bf.l_type;
361*7c478bd9Sstevel@tonic-gate 				sbf.l_whence = bf.l_whence;
362*7c478bd9Sstevel@tonic-gate 				sbf.l_start = (off_t)bf.l_start;
363*7c478bd9Sstevel@tonic-gate 				sbf.l_len = (off_t)bf.l_len;
364*7c478bd9Sstevel@tonic-gate 				sbf.l_sysid = bf.l_sysid;
365*7c478bd9Sstevel@tonic-gate 				sbf.l_pid = bf.l_pid;
366*7c478bd9Sstevel@tonic-gate 				if (copyout(&sbf, (void *)arg, sizeof (sbf)))
367*7c478bd9Sstevel@tonic-gate 					error = EFAULT;
368*7c478bd9Sstevel@tonic-gate 			}
369*7c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL)
370*7c478bd9Sstevel@tonic-gate 			else {
371*7c478bd9Sstevel@tonic-gate 				struct flock32 sbf32;
372*7c478bd9Sstevel@tonic-gate 				if (bf.l_start > MAXOFF32_T ||
373*7c478bd9Sstevel@tonic-gate 				    bf.l_len > MAXOFF32_T) {
374*7c478bd9Sstevel@tonic-gate 					error = EOVERFLOW;
375*7c478bd9Sstevel@tonic-gate 					break;
376*7c478bd9Sstevel@tonic-gate 				}
377*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < 4; i++)
378*7c478bd9Sstevel@tonic-gate 					sbf32.l_pad[i] = 0;
379*7c478bd9Sstevel@tonic-gate 				sbf32.l_type = (int16_t)bf.l_type;
380*7c478bd9Sstevel@tonic-gate 				sbf32.l_whence = (int16_t)bf.l_whence;
381*7c478bd9Sstevel@tonic-gate 				sbf32.l_start = (off32_t)bf.l_start;
382*7c478bd9Sstevel@tonic-gate 				sbf32.l_len = (off32_t)bf.l_len;
383*7c478bd9Sstevel@tonic-gate 				sbf32.l_sysid = (int32_t)bf.l_sysid;
384*7c478bd9Sstevel@tonic-gate 				sbf32.l_pid = (pid32_t)bf.l_pid;
385*7c478bd9Sstevel@tonic-gate 				if (copyout(&sbf32,
386*7c478bd9Sstevel@tonic-gate 				    (void *)arg, sizeof (sbf32)))
387*7c478bd9Sstevel@tonic-gate 					error = EFAULT;
388*7c478bd9Sstevel@tonic-gate 			}
389*7c478bd9Sstevel@tonic-gate #endif
390*7c478bd9Sstevel@tonic-gate 		}
391*7c478bd9Sstevel@tonic-gate 		break;
392*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	case F_CHKFL:
395*7c478bd9Sstevel@tonic-gate 		/*
396*7c478bd9Sstevel@tonic-gate 		 * This is for internal use only, to allow the vnode layer
397*7c478bd9Sstevel@tonic-gate 		 * to validate a flags setting before applying it.  User
398*7c478bd9Sstevel@tonic-gate 		 * programs can't issue it.
399*7c478bd9Sstevel@tonic-gate 		 */
400*7c478bd9Sstevel@tonic-gate 		error = EINVAL;
401*7c478bd9Sstevel@tonic-gate 		break;
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 	case F_ALLOCSP:
404*7c478bd9Sstevel@tonic-gate 	case F_FREESP:
405*7c478bd9Sstevel@tonic-gate 		if ((flag & FWRITE) == 0) {
406*7c478bd9Sstevel@tonic-gate 			error = EBADF;
407*7c478bd9Sstevel@tonic-gate 			break;
408*7c478bd9Sstevel@tonic-gate 		}
409*7c478bd9Sstevel@tonic-gate 		if (vp->v_type != VREG) {
410*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
411*7c478bd9Sstevel@tonic-gate 			break;
412*7c478bd9Sstevel@tonic-gate 		}
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate #if defined(_ILP32) || defined(_SYSCALL32_IMPL)
415*7c478bd9Sstevel@tonic-gate 		if (datamodel == DATAMODEL_ILP32) {
416*7c478bd9Sstevel@tonic-gate 			struct flock32 sbf32;
417*7c478bd9Sstevel@tonic-gate 			/*
418*7c478bd9Sstevel@tonic-gate 			 * For compatibility we overlay an SVR3 flock on an SVR4
419*7c478bd9Sstevel@tonic-gate 			 * flock.  This works because the input field offsets
420*7c478bd9Sstevel@tonic-gate 			 * in "struct flock" were preserved.
421*7c478bd9Sstevel@tonic-gate 			 */
422*7c478bd9Sstevel@tonic-gate 			if (copyin((void *)arg, &sbf32, sizeof (sbf32))) {
423*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
424*7c478bd9Sstevel@tonic-gate 				break;
425*7c478bd9Sstevel@tonic-gate 			} else {
426*7c478bd9Sstevel@tonic-gate 				bf.l_type = sbf32.l_type;
427*7c478bd9Sstevel@tonic-gate 				bf.l_whence = sbf32.l_whence;
428*7c478bd9Sstevel@tonic-gate 				bf.l_start = (off64_t)sbf32.l_start;
429*7c478bd9Sstevel@tonic-gate 				bf.l_len = (off64_t)sbf32.l_len;
430*7c478bd9Sstevel@tonic-gate 				bf.l_sysid = sbf32.l_sysid;
431*7c478bd9Sstevel@tonic-gate 				bf.l_pid = sbf32.l_pid;
432*7c478bd9Sstevel@tonic-gate 			}
433*7c478bd9Sstevel@tonic-gate 		}
434*7c478bd9Sstevel@tonic-gate #endif /* _ILP32 || _SYSCALL32_IMPL */
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate #if defined(_LP64)
437*7c478bd9Sstevel@tonic-gate 		if (datamodel == DATAMODEL_LP64) {
438*7c478bd9Sstevel@tonic-gate 			if (copyin((void *)arg, &bf, sizeof (bf))) {
439*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
440*7c478bd9Sstevel@tonic-gate 				break;
441*7c478bd9Sstevel@tonic-gate 			}
442*7c478bd9Sstevel@tonic-gate 		}
443*7c478bd9Sstevel@tonic-gate #endif
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 		if ((error = flock_check(vp, &bf, offset, maxoffset)) != 0)
446*7c478bd9Sstevel@tonic-gate 			break;
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 		if (vp->v_type == VREG && bf.l_len == 0 &&
449*7c478bd9Sstevel@tonic-gate 		    bf.l_start > OFFSET_MAX(fp)) {
450*7c478bd9Sstevel@tonic-gate 			error = EFBIG;
451*7c478bd9Sstevel@tonic-gate 			break;
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 		/*
455*7c478bd9Sstevel@tonic-gate 		 * Make sure that there are no conflicting non-blocking
456*7c478bd9Sstevel@tonic-gate 		 * mandatory locks in the region being manipulated. If
457*7c478bd9Sstevel@tonic-gate 		 * there are such locks then return EACCES.
458*7c478bd9Sstevel@tonic-gate 		 */
459*7c478bd9Sstevel@tonic-gate 		if ((error = flock_get_start(vp, &bf, offset, &start)) != 0)
460*7c478bd9Sstevel@tonic-gate 			break;
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 		if (nbl_need_check(vp)) {
463*7c478bd9Sstevel@tonic-gate 			u_offset_t	begin;
464*7c478bd9Sstevel@tonic-gate 			ssize_t		length;
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 			nbl_start_crit(vp, RW_READER);
467*7c478bd9Sstevel@tonic-gate 			in_crit = 1;
468*7c478bd9Sstevel@tonic-gate 			vattr.va_mask = AT_SIZE;
469*7c478bd9Sstevel@tonic-gate 			if ((error = VOP_GETATTR(vp, &vattr, 0, CRED())) != 0)
470*7c478bd9Sstevel@tonic-gate 				break;
471*7c478bd9Sstevel@tonic-gate 			begin = start > vattr.va_size ? vattr.va_size : start;
472*7c478bd9Sstevel@tonic-gate 			length = vattr.va_size > start ? vattr.va_size - start :
473*7c478bd9Sstevel@tonic-gate 				start - vattr.va_size;
474*7c478bd9Sstevel@tonic-gate 			if (nbl_conflict(vp, NBL_WRITE, begin, length, 0)) {
475*7c478bd9Sstevel@tonic-gate 				error = EACCES;
476*7c478bd9Sstevel@tonic-gate 				break;
477*7c478bd9Sstevel@tonic-gate 			}
478*7c478bd9Sstevel@tonic-gate 		}
479*7c478bd9Sstevel@tonic-gate 		error = VOP_SPACE(vp, cmd, &bf, flag, offset, fp->f_cred, NULL);
480*7c478bd9Sstevel@tonic-gate 		break;
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate #if !defined(_LP64) || defined(_SYSCALL32_IMPL)
483*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
484*7c478bd9Sstevel@tonic-gate 	case F_GETLK64:
485*7c478bd9Sstevel@tonic-gate 	case F_SETLK64:
486*7c478bd9Sstevel@tonic-gate 	case F_SETLKW64:
487*7c478bd9Sstevel@tonic-gate 	case F_SETLK64_NBMAND:
488*7c478bd9Sstevel@tonic-gate 		/*
489*7c478bd9Sstevel@tonic-gate 		 * Large Files: Here we set cmd as *LK and send it to
490*7c478bd9Sstevel@tonic-gate 		 * lower layers. *LK64 is only for the user land.
491*7c478bd9Sstevel@tonic-gate 		 * Most of the comments described above for F_SETLK
492*7c478bd9Sstevel@tonic-gate 		 * applies here too.
493*7c478bd9Sstevel@tonic-gate 		 * Large File support is only needed for ILP32 apps!
494*7c478bd9Sstevel@tonic-gate 		 */
495*7c478bd9Sstevel@tonic-gate 		if (datamodel != DATAMODEL_ILP32) {
496*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
497*7c478bd9Sstevel@tonic-gate 			break;
498*7c478bd9Sstevel@tonic-gate 		}
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 		if (cmd == F_GETLK64)
501*7c478bd9Sstevel@tonic-gate 			cmd = F_GETLK;
502*7c478bd9Sstevel@tonic-gate 		else if (cmd == F_SETLK64)
503*7c478bd9Sstevel@tonic-gate 			cmd = F_SETLK;
504*7c478bd9Sstevel@tonic-gate 		else if (cmd == F_SETLKW64)
505*7c478bd9Sstevel@tonic-gate 			cmd = F_SETLKW;
506*7c478bd9Sstevel@tonic-gate 		else if (cmd == F_SETLK64_NBMAND)
507*7c478bd9Sstevel@tonic-gate 			cmd = F_SETLK_NBMAND;
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 		/*
510*7c478bd9Sstevel@tonic-gate 		 * Note that the size of flock64 is different in the ILP32
511*7c478bd9Sstevel@tonic-gate 		 * and LP64 models, due to the sucking l_pad field.
512*7c478bd9Sstevel@tonic-gate 		 * We do not want to assume that the flock64 structure is
513*7c478bd9Sstevel@tonic-gate 		 * laid out in the same in ILP32 and LP64 environments, so
514*7c478bd9Sstevel@tonic-gate 		 * we will copy in the ILP32 version of flock64 explicitly
515*7c478bd9Sstevel@tonic-gate 		 * and copy it to the native flock64 structure.
516*7c478bd9Sstevel@tonic-gate 		 */
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 		if (copyin((void *)arg, &bf64_32, sizeof (bf64_32))) {
519*7c478bd9Sstevel@tonic-gate 			error = EFAULT;
520*7c478bd9Sstevel@tonic-gate 			break;
521*7c478bd9Sstevel@tonic-gate 		}
522*7c478bd9Sstevel@tonic-gate 		bf.l_type = (short)bf64_32.l_type;
523*7c478bd9Sstevel@tonic-gate 		bf.l_whence = (short)bf64_32.l_whence;
524*7c478bd9Sstevel@tonic-gate 		bf.l_start = bf64_32.l_start;
525*7c478bd9Sstevel@tonic-gate 		bf.l_len = bf64_32.l_len;
526*7c478bd9Sstevel@tonic-gate 		bf.l_sysid = (int)bf64_32.l_sysid;
527*7c478bd9Sstevel@tonic-gate 		bf.l_pid = (pid_t)bf64_32.l_pid;
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 		if ((error = flock_check(vp, &bf, offset, MAXOFFSET_T)) != 0)
530*7c478bd9Sstevel@tonic-gate 			break;
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 		if ((error = VOP_FRLOCK(vp, cmd, &bf, flag, offset,
533*7c478bd9Sstevel@tonic-gate 		    NULL, fp->f_cred)) != 0)
534*7c478bd9Sstevel@tonic-gate 			break;
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate 		if ((cmd == F_GETLK) && bf.l_type == F_UNLCK) {
537*7c478bd9Sstevel@tonic-gate 			if (copyout(&bf.l_type, &((struct flock *)arg)->l_type,
538*7c478bd9Sstevel@tonic-gate 			    sizeof (bf.l_type)))
539*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
540*7c478bd9Sstevel@tonic-gate 			break;
541*7c478bd9Sstevel@tonic-gate 		}
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 		if (cmd == F_GETLK) {
544*7c478bd9Sstevel@tonic-gate 			int i;
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 			/*
547*7c478bd9Sstevel@tonic-gate 			 * We do not want to assume that the flock64 structure
548*7c478bd9Sstevel@tonic-gate 			 * is laid out in the same in ILP32 and LP64
549*7c478bd9Sstevel@tonic-gate 			 * environments, so we will copy out the ILP32 version
550*7c478bd9Sstevel@tonic-gate 			 * of flock64 explicitly after copying the native
551*7c478bd9Sstevel@tonic-gate 			 * flock64 structure to it.
552*7c478bd9Sstevel@tonic-gate 			 */
553*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < 4; i++)
554*7c478bd9Sstevel@tonic-gate 				bf64_32.l_pad[i] = 0;
555*7c478bd9Sstevel@tonic-gate 			bf64_32.l_type = (int16_t)bf.l_type;
556*7c478bd9Sstevel@tonic-gate 			bf64_32.l_whence = (int16_t)bf.l_whence;
557*7c478bd9Sstevel@tonic-gate 			bf64_32.l_start = bf.l_start;
558*7c478bd9Sstevel@tonic-gate 			bf64_32.l_len = bf.l_len;
559*7c478bd9Sstevel@tonic-gate 			bf64_32.l_sysid = (int32_t)bf.l_sysid;
560*7c478bd9Sstevel@tonic-gate 			bf64_32.l_pid = (pid32_t)bf.l_pid;
561*7c478bd9Sstevel@tonic-gate 			if (copyout(&bf64_32, (void *)arg, sizeof (bf64_32)))
562*7c478bd9Sstevel@tonic-gate 				error = EFAULT;
563*7c478bd9Sstevel@tonic-gate 		}
564*7c478bd9Sstevel@tonic-gate 		break;
565*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	case F_FREESP64:
568*7c478bd9Sstevel@tonic-gate 		if (datamodel != DATAMODEL_ILP32) {
569*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
570*7c478bd9Sstevel@tonic-gate 			break;
571*7c478bd9Sstevel@tonic-gate 		}
572*7c478bd9Sstevel@tonic-gate 		cmd = F_FREESP;
573*7c478bd9Sstevel@tonic-gate 		if ((flag & FWRITE) == 0)
574*7c478bd9Sstevel@tonic-gate 			error = EBADF;
575*7c478bd9Sstevel@tonic-gate 		else if (vp->v_type != VREG)
576*7c478bd9Sstevel@tonic-gate 			error = EINVAL;
577*7c478bd9Sstevel@tonic-gate 		else if (copyin((void *)arg, &bf64_32, sizeof (bf64_32)))
578*7c478bd9Sstevel@tonic-gate 			error = EFAULT;
579*7c478bd9Sstevel@tonic-gate 		else {
580*7c478bd9Sstevel@tonic-gate 			/*
581*7c478bd9Sstevel@tonic-gate 			 * Note that the size of flock64 is different in
582*7c478bd9Sstevel@tonic-gate 			 * the ILP32 and LP64 models, due to the l_pad field.
583*7c478bd9Sstevel@tonic-gate 			 * We do not want to assume that the flock64 structure
584*7c478bd9Sstevel@tonic-gate 			 * is laid out the same in ILP32 and LP64
585*7c478bd9Sstevel@tonic-gate 			 * environments, so we will copy in the ILP32
586*7c478bd9Sstevel@tonic-gate 			 * version of flock64 explicitly and copy it to
587*7c478bd9Sstevel@tonic-gate 			 * the native flock64 structure.
588*7c478bd9Sstevel@tonic-gate 			 */
589*7c478bd9Sstevel@tonic-gate 			bf.l_type = (short)bf64_32.l_type;
590*7c478bd9Sstevel@tonic-gate 			bf.l_whence = (short)bf64_32.l_whence;
591*7c478bd9Sstevel@tonic-gate 			bf.l_start = bf64_32.l_start;
592*7c478bd9Sstevel@tonic-gate 			bf.l_len = bf64_32.l_len;
593*7c478bd9Sstevel@tonic-gate 			bf.l_sysid = (int)bf64_32.l_sysid;
594*7c478bd9Sstevel@tonic-gate 			bf.l_pid = (pid_t)bf64_32.l_pid;
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 			if ((error = flock_check(vp, &bf, offset,
597*7c478bd9Sstevel@tonic-gate 			    MAXOFFSET_T)) != 0)
598*7c478bd9Sstevel@tonic-gate 				break;
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 			if (vp->v_type == VREG && bf.l_len == 0 &&
601*7c478bd9Sstevel@tonic-gate 			    bf.l_start > OFFSET_MAX(fp)) {
602*7c478bd9Sstevel@tonic-gate 				error = EFBIG;
603*7c478bd9Sstevel@tonic-gate 				break;
604*7c478bd9Sstevel@tonic-gate 			}
605*7c478bd9Sstevel@tonic-gate 			/*
606*7c478bd9Sstevel@tonic-gate 			 * Make sure that there are no conflicting non-blocking
607*7c478bd9Sstevel@tonic-gate 			 * mandatory locks in the region being manipulated. If
608*7c478bd9Sstevel@tonic-gate 			 * there are such locks then return EACCES.
609*7c478bd9Sstevel@tonic-gate 			 */
610*7c478bd9Sstevel@tonic-gate 			if ((error = flock_get_start(vp, &bf, offset,
611*7c478bd9Sstevel@tonic-gate 			    &start)) != 0)
612*7c478bd9Sstevel@tonic-gate 				break;
613*7c478bd9Sstevel@tonic-gate 			if (nbl_need_check(vp)) {
614*7c478bd9Sstevel@tonic-gate 				u_offset_t	begin;
615*7c478bd9Sstevel@tonic-gate 				ssize_t		length;
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 				nbl_start_crit(vp, RW_READER);
618*7c478bd9Sstevel@tonic-gate 				in_crit = 1;
619*7c478bd9Sstevel@tonic-gate 				vattr.va_mask = AT_SIZE;
620*7c478bd9Sstevel@tonic-gate 				if ((error = VOP_GETATTR(vp, &vattr, 0,
621*7c478bd9Sstevel@tonic-gate 				    CRED())) != 0)
622*7c478bd9Sstevel@tonic-gate 					break;
623*7c478bd9Sstevel@tonic-gate 				begin = start > vattr.va_size ?
624*7c478bd9Sstevel@tonic-gate 					vattr.va_size : start;
625*7c478bd9Sstevel@tonic-gate 				length = vattr.va_size > start ?
626*7c478bd9Sstevel@tonic-gate 						vattr.va_size - start :
627*7c478bd9Sstevel@tonic-gate 						start - vattr.va_size;
628*7c478bd9Sstevel@tonic-gate 				if (nbl_conflict(vp, NBL_WRITE, begin,
629*7c478bd9Sstevel@tonic-gate 				    length, 0)) {
630*7c478bd9Sstevel@tonic-gate 					error = EACCES;
631*7c478bd9Sstevel@tonic-gate 					break;
632*7c478bd9Sstevel@tonic-gate 				}
633*7c478bd9Sstevel@tonic-gate 			}
634*7c478bd9Sstevel@tonic-gate 			error = VOP_SPACE(vp, cmd, &bf, flag, offset,
635*7c478bd9Sstevel@tonic-gate 			    fp->f_cred, NULL);
636*7c478bd9Sstevel@tonic-gate 		}
637*7c478bd9Sstevel@tonic-gate 		break;
638*7c478bd9Sstevel@tonic-gate #endif /*  !_LP64 || _SYSCALL32_IMPL */
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
641*7c478bd9Sstevel@tonic-gate 	case F_SHARE:
642*7c478bd9Sstevel@tonic-gate 	case F_SHARE_NBMAND:
643*7c478bd9Sstevel@tonic-gate 	case F_UNSHARE:
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 		/*
646*7c478bd9Sstevel@tonic-gate 		 * Copy in input fields only.
647*7c478bd9Sstevel@tonic-gate 		 */
648*7c478bd9Sstevel@tonic-gate 		if (copyin((void *)arg, &fsh, sizeof (fsh))) {
649*7c478bd9Sstevel@tonic-gate 			error = EFAULT;
650*7c478bd9Sstevel@tonic-gate 			break;
651*7c478bd9Sstevel@tonic-gate 		}
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 		/*
654*7c478bd9Sstevel@tonic-gate 		 * Local share reservations always have this simple form
655*7c478bd9Sstevel@tonic-gate 		 */
656*7c478bd9Sstevel@tonic-gate 		shr.s_access = fsh.f_access;
657*7c478bd9Sstevel@tonic-gate 		shr.s_deny = fsh.f_deny;
658*7c478bd9Sstevel@tonic-gate 		shr.s_sysid = 0;
659*7c478bd9Sstevel@tonic-gate 		shr.s_pid = ttoproc(curthread)->p_pid;
660*7c478bd9Sstevel@tonic-gate 		shr_own.sl_pid = shr.s_pid;
661*7c478bd9Sstevel@tonic-gate 		shr_own.sl_id = fsh.f_id;
662*7c478bd9Sstevel@tonic-gate 		shr.s_own_len = sizeof (shr_own);
663*7c478bd9Sstevel@tonic-gate 		shr.s_owner = (caddr_t)&shr_own;
664*7c478bd9Sstevel@tonic-gate 		error = VOP_SHRLOCK(vp, cmd, &shr, flag, fp->f_cred);
665*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
666*7c478bd9Sstevel@tonic-gate 		break;
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 	default:
669*7c478bd9Sstevel@tonic-gate 		error = EINVAL;
670*7c478bd9Sstevel@tonic-gate 		break;
671*7c478bd9Sstevel@tonic-gate 	}
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 	if (in_crit)
674*7c478bd9Sstevel@tonic-gate 		nbl_end_crit(vp);
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate done:
677*7c478bd9Sstevel@tonic-gate 	releasef(fdes);
678*7c478bd9Sstevel@tonic-gate out:
679*7c478bd9Sstevel@tonic-gate 	if (error)
680*7c478bd9Sstevel@tonic-gate 		return (set_errno(error));
681*7c478bd9Sstevel@tonic-gate 	return (retval);
682*7c478bd9Sstevel@tonic-gate }
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate int
685*7c478bd9Sstevel@tonic-gate dup(int fd)
686*7c478bd9Sstevel@tonic-gate {
687*7c478bd9Sstevel@tonic-gate 	return (fcntl(fd, F_DUPFD, 0));
688*7c478bd9Sstevel@tonic-gate }
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
691*7c478bd9Sstevel@tonic-gate int
692*7c478bd9Sstevel@tonic-gate flock_check(vnode_t *vp, flock64_t *flp, offset_t offset, offset_t max)
693*7c478bd9Sstevel@tonic-gate {
694*7c478bd9Sstevel@tonic-gate 	struct vattr	vattr;
695*7c478bd9Sstevel@tonic-gate 	int	error;
696*7c478bd9Sstevel@tonic-gate 	u_offset_t start, end;
697*7c478bd9Sstevel@tonic-gate 
698*7c478bd9Sstevel@tonic-gate 	/*
699*7c478bd9Sstevel@tonic-gate 	 * Determine the starting point of the request
700*7c478bd9Sstevel@tonic-gate 	 */
701*7c478bd9Sstevel@tonic-gate 	switch (flp->l_whence) {
702*7c478bd9Sstevel@tonic-gate 	case 0:		/* SEEK_SET */
703*7c478bd9Sstevel@tonic-gate 		start = (u_offset_t)flp->l_start;
704*7c478bd9Sstevel@tonic-gate 		if (start > max)
705*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
706*7c478bd9Sstevel@tonic-gate 		break;
707*7c478bd9Sstevel@tonic-gate 	case 1:		/* SEEK_CUR */
708*7c478bd9Sstevel@tonic-gate 		if (flp->l_start > (max - offset))
709*7c478bd9Sstevel@tonic-gate 			return (EOVERFLOW);
710*7c478bd9Sstevel@tonic-gate 		start = (u_offset_t)(flp->l_start + offset);
711*7c478bd9Sstevel@tonic-gate 		if (start > max)
712*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
713*7c478bd9Sstevel@tonic-gate 		break;
714*7c478bd9Sstevel@tonic-gate 	case 2:		/* SEEK_END */
715*7c478bd9Sstevel@tonic-gate 		vattr.va_mask = AT_SIZE;
716*7c478bd9Sstevel@tonic-gate 		if (error = VOP_GETATTR(vp, &vattr, 0, CRED()))
717*7c478bd9Sstevel@tonic-gate 			return (error);
718*7c478bd9Sstevel@tonic-gate 		if (flp->l_start > (max - (offset_t)vattr.va_size))
719*7c478bd9Sstevel@tonic-gate 			return (EOVERFLOW);
720*7c478bd9Sstevel@tonic-gate 		start = (u_offset_t)(flp->l_start + (offset_t)vattr.va_size);
721*7c478bd9Sstevel@tonic-gate 		if (start > max)
722*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
723*7c478bd9Sstevel@tonic-gate 		break;
724*7c478bd9Sstevel@tonic-gate 	default:
725*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
726*7c478bd9Sstevel@tonic-gate 	}
727*7c478bd9Sstevel@tonic-gate 
728*7c478bd9Sstevel@tonic-gate 	/*
729*7c478bd9Sstevel@tonic-gate 	 * Determine the range covered by the request.
730*7c478bd9Sstevel@tonic-gate 	 */
731*7c478bd9Sstevel@tonic-gate 	if (flp->l_len == 0)
732*7c478bd9Sstevel@tonic-gate 		end = MAXEND;
733*7c478bd9Sstevel@tonic-gate 	else if ((offset_t)flp->l_len > 0) {
734*7c478bd9Sstevel@tonic-gate 		if (flp->l_len > (max - start + 1))
735*7c478bd9Sstevel@tonic-gate 			return (EOVERFLOW);
736*7c478bd9Sstevel@tonic-gate 		end = (u_offset_t)(start + (flp->l_len - 1));
737*7c478bd9Sstevel@tonic-gate 		ASSERT(end <= max);
738*7c478bd9Sstevel@tonic-gate 	} else {
739*7c478bd9Sstevel@tonic-gate 		/*
740*7c478bd9Sstevel@tonic-gate 		 * Negative length; why do we even allow this ?
741*7c478bd9Sstevel@tonic-gate 		 * Because this allows easy specification of
742*7c478bd9Sstevel@tonic-gate 		 * the last n bytes of the file.
743*7c478bd9Sstevel@tonic-gate 		 */
744*7c478bd9Sstevel@tonic-gate 		end = start;
745*7c478bd9Sstevel@tonic-gate 		start += (u_offset_t)flp->l_len;
746*7c478bd9Sstevel@tonic-gate 		(start)++;
747*7c478bd9Sstevel@tonic-gate 		if (start > max)
748*7c478bd9Sstevel@tonic-gate 			return (EINVAL);
749*7c478bd9Sstevel@tonic-gate 		ASSERT(end <= max);
750*7c478bd9Sstevel@tonic-gate 	}
751*7c478bd9Sstevel@tonic-gate 	ASSERT(start <= max);
752*7c478bd9Sstevel@tonic-gate 	if (flp->l_type == F_UNLCK && flp->l_len > 0 &&
753*7c478bd9Sstevel@tonic-gate 	    end == (offset_t)max) {
754*7c478bd9Sstevel@tonic-gate 		flp->l_len = 0;
755*7c478bd9Sstevel@tonic-gate 	}
756*7c478bd9Sstevel@tonic-gate 	if (start  > end)
757*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
758*7c478bd9Sstevel@tonic-gate 	return (0);
759*7c478bd9Sstevel@tonic-gate }
760*7c478bd9Sstevel@tonic-gate 
761*7c478bd9Sstevel@tonic-gate static int
762*7c478bd9Sstevel@tonic-gate flock_get_start(vnode_t *vp, flock64_t *flp, offset_t offset, u_offset_t *start)
763*7c478bd9Sstevel@tonic-gate {
764*7c478bd9Sstevel@tonic-gate 	struct vattr	vattr;
765*7c478bd9Sstevel@tonic-gate 	int	error;
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate 	/*
768*7c478bd9Sstevel@tonic-gate 	 * Determine the starting point of the request. Assume that it is
769*7c478bd9Sstevel@tonic-gate 	 * a valid starting point.
770*7c478bd9Sstevel@tonic-gate 	 */
771*7c478bd9Sstevel@tonic-gate 	switch (flp->l_whence) {
772*7c478bd9Sstevel@tonic-gate 	case 0:		/* SEEK_SET */
773*7c478bd9Sstevel@tonic-gate 		*start = (u_offset_t)flp->l_start;
774*7c478bd9Sstevel@tonic-gate 		break;
775*7c478bd9Sstevel@tonic-gate 	case 1:		/* SEEK_CUR */
776*7c478bd9Sstevel@tonic-gate 		*start = (u_offset_t)(flp->l_start + offset);
777*7c478bd9Sstevel@tonic-gate 		break;
778*7c478bd9Sstevel@tonic-gate 	case 2:		/* SEEK_END */
779*7c478bd9Sstevel@tonic-gate 		vattr.va_mask = AT_SIZE;
780*7c478bd9Sstevel@tonic-gate 		if (error = VOP_GETATTR(vp, &vattr, 0, CRED()))
781*7c478bd9Sstevel@tonic-gate 			return (error);
782*7c478bd9Sstevel@tonic-gate 		*start = (u_offset_t)(flp->l_start + (offset_t)vattr.va_size);
783*7c478bd9Sstevel@tonic-gate 		break;
784*7c478bd9Sstevel@tonic-gate 	default:
785*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
786*7c478bd9Sstevel@tonic-gate 	}
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	return (0);
789*7c478bd9Sstevel@tonic-gate }
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate /*
792*7c478bd9Sstevel@tonic-gate  * Take rctl action when the requested file descriptor is too big.
793*7c478bd9Sstevel@tonic-gate  */
794*7c478bd9Sstevel@tonic-gate static void
795*7c478bd9Sstevel@tonic-gate fd_too_big(proc_t *p)
796*7c478bd9Sstevel@tonic-gate {
797*7c478bd9Sstevel@tonic-gate 	mutex_enter(&p->p_lock);
798*7c478bd9Sstevel@tonic-gate 	(void) rctl_action(rctlproc_legacy[RLIMIT_NOFILE],
799*7c478bd9Sstevel@tonic-gate 	    p->p_rctls, p, RCA_SAFE);
800*7c478bd9Sstevel@tonic-gate 	mutex_exit(&p->p_lock);
801*7c478bd9Sstevel@tonic-gate }
802*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
803