/* * release an inode. * decrease the reference count, write updates to disk if nessary. * also check the link count, if zero, trucate it. * */ void iput(struct inode *ip){ ushort dev; if(ip==NULL) panic("bad struct inode*"); ip->i_flag |= I_LOCK; if (ip->i_count > 0) { ip->i_count--; } if (ip->i_count==0){ if (ip->i_nlink==0) { itrunc(ip); ifree(ip->i_dev, ip->i_num); } // if it's a device file, the dev number is stored in zone[0]. dev = ip->i_zone[0]; switch (ip->i_mode & S_IFMT) { case S_IFBLK: (*bdevsw[MAJOR(dev)].d_close)(dev); break; case S_IFCHR: (*cdevsw[MAJOR(dev)].d_close)(dev); break; } iupdate(ip); ip->i_flag = 0; ip->i_num = 0; } unlk_ino(ip); }
/* * open a file. flag indicated opened type like O_RDONLY, O_TRUNC, O_CREAT and blah. And * mode only used in the O_CREAT scenary, indicated the file (inode) type. * * each proc has got one user file table(p_ofile[NOFILE]), it's each entry is also a number, * indicated the number in the system file table(file[NFILE]). when user opened a file, it * first allocate a user file table entry(aka. file descriptor), then attach it with a system * file table entry. It's reference count is increased in fork() or dup(). * */ int do_open(char *path, uint flag, uint mode){ struct inode *ip; struct file *fp; ushort dev; int fd; // on create a new file. if (flag & O_CREAT){ ip = namei(path, 1); // if file is not existing yet. if (ip->i_nlink==0) { ip->i_mode = mode; ip->i_uid = cu->p_euid; ip->i_gid = cu->p_egid; ip->i_mtime = time(); ip->i_nlink = 1; iupdate(ip); } } // an existing file. else { ip = namei(path, 0); if (ip == NULL){ syserr(ENFILE); return -1; } // TODO: check access // if it's a device file, the dev number is stored in zone[0]. dev = ip->i_zone[0]; switch(ip->i_mode & S_IFMT) { case S_IFBLK: (*bdevsw[MAJOR(dev)].d_open)(dev); break; case S_IFCHR: (*cdevsw[MAJOR(dev)].d_open)(dev); break; } } if (((fd=ufalloc())<0) || (fp=falloc(fd))==NULL) { iput(ip); return -1; } if (flag & O_TRUNC){ itrunc(ip); } unlk_ino(ip); fp->f_oflag = flag; fp->f_ino = ip; cu->p_fdflag[fd] = FD_CLOEXEC; return fd; }