1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)kern_descrip.c 1.6 (2.11BSD) 1999/9/13 7: */ 8: 9: #include "param.h" 10: #include "user.h" 11: #include "proc.h" 12: #include "file.h" 13: #include "systm.h" 14: #include "inode.h" 15: #include "ioctl.h" 16: #include "stat.h" 17: #include "conf.h" 18: #ifdef INET 19: #include "socket.h" 20: #include "socketvar.h" 21: #endif 22: #include <syslog.h> 23: 24: /* 25: * Descriptor management. 26: */ 27: 28: /* 29: * System calls on descriptors. 30: */ 31: getdtablesize() 32: { 33: 34: u.u_r.r_val1 = NOFILE; 35: } 36: 37: dup() 38: { 39: register struct a { 40: int i; 41: } *uap = (struct a *) u.u_ap; 42: register struct file *fp; 43: register int j; 44: 45: if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 46: 47: GETF(fp, uap->i); 48: j = ufalloc(0); 49: if (j < 0) 50: return; 51: dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 52: } 53: 54: dup2() 55: { 56: register struct a { 57: int i, j; 58: } *uap = (struct a *) u.u_ap; 59: register struct file *fp; 60: 61: GETF(fp, uap->i); 62: if (uap->j < 0 || uap->j >= NOFILE) { 63: u.u_error = EBADF; 64: return; 65: } 66: u.u_r.r_val1 = uap->j; 67: if (uap->i == uap->j) 68: return; 69: if (u.u_ofile[uap->j]) 70: /* 71: * dup2 must succeed even if the close has an error. 72: */ 73: (void) closef(u.u_ofile[uap->j]); 74: dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 75: } 76: 77: dupit(fd, fp, flags) 78: register int fd; 79: register struct file *fp; 80: int flags; 81: { 82: 83: u.u_ofile[fd] = fp; 84: u.u_pofile[fd] = flags; 85: fp->f_count++; 86: if (fd > u.u_lastfile) 87: u.u_lastfile = fd; 88: } 89: 90: /* 91: * The file control system call. 92: */ 93: fcntl() 94: { 95: register struct file *fp; 96: register struct a { 97: int fdes; 98: int cmd; 99: int arg; 100: } *uap; 101: register i; 102: register char *pop; 103: 104: uap = (struct a *)u.u_ap; 105: if ((fp = getf(uap->fdes)) == NULL) 106: return; 107: pop = &u.u_pofile[uap->fdes]; 108: switch(uap->cmd) { 109: case F_DUPFD: 110: i = uap->arg; 111: if (i < 0 || i >= NOFILE) { 112: u.u_error = EINVAL; 113: return; 114: } 115: if ((i = ufalloc(i)) < 0) 116: return; 117: dupit(i, fp, *pop &~ UF_EXCLOSE); 118: break; 119: 120: case F_GETFD: 121: u.u_r.r_val1 = *pop & 1; 122: break; 123: 124: case F_SETFD: 125: *pop = (*pop &~ 1) | (uap->arg & 1); 126: break; 127: 128: case F_GETFL: 129: u.u_r.r_val1 = OFLAGS(fp->f_flag); 130: break; 131: 132: case F_SETFL: 133: fp->f_flag &= ~FCNTLFLAGS; 134: fp->f_flag |= (FFLAGS(uap->arg)) & FCNTLFLAGS; 135: u.u_error = fset(fp, FNONBLOCK, fp->f_flag & FNONBLOCK); 136: if (u.u_error) 137: break; 138: u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 139: if (u.u_error) 140: (void) fset(fp, FNONBLOCK, 0); 141: break; 142: 143: case F_GETOWN: 144: u.u_error = fgetown(fp, &u.u_r.r_val1); 145: break; 146: 147: case F_SETOWN: 148: u.u_error = fsetown(fp, uap->arg); 149: break; 150: 151: default: 152: u.u_error = EINVAL; 153: } 154: } 155: 156: fset(fp, bit, value) 157: register struct file *fp; 158: int bit, value; 159: { 160: 161: if (value) 162: fp->f_flag |= bit; 163: else 164: fp->f_flag &= ~bit; 165: return (fioctl(fp, (u_int)(bit == FNONBLOCK ? FIONBIO : FIOASYNC), 166: (caddr_t)&value)); 167: } 168: 169: fgetown(fp, valuep) 170: register struct file *fp; 171: register int *valuep; 172: { 173: register int error; 174: 175: #ifdef INET 176: if (fp->f_type == DTYPE_SOCKET) { 177: *valuep = mfsd(&fp->f_socket->so_pgrp); 178: return (0); 179: } 180: #endif 181: error = fioctl(fp, (u_int)TIOCGPGRP, (caddr_t)valuep); 182: *valuep = -*valuep; 183: return (error); 184: } 185: 186: fsetown(fp, value) 187: register struct file *fp; 188: int value; 189: { 190: 191: #ifdef INET 192: if (fp->f_type == DTYPE_SOCKET) { 193: mtsd(&fp->f_socket->so_pgrp, value); 194: return (0); 195: } 196: #endif 197: if (value > 0) { 198: register struct proc *p = pfind(value); 199: if (p == 0) 200: return (ESRCH); 201: value = p->p_pgrp; 202: } else 203: value = -value; 204: return (fioctl(fp, (u_int)TIOCSPGRP, (caddr_t)&value)); 205: } 206: 207: extern struct fileops *Fops[]; 208: 209: fioctl(fp, cmd, value) 210: register struct file *fp; 211: u_int cmd; 212: caddr_t value; 213: { 214: 215: return ((*Fops[fp->f_type]->fo_ioctl)(fp, cmd, value)); 216: } 217: 218: close() 219: { 220: register struct a { 221: int i; 222: } *uap = (struct a *)u.u_ap; 223: register struct file *fp; 224: 225: GETF(fp, uap->i); 226: u.u_ofile[uap->i] = NULL; 227: while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 228: u.u_lastfile--; 229: u.u_error = closef(fp); 230: /* WHAT IF u.u_error ? */ 231: } 232: 233: fstat() 234: { 235: register struct file *fp; 236: register struct a { 237: int fdes; 238: struct stat *sb; 239: } *uap; 240: struct stat ub; 241: 242: uap = (struct a *)u.u_ap; 243: if ((fp = getf(uap->fdes)) == NULL) 244: return; 245: switch (fp->f_type) { 246: 247: case DTYPE_PIPE: 248: case DTYPE_INODE: 249: u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 250: if (fp->f_type == DTYPE_PIPE) 251: ub.st_size -= fp->f_offset; 252: break; 253: 254: #ifdef INET 255: case DTYPE_SOCKET: 256: u.u_error = SOO_STAT(fp->f_socket, &ub); 257: break; 258: #endif 259: default: 260: u.u_error = EINVAL; 261: break; 262: } 263: if (u.u_error == 0) 264: u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 265: sizeof (ub)); 266: } 267: 268: /* copied, for supervisory networking, to sys_net.c */ 269: /* 270: * Allocate a user file descriptor. 271: */ 272: ufalloc(i) 273: register int i; 274: { 275: 276: for (; i < NOFILE; i++) 277: if (u.u_ofile[i] == NULL) { 278: u.u_r.r_val1 = i; 279: u.u_pofile[i] = 0; 280: if (i > u.u_lastfile) 281: u.u_lastfile = i; 282: return (i); 283: } 284: u.u_error = EMFILE; 285: return (-1); 286: } 287: 288: struct file *lastf; 289: /* 290: * Allocate a user file descriptor 291: * and a file structure. 292: * Initialize the descriptor 293: * to point at the file structure. 294: */ 295: struct file * 296: falloc() 297: { 298: register struct file *fp; 299: register i; 300: 301: i = ufalloc(0); 302: if (i < 0) 303: return (NULL); 304: if (lastf == 0) 305: lastf = file; 306: for (fp = lastf; fp < fileNFILE; fp++) 307: if (fp->f_count == 0) 308: goto slot; 309: for (fp = file; fp < lastf; fp++) 310: if (fp->f_count == 0) 311: goto slot; 312: tablefull("file"); 313: u.u_error = ENFILE; 314: return (NULL); 315: slot: 316: u.u_ofile[i] = fp; 317: fp->f_count = 1; 318: fp->f_data = 0; 319: fp->f_offset = 0; 320: lastf = fp + 1; 321: return (fp); 322: } 323: 324: /* 325: * Convert a user supplied file descriptor into a pointer 326: * to a file structure. Only task is to check range of the descriptor. 327: * Critical paths should use the GETF macro unless code size is a 328: * consideration. 329: */ 330: struct file * 331: getf(f) 332: register int f; 333: { 334: register struct file *fp; 335: 336: if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 337: u.u_error = EBADF; 338: return (NULL); 339: } 340: return (fp); 341: } 342: 343: /* 344: * Internal form of close. 345: * Decrement reference count on file structure. 346: */ 347: closef(fp) 348: register struct file *fp; 349: { 350: int error; 351: 352: if (fp == NULL) 353: return(0); 354: if (fp->f_count > 1) { 355: fp->f_count--; 356: return(0); 357: } 358: 359: if ((fp->f_flag & (FSHLOCK|FEXLOCK)) && fp->f_type == DTYPE_INODE) 360: ino_unlock(fp, FSHLOCK|FEXLOCK); 361: 362: error = (*Fops[fp->f_type]->fo_close)(fp); 363: fp->f_count = 0; 364: return(error); 365: } 366: 367: /* 368: * Apply an advisory lock on a file descriptor. 369: */ 370: flock() 371: { 372: register struct a { 373: int fd; 374: int how; 375: } *uap = (struct a *)u.u_ap; 376: register struct file *fp; 377: int error; 378: 379: if ((fp = getf(uap->fd)) == NULL) 380: return; 381: if (fp->f_type != DTYPE_INODE) { 382: u.u_error = EOPNOTSUPP; 383: return; 384: } 385: if (uap->how & LOCK_UN) { 386: ino_unlock(fp, FSHLOCK | FEXLOCK); 387: return; 388: } 389: if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 390: return; /* error? */ 391: if (uap->how & LOCK_EX) 392: uap->how &= ~LOCK_SH; 393: /* avoid work... */ 394: if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 395: (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 396: return; 397: error = ino_lock(fp, uap->how); 398: return(u.u_error = error); 399: } 400: 401: /* 402: * File Descriptor pseudo-device driver (/dev/fd/). 403: * 404: * Opening minor device N dup()s the file (if any) connected to file 405: * descriptor N belonging to the calling process. Note that this driver 406: * consists of only the ``open()'' routine, because all subsequent 407: * references to this file will be direct to the other driver. 408: */ 409: /* ARGSUSED */ 410: fdopen(dev, mode, type) 411: dev_t dev; 412: int mode, type; 413: { 414: 415: /* 416: * XXX Kludge: set u.u_dupfd to contain the value of the 417: * the file descriptor being sought for duplication. The error 418: * return ensures that the vnode for this device will be released 419: * by vn_open. Open will detect this special error and take the 420: * actions in dupfdopen below. Other callers of vn_open will 421: * simply report the error. 422: */ 423: u.u_dupfd = minor(dev); 424: return(ENODEV); 425: } 426: 427: /* 428: * Duplicate the specified descriptor to a free descriptor. 429: */ 430: dupfdopen(indx, dfd, mode, error) 431: register int indx, dfd; 432: int mode; 433: int error; 434: { 435: register register struct file *wfp; 436: struct file *fp; 437: 438: /* 439: * If the to-be-dup'd fd number is greater than the allowed number 440: * of file descriptors, or the fd to be dup'd has already been 441: * closed, reject. Note, check for new == old is necessary as 442: * falloc could allocate an already closed to-be-dup'd descriptor 443: * as the new descriptor. 444: */ 445: fp = u.u_ofile[indx]; 446: if (dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL || fp == wfp) 447: return(EBADF); 448: 449: /* 450: * There are two cases of interest here. 451: * 452: * For ENODEV simply dup (dfd) to file descriptor 453: * (indx) and return. 454: * 455: * For ENXIO steal away the file structure from (dfd) and 456: * store it in (indx). (dfd) is effectively closed by 457: * this operation. 458: * 459: * NOTE: ENXIO only comes out of the 'portal fs' code of 4.4 - since 460: * 2.11BSD does not implement the portal fs the code is ifdef'd out 461: * and a short message output. 462: * 463: * Any other error code is just returned. 464: */ 465: switch (error) { 466: case ENODEV: 467: /* 468: * Check that the mode the file is being opened for is a 469: * subset of the mode of the existing descriptor. 470: */ 471: if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) 472: return(EACCES); 473: u.u_ofile[indx] = wfp; 474: u.u_pofile[indx] = u.u_pofile[dfd]; 475: wfp->f_count++; 476: if (indx > u.u_lastfile) 477: u.u_lastfile = indx; 478: return(0); 479: #ifdef haveportalfs 480: case ENXIO: 481: /* 482: * Steal away the file pointer from dfd, and stuff it into indx. 483: */ 484: fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd]; 485: fdp->fd_ofiles[dfd] = NULL; 486: fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; 487: fdp->fd_ofileflags[dfd] = 0; 488: /* 489: * Complete the clean up of the filedesc structure by 490: * recomputing the various hints. 491: */ 492: if (indx > fdp->fd_lastfile) 493: fdp->fd_lastfile = indx; 494: else 495: while (fdp->fd_lastfile > 0 && 496: fdp->fd_ofiles[fdp->fd_lastfile] == NULL) 497: fdp->fd_lastfile--; 498: if (dfd < fdp->fd_freefile) 499: fdp->fd_freefile = dfd; 500: return (0); 501: #else 502: log(LOG_NOTICE, "dupfdopen"); 503: /* FALLTHROUGH */ 504: #endif 505: default: 506: return(error); 507: } 508: /* NOTREACHED */ 509: }