|
|
1.1 ! root 1: /* $Header: /ker/coh.386/RCS/fd.c,v 2.4 93/07/26 15:09:56 nigel Exp $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or persuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 2.3.37 ! 11: * Copyright (c) 1982, 1983, 1984. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * Coherent. ! 17: * File descriptor routines. ! 18: * ! 19: * $Log: fd.c,v $ ! 20: * Revision 2.4 93/07/26 15:09:56 nigel ! 21: * Nigel's R80 ! 22: * ! 23: * Revision 1.5 93/04/14 10:06:26 root ! 24: * r75 ! 25: * ! 26: * Revision 1.3 92/06/10 12:52:39 hal ! 27: * First record locking changes. ! 28: * ! 29: * Revision 1.2 92/01/06 11:59:07 hal ! 30: * Compile with cc.mwc. ! 31: * ! 32: * Revision 1.1 88/03/24 16:13:43 src ! 33: * Initial revision ! 34: * ! 35: */ ! 36: ! 37: #include <common/ccompat.h> ! 38: #include <sys/debug.h> ! 39: #include <sys/coherent.h> ! 40: #include <sys/errno.h> ! 41: #include <fcntl.h> ! 42: #include <sys/fd.h> ! 43: #include <sys/inode.h> ! 44: ! 45: /* ! 46: * Operations for converting from tagged to untagged "pointer to system file ! 47: * table entry" and vice versa. ! 48: */ ! 49: ! 50: enum { ! 51: TAGMASK = sizeof (int) - 1 ! 52: }; ! 53: ! 54: #define MAKE_TAGGED_FD(untag,flag) \ ! 55: (ASSERT (((int) (untag) & TAGMASK) == 0), \ ! 56: ASSERT (((flag) & ~ TAGMASK) == 0), \ ! 57: (tagfd_t) ((unsigned long) (untag) + (flag))) ! 58: ! 59: #define GET_UNTAGGED_FD(tagged) \ ! 60: ((FD *) ((unsigned long) (tagged) & ~ TAGMASK)) ! 61: ! 62: #define GET_TAGGED_FLAG(tagged) \ ! 63: ((int) (tagged) & TAGMASK) ! 64: ! 65: /* ! 66: * Given a file number, return the file descriptor. Now that file descriptors ! 67: * stored in the U area have their low bits tagged to store flag information ! 68: * that is FD-specific (gotta avoid that space crunch in the U area), this ! 69: * interface deals with masking out any extra stuff and returning a plain ! 70: * pointer. ! 71: */ ! 72: ! 73: #if __USE_PROTO__ ! 74: FD * fdget (fd_t fd) ! 75: #else ! 76: FD * ! 77: fdget (fd) ! 78: fd_t fd; ! 79: #endif ! 80: { ! 81: FD * fdp; ! 82: ! 83: if (fd >= NOFILE || ! 84: (fdp = GET_UNTAGGED_FD (u.u_filep [fd])) == NULL) { ! 85: u.u_error = EBADF; ! 86: return NULL; ! 87: } ! 88: return fdp; ! 89: } ! 90: ! 91: ! 92: /* ! 93: * Return tag bits from file descriptor. ! 94: */ ! 95: ! 96: #if __USE_PROTO__ ! 97: int fdgetflags (fd_t fd) ! 98: #else ! 99: int ! 100: fdgetflags (fd) ! 101: fd_t fd; ! 102: #endif ! 103: { ! 104: if (fd >= NOFILE || u.u_filep [fd] == NULL) { ! 105: u.u_error = EBADF; ! 106: return -1; ! 107: } ! 108: return GET_TAGGED_FLAG (u.u_filep [fd]); ! 109: } ! 110: ! 111: ! 112: /* ! 113: * This function allows clients to set the flag bits. ! 114: */ ! 115: ! 116: #if __USE_PROTO__ ! 117: int fdsetflags (fd_t fd, int flags) ! 118: #else ! 119: int ! 120: fdsetflags (fd, flags) ! 121: fd_t fd; ! 122: int flags; ! 123: #endif ! 124: { ! 125: if (fd >= NOFILE || u.u_filep [fd] == NULL) { ! 126: u.u_error = EBADF; ! 127: return -1; ! 128: } ! 129: if ((flags & ~ TAGMASK) != 0) { ! 130: u.u_error = EINVAL; ! 131: return -1; ! 132: } ! 133: ! 134: u.u_filep [fd] = MAKE_TAGGED_FD (GET_UNTAGGED_FD (u.u_filep [fd]), ! 135: flags); ! 136: return 0; ! 137: } ! 138: ! 139: ! 140: /* ! 141: * This function performs something similar to the F_DUPFD function of ! 142: * fcntl ()... this functionality is needed several places internally. ! 143: */ ! 144: ! 145: #if __USE_PROTO__ ! 146: fd_t fddup (fd_t old, fd_t base) ! 147: #else ! 148: fd_t ! 149: fddup (old, base) ! 150: fd_t old; ! 151: fd_t base; ! 152: #endif ! 153: { ! 154: while (base < NOFILE) ! 155: if (u.u_filep [base] == NULL) { ! 156: FD * fdp = fdget (old); ! 157: ! 158: if (fdp == NULL) ! 159: return ERROR_FD; ! 160: u.u_filep [base] = MAKE_TAGGED_FD (fdp, 0); ! 161: fdp->f_refc ++; ! 162: return base; ! 163: } else ! 164: base ++; ! 165: ! 166: u.u_error = EMFILE; ! 167: return ERROR_FD; ! 168: } ! 169: ! 170: ! 171: /* ! 172: * This function finds a free slot in the process file descriptor table and ! 173: * fills it in with a partially initialised entry. ! 174: * ! 175: * This function returns a file descriptor number on success, -1 on failure. ! 176: */ ! 177: ! 178: #if __USE_PROTO__ ! 179: fd_t fdalloc (void) ! 180: #else ! 181: fd_t ! 182: fdalloc () ! 183: #endif ! 184: { ! 185: int i; ! 186: ! 187: for (i = 0 ; i < sizeof (u.u_filep) / sizeof (* u.u_filep) ; i ++) { ! 188: if (u.u_filep [i] == NULL) { ! 189: FD * filep; ! 190: ! 191: if ((filep = kalloc (sizeof (FD))) == NULL) { ! 192: /* ! 193: * Insufficient resources! ! 194: */ ! 195: ! 196: u.u_error = EAGAIN; ! 197: return ERROR_FD; ! 198: } ! 199: ! 200: u.u_filep [i] = MAKE_TAGGED_FD (filep, 0); ! 201: ! 202: filep->f_flag = 0; ! 203: filep->f_refc = 0; ! 204: filep->f_seek = 0; ! 205: filep->f_ip = NULL; ! 206: ! 207: return i; ! 208: } ! 209: } ! 210: ! 211: u.u_error = EMFILE; ! 212: return ERROR_FD; ! 213: } ! 214: ! 215: ! 216: /* ! 217: * This function performs the second half of the file open process by filling ! 218: * in the inode member of the file table entry and requesting that the inode be ! 219: * opened. ! 220: * ! 221: * This function returns -1 on error, 0 on success. ! 222: */ ! 223: ! 224: #if __USE_PROTO__ ! 225: int fdinit (fd_t fd, INODE * ip, int mode) ! 226: #else ! 227: int ! 228: fdinit (fd, ip, mode) ! 229: fd_t fd; ! 230: INODE * ip; ! 231: int mode; ! 232: #endif ! 233: { ! 234: FD * filep; ! 235: ! 236: if ((filep = fdget (fd)) == NULL) ! 237: return -1; ! 238: ! 239: iopen (ip, mode); ! 240: ! 241: if (u.u_error != 0) ! 242: return -1; ! 243: ! 244: filep->f_ip = ip; ! 245: filep->f_flag = mode; ! 246: filep->f_refc = 1; ! 247: ! 248: return 0; ! 249: } ! 250: ! 251: ! 252: /* ! 253: * This function finalises an open; normally this does nothing, but if there ! 254: * has been an error, this code will take care of deallocating the entry. ! 255: * ! 256: * This function returns the file descriptor number on success, or -1 on error. ! 257: */ ! 258: ! 259: #if __USE_PROTO__ ! 260: fd_t fdfinish (fd_t fd) ! 261: #else ! 262: fd_t ! 263: fdfinish (fd) ! 264: fd_t fd; ! 265: #endif ! 266: { ! 267: FD * filep; ! 268: ! 269: if ((filep = fdget (fd)) == NULL) ! 270: return ERROR_FD; ! 271: ! 272: if (filep->f_refc == 0) { ! 273: /* ! 274: * The open never really succeeded, release resources. ! 275: */ ! 276: ! 277: kfree (filep); ! 278: u.u_filep [fd] = NULL; ! 279: fd = ERROR_FD; ! 280: } ! 281: ! 282: return fd; ! 283: } ! 284: ! 285: ! 286: /* ! 287: * Given an inode, and a mode containing permission flags, open the ! 288: * inode with the appropriate permissions and return a file descriptor ! 289: * containing it. ! 290: */ ! 291: ! 292: #if __USE_PROTO__ ! 293: fd_t fdopen (INODE * ip, int mode) ! 294: #else ! 295: fd_t ! 296: fdopen (ip, mode) ! 297: INODE * ip; ! 298: int mode; ! 299: #endif ! 300: { ! 301: int fd; ! 302: ! 303: if ((fd = fdalloc ()) != ERROR_FD) { ! 304: fdinit (fd, ip, mode); ! 305: fd = fdfinish (fd); ! 306: } ! 307: ! 308: return fd; ! 309: } ! 310: ! 311: ! 312: /* ! 313: * Close the given file number. ! 314: */ ! 315: ! 316: #if __USE_PROTO__ ! 317: void fdclose (unsigned fd) ! 318: #else ! 319: void ! 320: fdclose(fd) ! 321: unsigned fd; ! 322: #endif ! 323: { ! 324: register FD *fdp; ! 325: static struct flock flock = { F_UNLCK, 0, 0, 0 }; ! 326: ! 327: if (fd >= NOFILE || ! 328: (fdp = GET_UNTAGGED_FD (u.u_filep [fd])) == NULL) { ! 329: u.u_error = EBADF; ! 330: return; ! 331: } ! 332: ! 333: if (fdp->f_ip->i_rl != NULL) ! 334: rlock (fdp, F_SETLK, & flock); /* delete all record locks */ ! 335: ! 336: u.u_filep[fd] = NULL; ! 337: ! 338: if (fdp->f_refc == 0) ! 339: panic("fdclose()"); ! 340: ! 341: if (-- fdp->f_refc == 0) { ! 342: iclose (fdp->f_ip, fdp->f_flag); ! 343: kfree (fdp); ! 344: } ! 345: } ! 346: ! 347: ! 348: /* ! 349: * Assuming we have made a copy of the user area, increment the reference ! 350: * of all open files. (used in fork). ! 351: */ ! 352: ! 353: #if __USE_PROTO__ ! 354: void fdadupl (void) ! 355: #else ! 356: void ! 357: fdadupl () ! 358: #endif ! 359: { ! 360: int i; ! 361: ! 362: for (i = 0 ; i < NOFILE ; i ++) ! 363: if (u.u_filep [i] != NULL) ! 364: GET_UNTAGGED_FD (u.u_filep [i])->f_refc ++; ! 365: } ! 366: ! 367: ! 368: /* ! 369: * Close all open files in the current process. ! 370: */ ! 371: ! 372: #if __USE_PROTO__ ! 373: void fdaclose (void) ! 374: #else ! 375: void ! 376: fdaclose() ! 377: #endif ! 378: { ! 379: int fd; ! 380: ! 381: for (fd = 0 ; fd < NOFILE ; fd ++) ! 382: if (u.u_filep [fd] != NULL) ! 383: fdclose (fd); ! 384: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.