int vfs_open(char *path, uint32_t open_flags, struct inode **node_store) { bool can_write = 0; switch (open_flags & O_ACCMODE) { case O_RDONLY: break; case O_WRONLY: case O_RDWR: can_write = 1; break; default: return -E_INVAL; } if (open_flags & O_TRUNC) { if (!can_write) { return -E_INVAL; } } int ret; struct inode *dir, *node; if (open_flags & O_CREAT) { char *name; bool excl = (open_flags & O_EXCL) != 0; if ((ret = vfs_lookup_parent(path, &dir, &name)) != 0) { return ret; } ret = vop_create(dir, name, excl, &node); vop_ref_dec(dir); } else { ret = vfs_lookup(path, &node); } if (ret != 0) { return ret; } assert(node != NULL); if ((ret = vop_open(node, open_flags)) != 0) { vop_ref_dec(node); return ret; } vop_open_inc(node); if (open_flags & O_TRUNC) { if ((ret = vop_truncate(node, 0)) != 0) { vop_open_dec(node); vop_ref_dec(node); return ret; } } *node_store = node; return 0; }
/* * sfs_tryseek - Check if seeking to the specified position within the file is legal. */ static int sfs_tryseek(struct inode *node, off_t pos) { if (pos < 0 || pos >= SFS_MAX_FILE_SIZE) { return -E_INVAL; } struct sfs_inode *sin = vop_info(node, sfs_inode); if (pos > sin->din->size) { return vop_truncate(node, pos); } return 0; }
/* * sfs_reclaim - Free all resources inode occupied . Called when inode is no longer in use. */ static int sfs_reclaim(struct inode *node) { struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs); struct sfs_inode *sin = vop_info(node, sfs_inode); int ret = -E_BUSY; uint32_t ent; lock_sfs_fs(sfs); assert(sin->reclaim_count > 0); if ((-- sin->reclaim_count) != 0 || inode_ref_count(node) != 0) { goto failed_unlock; } if (sin->din->nlinks == 0) { if ((ret = vop_truncate(node, 0)) != 0) { goto failed_unlock; } } if (sin->dirty) { if ((ret = vop_fsync(node)) != 0) { goto failed_unlock; } } sfs_remove_links(sin); unlock_sfs_fs(sfs); if (sin->din->nlinks == 0) { sfs_block_free(sfs, sin->ino); if ((ent = sin->din->indirect) != 0) { sfs_block_free(sfs, ent); } } kfree(sin->din); vop_kill(node); return 0; failed_unlock: unlock_sfs_fs(sfs); return ret; }