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