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

📄 open.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 2 页
字号:
/* This file contains the procedures for creating, opening, closing, and * seeking on files. * * The entry points into this file are *   do_creat:	perform the CREAT system call *   do_open:	perform the OPEN system call *   do_mknod:	perform the MKNOD system call *   do_mkdir:	perform the MKDIR system call *   do_close:	perform the CLOSE system call *   do_lseek:  perform the LSEEK system call */#include "fs.h"#include <sys/stat.h>#include <fcntl.h>#include <minix/callnr.h>#include <minix/com.h>#include "buf.h"#include "file.h"#include "fproc.h"#include "inode.h"#include "lock.h"#include "param.h"#include "super.h"#define offset m2_l1PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode)		);FORWARD _PROTOTYPE( int pipe_open, (struct inode *rip,mode_t bits,int oflags));FORWARD _PROTOTYPE( struct inode *new_node, (char *path, mode_t bits,							zone_t z0)	);/*===========================================================================* *				do_creat				     * *===========================================================================*/PUBLIC int do_creat(){/* Perform the creat(name, mode) system call. */  int r;  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);  return(r);}/*===========================================================================* *				do_open					     * *===========================================================================*/PUBLIC int do_open(){/* Perform the open(name, flags,...) system call. */  int create_mode = 0;		/* is really mode_t but this gives problems */  int r;  /* If O_CREAT is set, open has three parameters, otherwise two. */  if (m_in.mode & O_CREAT) {	create_mode = m_in.c_mode;		r = fetch_name(m_in.c_name, m_in.name1_length, M1);  } else {	r = fetch_name(m_in.name, m_in.name_length, M3);  }  if (r != OK) return(err_code); /* name was bad */  r = common_open(m_in.mode, create_mode);  return(r);}/*===========================================================================* *				common_open				     * *===========================================================================*/PRIVATE int common_open(register int oflags, mode_t omode){/* Common code from do_creat and do_open. */  register struct inode *rip;  int r, b, exist = TRUE;  dev_t dev;  mode_t bits;  off_t pos;  struct filp *fil_ptr, *filp2;  /* Remap the bottom two bits of oflags. */  bits = (mode_t) mode_map[oflags & O_ACCMODE];  /* See if file descriptor and filp slots are available. */  if ( (r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);  /* If O_CREATE is set, try to make the file. */   if (oflags & O_CREAT) {  	/* Create a new inode by calling new_node(). */        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);    	rip = new_node(user_path, omode, NO_ZONE);    	r = err_code;    	if (r == OK) exist = FALSE;      /* we just created the file */	else if (r != EEXIST) return(r); /* other error */	else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 					    flag is set this is an error */  } else {	 /* Scan path name. */    	if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);  }  /* Claim the file descriptor and filp slot and fill them in. */  fp->fp_filp[m_in.fd] = fil_ptr;  fil_ptr->filp_count = 1;  fil_ptr->filp_ino = rip;  fil_ptr->filp_flags = oflags;  /* Only do the normal open code if we didn't just create the file. */  if (exist) {  	/* Check protections. */  	if ((r = forbidden(rip, bits)) == OK) {  		/* Opening reg. files directories and special files differ. */	  	switch (rip->i_mode & I_TYPE) {    		   case I_REGULAR: 			/* Truncate regular file if O_TRUNC. */			if (oflags & O_TRUNC) {				if ((r = forbidden(rip, W_BIT)) !=OK) break;				truncate(rip);				wipe_inode(rip);				/* Send the inode from the inode cache to the				 * block cache, so it gets written on the next				 * cache flush.				 */				rw_inode(rip, WRITING);			}			break; 	    	   case I_DIRECTORY: 			/* Directories may be read but not written. */			r = (bits & W_BIT ? EISDIR : OK);			break;	     	   case I_CHAR_SPECIAL:     		   case I_BLOCK_SPECIAL:			/* Invoke the driver for special processing. */			dev = (dev_t) rip->i_zone[0];			r = dev_open(dev, who, bits | (oflags & ~O_ACCMODE));			break;		   case I_NAMED_PIPE:			oflags |= O_APPEND;	/* force append mode */			fil_ptr->filp_flags = oflags;			r = pipe_open(rip, bits, oflags);			if (r != ENXIO) {				/* See if someone else is doing a rd or wt on				 * the FIFO.  If so, use its filp entry so the				 * file position will be automatically shared.				 */				b = (bits & R_BIT ? R_BIT : W_BIT);				fil_ptr->filp_count = 0; /* don't find self */				if ((filp2 = find_filp(rip, b)) != NIL_FILP) {					/* Co-reader or writer found. Use it.*/					fp->fp_filp[m_in.fd] = filp2;					filp2->filp_count++;					filp2->filp_ino = rip;					filp2->filp_flags = oflags;					/* i_count was incremented incorrectly					 * by eatpath above, not knowing that					 * we were going to use an existing					 * filp entry.  Correct this error.					 */					rip->i_count--;				} else {					/* Nobody else found.  Restore filp. */					fil_ptr->filp_count = 1;					if (b == R_BIT)					     pos = rip->i_zone[V2_NR_DZONES+0];					else					     pos = rip->i_zone[V2_NR_DZONES+1];					fil_ptr->filp_pos = pos;				}			}			break; 		}  	}  }  /* If error, release inode. */  if (r != OK) {	if (r == SUSPEND) return(r);		/* Oops, just suspended */	fp->fp_filp[m_in.fd] = NIL_FILP;	fil_ptr->filp_count= 0;	put_inode(rip);	return(r);  }    return(m_in.fd);}/*===========================================================================* *				new_node				     * *===========================================================================*/PRIVATE struct inode *new_node(char *path, mode_t bits,	zone_t z0){/* New_node() is called by common_open(), do_mknod(), and do_mkdir().   * In all cases it allocates a new inode, makes a directory entry for it on  * the path 'path', and initializes it.  It returns a pointer to the inode if  * it can do this; otherwise it returns NIL_INODE.  It always sets 'err_code' * to an appropriate value (OK or an error code). */  register struct inode *rlast_dir_ptr, *rip;  register int r;  char string[NAME_MAX];  /* See if the path can be opened down to the last directory. */  if ((rlast_dir_ptr = last_dir(path, string)) == NIL_INODE) return(NIL_INODE);  /* The final directory is accessible. Get final component of the path. */  rip = advance(rlast_dir_ptr, string);  if ( rip == NIL_INODE && err_code == ENOENT) {	/* Last path component does not exist.  Make new directory entry. */	if ( (rip = alloc_inode(rlast_dir_ptr->i_dev, bits)) == NIL_INODE) {		/* Can't creat new inode: out of inodes. */		put_inode(rlast_dir_ptr);		return(NIL_INODE);	}	/* Force inode to the disk before making directory entry to make	 * the system more robust in the face of a crash: an inode with	 * no directory entry is much better than the opposite.	 */	rip->i_nlinks++;	rip->i_zone[0] = z0;		/* major/minor device numbers */	rw_inode(rip, WRITING);		/* force inode to disk now */	/* New inode acquired.  Try to make directory entry. */	if ((r = search_dir(rlast_dir_ptr, string, &rip->i_num,ENTER)) != OK) {		put_inode(rlast_dir_ptr);		rip->i_nlinks--;	/* pity, have to free disk inode */		rip->i_dirt = DIRTY;	/* dirty inodes are written out */		put_inode(rip);	/* this call frees the inode */

⌨️ 快捷键说明

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