test_io.c revision 31dbecd482405e0d3a67eb58e1a1c8cb9f2ad83e
1/* 2 * test_io.c --- This is the Test I/O interface. 3 * 4 * Copyright (C) 1996 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Public 8 * License. 9 * %End-Header% 10 */ 11 12#include <stdio.h> 13#include <string.h> 14#if HAVE_UNISTD_H 15#include <unistd.h> 16#endif 17#include <fcntl.h> 18#include <time.h> 19#if HAVE_SYS_STAT_H 20#include <sys/stat.h> 21#endif 22#if HAVE_SYS_TYPES_H 23#include <sys/types.h> 24#endif 25 26#if EXT2_FLAT_INCLUDES 27#include "ext2_fs.h" 28#else 29#include <linux/ext2_fs.h> 30#endif 31 32#include "ext2fs.h" 33 34/* 35 * For checking structure magic numbers... 36 */ 37 38#define EXT2_CHECK_MAGIC(struct, code) \ 39 if ((struct)->magic != (code)) return (code) 40 41struct test_private_data { 42 int magic; 43 io_channel real; 44 void (*read_blk)(unsigned long block, int count, errcode_t err); 45 void (*write_blk)(unsigned long block, int count, errcode_t err); 46 void (*set_blksize)(int blksize, errcode_t err); 47 void (*write_byte)(unsigned long block, int count, errcode_t err); 48}; 49 50static errcode_t test_open(const char *name, int flags, io_channel *channel); 51static errcode_t test_close(io_channel channel); 52static errcode_t test_set_blksize(io_channel channel, int blksize); 53static errcode_t test_read_blk(io_channel channel, unsigned long block, 54 int count, void *data); 55static errcode_t test_write_blk(io_channel channel, unsigned long block, 56 int count, const void *data); 57static errcode_t test_flush(io_channel channel); 58static errcode_t test_write_byte(io_channel channel, unsigned long offset, 59 int count, const void *buf); 60 61static struct struct_io_manager struct_test_manager = { 62 EXT2_ET_MAGIC_IO_MANAGER, 63 "Test I/O Manager", 64 test_open, 65 test_close, 66 test_set_blksize, 67 test_read_blk, 68 test_write_blk, 69 test_flush, 70 test_write_byte 71 72}; 73 74io_manager test_io_manager = &struct_test_manager; 75 76/* 77 * These global variable can be set by the test program as 78 * necessary *before* calling test_open 79 */ 80io_manager test_io_backing_manager = 0; 81void (*test_io_cb_read_blk) 82 (unsigned long block, int count, errcode_t err) = 0; 83void (*test_io_cb_write_blk) 84 (unsigned long block, int count, errcode_t err) = 0; 85void (*test_io_cb_set_blksize) 86 (int blksize, errcode_t err) = 0; 87void (*test_io_cb_write_byte) 88 (unsigned long block, int count, errcode_t err) = 0; 89 90static errcode_t test_open(const char *name, int flags, io_channel *channel) 91{ 92 io_channel io = NULL; 93 struct test_private_data *data = NULL; 94 errcode_t retval; 95 96 if (name == 0) 97 return EXT2_ET_BAD_DEVICE_NAME; 98 retval = ext2fs_get_mem(sizeof(struct struct_io_channel), 99 (void **) &io); 100 if (retval) 101 return retval; 102 memset(io, 0, sizeof(struct struct_io_channel)); 103 io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 104 retval = ext2fs_get_mem(sizeof(struct test_private_data), 105 (void **) &data); 106 if (retval) { 107 retval = EXT2_ET_NO_MEMORY; 108 goto cleanup; 109 } 110 io->manager = test_io_manager; 111 retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name); 112 if (retval) 113 goto cleanup; 114 115 strcpy(io->name, name); 116 io->private_data = data; 117 io->block_size = 1024; 118 io->read_error = 0; 119 io->write_error = 0; 120 io->refcount = 1; 121 122 memset(data, 0, sizeof(struct test_private_data)); 123 data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL; 124 if (test_io_backing_manager) { 125 retval = test_io_backing_manager->open(name, flags, 126 &data->real); 127 if (retval) 128 goto cleanup; 129 } else 130 data->real = 0; 131 data->read_blk = test_io_cb_read_blk; 132 data->write_blk = test_io_cb_write_blk; 133 data->set_blksize = test_io_cb_set_blksize; 134 data->write_byte = test_io_cb_write_byte; 135 136 *channel = io; 137 return 0; 138 139cleanup: 140 if (io) 141 ext2fs_free_mem((void **) &io); 142 if (data) 143 ext2fs_free_mem((void **) &data); 144 return retval; 145} 146 147static errcode_t test_close(io_channel channel) 148{ 149 struct test_private_data *data; 150 errcode_t retval = 0; 151 152 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 153 data = (struct test_private_data *) channel->private_data; 154 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 155 156 if (--channel->refcount > 0) 157 return 0; 158 159 if (data->real) 160 retval = io_channel_close(data->real); 161 162 if (channel->private_data) 163 ext2fs_free_mem((void **) &channel->private_data); 164 if (channel->name) 165 ext2fs_free_mem((void **) &channel->name); 166 ext2fs_free_mem((void **) &channel); 167 return retval; 168} 169 170static errcode_t test_set_blksize(io_channel channel, int blksize) 171{ 172 struct test_private_data *data; 173 errcode_t retval = 0; 174 175 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 176 data = (struct test_private_data *) channel->private_data; 177 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 178 179 if (data->real) 180 retval = io_channel_set_blksize(data->real, blksize); 181 if (data->set_blksize) 182 data->set_blksize(blksize, retval); 183 else 184 printf("Test_io: set_blksize(%d) returned %s\n", 185 blksize, retval ? error_message(retval) : "OK"); 186 return retval; 187} 188 189 190static errcode_t test_read_blk(io_channel channel, unsigned long block, 191 int count, void *buf) 192{ 193 struct test_private_data *data; 194 errcode_t retval = 0; 195 196 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 197 data = (struct test_private_data *) channel->private_data; 198 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 199 200 if (data->real) 201 retval = io_channel_read_blk(data->real, block, count, buf); 202 if (data->read_blk) 203 data->read_blk(block, count, retval); 204 else 205 printf("Test_io: read_blk(%lu, %d) returned %s\n", 206 block, count, retval ? error_message(retval) : "OK"); 207 return retval; 208} 209 210static errcode_t test_write_blk(io_channel channel, unsigned long block, 211 int count, const void *buf) 212{ 213 struct test_private_data *data; 214 errcode_t retval = 0; 215 216 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 217 data = (struct test_private_data *) channel->private_data; 218 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 219 220 if (data->real) 221 retval = io_channel_write_blk(data->real, block, count, buf); 222 if (data->write_blk) 223 data->write_blk(block, count, retval); 224 else 225 printf("Test_io: write_blk(%lu, %d) returned %s\n", 226 block, count, retval ? error_message(retval) : "OK"); 227 return retval; 228} 229 230static errcode_t test_write_byte(io_channel channel, unsigned long offset, 231 int count, const void *buf) 232{ 233 struct test_private_data *data; 234 errcode_t retval = 0; 235 236 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 237 data = (struct test_private_data *) channel->private_data; 238 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 239 240 if (data->real && data->real->manager->write_byte) 241 retval = io_channel_write_byte(data->real, offset, count, buf); 242 if (data->write_byte) 243 data->write_byte(offset, count, retval); 244 else 245 printf("Test_io: write_byte(%lu, %d) returned %s\n", 246 offset, count, retval ? error_message(retval) : "OK"); 247 return retval; 248} 249 250/* 251 * Flush data buffers to disk. 252 */ 253static errcode_t test_flush(io_channel channel) 254{ 255 struct test_private_data *data; 256 errcode_t retval = 0; 257 258 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 259 data = (struct test_private_data *) channel->private_data; 260 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 261 262 if (data->real) 263 retval = io_channel_flush(data->real); 264 265 printf("Test_io: flush() returned %s\n", 266 retval ? error_message(retval) : "OK"); 267 268 return retval; 269} 270 271