📄 open.c
字号:
/* 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 + -