void fs_fd(struct FileDescriptor* to, struct fs_Inode* inode, int flags) { inode->refCount++; to->inode = inode; to->offset = 0; to->flags = flags; to->ops = &opsTable[INODE_TYPE(inode->data)]; if (to->ops->open) { to->ops->open(to); } }
int fs_unlink(struct fs_Inode* path, const char* name) { struct fs_DirectoryEntry entry = fs_findentry(path, name); if (!entry.inode) { return ENOENT; } struct fs_Inode* inode = fs_inode_open(entry.inode); if (inode == NULL) { return EIO; } if (INODE_TYPE(inode->data) == INODE_DIR) { fs_inode_close(inode); return EISDIR; } int res = remove_link(path, name, inode); fs_inode_close(inode); return res; }
int fs_rmdir(struct fs_Inode* path, const char* name) { struct fs_DirectoryEntry entry = fs_findentry(path, name); if (!entry.inode) { return ENOENT; } struct fs_Inode* dir = fs_inode_open(entry.inode); if (dir == NULL) { return EIO; } if (INODE_TYPE(dir->data) != INODE_DIR) { fs_inode_close(dir); return ENOTDIR; } size_t offset = 0; struct DirectoryEntry child = ext2_dir_read(dir, offset); while (child.entryLength != 0) { if (child.inode != path->number && child.inode != entry.inode) { fs_inode_close(dir); return ENOTEMPTY; } offset += child.entryLength; child = ext2_dir_read(dir, offset); } int res = remove_link(path, name, dir); if (dir->data->hardLinks == 1) { remove_link(dir, ".", dir); remove_link(dir, "..", path); } fs_inode_close(dir); return res; }
/* * ext3301 write: wrapper for the standard file write function. * modifications: handling encryption and immediate files. * original: do_sync_write */ ssize_t ext3301_write(struct file * filp, char __user * buf, size_t len, loff_t * ppos) { ssize_t ret, written; struct inode * i = FILP_INODE(filp); dbg_im(KERN_DEBUG "Write: '%s'\n", FILP_NAME(filp)); //Encryption: Check if the file is in the encryption tree if (ext3301_isencrypted(filp->f_path.dentry)) { //Encrypt the data being written dbg_cr(KERN_DEBUG "- Encrypting data (%d bytes)\n", (int)len); if (ext3301_cryptbuf(buf, len) < 0) return -EIO; } //Immediate file only: walk ppos forward manually for Append mode if (I_ISIM(i) && (FILP_FLAGS(filp) & O_APPEND)) { dbg_im(KERN_DEBUG "O_APPEND: walking ppos to EoF\n"); *ppos += INODE_ISIZE(i); } //Immediate file only: Check if it needs to grow into a regular file if (I_ISIM(i) && (*ppos+len > EXT3301_IM_SIZE(i))) { dbg_im(KERN_DEBUG "- IM-->REG conversion\n"); ret = ext3301_im2reg(filp); if (ret < 0) { printk(KERN_DEBUG "IM-->REG conversion fail: ino %lu, err %d\n", INODE_INO(i), (int)ret); return ret; } //Append mode: undo the ppos offset. We are now writing to a //regular file, and the default methods already handle this. if (FILP_FLAGS(filp) & O_APPEND) { dbg_im(KERN_DEBUG "O_APPEND: walking ppos back (REG)\n"); *ppos -= INODE_ISIZE(i); } } //Write to file (immediate and regular files have different methods) if (I_ISIM(i)) { dbg_im(KERN_DEBUG "- Write-immediate\n"); written = ext3301_write_immediate(filp, buf, len, ppos); } else { dbg_im(KERN_DEBUG "- Write-regular\n"); written = do_sync_write(filp, buf, len, ppos); } //Regular file only: Check if it's small enough to convert to immediate if (INODE_TYPE(i)==DT_REG && (INODE_ISIZE(i)<=EXT3301_IM_SIZE(i))) { dbg_im(KERN_DEBUG "- REG-->IM conversion\n"); ret = ext3301_reg2im(filp); if (ret < 0) { printk(KERN_DEBUG "REG-->IM file conversion failed: ino %lu\n", INODE_INO(i)); return ret; } } return written; }