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
13d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h"
14f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <stdio.h>
15f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <string.h>
16f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#if HAVE_UNISTD_H
17f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <unistd.h>
18f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#endif
19f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#if HAVE_ERRNO_H
20f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <errno.h>
21f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#endif
22f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include <time.h>
23f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
24f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include "ext2_fs.h"
25f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#include "ext2fs.h"
26f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
27f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o/*
28f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o * For checking structure magic numbers...
29f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o */
30f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
31f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o#define EXT2_CHECK_MAGIC(struct, code) \
32f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	  if ((struct)->magic != (code)) return (code)
33f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
34f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostruct inode_private_data {
35f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	int				magic;
36f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	char				name[32];
37f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	ext2_file_t			file;
38f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	ext2_filsys			fs;
39f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	ext2_ino_t 			ino;
40a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	struct ext2_inode		inode;
41f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	int				flags;
42f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data	*next;
43f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o};
44f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
45a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o#define CHANNEL_HAS_INODE	0x8000
46a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o
47f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic struct inode_private_data *top_intern;
48f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic int ino_unique = 0;
49f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
50f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_open(const char *name, int flags, io_channel *channel);
51f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_close(io_channel channel);
52f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_set_blksize(io_channel channel, int blksize);
53f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_read_blk(io_channel channel, unsigned long block,
54f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o			       int count, void *data);
55f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_write_blk(io_channel channel, unsigned long block,
56f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o				int count, const void *data);
57f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_flush(io_channel channel);
58f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_write_byte(io_channel channel, unsigned long offset,
59f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o				int size, const void *data);
60efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t inode_read_blk64(io_channel channel,
6151b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				unsigned long long block, int count, void *data);
62efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t inode_write_blk64(io_channel channel,
6351b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				unsigned long long block, int count, const void *data);
64efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
65f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic struct struct_io_manager struct_inode_manager = {
66d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.magic		= EXT2_ET_MAGIC_IO_MANAGER,
67d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.name		= "Inode I/O Manager",
68d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.open		= inode_open,
69d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.close		= inode_close,
70d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.set_blksize	= inode_set_blksize,
71d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.read_blk	= inode_read_blk,
72d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.write_blk	= inode_write_blk,
73d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.flush		= inode_flush,
74d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.write_byte	= inode_write_byte,
75d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.read_blk64	= inode_read_blk64,
76d4ecec45ab0d9d291bcac575988f68993ec98bd0Theodore Ts'o	.write_blk64	= inode_write_blk64
77f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o};
78f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
79f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'oio_manager inode_io_manager = &struct_inode_manager;
80f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
81a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'oerrcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
82a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				  struct ext2_inode *inode,
83a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				  char **name)
84f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
85f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data 	*data;
86f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t			retval;
87f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
88f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
89c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o				     &data)))
90f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return retval;
91f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
92546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o	sprintf(data->name, "%u:%d", ino, ino_unique++);
93f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->file = 0;
94f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->fs = fs;
95f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->ino = ino;
96f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->flags = 0;
97a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	if (inode) {
98a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o		memcpy(&data->inode, inode, sizeof(struct ext2_inode));
99a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o		data->flags |= CHANNEL_HAS_INODE;
100a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	}
101f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data->next = top_intern;
102f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	top_intern = data;
103f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	*name = data->name;
104f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return 0;
105f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
106f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
107a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'oerrcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
108a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				 char **name)
109a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o{
110a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	return ext2fs_inode_io_intern2(fs, ino, NULL, name);
111a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o}
112a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o
113f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
114f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_open(const char *name, int flags, io_channel *channel)
115f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
116f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io_channel	io = NULL;
117f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *prev, *data = NULL;
118f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t	retval;
119f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	int		open_flags;
120f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
121f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (name == 0)
122f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return EXT2_ET_BAD_DEVICE_NAME;
123f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
124f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	for (data = top_intern, prev = NULL; data;
125f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	     prev = data, data = data->next)
126f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		if (strcmp(name, data->name) == 0)
127f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o			break;
128f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (!data)
129f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return ENOENT;
130f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (prev)
131f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		prev->next = data->next;
132f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	else
133f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		top_intern = data->next;
134f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
135c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
136f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (retval)
137f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		goto cleanup;
138f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	memset(io, 0, sizeof(struct struct_io_channel));
139f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
140f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
141f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->manager = inode_io_manager;
142c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	retval = ext2fs_get_mem(strlen(name)+1, &io->name);
143f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (retval)
144f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		goto cleanup;
145f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
146f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	strcpy(io->name, name);
147f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->private_data = data;
148f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->block_size = 1024;
149f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->read_error = 0;
150f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->write_error = 0;
151f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	io->refcount = 1;
152f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
153f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
154a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o	retval = ext2fs_file_open2(data->fs, data->ino,
155a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				   (data->flags & CHANNEL_HAS_INODE) ?
156a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				   &data->inode : 0, open_flags,
157a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o				   &data->file);
158f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (retval)
159f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		goto cleanup;
160efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
161f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	*channel = io;
162f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return 0;
163f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
164f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ocleanup:
165624e8ebe3058bad9af6e719b7f9e7afab7d3fe30Eric Sandeen	if (io && io->name)
16658caabc37d696363330c390f77a901bbc81cda1eTheodore Ts'o		ext2fs_free_mem(&io->name);
16758caabc37d696363330c390f77a901bbc81cda1eTheodore Ts'o	if (data)
168c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&data);
169f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (io)
170c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&io);
171f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return retval;
172f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
173f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
174f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_close(io_channel channel)
175f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
176f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
177f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t	retval = 0;
178f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
179f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
180f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
181f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
182f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
183f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (--channel->refcount > 0)
184f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return 0;
185f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
186f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	retval = ext2fs_file_close(data->file);
187efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
188c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&channel->private_data);
189f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if (channel->name)
190c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&channel->name);
191c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&channel);
192f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return retval;
193f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
194f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
195f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_set_blksize(io_channel channel, int blksize)
196f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
197f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
198f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
199f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
200f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
201f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
202f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
203f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	channel->block_size = blksize;
204f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return 0;
205f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
206f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
207f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
20851b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santosstatic errcode_t inode_read_blk64(io_channel channel,
20951b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				unsigned long long block, int count, void *buf)
210f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
211f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
212f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t	retval;
213f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
214f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
215f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
216f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
217f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
218f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if ((retval = ext2fs_file_lseek(data->file,
219f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					block * channel->block_size,
220f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					EXT2_SEEK_SET, 0)))
221f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return retval;
222f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
223f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	count = (count < 0) ? -count : (count * channel->block_size);
224f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
225f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return ext2fs_file_read(data->file, buf, count, 0);
226f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
227f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
22851b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santosstatic errcode_t inode_read_blk(io_channel channel, unsigned long block,
22951b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos			       int count, void *buf)
23051b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos{
23151b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	return inode_read_blk64(channel, block, count, buf);
23251b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos}
23351b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos
23451b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santosstatic errcode_t inode_write_blk64(io_channel channel,
23551b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				unsigned long long block, int count, const void *buf)
236f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
237f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
238546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o	errcode_t	retval;
239f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
240f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
241f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
242f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
243f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
244f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if ((retval = ext2fs_file_lseek(data->file,
245f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					block * channel->block_size,
246f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					EXT2_SEEK_SET, 0)))
247f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return retval;
248f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
249f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	count = (count < 0) ? -count : (count * channel->block_size);
250f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
251f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return ext2fs_file_write(data->file, buf, count, 0);
252f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
253f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
254efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t inode_write_blk(io_channel channel, unsigned long block,
25551b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos				int count, const void *buf)
25651b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos{
25751b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos	return inode_write_blk64(channel, block, count, buf);
25851b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos}
25951b263e3690ba3136fe63e5c722e0593772620e2Jose R. Santos
260f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_write_byte(io_channel channel, unsigned long offset,
261f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o				 int size, const void *buf)
262f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
263f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
264f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	errcode_t	retval = 0;
265f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
266f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
267f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
268f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
269f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
270f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	if ((retval = ext2fs_file_lseek(data->file, offset,
271f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o					EXT2_SEEK_SET, 0)))
272f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o		return retval;
273f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
274f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return ext2fs_file_write(data->file, buf, size, 0);
275f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
276f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
277f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o/*
278efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Flush data buffers to disk.
279f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o */
280f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'ostatic errcode_t inode_flush(io_channel channel)
281f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o{
282f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	struct inode_private_data *data;
283efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
284f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
285f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	data = (struct inode_private_data *) channel->private_data;
286f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
287f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
288f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o	return ext2fs_file_flush(data->file);
289f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o}
290f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o
291