1f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o/*
2f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o * inode_io.c --- This is allows an inode in an ext2 filesystem image
3f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o * 	to be accessed via the I/O manager interface.
4f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o *
5f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o * Copyright (C) 2002 Theodore Ts'o.
6f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o *
7f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o * %Begin-Header%
8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
9543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
10f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o * %End-Header%
11f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o */
12f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
13f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <stdio.h>
14f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <string.h>
15f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#if HAVE_UNISTD_H
16f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <unistd.h>
17f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#endif
18f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#if HAVE_ERRNO_H
19f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <errno.h>
20f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#endif
21f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <time.h>
22f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
23f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include "ext2_fs.h"
24f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include "ext2fs.h"
25f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
26f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o/*
27f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o * For checking structure magic numbers...
28f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o */
29f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
30f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#define EXT2_CHECK_MAGIC(struct, code) \
31f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	  if ((struct)->magic != (code)) return (code)
32f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
33f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostruct inode_private_data {
34f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	int				magic;
35f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	char				name[32];
36f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	ext2_file_t			file;
37f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	ext2_filsys			fs;
38f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	ext2_ino_t 			ino;
39a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	struct ext2_inode		inode;
40f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	int				flags;
41f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data	*next;
42f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o};
43f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
44a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o#define CHANNEL_HAS_INODE	0x8000
45a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o
46f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic struct inode_private_data *top_intern;
47f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic int ino_unique = 0;
48f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
49f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_open(const char *name, int flags, io_channel *channel);
50f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_close(io_channel channel);
51f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_set_blksize(io_channel channel, int blksize);
52f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_read_blk(io_channel channel, unsigned long block,
53f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o			       int count, void *data);
54f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_write_blk(io_channel channel, unsigned long block,
55f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o				int count, const void *data);
56f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_flush(io_channel channel);
57f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_write_byte(io_channel channel, unsigned long offset,
58f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o				int size, const void *data);
59efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t inode_read_blk64(io_channel channel,
6051b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				unsigned long long block, int count, void *data);
61efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t inode_write_blk64(io_channel channel,
6251b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				unsigned long long block, int count, const void *data);
63efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
64f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic struct struct_io_manager struct_inode_manager = {
65f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_ET_MAGIC_IO_MANAGER,
66f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	"Inode I/O Manager",
67f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	inode_open,
68f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	inode_close,
69f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	inode_set_blksize,
70f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	inode_read_blk,
71f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	inode_write_blk,
72f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	inode_flush,
7351b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	inode_write_byte,
7451b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	NULL,
7551b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	NULL,
7651b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	inode_read_blk64,
7751b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	inode_write_blk64
78f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o};
79f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
80f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'oio_manager inode_io_manager = &struct_inode_manager;
81f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
82a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'oerrcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
83a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				  struct ext2_inode *inode,
84a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				  char **name)
85f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
86f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data 	*data;
87f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t			retval;
88f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
89f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
90c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o				     &data)))
91f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return retval;
92f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
93546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o	sprintf(data->name, "%u:%d", ino, ino_unique++);
94f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->file = 0;
95f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->fs = fs;
96f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->ino = ino;
97f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->flags = 0;
98a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	if (inode) {
99a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o		memcpy(&data->inode, inode, sizeof(struct ext2_inode));
100a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o		data->flags |= CHANNEL_HAS_INODE;
101a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	}
102f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->next = top_intern;
103f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	top_intern = data;
104f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	*name = data->name;
105f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return 0;
106f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
107f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
108a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'oerrcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
109a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				 char **name)
110a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o{
111a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	return ext2fs_inode_io_intern2(fs, ino, NULL, name);
112a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o}
113a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o
114f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
115f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_open(const char *name, int flags, io_channel *channel)
116f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
117f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io_channel	io = NULL;
118f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *prev, *data = NULL;
119f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t	retval;
120f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	int		open_flags;
121f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
122f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (name == 0)
123f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return EXT2_ET_BAD_DEVICE_NAME;
124f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
125f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	for (data = top_intern, prev = NULL; data;
126f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	     prev = data, data = data->next)
127f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		if (strcmp(name, data->name) == 0)
128f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o			break;
129f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (!data)
130f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return ENOENT;
131f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (prev)
132f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		prev->next = data->next;
133f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	else
134f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		top_intern = data->next;
135f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
136c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
137f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (retval)
138f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		goto cleanup;
139f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	memset(io, 0, sizeof(struct struct_io_channel));
140f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
141f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
142f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->manager = inode_io_manager;
143c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	retval = ext2fs_get_mem(strlen(name)+1, &io->name);
144f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (retval)
145f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		goto cleanup;
146f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
147f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	strcpy(io->name, name);
148f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->private_data = data;
149f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->block_size = 1024;
150f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->read_error = 0;
151f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->write_error = 0;
152f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->refcount = 1;
153f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
154f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
155a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	retval = ext2fs_file_open2(data->fs, data->ino,
156a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				   (data->flags & CHANNEL_HAS_INODE) ?
157a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				   &data->inode : 0, open_flags,
158a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				   &data->file);
159f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (retval)
160f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		goto cleanup;
161efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
162f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	*channel = io;
163f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return 0;
164f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
165f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ocleanup:
166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (io && io->name)
167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_free_mem(&io->name);
168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (data)
169c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&data);
170f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (io)
171c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&io);
172f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return retval;
173f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
174f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
175f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_close(io_channel channel)
176f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
177f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
178f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t	retval = 0;
179f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
180f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
181f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
182f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
183f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
184f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (--channel->refcount > 0)
185f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return 0;
186f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
187f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	retval = ext2fs_file_close(data->file);
188efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
189c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&channel->private_data);
190f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (channel->name)
191c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&channel->name);
192c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&channel);
193f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return retval;
194f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
195f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
196f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_set_blksize(io_channel channel, int blksize)
197f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
198f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
199f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
200f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
201f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
202f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
203f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
204f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	channel->block_size = blksize;
205f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return 0;
206f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
207f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
208f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
20951b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santosstatic errcode_t inode_read_blk64(io_channel channel,
21051b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				unsigned long long block, int count, void *buf)
211f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
212f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
213f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t	retval;
214f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
215f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
216f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
217f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
218f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
219f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if ((retval = ext2fs_file_lseek(data->file,
220f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					block * channel->block_size,
221f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					EXT2_SEEK_SET, 0)))
222f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return retval;
223f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
224f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	count = (count < 0) ? -count : (count * channel->block_size);
225f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
226f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return ext2fs_file_read(data->file, buf, count, 0);
227f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
228f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
22951b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santosstatic errcode_t inode_read_blk(io_channel channel, unsigned long block,
23051b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos			       int count, void *buf)
23151b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos{
23251b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	return inode_read_blk64(channel, block, count, buf);
23351b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos}
23451b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos
23551b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santosstatic errcode_t inode_write_blk64(io_channel channel,
23651b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				unsigned long long block, int count, const void *buf)
237f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
238f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
239546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o	errcode_t	retval;
240f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
241f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
242f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
243f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
244f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
245f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if ((retval = ext2fs_file_lseek(data->file,
246f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					block * channel->block_size,
247f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					EXT2_SEEK_SET, 0)))
248f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return retval;
249f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
250f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	count = (count < 0) ? -count : (count * channel->block_size);
251f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
252f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return ext2fs_file_write(data->file, buf, count, 0);
253f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
254f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
255efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t inode_write_blk(io_channel channel, unsigned long block,
25651b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				int count, const void *buf)
25751b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos{
25851b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	return inode_write_blk64(channel, block, count, buf);
25951b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos}
26051b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos
261f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_write_byte(io_channel channel, unsigned long offset,
262f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o				 int size, const void *buf)
263f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
264f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
265f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t	retval = 0;
266f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
267f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
268f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
269f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
270f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
271f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if ((retval = ext2fs_file_lseek(data->file, offset,
272f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					EXT2_SEEK_SET, 0)))
273f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return retval;
274f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
275f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return ext2fs_file_write(data->file, buf, size, 0);
276f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
277f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
278f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o/*
279efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Flush data buffers to disk.
280f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o */
281f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_flush(io_channel channel)
282f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
283f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
284efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
285f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
286f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
287f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
288f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
289f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return ext2fs_file_flush(data->file);
290f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
291f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
292