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 Theodore Ts'o. This file may be redistributed
7 * under the terms of the GNU Public License.
17 #include <sys/types.h>
19 #include "et/com_err.h"
23 struct unix_private_data {
30 static errcode_t unix_open(const char *name, int flags, io_channel *channel);
31 static errcode_t unix_close(io_channel channel);
32 static errcode_t unix_set_blksize(io_channel channel, int blksize);
33 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
34 int count, void *data);
35 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
36 int count, const void *data);
37 static errcode_t unix_flush(io_channel channel);
39 struct struct_io_manager struct_unix_manager = {
49 io_manager unix_io_manager = &struct_unix_manager;
51 static errcode_t unix_open(const char *name, int flags, io_channel *channel)
54 struct unix_private_data *data = NULL;
57 io = (io_channel) malloc(sizeof(struct struct_io_channel));
60 data = (struct unix_private_data *)
61 malloc(sizeof(struct unix_private_data));
66 io->manager = unix_io_manager;
67 io->name = malloc(strlen(name)+1);
72 strcpy(io->name, name);
73 io->private_data = data;
75 memset(data, 0, sizeof(struct unix_private_data));
76 io->block_size = 1024;
77 data->buf = malloc(io->block_size);
78 data->buf_block_nr = -1;
83 data->dev = open(name, (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY);
102 static errcode_t unix_close(io_channel channel)
104 struct unix_private_data *data;
105 errcode_t retval = 0;
107 data = (struct unix_private_data *) channel->private_data;
108 if (close(data->dev) < 0)
112 if (channel->private_data)
113 free(channel->private_data);
120 static errcode_t unix_set_blksize(io_channel channel, int blksize)
122 struct unix_private_data *data;
124 data = (struct unix_private_data *) channel->private_data;
125 if (channel->block_size != blksize) {
126 channel->block_size = blksize;
128 data->buf = malloc(blksize);
131 data->buf_block_nr = -1;
137 static errcode_t unix_read_blk(io_channel channel, unsigned long block,
138 int count, void *buf)
140 struct unix_private_data *data;
145 data = (struct unix_private_data *) channel->private_data;
148 * If it's in the cache, use it!
150 if ((count == 1) && (block == data->buf_block_nr)) {
151 memcpy(buf, data->buf, channel->block_size);
154 size = (count < 0) ? -count : count * channel->block_size;
155 if (lseek(data->dev, block * channel->block_size, SEEK_SET) !=
156 block * channel->block_size) {
160 actual = read(data->dev, buf, size);
161 if (actual != size) {
164 retval = EXT2_ET_SHORT_READ;
168 data->buf_block_nr = block;
169 memcpy(data->buf, buf, size); /* Update the cache */
174 memset((char *) buf+actual, 0, size-actual);
175 if (channel->read_error)
176 retval = (channel->read_error)(channel, block, count, buf,
177 size, actual, retval);
181 static errcode_t unix_write_blk(io_channel channel, unsigned long block,
182 int count, const void *buf)
184 struct unix_private_data *data;
189 data = (struct unix_private_data *) channel->private_data;
192 size = channel->block_size;
194 data->buf_block_nr = -1; /* Invalidate the cache */
198 size = count * channel->block_size;
201 if (lseek(data->dev, block * channel->block_size, SEEK_SET) !=
202 block * channel->block_size) {
207 actual = write(data->dev, buf, size);
208 if (actual != size) {
209 retval = EXT2_ET_SHORT_WRITE;
213 if ((count == 1) && (block == data->buf_block_nr))
214 memcpy(data->buf, buf, size); /* Update the cache */
219 if (channel->write_error)
220 retval = (channel->write_error)(channel, block, count, buf,
221 size, actual, retval);
226 * Flush data buffers to disk. Since we are currently using a
227 * write-through cache, this is a no-op.
229 static errcode_t unix_flush(io_channel channel)