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: }

Defined functions

close defined in line 218; used 2 times
dup defined in line 37; used 2 times
dup2 defined in line 54; used 3 times
dupfdopen defined in line 430; used 1 times
dupit defined in line 77; used 3 times
fcntl defined in line 93; used 2 times
fdopen defined in line 410; used 2 times
fgetown defined in line 169; used 2 times
fioctl defined in line 209; used 3 times
flock defined in line 370; used 2 times
fset defined in line 156; used 5 times
fsetown defined in line 186; used 2 times
fstat defined in line 233; used 2 times
getdtablesize defined in line 31; used 2 times
ufalloc defined in line 272; used 5 times

Defined variables

lastf defined in line 288; used 5 times

Defined struct's

a defined in line 372; used 12 times
Last modified: 1999-09-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4418
Valid CSS Valid XHTML 1.0 Strict