2 * inode_io.c --- This is allows an inode in an ext2 filesystem image
3 * to be accessed via the I/O manager interface.
5 * Copyright (C) 2002 Theodore Ts'o.
8 * This file may be redistributed under the terms of the GNU Library
9 * General Public License, version 2.
28 * For checking structure magic numbers...
31 #define EXT2_CHECK_MAGIC(struct, code) \
32 if ((struct)->magic != (code)) return (code)
34 struct inode_private_data
{
40 struct ext2_inode inode
;
42 struct inode_private_data
*next
;
45 #define CHANNEL_HAS_INODE 0x8000
47 static struct inode_private_data
*top_intern
;
48 static int ino_unique
= 0;
50 static errcode_t
inode_open(const char *name
, int flags
, io_channel
*channel
);
51 static errcode_t
inode_close(io_channel channel
);
52 static errcode_t
inode_set_blksize(io_channel channel
, int blksize
);
53 static errcode_t
inode_read_blk(io_channel channel
, unsigned long block
,
54 int count
, void *data
);
55 static errcode_t
inode_write_blk(io_channel channel
, unsigned long block
,
56 int count
, const void *data
);
57 static errcode_t
inode_flush(io_channel channel
);
58 static errcode_t
inode_write_byte(io_channel channel
, unsigned long offset
,
59 int size
, const void *data
);
60 static errcode_t
inode_read_blk64(io_channel channel
,
61 unsigned long long block
, int count
, void *data
);
62 static errcode_t
inode_write_blk64(io_channel channel
,
63 unsigned long long block
, int count
, const void *data
);
65 static struct struct_io_manager struct_inode_manager
= {
66 .magic
= EXT2_ET_MAGIC_IO_MANAGER
,
67 .name
= "Inode I/O Manager",
70 .set_blksize
= inode_set_blksize
,
71 .read_blk
= inode_read_blk
,
72 .write_blk
= inode_write_blk
,
74 .write_byte
= inode_write_byte
,
75 .read_blk64
= inode_read_blk64
,
76 .write_blk64
= inode_write_blk64
79 io_manager inode_io_manager
= &struct_inode_manager
;
81 errcode_t
ext2fs_inode_io_intern2(ext2_filsys fs
, ext2_ino_t ino
,
82 struct ext2_inode
*inode
,
85 struct inode_private_data
*data
;
88 if ((retval
= ext2fs_get_mem(sizeof(struct inode_private_data
),
91 data
->magic
= EXT2_ET_MAGIC_INODE_IO_CHANNEL
;
92 sprintf(data
->name
, "%u:%d", ino
, ino_unique
++);
98 memcpy(&data
->inode
, inode
, sizeof(struct ext2_inode
));
99 data
->flags
|= CHANNEL_HAS_INODE
;
101 data
->next
= top_intern
;
107 errcode_t
ext2fs_inode_io_intern(ext2_filsys fs
, ext2_ino_t ino
,
110 return ext2fs_inode_io_intern2(fs
, ino
, NULL
, name
);
114 static errcode_t
inode_open(const char *name
, int flags
, io_channel
*channel
)
116 io_channel io
= NULL
;
117 struct inode_private_data
*prev
, *data
= NULL
;
122 return EXT2_ET_BAD_DEVICE_NAME
;
124 for (data
= top_intern
, prev
= NULL
; data
;
125 prev
= data
, data
= data
->next
)
126 if (strcmp(name
, data
->name
) == 0)
131 prev
->next
= data
->next
;
133 top_intern
= data
->next
;
135 retval
= ext2fs_get_mem(sizeof(struct struct_io_channel
), &io
);
138 memset(io
, 0, sizeof(struct struct_io_channel
));
140 io
->magic
= EXT2_ET_MAGIC_IO_CHANNEL
;
141 io
->manager
= inode_io_manager
;
142 retval
= ext2fs_get_mem(strlen(name
)+1, &io
->name
);
146 strcpy(io
->name
, name
);
147 io
->private_data
= data
;
148 io
->block_size
= 1024;
153 open_flags
= (flags
& IO_FLAG_RW
) ? EXT2_FILE_WRITE
: 0;
154 retval
= ext2fs_file_open2(data
->fs
, data
->ino
,
155 (data
->flags
& CHANNEL_HAS_INODE
) ?
156 &data
->inode
: 0, open_flags
,
166 ext2fs_free_mem(&io
->name
);
168 ext2fs_free_mem(&data
);
170 ext2fs_free_mem(&io
);
174 static errcode_t
inode_close(io_channel channel
)
176 struct inode_private_data
*data
;
177 errcode_t retval
= 0;
179 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
180 data
= (struct inode_private_data
*) channel
->private_data
;
181 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
183 if (--channel
->refcount
> 0)
186 retval
= ext2fs_file_close(data
->file
);
188 ext2fs_free_mem(&channel
->private_data
);
190 ext2fs_free_mem(&channel
->name
);
191 ext2fs_free_mem(&channel
);
195 static errcode_t
inode_set_blksize(io_channel channel
, int blksize
)
197 struct inode_private_data
*data
;
199 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
200 data
= (struct inode_private_data
*) channel
->private_data
;
201 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
203 channel
->block_size
= blksize
;
208 static errcode_t
inode_read_blk64(io_channel channel
,
209 unsigned long long block
, int count
, void *buf
)
211 struct inode_private_data
*data
;
214 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
215 data
= (struct inode_private_data
*) channel
->private_data
;
216 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
218 if ((retval
= ext2fs_file_llseek(data
->file
,
219 (ext2_off64_t
)(block
* channel
->block_size
),
223 count
= (count
< 0) ? -count
: (count
* channel
->block_size
);
225 return ext2fs_file_read(data
->file
, buf
, count
, 0);
228 static errcode_t
inode_read_blk(io_channel channel
, unsigned long block
,
229 int count
, void *buf
)
231 return inode_read_blk64(channel
, block
, count
, buf
);
234 static errcode_t
inode_write_blk64(io_channel channel
,
235 unsigned long long block
, int count
, const void *buf
)
237 struct inode_private_data
*data
;
240 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
241 data
= (struct inode_private_data
*) channel
->private_data
;
242 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
244 if ((retval
= ext2fs_file_llseek(data
->file
,
245 (ext2_off64_t
) (block
* channel
->block_size
),
249 count
= (count
< 0) ? -count
: (count
* channel
->block_size
);
251 return ext2fs_file_write(data
->file
, buf
, count
, 0);
254 static errcode_t
inode_write_blk(io_channel channel
, unsigned long block
,
255 int count
, const void *buf
)
257 return inode_write_blk64(channel
, block
, count
, buf
);
260 static errcode_t
inode_write_byte(io_channel channel
, unsigned long offset
,
261 int size
, const void *buf
)
263 struct inode_private_data
*data
;
264 errcode_t retval
= 0;
266 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
267 data
= (struct inode_private_data
*) channel
->private_data
;
268 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
270 if ((retval
= ext2fs_file_lseek(data
->file
, offset
,
274 return ext2fs_file_write(data
->file
, buf
, size
, 0);
278 * Flush data buffers to disk.
280 static errcode_t
inode_flush(io_channel channel
)
282 struct inode_private_data
*data
;
284 EXT2_CHECK_MAGIC(channel
, EXT2_ET_MAGIC_IO_CHANNEL
);
285 data
= (struct inode_private_data
*) channel
->private_data
;
286 EXT2_CHECK_MAGIC(data
, EXT2_ET_MAGIC_INODE_IO_CHANNEL
);
288 return ext2fs_file_flush(data
->file
);