2 * unix_io.c --- This is the Unix I/O interface to the I/O manager.
4 * Implements a one-block write-through cache.
6 * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
9 * This file may be redistributed under the terms of the GNU Public
26 #include <sys/types.h>
29 #include "et/com_err.h"
30 #include "ext2fs/ext2_err.h"
31 #include "ext2fs/ext2_io.h"
34 * For checking structure magic numbers...
37 #define EXT2_CHECK_MAGIC(struct, code) \
38 if ((struct)->magic != (code)) return (code)
40 struct unix_private_data {
48 static errcode_t unix_open(const char *name, int flags, io_channel *channel);
49 static errcode_t unix_close(io_channel channel);
50 static errcode_t unix_set_blksize(io_channel channel, int blksize);
51 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
52 int count, void *data);
53 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
54 int count, const void *data);
55 static errcode_t unix_flush(io_channel channel);
57 static struct struct_io_manager struct_unix_manager = {
58 EXT2_ET_MAGIC_IO_MANAGER,
68 io_manager unix_io_manager = &struct_unix_manager;
70 static errcode_t unix_open(const char *name, int flags, io_channel *channel)
73 struct unix_private_data *data = NULL;
77 return EXT2_ET_BAD_DEVICE_NAME;
78 io = (io_channel) malloc(sizeof(struct struct_io_channel));
80 return EXT2_NO_MEMORY;
81 memset(io, 0, sizeof(struct struct_io_channel));
82 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
83 data = (struct unix_private_data *)
84 malloc(sizeof(struct unix_private_data));
86 retval = EXT2_NO_MEMORY;
89 io->manager = unix_io_manager;
90 io->name = malloc(strlen(name)+1);
92 retval = EXT2_NO_MEMORY;
95 strcpy(io->name, name);
96 io->private_data = data;
97 io->block_size = 1024;
102 memset(data, 0, sizeof(struct unix_private_data));
103 data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
104 data->buf = malloc(io->block_size);
105 data->buf_block_nr = -1;
107 retval = EXT2_NO_MEMORY;
110 data->dev = open(name, (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY);
129 static errcode_t unix_close(io_channel channel)
131 struct unix_private_data *data;
132 errcode_t retval = 0;
134 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
135 data = (struct unix_private_data *) channel->private_data;
136 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
138 if (--channel->refcount > 0)
141 if (close(data->dev) < 0)
145 if (channel->private_data)
146 free(channel->private_data);
153 static errcode_t unix_set_blksize(io_channel channel, int blksize)
155 struct unix_private_data *data;
157 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
158 data = (struct unix_private_data *) channel->private_data;
159 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
161 if (channel->block_size != blksize) {
162 channel->block_size = blksize;
164 data->buf = malloc(blksize);
166 return EXT2_NO_MEMORY;
167 data->buf_block_nr = -1;
173 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
174 int count, void *buf)
176 struct unix_private_data *data;
179 ext2_loff_t location;
182 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
183 data = (struct unix_private_data *) channel->private_data;
184 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
187 * If it's in the cache, use it!
189 if ((count == 1) && (block == data->buf_block_nr)) {
190 memcpy(buf, data->buf, channel->block_size);
194 printf("read_block %lu (%d)\n", block, count);
196 size = (count < 0) ? -count : count * channel->block_size;
197 location = (ext2_loff_t) block * channel->block_size;
198 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
199 retval = errno ? errno : EXT2_IO_LLSEEK_FAILED;
202 actual = read(data->dev, buf, size);
203 if (actual != size) {
206 retval = EXT2_ET_SHORT_READ;
210 data->buf_block_nr = block;
211 memcpy(data->buf, buf, size); /* Update the cache */
216 memset((char *) buf+actual, 0, size-actual);
217 if (channel->read_error)
218 retval = (channel->read_error)(channel, block, count, buf,
219 size, actual, retval);
223 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
224 int count, const void *buf)
226 struct unix_private_data *data;
228 ext2_loff_t location;
232 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
233 data = (struct unix_private_data *) channel->private_data;
234 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
237 size = channel->block_size;
239 data->buf_block_nr = -1; /* Invalidate the cache */
243 size = count * channel->block_size;
246 location = (ext2_loff_t) block * channel->block_size;
247 if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
248 retval = errno ? errno : EXT2_IO_LLSEEK_FAILED;
252 actual = write(data->dev, buf, size);
253 if (actual != size) {
254 retval = EXT2_ET_SHORT_WRITE;
258 if ((count == 1) && (block == data->buf_block_nr))
259 memcpy(data->buf, buf, size); /* Update the cache */
264 if (channel->write_error)
265 retval = (channel->write_error)(channel, block, count, buf,
266 size, actual, retval);
271 * Flush data buffers to disk.
273 static errcode_t unix_flush(io_channel channel)
275 struct unix_private_data *data;
277 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
278 data = (struct unix_private_data *) channel->private_data;
279 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);