1: /* 2: * Copyright (c) 1982, 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 7.1 (Berkeley) 6/5/86 7: */ 8: 9: #include "param.h" 10: #include "systm.h" 11: #include "dir.h" 12: #include "user.h" 13: #include "kernel.h" 14: #include "inode.h" 15: #include "proc.h" 16: #include "file.h" 17: #include "socket.h" 18: #include "socketvar.h" 19: #include "mount.h" 20: #include "stat.h" 21: 22: #include "ioctl.h" 23: 24: /* 25: * Descriptor management. 26: */ 27: 28: /* 29: * TODO: 30: * eliminate u.u_error side effects 31: */ 32: 33: /* 34: * System calls on descriptors. 35: */ 36: getdtablesize() 37: { 38: 39: u.u_r.r_val1 = NOFILE; 40: } 41: 42: getdopt() 43: { 44: 45: } 46: 47: setdopt() 48: { 49: 50: } 51: 52: dup() 53: { 54: register struct a { 55: int i; 56: } *uap = (struct a *) u.u_ap; 57: struct file *fp; 58: int j; 59: 60: if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 61: 62: GETF(fp, uap->i); 63: j = ufalloc(0); 64: if (j < 0) 65: return; 66: dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 67: } 68: 69: dup2() 70: { 71: register struct a { 72: int i, j; 73: } *uap = (struct a *) u.u_ap; 74: register struct file *fp; 75: 76: GETF(fp, uap->i); 77: if (uap->j < 0 || uap->j >= NOFILE) { 78: u.u_error = EBADF; 79: return; 80: } 81: u.u_r.r_val1 = uap->j; 82: if (uap->i == uap->j) 83: return; 84: if (u.u_ofile[uap->j]) { 85: if (u.u_pofile[uap->j] & UF_MAPPED) 86: munmapfd(uap->j); 87: closef(u.u_ofile[uap->j]); 88: if (u.u_error) 89: return; 90: } 91: dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 92: } 93: 94: dupit(fd, fp, flags) 95: int fd; 96: register struct file *fp; 97: register int flags; 98: { 99: 100: u.u_ofile[fd] = fp; 101: u.u_pofile[fd] = flags; 102: fp->f_count++; 103: if (fd > u.u_lastfile) 104: u.u_lastfile = fd; 105: } 106: 107: /* 108: * The file control system call. 109: */ 110: fcntl() 111: { 112: register struct file *fp; 113: register struct a { 114: int fdes; 115: int cmd; 116: int arg; 117: } *uap; 118: register i; 119: register char *pop; 120: 121: uap = (struct a *)u.u_ap; 122: GETF(fp, uap->fdes); 123: pop = &u.u_pofile[uap->fdes]; 124: switch(uap->cmd) { 125: case F_DUPFD: 126: i = uap->arg; 127: if (i < 0 || i >= NOFILE) { 128: u.u_error = EINVAL; 129: return; 130: } 131: if ((i = ufalloc(i)) < 0) 132: return; 133: dupit(i, fp, *pop &~ UF_EXCLOSE); 134: break; 135: 136: case F_GETFD: 137: u.u_r.r_val1 = *pop & 1; 138: break; 139: 140: case F_SETFD: 141: *pop = (*pop &~ 1) | (uap->arg & 1); 142: break; 143: 144: case F_GETFL: 145: u.u_r.r_val1 = fp->f_flag+FOPEN; 146: break; 147: 148: case F_SETFL: 149: fp->f_flag &= FCNTLCANT; 150: fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 151: u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); 152: if (u.u_error) 153: break; 154: u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 155: if (u.u_error) 156: (void) fset(fp, FNDELAY, 0); 157: break; 158: 159: case F_GETOWN: 160: u.u_error = fgetown(fp, &u.u_r.r_val1); 161: break; 162: 163: case F_SETOWN: 164: u.u_error = fsetown(fp, uap->arg); 165: break; 166: 167: default: 168: u.u_error = EINVAL; 169: } 170: } 171: 172: fset(fp, bit, value) 173: struct file *fp; 174: int bit, value; 175: { 176: 177: if (value) 178: fp->f_flag |= bit; 179: else 180: fp->f_flag &= ~bit; 181: return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 182: (caddr_t)&value)); 183: } 184: 185: fgetown(fp, valuep) 186: struct file *fp; 187: int *valuep; 188: { 189: int error; 190: 191: switch (fp->f_type) { 192: 193: case DTYPE_SOCKET: 194: *valuep = ((struct socket *)fp->f_data)->so_pgrp; 195: return (0); 196: 197: default: 198: error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 199: *valuep = -*valuep; 200: return (error); 201: } 202: } 203: 204: fsetown(fp, value) 205: struct file *fp; 206: int value; 207: { 208: 209: if (fp->f_type == DTYPE_SOCKET) { 210: ((struct socket *)fp->f_data)->so_pgrp = value; 211: return (0); 212: } 213: if (value > 0) { 214: struct proc *p = pfind(value); 215: if (p == 0) 216: return (ESRCH); 217: value = p->p_pgrp; 218: } else 219: value = -value; 220: return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 221: } 222: 223: fioctl(fp, cmd, value) 224: struct file *fp; 225: int cmd; 226: caddr_t value; 227: { 228: 229: return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 230: } 231: 232: close() 233: { 234: struct a { 235: int i; 236: } *uap = (struct a *)u.u_ap; 237: register int i = uap->i; 238: register struct file *fp; 239: register u_char *pf; 240: 241: GETF(fp, i); 242: pf = (u_char *)&u.u_pofile[i]; 243: if (*pf & UF_MAPPED) 244: munmapfd(i); 245: u.u_ofile[i] = NULL; 246: while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 247: u.u_lastfile--; 248: *pf = 0; 249: closef(fp); 250: /* WHAT IF u.u_error ? */ 251: } 252: 253: fstat() 254: { 255: register struct file *fp; 256: register struct a { 257: int fdes; 258: struct stat *sb; 259: } *uap; 260: struct stat ub; 261: 262: uap = (struct a *)u.u_ap; 263: GETF(fp, uap->fdes); 264: switch (fp->f_type) { 265: 266: case DTYPE_INODE: 267: u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 268: break; 269: 270: case DTYPE_SOCKET: 271: u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 272: break; 273: 274: default: 275: panic("fstat"); 276: /*NOTREACHED*/ 277: } 278: if (u.u_error == 0) 279: u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 280: sizeof (ub)); 281: } 282: 283: /* 284: * Allocate a user file descriptor. 285: */ 286: ufalloc(i) 287: register int i; 288: { 289: 290: for (; i < NOFILE; i++) 291: if (u.u_ofile[i] == NULL) { 292: u.u_r.r_val1 = i; 293: u.u_pofile[i] = 0; 294: if (i > u.u_lastfile) 295: u.u_lastfile = i; 296: return (i); 297: } 298: u.u_error = EMFILE; 299: return (-1); 300: } 301: 302: ufavail() 303: { 304: register int i, avail = 0; 305: 306: for (i = 0; i < NOFILE; i++) 307: if (u.u_ofile[i] == NULL) 308: avail++; 309: return (avail); 310: } 311: 312: struct file *lastf; 313: /* 314: * Allocate a user file descriptor 315: * and a file structure. 316: * Initialize the descriptor 317: * to point at the file structure. 318: */ 319: struct file * 320: falloc() 321: { 322: register struct file *fp; 323: register i; 324: 325: i = ufalloc(0); 326: if (i < 0) 327: return (NULL); 328: if (lastf == 0) 329: lastf = file; 330: for (fp = lastf; fp < fileNFILE; fp++) 331: if (fp->f_count == 0) 332: goto slot; 333: for (fp = file; fp < lastf; fp++) 334: if (fp->f_count == 0) 335: goto slot; 336: tablefull("file"); 337: u.u_error = ENFILE; 338: return (NULL); 339: slot: 340: u.u_ofile[i] = fp; 341: fp->f_count = 1; 342: fp->f_data = 0; 343: fp->f_offset = 0; 344: lastf = fp + 1; 345: return (fp); 346: } 347: 348: /* 349: * Convert a user supplied file descriptor into a pointer 350: * to a file structure. Only task is to check range of the descriptor. 351: * Critical paths should use the GETF macro. 352: */ 353: struct file * 354: getf(f) 355: register int f; 356: { 357: register struct file *fp; 358: 359: if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 360: u.u_error = EBADF; 361: return (NULL); 362: } 363: return (fp); 364: } 365: 366: /* 367: * Internal form of close. 368: * Decrement reference count on file structure. 369: */ 370: closef(fp) 371: register struct file *fp; 372: { 373: 374: if (fp == NULL) 375: return; 376: if (fp->f_count > 1) { 377: fp->f_count--; 378: return; 379: } 380: (*fp->f_ops->fo_close)(fp); 381: fp->f_count = 0; 382: } 383: 384: /* 385: * Apply an advisory lock on a file descriptor. 386: */ 387: flock() 388: { 389: register struct a { 390: int fd; 391: int how; 392: } *uap = (struct a *)u.u_ap; 393: register struct file *fp; 394: 395: GETF(fp, uap->fd); 396: if (fp->f_type != DTYPE_INODE) { 397: u.u_error = EOPNOTSUPP; 398: return; 399: } 400: if (uap->how & LOCK_UN) { 401: ino_unlock(fp, FSHLOCK|FEXLOCK); 402: return; 403: } 404: if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 405: return; /* error? */ 406: if (uap->how & LOCK_EX) 407: uap->how &= ~LOCK_SH; 408: /* avoid work... */ 409: if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 410: (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 411: return; 412: u.u_error = ino_lock(fp, uap->how); 413: }