⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc.c

📁 一个简单的操作系统minix的核心代码
💻 C
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/fs/misc.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

26600	/* This file contains a collection of miscellaneous procedures.  Some of them
26601	 * perform simple system calls.  Some others do a little part of system calls
26602	 * that are mostly performed by the Memory Manager.
26603	 *
26604	 * The entry points into this file are
26605	 *   do_dup:      perform the DUP system call
26606	 *   do_fcntl:    perform the FCNTL system call
26607	 *   do_sync:     perform the SYNC system call
26608	 *   do_fork:     adjust the tables after MM has performed a FORK system call
26609	 *   do_exec:     handle files with FD_CLOEXEC on after MM has done an EXEC
26610	 *   do_exit:     a process has exited; note that in the tables
26611	 *   do_set:      set uid or gid for some process
26612	 *   do_revive:   revive a process that was waiting for something (e.g. TTY)
26613	 */
26614	
26615	#include "fs.h"
26616	#include <fcntl.h>
26617	#include <unistd.h>     /* cc runs out of memory with unistd.h :-( */
26618	#include <minix/callnr.h>
26619	#include <minix/com.h>
26620	#include <minix/boot.h>
26621	#include "buf.h"
26622	#include "file.h"
26623	#include "fproc.h"
26624	#include "inode.h"
26625	#include "dev.h"
26626	#include "param.h"
26627	
26628	
26629	/*===========================================================================*
26630	 *                              do_dup                                       *
26631	 *===========================================================================*/
26632	PUBLIC int do_dup()
26633	{
26634	/* Perform the dup(fd) or dup2(fd,fd2) system call. These system calls are
26635	 * obsolete.  In fact, it is not even possible to invoke them using the
26636	 * current library because the library routines call fcntl().  They are
26637	 * provided to permit old binary programs to continue to run.
26638	 */
26639	
26640	  register int rfd;
26641	  register struct filp *f;
26642	  struct filp *dummy;
26643	  int r;
26644	
26645	  /* Is the file descriptor valid? */
26646	  rfd = fd & ~DUP_MASK;         /* kill off dup2 bit, if on */
26647	  if ((f = get_filp(rfd)) == NIL_FILP) return(err_code);
26648	
26649	  /* Distinguish between dup and dup2. */
26650	  if (fd == rfd) {                      /* bit not on */
26651	        /* dup(fd) */
26652	        if ( (r = get_fd(0, 0, &fd2, &dummy)) != OK) return(r);
26653	  } else {
26654	        /* dup2(fd, fd2) */
26655	        if (fd2 < 0 || fd2 >= OPEN_MAX) return(EBADF);
26656	        if (rfd == fd2) return(fd2);    /* ignore the call: dup2(x, x) */
26657	        fd = fd2;               /* prepare to close fd2 */
26658	        (void) do_close();      /* cannot fail */
26659	  }
26660	
26661	  /* Success. Set up new file descriptors. */
26662	  f->filp_count++;
26663	  fp->fp_filp[fd2] = f;
26664	  return(fd2);
26665	}
	
26667	/*===========================================================================*
26668	 *                              do_fcntl                                     *
26669	 *===========================================================================*/
26670	PUBLIC int do_fcntl()
26671	{
26672	/* Perform the fcntl(fd, request, ...) system call. */
26673	
26674	  register struct filp *f;
26675	  int new_fd, r, fl;
26676	  long cloexec_mask;            /* bit map for the FD_CLOEXEC flag */
26677	  long clo_value;               /* FD_CLOEXEC flag in proper position */
26678	  struct filp *dummy;
26679	
26680	  /* Is the file descriptor valid? */
26681	  if ((f = get_filp(fd)) == NIL_FILP) return(err_code);
26682	
26683	  switch (request) {
26684	     case F_DUPFD: 
26685	        /* This replaces the old dup() system call. */
26686	        if (addr < 0 || addr >= OPEN_MAX) return(EINVAL);
26687	        if ((r = get_fd(addr, 0, &new_fd, &dummy)) != OK) return(r);
26688	        f->filp_count++;
26689	        fp->fp_filp[new_fd] = f;
26690	        return(new_fd);
26691	
26692	     case F_GETFD: 
26693	        /* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
26694	        return( ((fp->fp_cloexec >> fd) & 01) ? FD_CLOEXEC : 0);
26695	
26696	     case F_SETFD: 
26697	        /* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
26698	        cloexec_mask = 1L << fd;        /* singleton set position ok */
26699	        clo_value = (addr & FD_CLOEXEC ? cloexec_mask : 0L);
26700	        fp->fp_cloexec = (fp->fp_cloexec & ~cloexec_mask) | clo_value;
26701	        return(OK);
26702	
26703	     case F_GETFL: 
26704	        /* Get file status flags (O_NONBLOCK and O_APPEND). */
26705	        fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
26706	        return(fl);     
26707	
26708	     case F_SETFL: 
26709	        /* Set file status flags (O_NONBLOCK and O_APPEND). */
26710	        fl = O_NONBLOCK | O_APPEND;
26711	        f->filp_flags = (f->filp_flags & ~fl) | (addr & fl);
26712	        return(OK);
26713	
26714	     case F_GETLK:
26715	     case F_SETLK:
26716	     case F_SETLKW:
26717	        /* Set or clear a file lock. */
26718	        r = lock_op(f, request);
26719	        return(r);
26720	
26721	     default:
26722	        return(EINVAL);
26723	  }
26724	}
	
	
26727	/*===========================================================================*
26728	 *                              do_sync                                      *
26729	 *===========================================================================*/
26730	PUBLIC int do_sync()
26731	{
26732	/* Perform the sync() system call.  Flush all the tables. */
26733	
26734	  register struct inode *rip;
26735	  register struct buf *bp;
26736	
26737	  /* The order in which the various tables are flushed is critical.  The
26738	   * blocks must be flushed last, since rw_inode() leaves its results in
26739	   * the block cache.
26740	   */
26741	
26742	  /* Write all the dirty inodes to the disk. */
26743	  for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
26744	        if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
26745	
26746	  /* Write all the dirty blocks to the disk, one drive at a time. */
26747	  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
26748	        if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) flushall(bp->b_dev);
26749	
26750	  return(OK);           /* sync() can't fail */
26751	}
	
	
26754	/*===========================================================================*
26755	 *                              do_fork                                      *
26756	 *===========================================================================*/
26757	PUBLIC int do_fork()
26758	{
26759	/* Perform those aspects of the fork() system call that relate to files.
26760	 * In particular, let the child inherit its parent's file descriptors.
26761	 * The parent and child parameters tell who forked off whom. The file
26762	 * system uses the same slot numbers as the kernel.  Only MM makes this call.
26763	 */
26764	
26765	  register struct fproc *cp;
26766	  int i;
26767	
26768	  /* Only MM may make this call directly. */
26769	  if (who != MM_PROC_NR) return(EGENERIC);
26770	
26771	  /* Copy the parent's fproc struct to the child. */
26772	  fproc[child] = fproc[parent];
26773	
26774	  /* Increase the counters in the 'filp' table. */
26775	  cp = &fproc[child];
26776	  for (i = 0; i < OPEN_MAX; i++)
26777	        if (cp->fp_filp[i] != NIL_FILP) cp->fp_filp[i]->filp_count++;
26778	
26779	  /* Fill in new process id. */
26780	  cp->fp_pid = pid;
26781	
26782	  /* A child is not a process leader. */
26783	  cp->fp_sesldr = 0;
26784	
26785	  /* Record the fact that both root and working dir have another user. */
26786	  dup_inode(cp->fp_rootdir);
26787	  dup_inode(cp->fp_workdir);
26788	  return(OK);
26789	}
	
	
26792	/*===========================================================================*
26793	 *                              do_exec                                      *
26794	 *===========================================================================*/
26795	PUBLIC int do_exec()
26796	{
26797	/* Files can be marked with the FD_CLOEXEC bit (in fp->fp_cloexec).  When
26798	 * MM does an EXEC, it calls FS to allow FS to find these files and close them.
26799	 */
26800	
26801	  register int i;
26802	  long bitmap;
26803	
26804	  /* Only MM may make this call directly. */
26805	  if (who != MM_PROC_NR) return(EGENERIC);
26806	
26807	  /* The array of FD_CLOEXEC bits is in the fp_cloexec bit map. */
26808	  fp = &fproc[slot1];           /* get_filp() needs 'fp' */
26809	  bitmap = fp->fp_cloexec;
26810	  if (bitmap == 0) return(OK);  /* normal case, no FD_CLOEXECs */
26811	
26812	  /* Check the file desriptors one by one for presence of FD_CLOEXEC. */
26813	  for (i = 0; i < OPEN_MAX; i++) {
26814	        fd = i;
26815	        if ( (bitmap >> i) & 01) (void) do_close();
26816	  }
26817	
26818	  return(OK);
26819	}
	
	
26822	/*===========================================================================*
26823	 *                              do_exit                                      *
26824	 *===========================================================================*/
26825	PUBLIC int do_exit()
26826	{
26827	/* Perform the file system portion of the exit(status) system call. */
26828	
26829	  register int i, exitee, task;
26830	  register struct fproc *rfp;
26831	  register struct filp *rfilp;
26832	  register struct inode *rip;
26833	  int major;
26834	  dev_t dev;
26835	  message dev_mess;
26836	
26837	  /* Only MM may do the EXIT call directly. */
26838	  if (who != MM_PROC_NR) return(EGENERIC);
26839	
26840	  /* Nevertheless, pretend that the call came from the user. */
26841	  fp = &fproc[slot1];           /* get_filp() needs 'fp' */
26842	  exitee = slot1;
26843	
26844	  if (fp->fp_suspended == SUSPENDED) {
26845	        task = -fp->fp_task;
26846	        if (task == XPIPE || task == XPOPEN) susp_count--;
26847	        pro = exitee;
26848	        (void) do_unpause();    /* this always succeeds for MM */
26849	        fp->fp_suspended = NOT_SUSPENDED;
26850	  }
26851	
26852	  /* Loop on file descriptors, closing any that are open. */
26853	  for (i = 0; i < OPEN_MAX; i++) {
26854	        fd = i;
26855	        (void) do_close();
26856	  }
26857	
26858	  /* Release root and working directories. */
26859	  put_inode(fp->fp_rootdir);
26860	  put_inode(fp->fp_workdir);
26861	  fp->fp_rootdir = NIL_INODE;
26862	  fp->fp_workdir = NIL_INODE;
26863	
26864	  /* If a session leader exits then revoke access to its controlling tty from
26865	   * all other processes using it.
26866	   */
26867	  if (!fp->fp_sesldr) return(OK);               /* not a session leader */
26868	  fp->fp_sesldr = FALSE;
26869	  if (fp->fp_tty == 0) return(OK);              /* no controlling tty */
26870	  dev = fp->fp_tty;
26871	
26872	  for (rfp = &fproc[LOW_USER]; rfp < &fproc[NR_PROCS]; rfp++) {
26873	        if (rfp->fp_tty == dev) rfp->fp_tty = 0;
26874	
26875	        for (i = 0; i < OPEN_MAX; i++) {
26876	                if ((rfilp = rfp->fp_filp[i]) == NIL_FILP) continue;
26877	                if (rfilp->filp_mode == FILP_CLOSED) continue;
26878	                rip = rfilp->filp_ino;
26879	                if ((rip->i_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
26880	                if ((dev_t) rip->i_zone[0] != dev) continue;
26881	                dev_mess.m_type = DEV_CLOSE;
26882	                dev_mess.DEVICE = dev;
26883	                major = (dev >> MAJOR) & BYTE;  /* major device nr */
26884	                task = dmap[major].dmap_task;   /* device task nr */
26885	                (*dmap[major].dmap_close)(task, &dev_mess);
26886	                rfilp->filp_mode = FILP_CLOSED;
26887	        }
26888	  }
26889	  return(OK);
26890	}
	
	
26893	/*===========================================================================*
26894	 *                              do_set                                       *
26895	 *===========================================================================*/
26896	PUBLIC int do_set()
26897	{
26898	/* Set uid_t or gid_t field. */
26899	
26900	  register struct fproc *tfp;
26901	
26902	  /* Only MM may make this call directly. */
26903	  if (who != MM_PROC_NR) return(EGENERIC);
26904	
26905	  tfp = &fproc[slot1];
26906	  if (fs_call == SETUID) {
26907	        tfp->fp_realuid = (uid_t) real_user_id;
26908	        tfp->fp_effuid =  (uid_t) eff_user_id;
26909	  }
26910	  if (fs_call == SETGID) {
26911	        tfp->fp_effgid =  (gid_t) eff_grp_id;
26912	        tfp->fp_realgid = (gid_t) real_grp_id;
26913	  }
26914	  return(OK);
26915	}
	
	
26918	/*===========================================================================*
26919	 *                              do_revive                                    *
26920	 *===========================================================================*/
26921	PUBLIC int do_revive()
26922	{
26923	/* A task, typically TTY, has now gotten the characters that were needed for a
26924	 * previous read.  The process did not get a reply when it made the call.
26925	 * Instead it was suspended.  Now we can send the reply to wake it up.  This
26926	 * business has to be done carefully, since the incoming message is from
26927	 * a task (to which no reply can be sent), and the reply must go to a process
26928	 * that blocked earlier.  The reply to the caller is inhibited by setting the
26929	 * 'dont_reply' flag, and the reply to the blocked process is done explicitly
26930	 * in revive().
26931	 */
26932	
26933	#if !ALLOW_USER_SEND
26934	  if (who >= LOW_USER) return(EPERM);
26935	#endif
26936	
26937	  revive(m.REP_PROC_NR, m.REP_STATUS);
26938	  dont_reply = TRUE;            /* don't reply to the TTY task */
26939	  return(OK);
26940	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -