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 Public
27 * For checking structure magic numbers...
30 #define EXT2_CHECK_MAGIC(struct, code) \
31 if ((struct)->magic != (code)) return (code)
33 struct inode_private_data
{
39 struct ext2_inode inode
;
41 struct inode_private_data
*next
;
44 #define CHANNEL_HAS_INODE 0x8000
46 static struct inode_private_data
*top_intern
;
47 static int ino_unique
= 0;
49 static errcode_t
inode_open(const char *name
, int flags
, io_channel
*channel
);
50 static errcode_t
inode_close(io_channel channel
);
51 static errcode_t
inode_set_blksize(io_channel channel
, int blksize
);
52 static errcode_t
inode_read_blk(io_channel channel
, unsigned long block
,
53 int count
, void *data
);
54 static errcode_t
inode_write_blk(io_channel channel
, unsigned long block
,
55 int count
, const void *data
);
56 static errcode_t
inode_flush(io_channel channel
);
57 static errcode_t
inode_write_byte(io_channel channel
, unsigned long offset
,
58 int size
, const void *data
);
59 static errcode_t
inode_read_blk64(io_channel channel
,
60 unsigned long long block
, int count
, void *data
);
61 static errcode_t
inode_write_blk64(io_channel channel
,
62 unsigned long long block
, int count
, const void *data
);
64 static struct struct_io_manager struct_inode_manager
= {
65 EXT2_ET_MAGIC_IO_MANAGER
,
80 io_manager inode_io_manager
= &struct_inode_manager
;
82 errcode_t
ext2fs_inode_io_intern2(ext2_filsys fs
, ext2_ino_t ino
,
83 struct ext2_inode
*inode
,
86 struct inode_private_data
*data
;
89 if ((retval
= ext2fs_get_mem(sizeof(struct inode_private_data
),
92 data
->magic
= EXT2_ET_MAGIC_INODE_IO_CHANNEL
;
93 sprintf(data
->name
, "%u:%d", ino
, ino_unique
++);
99 memcpy(&data
->inode
, inode
, sizeof(struct ext2_inode
));
100 data
->flags
|= CHANNEL_HAS_INODE
;
102 data
->next
= top_intern
;
108 errcode_t
ext2fs_inode_io_intern(ext2_filsys fs
, ext2_ino_t ino
,
111 return ext2fs_inode_io_intern2(fs
, ino
, NULL
, name
);
115 static errcode_t
inode_open(const char *name
, int flags
, io_channel
*channel
)
117 io_channel io
= NULL
;
118 struct inode_private_data
*prev
, *data
= NULL
;
123 return EXT2_ET_BAD_DEVICE_NAME
;
125 for (data
= top_intern
, prev
= NULL
; data
;
126 prev
= data
, data
= data
->next
)
127 if (strcmp(name
, data
->name
) == 0)
132 prev
->next
= data
->next
;
134 top_intern
= data
->next
;
136 retval
= ext2fs_get_mem(sizeof(struct struct_io_channel
), &io
);
139 memset(io
, 0, sizeof(struct struct_io_channel
));
141 io
->magic
= EXT2_ET_MAGIC_IO_CHANNEL
;
142 io
->manager
= inode_io_manager
;
143 retval
= ext2fs_get_mem(strlen(name
)+1, &io
->name
);
147 strcpy(io
->name
, name
);
148 io
->private_data
= data
;
149 io
->block_size
= 1024;
154 open_flags
= (flags
& IO_FLAG_RW
) ? EXT2_FILE_WRITE
: 0;
155 retval
= ext2fs_file_open2(data
->fs
, data
->ino
,
156 (data
->flags
& CHANNEL_HAS_INODE
) ?
157 &data
->inode
: 0, open_flags
,
167 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_lseek(data
->file
,
219 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_lseek(data
->file
,
245 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
);