/* * See the comment in vnode.h for what is expected of this function. * * You'll probably want to use s5_seek_to_block and the device's * read_block function. */ static int s5fs_fillpage(vnode_t *vnode, off_t offset, void *pagebuf) { int blocknum = s5_seek_to_block(vnode, offset, 0); switch (blocknum){ case -EFBIG: case -ENOSPC: return blocknum; default: /* do nothing */; } KASSERT(blocknum >= 0 && "forgot to handle an error case"); if (blocknum == 0){ bytedev_t *bd = bytedev_lookup(MEM_ZERO_DEVID); return bd->cd_ops->read(bd, 0, pagebuf, S5_BLOCK_SIZE); } else { blockdev_t *bd = ((s5fs_t *) vnode->vn_fs->fs_i)->s5f_bdev; return bd->bd_ops->read_block(bd, (char *) pagebuf, blocknum, 1/*S5_BLOCK_SIZE*/); } }
int do_open(const char *filename, int oflags) { /*NOT_YET_IMPLEMENTED("VFS: do_open");*/ if (oflags!=O_RDONLY && oflags!=O_WRONLY && oflags!=O_RDWR && oflags!=O_APPEND && oflags!= (O_RDONLY | O_CREAT) && oflags != (O_RDWR | O_CREAT) && oflags != (O_RDWR | O_APPEND)) { return -EINVAL; } int fd = get_empty_fd(curproc); if( fd == -EMFILE){ return -EMFILE; } file_t *f = fget(-1); if( f == NULL){ return -ENOMEM; } curproc->p_files[fd] = f; /*Set file_t->f_mode to OR of FMODE_(READ|WRITE|APPEND) based on * oflags, which can be O_RDONLY, O_WRONLY or O_RDWR, possibly OR'd with * O_APPEND. */ /*FIXME check the logic below*/ if(oflags == O_RDONLY){ f->f_mode = FMODE_READ; }else if(oflags == O_WRONLY){ f->f_mode = FMODE_WRITE; }else if(oflags == O_RDWR){ f->f_mode = FMODE_READ | FMODE_WRITE; }else if(oflags == O_APPEND){ f->f_mode = FMODE_WRITE | FMODE_APPEND; }else if(oflags == (O_RDONLY | O_CREAT)){ f->f_mode = FMODE_READ; }else if(oflags == (O_RDWR | O_CREAT) ){ f->f_mode = FMODE_READ | FMODE_WRITE; }else if(oflags == (O_RDWR | O_APPEND) ){ f->f_mode = FMODE_READ | FMODE_WRITE | FMODE_APPEND; } vnode_t *pVnode; int s = open_namev(filename, oflags, &pVnode, NULL); if(s != 0){ curproc->p_files[fd] = NULL; fput(f); return s; } if(S_ISDIR(pVnode->vn_mode) && ((oflags & O_WRONLY) || (oflags & O_RDWR)) ){ curproc->p_files[fd] = NULL; vput(pVnode); fput(f); return -EISDIR; } if(S_ISBLK(pVnode->vn_mode)){ if(!(pVnode->vn_bdev = blockdev_lookup(pVnode->vn_devid))){ curproc->p_files[fd] = NULL; fput(f); vput(pVnode); return -ENXIO; } } if(S_ISCHR(pVnode->vn_mode)){ if(!(pVnode->vn_cdev = bytedev_lookup(pVnode->vn_devid))){ curproc->p_files[fd] = NULL; fput(f); vput(pVnode); return -ENXIO; } } f->f_pos=0; f->f_vnode = pVnode; return fd; }
/* * s5fs_read_vnode: * s5fs_read_vnode will be passed a vnode_t*, which will have its vn_fs * and vn_vno fields initialized. * param *vnode: the pointer to the vnode object */ static void s5fs_read_vnode(vnode_t *vnode) { dbg(DBG_S5FS, "{\n"); KASSERT(vnode != NULL); KASSERT(vnode->vn_fs != NULL); kmutex_lock(&vnode->vn_mutex); pframe_t* page = NULL; int ret = pframe_get(S5FS_TO_VMOBJ(FS_TO_S5FS(vnode->vn_fs)), S5_INODE_BLOCK(vnode->vn_vno), &page); KASSERT(ret == 0); KASSERT(page != NULL); pframe_pin(page); s5_inode_t* inode = ((s5_inode_t*)page->pf_addr) + S5_INODE_OFFSET(vnode->vn_vno); inode->s5_linkcount++; s5_dirty_inode(VNODE_TO_S5FS(vnode), inode); vnode->vn_i = inode; vnode->vn_len = inode->s5_size; switch(inode->s5_type) { case S5_TYPE_DIR: { vnode->vn_mode = S_IFDIR; vnode->vn_ops = &s5fs_dir_vops; break; } case S5_TYPE_DATA: { vnode->vn_mode = S_IFREG; vnode->vn_ops = &s5fs_file_vops; break; } case S5_TYPE_CHR: { vnode->vn_mode = S_IFCHR; vnode->vn_ops = NULL; vnode->vn_devid = (devid_t)(inode->s5_indirect_block); vnode->vn_cdev = bytedev_lookup(vnode->vn_devid); break; } case S5_TYPE_BLK: { vnode->vn_mode = S_IFBLK; vnode->vn_ops = NULL; vnode->vn_devid = (devid_t)(inode->s5_indirect_block); vnode->vn_bdev = blockdev_lookup(vnode->vn_devid); break; } default: { panic("inode %d has unknown/invalid type %d!!\n", (int)vnode->vn_vno, (int)inode->s5_type); } } kmutex_unlock(&vnode->vn_mutex); dbg(DBG_S5FS, "}\n"); }