1/* 2 * Copyright (c) 1982, 1986, 1989, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 22 unchanged lines hidden (view full) --- 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 |
39 * $FreeBSD: head/sys/kern/kern_descrip.c 82749 2001-09-01 19:04:37Z dillon $ |
40 */ 41 42#include "opt_compat.h" 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/lock.h> 47#include <sys/mutex.h> --- 63 unchanged lines hidden (view full) --- 111/* 112 * System calls on descriptors. 113 */ 114#ifndef _SYS_SYSPROTO_H_ 115struct getdtablesize_args { 116 int dummy; 117}; 118#endif |
119/* 120 * MPSAFE 121 */ |
122/* ARGSUSED */ 123int 124getdtablesize(p, uap) 125 struct proc *p; 126 struct getdtablesize_args *uap; 127{ 128 |
129 mtx_lock(&Giant); |
130 p->p_retval[0] = 131 min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc); |
132 mtx_unlock(&Giant); |
133 return (0); 134} 135 136/* 137 * Duplicate a file descriptor to a particular value. 138 * 139 * note: keep in mind that a potential race condition exists when closing 140 * descriptors from a shared descriptor table (via rfork). 141 */ 142#ifndef _SYS_SYSPROTO_H_ 143struct dup2_args { 144 u_int from; 145 u_int to; 146}; 147#endif |
148/* 149 * MPSAFE 150 */ |
151/* ARGSUSED */ 152int 153dup2(p, uap) 154 struct proc *p; 155 struct dup2_args *uap; 156{ 157 register struct filedesc *fdp = p->p_fd; 158 register u_int old = uap->from, new = uap->to; 159 int i, error; 160 |
161 mtx_lock(&Giant); |
162retry: 163 if (old >= fdp->fd_nfiles || 164 fdp->fd_ofiles[old] == NULL || 165 new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || 166 new >= maxfilesperproc) { |
167 error = EBADF; 168 goto done2; |
169 } 170 if (old == new) { 171 p->p_retval[0] = new; |
172 error = 0; 173 goto done2; |
174 } 175 if (new >= fdp->fd_nfiles) { 176 if ((error = fdalloc(p, new, &i))) |
177 goto done2; |
178 if (new != i) 179 panic("dup2: fdalloc"); 180 /* 181 * fdalloc() may block, retest everything. 182 */ 183 goto retry; 184 } |
185 error = do_dup(fdp, (int)old, (int)new, p->p_retval, p); 186done2: 187 mtx_unlock(&Giant); 188 return(error); |
189} 190 191/* 192 * Duplicate a file descriptor. 193 */ 194#ifndef _SYS_SYSPROTO_H_ 195struct dup_args { 196 u_int fd; 197}; 198#endif |
199/* 200 * MPSAFE 201 */ |
202/* ARGSUSED */ 203int 204dup(p, uap) 205 struct proc *p; 206 struct dup_args *uap; 207{ 208 register struct filedesc *fdp; 209 u_int old; 210 int new, error; 211 |
212 mtx_lock(&Giant); |
213 old = uap->fd; 214 fdp = p->p_fd; |
215 if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL) { 216 error = EBADF; 217 goto done2; 218 } |
219 if ((error = fdalloc(p, 0, &new))) |
220 goto done2; 221 error = do_dup(fdp, (int)old, new, p->p_retval, p); 222done2: 223 mtx_unlock(&Giant); 224 return (error); |
225} 226 227/* 228 * The file control system call. 229 */ 230#ifndef _SYS_SYSPROTO_H_ 231struct fcntl_args { 232 int fd; 233 int cmd; 234 long arg; 235}; 236#endif |
237/* 238 * MPSAFE 239 */ |
240/* ARGSUSED */ 241int 242fcntl(p, uap) 243 struct proc *p; 244 register struct fcntl_args *uap; 245{ |
246 register struct filedesc *fdp; |
247 register struct file *fp; 248 register char *pop; 249 struct vnode *vp; |
250 int i, tmp, error = 0, flg = F_POSIX; |
251 struct flock fl; 252 u_int newmin; 253 |
254 mtx_lock(&Giant); 255 256 fdp = p->p_fd; |
257 if ((unsigned)uap->fd >= fdp->fd_nfiles || |
258 (fp = fdp->fd_ofiles[uap->fd]) == NULL) { 259 error = EBADF; 260 goto done2; 261 } |
262 pop = &fdp->fd_ofileflags[uap->fd]; 263 264 switch (uap->cmd) { 265 case F_DUPFD: 266 newmin = uap->arg; 267 if (newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || |
268 newmin >= maxfilesperproc) { 269 error = EINVAL; 270 break; 271 } |
272 if ((error = fdalloc(p, newmin, &i))) |
273 break; 274 error = do_dup(fdp, uap->fd, i, p->p_retval, p); 275 break; |
276 277 case F_GETFD: 278 p->p_retval[0] = *pop & 1; |
279 break; |
280 281 case F_SETFD: 282 *pop = (*pop &~ 1) | (uap->arg & 1); |
283 break; |
284 285 case F_GETFL: 286 p->p_retval[0] = OFLAGS(fp->f_flag); |
287 break; |
288 289 case F_SETFL: 290 fhold(fp); 291 fp->f_flag &= ~FCNTLFLAGS; 292 fp->f_flag |= FFLAGS(uap->arg & ~O_ACCMODE) & FCNTLFLAGS; 293 tmp = fp->f_flag & FNONBLOCK; 294 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p); 295 if (error) { 296 fdrop(fp, p); |
297 break; |
298 } 299 tmp = fp->f_flag & FASYNC; 300 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p); 301 if (!error) { 302 fdrop(fp, p); |
303 break; |
304 } 305 fp->f_flag &= ~FNONBLOCK; 306 tmp = 0; 307 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p); 308 fdrop(fp, p); |
309 break; |
310 311 case F_GETOWN: 312 fhold(fp); 313 error = fo_ioctl(fp, FIOGETOWN, (caddr_t)p->p_retval, p); 314 fdrop(fp, p); |
315 break; |
316 317 case F_SETOWN: 318 fhold(fp); 319 error = fo_ioctl(fp, FIOSETOWN, (caddr_t)&uap->arg, p); 320 fdrop(fp, p); |
321 break; |
322 323 case F_SETLKW: 324 flg |= F_WAIT; 325 /* Fall into F_SETLK */ 326 327 case F_SETLK: |
328 if (fp->f_type != DTYPE_VNODE) { 329 error = EBADF; 330 break; 331 } |
332 vp = (struct vnode *)fp->f_data; 333 334 /* 335 * copyin/lockop may block 336 */ 337 fhold(fp); 338 /* Copy in the lock structure */ 339 error = copyin((caddr_t)(intptr_t)uap->arg, (caddr_t)&fl, 340 sizeof(fl)); 341 if (error) { 342 fdrop(fp, p); |
343 break; |
344 } 345 if (fl.l_whence == SEEK_CUR) { 346 if (fp->f_offset < 0 || 347 (fl.l_start > 0 && 348 fp->f_offset > OFF_MAX - fl.l_start)) { 349 fdrop(fp, p); |
350 error = EOVERFLOW; 351 break; |
352 } 353 fl.l_start += fp->f_offset; 354 } 355 356 switch (fl.l_type) { 357 case F_RDLCK: 358 if ((fp->f_flag & FREAD) == 0) { 359 error = EBADF; --- 16 unchanged lines hidden (view full) --- 376 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_UNLCK, 377 &fl, F_POSIX); 378 break; 379 default: 380 error = EINVAL; 381 break; 382 } 383 fdrop(fp, p); |
384 break; |
385 case F_GETLK: |
386 if (fp->f_type != DTYPE_VNODE) { 387 error = EBADF; 388 break; 389 } |
390 vp = (struct vnode *)fp->f_data; 391 /* 392 * copyin/lockop may block 393 */ 394 fhold(fp); 395 /* Copy in the lock structure */ 396 error = copyin((caddr_t)(intptr_t)uap->arg, (caddr_t)&fl, 397 sizeof(fl)); 398 if (error) { 399 fdrop(fp, p); |
400 break; |
401 } 402 if (fl.l_type != F_RDLCK && fl.l_type != F_WRLCK && 403 fl.l_type != F_UNLCK) { 404 fdrop(fp, p); |
405 error = EINVAL; 406 break; |
407 } 408 if (fl.l_whence == SEEK_CUR) { 409 if ((fl.l_start > 0 && 410 fp->f_offset > OFF_MAX - fl.l_start) || 411 (fl.l_start < 0 && 412 fp->f_offset < OFF_MIN - fl.l_start)) { 413 fdrop(fp, p); |
414 error = EOVERFLOW; 415 break; |
416 } 417 fl.l_start += fp->f_offset; 418 } 419 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_GETLK, 420 &fl, F_POSIX); 421 fdrop(fp, p); 422 if (error == 0) { 423 error = copyout((caddr_t)&fl, 424 (caddr_t)(intptr_t)uap->arg, sizeof(fl)); 425 } |
426 break; |
427 default: |
428 error = EINVAL; 429 break; |
430 } |
431done2: 432 mtx_unlock(&Giant); 433 return (error); |
434} 435 436/* 437 * Common code for dup, dup2, and fcntl(F_DUPFD). 438 */ 439static int 440do_dup(fdp, old, new, retval, p) 441 register struct filedesc *fdp; --- 164 unchanged lines hidden (view full) --- 606/* 607 * Close a file descriptor. 608 */ 609#ifndef _SYS_SYSPROTO_H_ 610struct close_args { 611 int fd; 612}; 613#endif |
614/* 615 * MPSAFE 616 */ |
617/* ARGSUSED */ 618int 619close(p, uap) 620 struct proc *p; 621 struct close_args *uap; 622{ |
623 register struct filedesc *fdp; |
624 register struct file *fp; 625 register int fd = uap->fd; |
626 int error = 0; |
627 |
628 mtx_lock(&Giant); 629 fdp = p->p_fd; |
630 if ((unsigned)fd >= fdp->fd_nfiles || |
631 (fp = fdp->fd_ofiles[fd]) == NULL) { 632 error = EBADF; 633 goto done2; 634 } |
635#if 0 636 if (fdp->fd_ofileflags[fd] & UF_MAPPED) 637 (void) munmapfd(p, fd); 638#endif 639 fdp->fd_ofiles[fd] = NULL; 640 fdp->fd_ofileflags[fd] = 0; 641 642 /* 643 * we now hold the fp reference that used to be owned by the descriptor 644 * array. 645 */ 646 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) 647 fdp->fd_lastfile--; 648 if (fd < fdp->fd_freefile) 649 fdp->fd_freefile = fd; 650 if (fd < fdp->fd_knlistsize) 651 knote_fdclose(p, fd); |
652 error = closef(fp, p); 653done2: 654 mtx_unlock(&Giant); 655 return(error); |
656} 657 658#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 659/* 660 * Return status information about a file descriptor. 661 */ 662#ifndef _SYS_SYSPROTO_H_ 663struct ofstat_args { 664 int fd; 665 struct ostat *sb; 666}; 667#endif |
668/* 669 * MPSAFE 670 */ |
671/* ARGSUSED */ 672int 673ofstat(p, uap) 674 struct proc *p; 675 register struct ofstat_args *uap; 676{ 677 register struct filedesc *fdp = p->p_fd; 678 register struct file *fp; 679 struct stat ub; 680 struct ostat oub; 681 int error; 682 |
683 mtx_lock(&Giant); 684 |
685 if ((unsigned)uap->fd >= fdp->fd_nfiles || |
686 (fp = fdp->fd_ofiles[uap->fd]) == NULL) { 687 error = EBADF; 688 goto done2; 689 } |
690 fhold(fp); 691 error = fo_stat(fp, &ub, p); 692 if (error == 0) { 693 cvtstat(&ub, &oub); 694 error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub)); 695 } 696 fdrop(fp, p); |
697done2: 698 mtx_unlock(&Giant); |
699 return (error); 700} 701#endif /* COMPAT_43 || COMPAT_SUNOS */ 702 703/* 704 * Return status information about a file descriptor. 705 */ 706#ifndef _SYS_SYSPROTO_H_ 707struct fstat_args { 708 int fd; 709 struct stat *sb; 710}; 711#endif |
712/* 713 * MPSAFE 714 */ |
715/* ARGSUSED */ 716int 717fstat(p, uap) 718 struct proc *p; 719 register struct fstat_args *uap; 720{ |
721 register struct filedesc *fdp; |
722 register struct file *fp; 723 struct stat ub; 724 int error; 725 |
726 mtx_lock(&Giant); 727 fdp = p->p_fd; 728 |
729 if ((unsigned)uap->fd >= fdp->fd_nfiles || |
730 (fp = fdp->fd_ofiles[uap->fd]) == NULL) { 731 error = EBADF; 732 goto done2; 733 } |
734 fhold(fp); 735 error = fo_stat(fp, &ub, p); 736 if (error == 0) 737 error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); 738 fdrop(fp, p); |
739done2: 740 mtx_unlock(&Giant); |
741 return (error); 742} 743 744/* 745 * Return status information about a file descriptor. 746 */ 747#ifndef _SYS_SYSPROTO_H_ 748struct nfstat_args { 749 int fd; 750 struct nstat *sb; 751}; 752#endif |
753/* 754 * MPSAFE 755 */ |
756/* ARGSUSED */ 757int 758nfstat(p, uap) 759 struct proc *p; 760 register struct nfstat_args *uap; 761{ |
762 register struct filedesc *fdp; |
763 register struct file *fp; 764 struct stat ub; 765 struct nstat nub; 766 int error; 767 |
768 mtx_lock(&Giant); 769 770 fdp = p->p_fd; |
771 if ((unsigned)uap->fd >= fdp->fd_nfiles || |
772 (fp = fdp->fd_ofiles[uap->fd]) == NULL) { 773 error = EBADF; 774 goto done2; 775 } |
776 fhold(fp); 777 error = fo_stat(fp, &ub, p); 778 if (error == 0) { 779 cvtnstat(&ub, &nub); 780 error = copyout((caddr_t)&nub, (caddr_t)uap->sb, sizeof (nub)); 781 } 782 fdrop(fp, p); |
783done2: 784 mtx_unlock(&Giant); |
785 return (error); 786} 787 788/* 789 * Return pathconf information about a file descriptor. 790 */ 791#ifndef _SYS_SYSPROTO_H_ 792struct fpathconf_args { 793 int fd; 794 int name; 795}; 796#endif |
797/* 798 * MPSAFE 799 */ |
800/* ARGSUSED */ 801int 802fpathconf(p, uap) 803 struct proc *p; 804 register struct fpathconf_args *uap; 805{ |
806 struct filedesc *fdp; |
807 struct file *fp; 808 struct vnode *vp; 809 int error = 0; 810 |
811 mtx_lock(&Giant); 812 fdp = p->p_fd; 813 |
814 if ((unsigned)uap->fd >= fdp->fd_nfiles || |
815 (fp = fdp->fd_ofiles[uap->fd]) == NULL) { 816 error = EBADF; 817 goto done2; 818 } |
819 820 fhold(fp); 821 822 switch (fp->f_type) { 823 case DTYPE_PIPE: 824 case DTYPE_SOCKET: |
825 if (uap->name != _PC_PIPE_BUF) { 826 error = EINVAL; 827 goto done2; 828 } |
829 p->p_retval[0] = PIPE_BUF; 830 error = 0; 831 break; 832 case DTYPE_FIFO: 833 case DTYPE_VNODE: 834 vp = (struct vnode *)fp->f_data; 835 error = VOP_PATHCONF(vp, uap->name, p->p_retval); 836 break; 837 default: 838 error = EOPNOTSUPP; 839 break; 840 } 841 fdrop(fp, p); |
842done2: 843 mtx_unlock(&Giant); |
844 return(error); 845} 846 847/* 848 * Allocate a file descriptor for the process. 849 */ 850static int fdexpand; 851SYSCTL_INT(_debug, OID_AUTO, fdexpand, CTLFLAG_RD, &fdexpand, 0, ""); --- 512 unchanged lines hidden (view full) --- 1364 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). 1365 */ 1366#ifndef _SYS_SYSPROTO_H_ 1367struct flock_args { 1368 int fd; 1369 int how; 1370}; 1371#endif |
1372/* 1373 * MPSAFE 1374 */ |
1375/* ARGSUSED */ 1376int 1377flock(p, uap) 1378 struct proc *p; 1379 register struct flock_args *uap; 1380{ 1381 register struct filedesc *fdp = p->p_fd; 1382 register struct file *fp; 1383 struct vnode *vp; 1384 struct flock lf; |
1385 int error; |
1386 |
1387 mtx_lock(&Giant); 1388 |
1389 if ((unsigned)uap->fd >= fdp->fd_nfiles || |
1390 (fp = fdp->fd_ofiles[uap->fd]) == NULL) { 1391 error = EBADF; 1392 goto done2; 1393 } 1394 if (fp->f_type != DTYPE_VNODE) { 1395 error = EOPNOTSUPP; 1396 goto done2; 1397 } |
1398 vp = (struct vnode *)fp->f_data; 1399 lf.l_whence = SEEK_SET; 1400 lf.l_start = 0; 1401 lf.l_len = 0; 1402 if (uap->how & LOCK_UN) { 1403 lf.l_type = F_UNLCK; 1404 fp->f_flag &= ~FHASLOCK; |
1405 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); 1406 goto done2; |
1407 } 1408 if (uap->how & LOCK_EX) 1409 lf.l_type = F_WRLCK; 1410 else if (uap->how & LOCK_SH) 1411 lf.l_type = F_RDLCK; |
1412 else { 1413 error = EBADF; 1414 goto done2; 1415 } |
1416 fp->f_flag |= FHASLOCK; 1417 if (uap->how & LOCK_NB) |
1418 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK); 1419 else 1420 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT); 1421done2: 1422 mtx_unlock(&Giant); 1423 return (error); |
1424} 1425 1426/* 1427 * File Descriptor pseudo-device driver (/dev/fd/). 1428 * 1429 * Opening minor device N dup()s the file (if any) connected to file 1430 * descriptor N belonging to the calling process. Note that this driver 1431 * consists of only the ``open()'' routine, because all subsequent --- 264 unchanged lines hidden --- |