Example #1
0
/* 
 * 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);
}
Example #2
0
/*
 * 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;
}