test_io.c revision 1d2ff46ae7533ffd038534b189f272d2a4122e4e
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 <stdlib.h> 18#include <fcntl.h> 19#include <time.h> 20#if HAVE_SYS_STAT_H 21#include <sys/stat.h> 22#endif 23#if HAVE_SYS_TYPES_H 24#include <sys/types.h> 25#endif 26#if HAVE_ERRNO_H 27#include <errno.h> 28#endif 29 30#include "et/com_err.h" 31#include "ext2fs/ext2_err.h" 32#include "io.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}; 48 49static errcode_t test_open(const char *name, int flags, io_channel *channel); 50static errcode_t test_close(io_channel channel); 51static errcode_t test_set_blksize(io_channel channel, int blksize); 52static errcode_t test_read_blk(io_channel channel, unsigned long block, 53 int count, void *data); 54static errcode_t test_write_blk(io_channel channel, unsigned long block, 55 int count, const void *data); 56static errcode_t test_flush(io_channel channel); 57 58static struct struct_io_manager struct_test_manager = { 59 EXT2_ET_MAGIC_IO_MANAGER, 60 "Test I/O Manager", 61 test_open, 62 test_close, 63 test_set_blksize, 64 test_read_blk, 65 test_write_blk, 66 test_flush 67}; 68 69io_manager test_io_manager = &struct_test_manager; 70 71/* 72 * These global variable can be set by the test program as 73 * necessary *before* calling test_open 74 */ 75io_manager test_io_backing_manager = 0; 76void (*test_io_cb_read_blk) 77 (unsigned long block, int count, errcode_t err) = 0; 78void (*test_io_cb_write_blk) 79 (unsigned long block, int count, errcode_t err) = 0; 80void (*test_io_cb_set_blksize) 81 (int blksize, errcode_t err) = 0; 82 83static errcode_t test_open(const char *name, int flags, io_channel *channel) 84{ 85 io_channel io = NULL; 86 struct test_private_data *data = NULL; 87 errcode_t retval; 88 89 if (name == 0) 90 return EXT2_ET_BAD_DEVICE_NAME; 91 io = (io_channel) malloc(sizeof(struct struct_io_channel)); 92 if (!io) 93 return ENOMEM; 94 memset(io, 0, sizeof(struct struct_io_channel)); 95 io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 96 data = (struct test_private_data *) 97 malloc(sizeof(struct test_private_data)); 98 if (!data) { 99 retval = ENOMEM; 100 goto cleanup; 101 } 102 io->manager = test_io_manager; 103 io->name = malloc(strlen(name)+1); 104 if (!io->name) { 105 retval = ENOMEM; 106 goto cleanup; 107 } 108 strcpy(io->name, name); 109 io->private_data = data; 110 io->block_size = 1024; 111 io->read_error = 0; 112 io->write_error = 0; 113 io->refcount = 1; 114 115 memset(data, 0, sizeof(struct test_private_data)); 116 data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL; 117 if (test_io_backing_manager) { 118 retval = test_io_backing_manager->open(name, flags, 119 &data->real); 120 if (retval) 121 goto cleanup; 122 } else 123 data->real = 0; 124 data->read_blk = test_io_cb_read_blk; 125 data->write_blk = test_io_cb_write_blk; 126 data->set_blksize = test_io_cb_set_blksize; 127 128 *channel = io; 129 return 0; 130 131cleanup: 132 if (io) 133 free(io); 134 if (data) 135 free(data); 136 return retval; 137} 138 139static errcode_t test_close(io_channel channel) 140{ 141 struct test_private_data *data; 142 errcode_t retval = 0; 143 144 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 145 data = (struct test_private_data *) channel->private_data; 146 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 147 148 if (--channel->refcount > 0) 149 return 0; 150 151 if (data->real) 152 retval = io_channel_close(data->real); 153 154 if (channel->private_data) 155 free(channel->private_data); 156 if (channel->name) 157 free(channel->name); 158 free(channel); 159 return retval; 160} 161 162static errcode_t test_set_blksize(io_channel channel, int blksize) 163{ 164 struct test_private_data *data; 165 errcode_t retval = 0; 166 167 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 168 data = (struct test_private_data *) channel->private_data; 169 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 170 171 if (data->real) 172 retval = io_channel_set_blksize(data->real, blksize); 173 if (data->set_blksize) 174 data->set_blksize(blksize, retval); 175 else 176 printf("Test_io: set_blksize(%d) returned %s\n", 177 blksize, retval ? error_message(retval) : "OK"); 178 return retval; 179} 180 181 182static errcode_t test_read_blk(io_channel channel, unsigned long block, 183 int count, void *buf) 184{ 185 struct test_private_data *data; 186 errcode_t retval = 0; 187 188 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 189 data = (struct test_private_data *) channel->private_data; 190 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 191 192 if (data->real) 193 retval = io_channel_read_blk(data->real, block, count, buf); 194 if (data->read_blk) 195 data->read_blk(block, count, retval); 196 else 197 printf("Test_io: read_blk(%lu, %d) returned %s\n", 198 block, count, retval ? error_message(retval) : "OK"); 199 return retval; 200} 201 202static errcode_t test_write_blk(io_channel channel, unsigned long block, 203 int count, const void *buf) 204{ 205 struct test_private_data *data; 206 errcode_t retval = 0; 207 208 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 209 data = (struct test_private_data *) channel->private_data; 210 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 211 212 if (data->real) 213 retval = io_channel_write_blk(data->real, block, count, buf); 214 if (data->write_blk) 215 data->write_blk(block, count, retval); 216 else 217 printf("Test_io: write_blk(%lu, %d) returned %s\n", 218 block, count, retval ? error_message(retval) : "OK"); 219 return retval; 220} 221 222/* 223 * Flush data buffers to disk. 224 */ 225static errcode_t test_flush(io_channel channel) 226{ 227 struct test_private_data *data; 228 229 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 230 data = (struct test_private_data *) channel->private_data; 231 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 232 233 if (data->real) 234 return io_channel_flush(data->real); 235 return 0; 236} 237 238