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

📄 open.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 2 页
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/fs/open.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

22900	/* This file contains the procedures for creating, opening, closing, and
22901	 * seeking on files.
22902	 *
22903	 * The entry points into this file are
22904	 *   do_creat:  perform the CREAT system call
22905	 *   do_open:   perform the OPEN system call
22906	 *   do_mknod:  perform the MKNOD system call
22907	 *   do_mkdir:  perform the MKDIR system call
22908	 *   do_close:  perform the CLOSE system call
22909	 *   do_lseek:  perform the LSEEK system call
22910	 */
22911	
22912	#include "fs.h"
22913	#include <sys/stat.h>
22914	#include <fcntl.h>
22915	#include <minix/callnr.h>
22916	#include <minix/com.h>
22917	#include "buf.h"
22918	#include "dev.h"
22919	#include "file.h"
22920	#include "fproc.h"
22921	#include "inode.h"
22922	#include "lock.h"
22923	#include "param.h"
22924	
22925	PRIVATE message dev_mess;
22926	PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
22927	
22928	FORWARD _PROTOTYPE( int common_open, (int oflags, Mode_t omode)         );
22929	FORWARD _PROTOTYPE( int pipe_open, (struct inode *rip,Mode_t bits,int oflags));
22930	FORWARD _PROTOTYPE( struct inode *new_node, (char *path, Mode_t bits,
22931	                                                        zone_t z0)      );
22932	
22933	
22934	/*===========================================================================*
22935	 *                              do_creat                                     *
22936	 *===========================================================================*/
22937	PUBLIC int do_creat()
22938	{
22939	/* Perform the creat(name, mode) system call. */
22940	  int r;
22941	
22942	  if (fetch_name(name, name_length, M3) != OK) return(err_code);
22943	  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) mode);
22944	  return(r);
22945	}
	
	
22948	/*===========================================================================*
22949	 *                              do_open                                      *
22950	 *===========================================================================*/
22951	PUBLIC int do_open()
22952	{
22953	/* Perform the open(name, flags,...) system call. */
22954	
22955	  int create_mode = 0;          /* is really mode_t but this gives problems */
22956	  int r;
22957	
22958	  /* If O_CREAT is set, open has three parameters, otherwise two. */
22959	  if (mode & O_CREAT) {
22960	        create_mode = c_mode;   
22961	        r = fetch_name(c_name, name1_length, M1);
22962	  } else {
22963	        r = fetch_name(name, name_length, M3);
22964	  }
22965	
22966	  if (r != OK) return(err_code); /* name was bad */
22967	  r = common_open(mode, create_mode);
22968	  return(r);
22969	}
	
	
22972	/*===========================================================================*
22973	 *                              common_open                                  *
22974	 *===========================================================================*/
22975	PRIVATE int common_open(oflags, omode)
22976	register int oflags;
22977	mode_t omode;
22978	{
22979	/* Common code from do_creat and do_open. */
22980	
22981	  register struct inode *rip;
22982	  int r, b, major, task, exist = TRUE;
22983	  dev_t dev;
22984	  mode_t bits;
22985	  off_t pos;
22986	  struct filp *fil_ptr, *filp2;
22987	
22988	  /* Remap the bottom two bits of oflags. */
22989	  bits = (mode_t) mode_map[oflags & O_ACCMODE];
22990	
22991	  /* See if file descriptor and filp slots are available. */
22992	  if ( (r = get_fd(0, bits, &fd, &fil_ptr)) != OK) return(r);
22993	
22994	  /* If O_CREATE is set, try to make the file. */ 
22995	  if (oflags & O_CREAT) {
22996	        /* Create a new inode by calling new_node(). */
22997	        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
22998	        rip = new_node(user_path, omode, NO_ZONE);
22999	        r = err_code;
23000	        if (r == OK) exist = FALSE;      /* we just created the file */
23001	        else if (r != EEXIST) return(r); /* other error */
23002	        else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
23003	                                            flag is set this is an error */
23004	  } else {
23005	         /* Scan path name. */
23006	        if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
23007	  }
23008	
23009	  /* Claim the file descriptor and filp slot and fill them in. */
23010	  fp->fp_filp[fd] = fil_ptr;
23011	  fil_ptr->filp_count = 1;
23012	  fil_ptr->filp_ino = rip;
23013	  fil_ptr->filp_flags = oflags;
23014	
23015	  /* Only do the normal open code if we didn't just create the file. */
23016	  if (exist) {
23017	        /* Check protections. */
23018	        if ((r = forbidden(rip, bits)) == OK) {
23019	                /* Opening reg. files directories and special files differ. */
23020	                switch (rip->i_mode & I_TYPE) {
23021	                   case I_REGULAR: 
23022	                        /* Truncate regular file if O_TRUNC. */
23023	                        if (oflags & O_TRUNC) {
23024	                                if ((r = forbidden(rip, W_BIT)) !=OK) break;
23025	                                truncate(rip);
23026	                                wipe_inode(rip);
23027	                                /* Send the inode from the inode cache to the
23028	                                 * block cache, so it gets written on the next
23029	                                 * cache flush.
23030	                                 */
23031	                                rw_inode(rip, WRITING);
23032	                        }
23033	                        break;
23034	 
23035	                   case I_DIRECTORY: 
23036	                        /* Directories may be read but not written. */
23037	                        r = (bits & W_BIT ? EISDIR : OK);
23038	                        break;
23039	
23040	                   case I_CHAR_SPECIAL:
23041	                   case I_BLOCK_SPECIAL:
23042	                        /* Invoke the driver for special processing. */
23043	                        dev_mess.m_type = DEV_OPEN;
23044	                        dev = (dev_t) rip->i_zone[0];
23045	                        dev_mess.DEVICE = dev;
23046	                        dev_mess.COUNT = bits | (oflags & ~O_ACCMODE);
23047	                        major = (dev >> MAJOR) & BYTE;  /* major device nr */
23048	                        if (major <= 0 || major >= max_major) {
23049	                                r = ENODEV;
23050	                                break;
23051	                        }
23052	                        task = dmap[major].dmap_task;   /* device task nr */
23053	                        (*dmap[major].dmap_open)(task, &dev_mess);
23054	                        r = dev_mess.REP_STATUS;
23055	                        break;
23056	
23057	                   case I_NAMED_PIPE:
23058	                        oflags |= O_APPEND;     /* force append mode */
23059	                        fil_ptr->filp_flags = oflags;
23060	                        r = pipe_open(rip, bits, oflags);
23061	                        if (r == OK) {
23062	                                /* See if someone else is doing a rd or wt on
23063	                                 * the FIFO.  If so, use its filp entry so the
23064	                                 * file position will be automatically shared.
23065	                                 */
23066	                                b = (bits & R_BIT ? R_BIT : W_BIT);
23067	                                fil_ptr->filp_count = 0; /* don't find self */
23068	                                if ((filp2 = find_filp(rip, b)) != NIL_FILP) {
23069	                                        /* Co-reader or writer found. Use it.*/
23070	                                        fp->fp_filp[fd] = filp2;
23071	                                        filp2->filp_count++;
23072	                                        filp2->filp_ino = rip;
23073	                                        filp2->filp_flags = oflags;
23074	
23075	                                        /* i_count was incremented incorrectly
23076	                                         * by eatpath above, not knowing that
23077	                                         * we were going to use an existing
23078	                                         * filp entry.  Correct this error.
23079	                                         */
23080	                                        rip->i_count--;
23081	                                } else {
23082	                                        /* Nobody else found.  Restore filp. */
23083	                                        fil_ptr->filp_count = 1;
23084	                                        if (b == R_BIT)
23085	                                             pos = rip->i_zone[V2_NR_DZONES+1];
23086	                                        else
23087	                                             pos = rip->i_zone[V2_NR_DZONES+2];
23088	                                        fil_ptr->filp_pos = pos;
23089	                                }
23090	                        }
23091	                        break;
23092	                }
23093	        }
23094	  }
23095	
23096	  /* If error, release inode. */
23097	  if (r != OK) {
23098	        fp->fp_filp[fd] = NIL_FILP;
23099	        fil_ptr->filp_count= 0;
23100	        put_inode(rip);
23101	        return(r);
23102	  }
23103	  
23104	  return(fd);
23105	}
	
	
23108	/*===========================================================================*
23109	 *                              new_node                                     *
23110	 *===========================================================================*/
23111	PRIVATE struct inode *new_node(path, bits, z0)
23112	char *path;                     /* pointer to path name */
23113	mode_t bits;                    /* mode of the new inode */
23114	zone_t z0;                      /* zone number 0 for new inode */
23115	{
23116	/* New_node() is called by common_open(), do_mknod(), and do_mkdir().  
23117	 * In all cases it allocates a new inode, makes a directory entry for it on 
23118	 * the path 'path', and initializes it.  It returns a pointer to the inode if 
23119	 * it can do this; otherwise it returns NIL_INODE.  It always sets 'err_code'
23120	 * to an appropriate value (OK or an error code).
23121	 */
23122	
23123	  register struct inode *rlast_dir_ptr, *rip;
23124	  register int r;
23125	  char string[NAME_MAX];
23126	
23127	  /* See if the path can be opened down to the last directory. */
23128	  if ((rlast_dir_ptr = last_dir(path, string)) == NIL_INODE) return(NIL_INODE);
23129	
23130	  /* The final directory is accessible. Get final component of the path. */
23131	  rip = advance(rlast_dir_ptr, string);
23132	  if ( rip == NIL_INODE && err_code == ENOENT) {
23133	        /* Last path component does not exist.  Make new directory entry. */
23134	        if ( (rip = alloc_inode(rlast_dir_ptr->i_dev, bits)) == NIL_INODE) {
23135	                /* Can't creat new inode: out of inodes. */
23136	                put_inode(rlast_dir_ptr);
23137	                return(NIL_INODE);
23138	        }
23139	
23140	        /* Force inode to the disk before making directory entry to make
23141	         * the system more robust in the face of a crash: an inode with
23142	         * no directory entry is much better than the opposite.
23143	         */
23144	        rip->i_nlinks++;
23145	        rip->i_zone[0] = z0;            /* major/minor device numbers */
23146	        rw_inode(rip, WRITING);         /* force inode to disk now */
23147	

⌨️ 快捷键说明

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