📄 gfs_descrip.c
字号:
#ifndef lintstatic char *sccsid = "@(#)gfs_descrip.c 4.9 (ULTRIX) 5/2/91";#endif lint/************************************************************************ * * * Copyright (c) 1988 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * Modification History * * prs 4/2/91 * The F_GETLK request to fcntl() should always return the blocking * lock description relative to the beginning of the file if process * is running in POSIX mode. * * prs 2/28/91 * Added support for a configurable number of open * file descriptors. * * prs 1/21/91 * f_data is now controlled with lk_file instead of per file * table entry lock. This is for vhangup(). * * scott 03/29/90 * add check on fp->f_data before fetching mode and number * * prs 11/14/89 * Fixed EBADF detection within locking code of fcntl(). * * scott 10/16/89 * fix use of gnode dev # for audit * * scott 8/24/89 * moved closef() in close(). * * condylis 6/23/89 * Removed references to unp_gc(). * * prs 06/14/89 * Locked gnode during call to sfs close routine in closef(). * * Scott 06/09/89 * Add audit support * * McMenemy 05/04/89 * Add internal_dup2 call. * * prs 03/21/89 * Added lockinit of LK_ACCT in finit() * * Condylis 09/12/88 * Made SMP changes in flock() * * Fred Glover, 8/29/88 * add POSIX check for fcntl locking with F_GETFL; * change error code returned for file which does not support locking; * fix return from rewhence function for unimplemented GGETVAL function. * * Paul Shaughnessy, 8/22/88 * Cleaned up F_SETFL fcntl() requests. * * prs for chet , 8/15/88 * Don't call the close routine pointed to in the file ops * structure if f_data is NULL in closef(). * * prs - 7/12/88 * Added SMP file table entry locks around calls to dupit. * * Paul Shaughnessy, 7/11/88 * Added fifo support to fsetown() and fgetown(). * * Fred Glover 6/10/88 * Modify error return mapping from Sys-V locking (via fcntl). * Currently, EWOULDBLOCK and EDEADLK are the same errno. Thus * modify check in fcntl under locking commands: it is unnecessary * to map EWOULDBLOCK into a Sys-V errno, and in fact an error to * do so, since that would also remap EDEADLK. * * Paul Shaughnessy, 4/27/88 * Changed closef to handle closing a file pointer that was * "divorced" from its gnode via vhangup(). * * Paul Shaughnessy, 2/10/88 * Modified to handle the new fifo code. * * Fred Glover 1/26/88 * Modify fcntl lock routines to support kernel and daemon based * Sys-V style locking through the modified GRLOCK macro. * * Joe Amato, 8/28/87 * closef() returns err from the file systems. * close() sets u.u_error from closef(). * * Larry Palmer 8/25/87 * Made socket fsetown/fgetown set the pgrp as a positive * value. This mathces how the socket opt does it. * * Paul Shaughnessy, 10/02/86 * 005- Added code to clear the close_on_exec bit when the F_DUPFD * command is specified with the fcntl system call. * * Paul Shaughnessy, 12/23/85 * 004- Added commands to fcntl system calls to turn on/off * the syncronous write option to a file. * * 11 Nov 85 -- depp * Removed all conditional compiles for System V IPC. * * Stephen Reilly, 9/09/85 * 002- Modified to handle the new lockf code. * * Stephen Reilly, 2/19/85 * 001- Process group or process ID was not stored correctly into the * socket structure. * * Larry Cohen, 4/4/85 * 002- Changes for block in use capability. * Also changed calls to getf to GETF macro * * 15 Mar 85 -- funding * Added named pipe support (re. System V named pipes) * * Larry Cohen, 4/13/85 * call ioctl FIOCINUSE when closing inuse desriptor * * 05-May-85 - Larry Cohen * keep track of the highest number file descriptor opened * * I moved a line around as part of the inode count going negative * Rich * * kern_descrip.c 6.2 83/09/25 * ***********************************************************************/#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/kernel.h"#include "../h/gnode.h"#include "../h/proc.h"#include "../h/conf.h"#include "../h/file.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/mount.h"#include "../h/stat.h"#include "../h/ioctl.h"#include "../h/flock.h"#include "../h/exec.h"#include "../h/kmalloc.h"#ifdef KLMDEBUGextern int klm_debug;#endif KLMDEBUG/* * Descriptor management. *//* * TODO: * eliminate u.u_error side effects *//* * Private routine forward declarations. */int alloc_fd_slots();extern int max_nofile;/* * Ensure that descriptor slot n has been allocated, returning -1 if * unable to do so and 0 otherwise. Expressed as a macro to make it * cheap enough to call within loops iterating over all descriptors. * The predicate part arranges that the function to allocate descriptor * slots in the range [NOFILE_IN_U .. max_nofile] is called only when * necessary. */#define enable_fd_slot(n) \ (((n) < (NOFILE_IN_U + u.u_of_count)) ? \ 0 : alloc_fd_slots((n)))struct lock_t lk_file;/* * System calls on descriptors. */getdtablesize(){ u.u_r.r_val1 = max_nofile;}getdopt(){}setdopt(){}dup(){ register struct a { int i; } *uap = (struct a *) u.u_ap; register struct file *fp; register int j; if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ GETF(fp, uap->i); j = ufalloc(0); if (j < 0) return; smp_lock(&lk_file, LK_RETRY); dupit(j, fp, U_POFILE(uap->i)); smp_unlock(&lk_file);}dup2(){ register struct a { int i, j; } *uap = (struct a *) u.u_ap; internal_dup2(uap->i, uap->j);}internal_dup2(old, new) int old; int new;{ register struct file *fp; register struct file *fp2; register struct gnode *gp; GETF(fp, old); if (new < 0 || new >= max_nofile) { u.u_error = EBADF; return; } u.u_r.r_val1 = new; if (old == new) return; /* audit info */ if ( audswitch ) { if ( gp = (struct gnode *)fp->f_data ) { u.u_gno_dev[0] = (gp->g_mode & GFMT) == GFCHR ? gp->g_rdev : gp->g_dev; u.u_gno_num[0] = gp->g_number; u.u_gno_indx = 1; } } if (enable_fd_slot(new)) goto out; if (U_OFILE(new)) { /* Release all System-V style record locks, if any */ (void)gno_lockrelease (U_OFILE(new)); /* error? */ /* * It's a no-op, why call it? * * if (U_POFILE(new) & UF_MAPPED) * munmapfd(new); */ fp2 = U_OFILE(new); U_OFILE_SET(new, NULL); U_POFILE_SET(new, 0); closef(fp2); if (u.u_error) goto out; } if (new > u.u_omax) /* track largest file pointer number */ u.u_omax = new; smp_lock(&lk_file, LK_RETRY); dupit(new, fp, U_POFILE(old)); smp_unlock(&lk_file);out: AUDIT_CALL ( u.u_event, u.u_error, u.u_r.r_val1, AUD_HDR|AUD_PRM|AUD_RES, (int *)0, 0 );}dupit(fd, fp, flags) register int fd; register struct file *fp; register int flags;{ U_OFILE_SET(fd, fp);#ifdef notdef flags &= ~(UF_INUSE); /* remove INUSE reference to inode *002*/ #endif U_POFILE_SET(fd, flags); fp->f_count++;}/* * The file control system call. */fcntl(){ register struct file *fp; register struct a { int fdes; int cmd; int arg; } *uap; register int i; struct flock bf; register struct gnode *gp; /* 004 */ int oldwhence; /* whence of request */ uap = (struct a *)u.u_ap; GETF(fp, uap->fdes); smp_lock(&fp->f_lk, LK_RETRY); /* 004 - Fill gnode structure */ gp = (struct gnode *)fp->f_data; switch(uap->cmd) { case F_DUPFD: i = uap->arg; if (i < 0 || i >= max_nofile) { u.u_error = EINVAL; break; } if ((i = ufalloc(i)) >= 0) { smp_lock(&lk_file, LK_RETRY); dupit(i, fp, U_POFILE(uap->fdes) & ~UF_EXCLOSE); smp_unlock(&lk_file); } break; case F_GETFD: u.u_r.r_val1 = U_POFILE(uap->fdes) & UF_EXCLOSE; break; case F_SETFD: U_POFILE_SET(uap->fdes, (U_POFILE(uap->fdes) & ~UF_EXCLOSE) | (uap->arg & UF_EXCLOSE)); break; case F_GETFL: u.u_r.r_val1 = fp->f_flag+FOPEN; break; case F_SETFL: /* * Clear user-settable flags */ fp->f_flag &= ~FCNTLONLYSET; /* * Now, only and in the flags that a user can set * with this request. */ fp->f_flag |= ((uap->arg-FOPEN) & FCNTLONLYSET); /* * Setting FNDELAY may need a call to a driver, handle * it seperatly. */ u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); if (!u.u_error) { u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); if (u.u_error) (void) fset(fp, FNDELAY, 0); } break; case F_GETOWN: u.u_error = fgetown(fp, &u.u_r.r_val1); break; case F_SETOWN: u.u_error = fsetown(fp, uap->arg); break; case F_GETLK: case F_SETLK: case F_SETLKW: /* Locks supported for disk inodes only */ if (fp->f_type != DTYPE_INODE) { u.u_error = EINVAL; break; } /* Verify inode pointer */ if (fp->f_data == NULL) { u.u_error = EFAULT; break; } /* get flock structure from user space */ if (u.u_error = copyin((caddr_t)uap->arg, (caddr_t)&bf, sizeof(bf))){ break; } /* * check access permissions: * POSIX requires a valid type even for F_GETLK * requests; otherwise, F_GETLK requests may point * to an empty flock structure. */ if ((uap->cmd != F_GETLK) || (u.u_procp->p_progenv == A_POSIX)) { switch (bf.l_type) { case F_RDLCK: if ((uap->cmd != F_GETLK) && !(fp->f_flag & FREAD)) { u.u_error = EBADF; } break; case F_WRLCK: if ((uap->cmd != F_GETLK) && !(fp->f_flag & FWRITE)) { u.u_error = EBADF; } break; case F_UNLCK: break; default: u.u_error = EINVAL; break; } /* End switch */ if (u.u_error) /* error encountered above */ break; } /* convert offset to start of file */ oldwhence = bf.l_whence; /* save to renormalize later */ if (u.u_error = rewhence(&bf, fp, 0)) { break; } /* convert negative lengths to positive */ if (bf.l_len < 0) { bf.l_start += bf.l_len; /* adjust start */ bf.l_len = -(bf.l_len); /* absolute value */ } /* check for validity */ if (bf.l_start < 0) { u.u_error = EINVAL; break; } /* * Now, process the request */ if ((uap->cmd != F_GETLK) && (bf.l_type != F_UNLCK)) { /* If locking is attempted, mark file locked * to force unlock on close. * Also, since the SVID specifies that the * FIRST close releases all locks, mark process * to reduce the search overhead in * gno_lockrelease(). */ U_POFILE_SET(uap->fdes, U_POFILE(uap->fdes) | UF_FDLOCK); u.u_procp->p_file |= SLKDONE; } /* * Dispatch out to specific file system to do the actual * locking. Then, continue based upon the error returned. */ switch (u.u_error = GRLOCK (gp, &bf, uap->cmd, fp)) { case 0: break; /* continue, if successful */ default: /* some other error code */ break; } /* End Switch */ if (u.u_error) /* error encountered above */ break; /* if F_GETLK, return flock structure to user space */ if (uap->cmd == F_GETLK) { /* * per SVID and P1003.1 : change only 'l_type' * field if unlocked */ if (bf.l_type == F_UNLCK) { u.u_error = copyout((caddr_t)&bf.l_type, (caddr_t)&((struct flock*)uap->arg)->l_type, sizeof (bf.l_type)); } else { /* * per P1003.1 : 'l_whence' field must be * relative to start of file (SEEK_SET) */ if (u.u_procp->p_progenv != A_POSIX) u.u_error=rewhence(&bf, fp, oldwhence); if (!u.u_error) u.u_error = copyout((caddr_t) &bf, (caddr_t) uap->arg, sizeof (bf)); } } /* End if F_GETLK processing */# ifdef KLMDEBUG if (klm_debug) { printf ("fcntl(3) ret: eno:%d cmd:%d ty:%d wh:%d st:%d ln:%d pid:%d\n", u.u_error,uap->cmd, bf.l_type, bf.l_whence, bf.l_start, bf.l_len, bf.l_pid); }# endif KLMDEBUG break; case F_SETSYN:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -