int op_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { __u64 pos; errcode_t rc; unsigned int bytes; ext2_file_t efile = EXT2FS_FILE(fi->fh); ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); efile = do_open(e2fs, path, O_RDONLY); rc = ext2fs_file_llseek(efile, offset, SEEK_SET, &pos); if (rc) { do_release(efile); return -EINVAL; } rc = ext2fs_file_read(efile, buf, size, &bytes); if (rc) { do_release(efile); return -EIO; } do_release(efile); debugf("leave"); return bytes; }
int op_create (const char *path, mode_t mode, struct fuse_file_info *fi) { int rt; struct ext2_vnode * vnode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s, mode: 0%o", path, mode); fi->fh = (unsigned long) (vnode = do_open(e2fs, path, fi->flags)); if (vnode != NULL) { debugf("leave"); FUSE_EXT2_UNLOCK; return 0; } rt = do_create(e2fs, path, mode, 0, NULL); if (rt != 0) { FUSE_EXT2_UNLOCK; return rt; } fi->fh = (unsigned long) (vnode = do_open(e2fs, path, fi->flags)); if (vnode == NULL) { debugf("op_open(path, fi); failed"); FUSE_EXT2_UNLOCK; return -EIO; } debugf("leave"); FUSE_EXT2_UNLOCK; return 0; }
int op_create (const char *path, mode_t mode, struct fuse_file_info *fi) { int rt; ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s, mode: 0%o", path, mode); if (op_open(path, fi) == 0) { debugf("leave"); return 0; } rt = do_create(e2fs, path, mode, 0, NULL); if (rt != 0) { return rt; } if (op_open(path, fi)) { debugf("op_open(path, fi); failed"); return -EIO; } debugf("leave"); return 0; }
int op_mknod (const char *path, mode_t mode, dev_t dev) { int rt; ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s 0%o", path, mode); rt = do_create(e2fs, path, mode, dev, NULL); debugf("leave"); return rt; }
int op_access (const char *path, int mask) { ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s, mask = 0%o", path, mask); if ((mask & W_OK) && !(e2fs->flags & EXT2_FLAG_RW)) { return -1; } debugf("leave"); return 0; }
int op_statfs (const char *path, struct statvfs *buf) { unsigned long long i; unsigned long long s_gdb_count = 0; unsigned long long s_groups_count = 0; unsigned long long s_itb_per_group = 0; unsigned long long s_overhead_last = 0; unsigned long long s_inodes_per_block = 0; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); memset(buf, 0, sizeof(struct statvfs)); if (e2fs->super->s_default_mount_opts & EXT2_MOUNT_MINIX_DF) { s_overhead_last = 0; } else { s_overhead_last = e2fs->super->s_first_data_block; s_groups_count = ((EXT2_BLOCKS_COUNT(e2fs->super) - e2fs->super->s_first_data_block - 1) / e2fs->super->s_blocks_per_group) + 1; s_gdb_count = (s_groups_count + EXT2_DESC_PER_BLOCK(e2fs->super) - 1) / EXT2_DESC_PER_BLOCK(e2fs->super); for (i = 0; i < s_groups_count; i++) { s_overhead_last += ext2_bg_has_super(e2fs, i) + ((ext2_bg_num_gdb(e2fs, i) == 0) ? 0 : s_gdb_count); } s_inodes_per_block = EXT2_BLOCK_SIZE(e2fs->super) / EXT2_INODE_SIZE(e2fs->super); s_itb_per_group = e2fs->super->s_inodes_per_group / s_inodes_per_block; s_overhead_last += (s_groups_count * (2 + s_itb_per_group)); } buf->f_bsize = EXT2_BLOCK_SIZE(e2fs->super); buf->f_frsize = /*EXT2_FRAG_SIZE(e2fs->super);*/ buf->f_bsize; buf->f_blocks = EXT2_BLOCKS_COUNT(e2fs->super) - s_overhead_last; buf->f_bfree = EXT2_FBLOCKS_COUNT(e2fs->super); if (EXT2_FBLOCKS_COUNT(e2fs->super) < EXT2_RBLOCKS_COUNT(e2fs->super)) { buf->f_bavail = 0; } else { buf->f_bavail = EXT2_FBLOCKS_COUNT(e2fs->super) - EXT2_RBLOCKS_COUNT(e2fs->super); } buf->f_files = e2fs->super->s_inodes_count; buf->f_ffree = e2fs->super->s_free_inodes_count; buf->f_favail = e2fs->super->s_free_inodes_count; buf->f_namemax = EXT2_NAME_LEN; debugf("leave"); FUSE_EXT2_UNLOCK; return 0; }
int op_fsync (const char *path, int datasync, struct fuse_file_info *fi) { errcode_t rc; ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s (%p)", path, fi); rc = ext2fs_flush(e2fs); if (rc) { return -EIO; } debugf("leave"); return 0; }
int op_write (const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { size_t rt; ext2_file_t efile = EXT2FS_FILE(fi->fh); ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); efile = do_open(e2fs, path, O_WRONLY); rt = do_write(efile, buf, size, offset); do_release(efile); debugf("leave"); return rt; }
int op_chown (const char *path, uid_t uid, gid_t gid) { int rt; errcode_t rc; ext2_ino_t ino; struct ext2_vnode *vnode; struct ext2_inode *inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt = do_readvnode(e2fs, path, &ino, &vnode, DONT_OPEN_FILE); if (rt) { debugf("do_readvnode(%s, &ino, &vnode); failed", path); goto err; } inode = vnode2inode(vnode); if (uid != -1) inode->i_gid = gid; if (gid != -1) inode->i_uid = uid; rc=vnode_put(vnode,1); if (rc) { debugf("vnode_put(vnode,1); failed"); rt = -EIO; goto err; } rt = 0; err: debugf("leave"); FUSE_EXT2_UNLOCK; return rt; }
int op_chmod (const char *path, mode_t mode) { int rt; int mask; time_t tm; ext2_ino_t ino; struct ext2_inode inode; ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s 0%o", path, mode); rt = do_check(path); if (rt != 0) { debugf("do_check(%s); failed", path); return rt; } rt = do_readinode(e2fs, path, &ino, &inode); if (rt) { debugf("do_readinode(%s, &ino, &vnode); failed", path); return rt; } tm = e2fs->now ? e2fs->now : time(NULL); mask = S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX; inode.i_mode = (inode.i_mode & ~mask) | (mode & mask); inode.i_ctime = tm; rt = do_writeinode(e2fs, ino, &inode); if (rt) { debugf("do_writeinode(e2fs, ino, &inode); failed"); return -EIO; } debugf("leave"); return 0; }
int op_chown (const char *path, uid_t uid, gid_t gid) { int rt; ext2_ino_t ino; struct ext2_inode inode; ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt = do_check(path); if (rt != 0) { debugf("do_check(%s); failed", path); return rt; } rt = do_readinode(e2fs, path, &ino, &inode); if (rt) { debugf("do_readinode(%s, &ino, &vnode); failed", path); return rt; } if (uid != -1) { ext2_write_uid(&inode, uid); } if (gid != -1) { ext2_write_gid(&inode, gid); } rt = do_writeinode(e2fs, ino, &inode); if (rt) { debugf("do_writeinode(e2fs, ino, &inode); failed"); return -EIO; } debugf("leave"); return 0; }
int op_truncate(const char *path, off_t length) { int rt; ext2_file_t efile; ext2_filsys e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt = do_check(path); if (rt != 0) { debugf("do_check(%s); failed", path); return rt; } efile = do_open(e2fs, path, O_WRONLY); if (efile == NULL) { debugf("do_open(%s); failed", path); return -ENOENT; } rt = ext2fs_file_set_size(efile, length); if (rt) { do_release(efile); debugf("ext2fs_file_set_size(efile, %d); failed", length); return rt; } rt = do_release(efile); if (rt != 0) { debugf("do_release(efile); failed"); return rt; } debugf("leave"); return 0; }
int op_utimens (const char *path, const struct timespec tv[2]) { int rt; errcode_t rc; ext2_ino_t ino; struct ext2_vnode *vnode; struct ext2_inode *inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt = do_readvnode(e2fs, path, &ino, &vnode, DONT_OPEN_FILE); if (rt) { debugf("do_readvnode(%s, &ino, &vnode); failed", path); FUSE_EXT2_UNLOCK; return rt; } inode = vnode2inode(vnode); inode->i_atime = tv[0].tv_sec; inode->i_mtime = tv[0].tv_sec; rc=vnode_put(vnode,1); if (rc) { debugf("vnode_put(vnode,1); failed"); FUSE_EXT2_UNLOCK; return -EIO; } debugf("leave"); FUSE_EXT2_UNLOCK; return 0; }
int op_unlink (const char *path) { int rt; errcode_t rc; char *p_path; char *r_path; ext2_ino_t p_ino; struct ext2_inode p_inode; ext2_ino_t r_ino; struct ext2_vnode *r_vnode; struct ext2_inode *r_inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt=do_check_split(path, &p_path, &r_path); if (rt != 0) { debugf("do_check_split: failed"); goto err; } debugf("parent: %s, child: %s", p_path, r_path); rt = do_readinode(e2fs, p_path, &p_ino, &p_inode); if (rt) { debugf("do_readinode(%s, &p_ino, &p_inode); failed", p_path); goto err_free_split; } rt = do_readvnode(e2fs, path, &r_ino, &r_vnode, DONT_OPEN_FILE); if (rt) { debugf("do_readvnode(%s, &r_ino, &r_vnode); failed", path); goto err_free_split; } r_inode = vnode2inode(r_vnode); if(LINUX_S_ISDIR(r_inode->i_mode)) { debugf("%s is a directory", path); vnode_put(r_vnode,0); rt = -EISDIR; goto err_free_split; } rc = ext2fs_unlink(e2fs, p_ino, r_path, r_ino, 0); if (rc) { debugf("ext2fs_unlink(e2fs, %d, %s, %d, 0); failed", p_ino, r_path, r_ino); vnode_put(r_vnode,0); rt = -EIO; goto err_free_split; } if (r_inode->i_links_count > 0) { r_inode->i_links_count -= 1; } p_inode.i_ctime = p_inode.i_mtime = e2fs->now ? e2fs->now : time(NULL); rc = ext2fs_write_inode(e2fs, p_ino, &p_inode); if (rc) { debugf("ext2fs_write_inode(e2fs, p_ino, &p_inode); failed"); vnode_put(r_vnode,1); rt = -EIO; goto err_free_split; } r_inode->i_ctime = e2fs->now ? e2fs->now : time(NULL); rc = vnode_put(r_vnode,1); if (rc) { debugf("vnode_put(r_vnode,1); failed"); rt = -EIO; goto err_free_split; } free_split(p_path, r_path); debugf("leave"); FUSE_EXT2_UNLOCK; return 0; err_free_split: free_split(p_path, r_path); err: FUSE_EXT2_UNLOCK; return rt; }
int op_link (const char *source, const char *dest) { int rc; char *p_path; char *r_path; ext2_ino_t ino; ext2_ino_t d_ino; struct ext2_vnode *vnode; struct ext2_inode *inode; struct ext2_inode d_inode; ext2_filsys e2fs = current_ext2fs(); debugf("source: %s, dest: %s", source, dest); rc = do_check(source); if (rc != 0) { debugf("do_check(%s); failed", source); return rc; } rc = do_check_split(dest, &p_path, &r_path); if (rc != 0) { debugf("do_check(%s); failed", dest); return rc; } debugf("parent: %s, child: %s", p_path, r_path); rc = do_readinode(e2fs, p_path, &d_ino, &d_inode); if (rc) { debugf("do_readinode(%s, &ino, &inode); failed", p_path); free_split(p_path, r_path); return rc; } rc = do_readvnode(e2fs, source, &ino, &vnode); if (rc) { debugf("do_readvnode(%s, &ino, &vnode); failed", source); free_split(p_path, r_path); return rc; } inode = vnode2inode(vnode); do { debugf("calling ext2fs_link(e2fs, %d, %s, %d, %d);", d_ino, r_path, ino, do_modetoext2lag(inode->i_mode)); rc = ext2fs_link(e2fs, d_ino, r_path, ino, do_modetoext2lag(inode->i_mode)); if (rc == EXT2_ET_DIR_NO_SPACE) { debugf("calling ext2fs_expand_dir(e2fs, &d)", d_ino); if (ext2fs_expand_dir(e2fs, d_ino)) { debugf("error while expanding directory %s (%d)", p_path, d_ino); vnode_put(vnode, 0); free_split(p_path, r_path); return -ENOSPC; } } } while (rc == EXT2_ET_DIR_NO_SPACE); if (rc) { debugf("ext2fs_link(e2fs, %d, %s, %d, %d); failed", d_ino, r_path, ino, do_modetoext2lag(inode->i_mode)); vnode_put(vnode, 0); free_split(p_path, r_path); return -EIO; } d_inode.i_mtime = d_inode.i_ctime = inode->i_ctime = e2fs->now ? e2fs->now : time(NULL); inode->i_links_count += 1; rc=vnode_put(vnode,1); if (rc) { debugf("vnode_put(vnode,1); failed"); free_split(p_path, r_path); return -EIO; } rc = ext2fs_write_inode(e2fs, d_ino, &d_inode); if (rc) { debugf("ext2fs_write_inode(e2fs, d_ino, &d_inode); failed"); free_split(p_path, r_path); return -EIO; } debugf("done"); return 0; }
int op_readlink (const char *path, char *buf, size_t size) { int rt; size_t s; errcode_t rc; ext2_ino_t ino; char *b = NULL; char *pathname; struct ext2_inode inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt = do_readinode(e2fs, path, &ino, &inode); if (rt) { debugf("do_readinode(%s, &ino, &inode); failed", path); goto err; } if (!LINUX_S_ISLNK(inode.i_mode)) { debugf("%s is not a link", path); rt = -EINVAL; goto err; } if (ext2fs_inode_data_blocks(e2fs, &inode)) { rc = ext2fs_get_mem(EXT2_BLOCK_SIZE(e2fs->super), &b); if (rc) { debugf("ext2fs_get_mem(EXT2_BLOCK_SIZE(e2fs->super), &b); failed"); rt = -ENOMEM; goto err; } rc = io_channel_read_blk(e2fs->io, inode.i_block[0], 1, b); if (rc) { ext2fs_free_mem(&b); debugf("io_channel_read_blk(e2fs->io, inode.i_block[0], 1, b); failed"); rt = -EIO; goto err; } pathname = b; } else { pathname = (char *) &(inode.i_block[0]); } debugf("pathname: %s", pathname); s = (size < strlen(pathname) + 1) ? size : strlen(pathname) + 1; snprintf(buf, s, "%s", pathname); if (b) { ext2fs_free_mem(&b); } debugf("leave"); FUSE_EXT2_UNLOCK; return 0; err: FUSE_EXT2_UNLOCK; return rt; }