예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
0
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;
}
예제 #6
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;
}
예제 #7
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;
}
예제 #8
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;
}
예제 #9
0
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;
}
예제 #10
0
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;
}
예제 #11
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;
}
예제 #12
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;
}
예제 #13
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;
}
예제 #14
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;
}
예제 #15
0
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;
}
예제 #16
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;
}