test_io.c revision 3af0a45628c0984d298a885f8381498cdf866221
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/* 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * test_io.c --- This is the Test I/O interface. 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Copyright (C) 1996 Theodore Ts'o. 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * %Begin-Header% 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * This file may be redistributed under the terms of the GNU Public 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * License. 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * %End-Header% 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <stdio.h> 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <string.h> 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if HAVE_UNISTD_H 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <unistd.h> 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <fcntl.h> 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <time.h> 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if HAVE_SYS_STAT_H 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <sys/stat.h> 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if HAVE_SYS_TYPES_H 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <sys/types.h> 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#ifdef HAVE_SYS_PRCTL_H 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <sys/prctl.h> 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define PR_GET_DUMPABLE 3 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if (!defined(HAVE_PRCTL) && defined(linux)) 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <sys/syscall.h> 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ext2_fs.h" 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ext2fs.h" 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/* 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * For checking structure magic numbers... 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define EXT2_CHECK_MAGIC(struct, code) \ 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if ((struct)->magic != (code)) return (code) 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)struct test_private_data { 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int magic; 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) io_channel real; 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int flags; 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FILE *outfile; 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unsigned long block; 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int read_abort_count, write_abort_count; 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void (*read_blk)(unsigned long block, int count, errcode_t err); 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void (*write_blk)(unsigned long block, int count, errcode_t err); 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void (*set_blksize)(int blksize, errcode_t err); 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void (*write_byte)(unsigned long block, int count, errcode_t err); 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_open(const char *name, int flags, io_channel *channel); 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_close(io_channel channel); 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_set_blksize(io_channel channel, int blksize); 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_read_blk(io_channel channel, unsigned long block, 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int count, void *data); 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_write_blk(io_channel channel, unsigned long block, 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int count, const void *data); 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_flush(io_channel channel); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_write_byte(io_channel channel, unsigned long offset, 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int count, const void *buf); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_set_option(io_channel channel, const char *option, 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const char *arg); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static struct struct_io_manager struct_test_manager = { 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXT2_ET_MAGIC_IO_MANAGER, 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "Test I/O Manager", 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_open, 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_close, 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_set_blksize, 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_read_blk, 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_write_blk, 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_flush, 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) test_write_byte, 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_set_option 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)io_manager test_io_manager = &struct_test_manager; 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/* 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * These global variable can be set by the test program as 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * necessary *before* calling test_open 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)io_manager test_io_backing_manager = 0; 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void (*test_io_cb_read_blk) 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (unsigned long block, int count, errcode_t err) = 0; 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void (*test_io_cb_write_blk) 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (unsigned long block, int count, errcode_t err) = 0; 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void (*test_io_cb_set_blksize) 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (int blksize, errcode_t err) = 0; 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void (*test_io_cb_write_byte) 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (unsigned long block, int count, errcode_t err) = 0; 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/* 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Test flags 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */ 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define TEST_FLAG_READ 0x01 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define TEST_FLAG_WRITE 0x02 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define TEST_FLAG_SET_BLKSIZE 0x04 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define TEST_FLAG_FLUSH 0x08 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define TEST_FLAG_DUMP 0x10 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define TEST_FLAG_SET_OPTION 0x20 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void test_dump_block(io_channel channel, 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct test_private_data *data, 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unsigned long block, const void *buf) 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const unsigned char *cp; 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FILE *f = data->outfile; 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int i; 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unsigned long cksum = 0; 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (i=0, cp = buf; i < channel->block_size; i++, cp++) { 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) cksum += *cp; 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) fprintf(f, "Contents of block %lu, checksum %08lu: \n", block, cksum); 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (i=0, cp = buf; i < channel->block_size; i++, cp++) { 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((i % 16) == 0) 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) fprintf(f, "%04x: ", i); 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' '); 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void test_abort(io_channel channel, unsigned long block) 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){ 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct test_private_data *data; 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FILE *f; 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data = (struct test_private_data *) channel->private_data; 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) f = data->outfile; 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) test_flush(channel); 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) fprintf(f, "Aborting due to I/O to block %lu\n", block); 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) fflush(f); 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) abort(); 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static char *safe_getenv(const char *arg) 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if ((getuid() != geteuid()) || (getgid() != getegid())) 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return NULL; 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if HAVE_PRCTL 1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (prctl(PR_GET_DUMPABLE) == 0) 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return NULL; 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if (defined(linux) && defined(SYS_prctl)) 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (syscall(SYS_prctl, PR_GET_DUMPABLE) == 0) 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return NULL; 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#ifdef HAVE___SECURE_GETENV 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return __secure_getenv(arg); 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#else 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return getenv(arg); 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static errcode_t test_open(const char *name, int flags, io_channel *channel) 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){ 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) io_channel io = NULL; 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct test_private_data *data = NULL; 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) errcode_t retval; 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) char *value; 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (name == 0) 172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return EXT2_ET_BAD_DEVICE_NAME; 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (retval) 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return retval; 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(io, 0, sizeof(struct struct_io_channel)); 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) io->magic = EXT2_ET_MAGIC_IO_CHANNEL; 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) retval = ext2fs_get_mem(sizeof(struct test_private_data), &data); 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (retval) { 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) retval = EXT2_ET_NO_MEMORY; 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) goto cleanup; 182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) io->manager = test_io_manager; 184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) retval = ext2fs_get_mem(strlen(name)+1, &io->name); 185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (retval) 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) goto cleanup; 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) strcpy(io->name, name); 189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) io->private_data = data; 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) io->block_size = 1024; 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) io->read_error = 0; 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) io->write_error = 0; 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) io->refcount = 1; 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memset(data, 0, sizeof(struct test_private_data)); 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL; 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (test_io_backing_manager) { 198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) retval = test_io_backing_manager->open(name, flags, 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &data->real); 200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (retval) 201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) goto cleanup; 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else 203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->real = 0; 204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->read_blk = test_io_cb_read_blk; 205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->write_blk = test_io_cb_write_blk; 206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->set_blksize = test_io_cb_set_blksize; 207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->write_byte = test_io_cb_write_byte; 208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->outfile = NULL; 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((value = safe_getenv("TEST_IO_LOGFILE")) != NULL) 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->outfile = fopen(value, "w"); 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!data->outfile) 213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->outfile = stderr; 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->flags = 0; 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((value = safe_getenv("TEST_IO_FLAGS")) != NULL) 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->flags = strtoul(value, NULL, 0); 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->block = 0; 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((value = safe_getenv("TEST_IO_BLOCK")) != NULL) 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->block = strtoul(value, NULL, 0); 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->read_abort_count = 0; 224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((value = safe_getenv("TEST_IO_READ_ABORT")) != NULL) 225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data->read_abort_count = strtoul(value, NULL, 0); 226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data->write_abort_count = 0; 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if ((value = safe_getenv("TEST_IO_WRITE_ABORT")) != NULL) 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data->write_abort_count = strtoul(value, NULL, 0); 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *channel = io; 232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)cleanup: 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (io) 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ext2fs_free_mem(&io); 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (data) 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ext2fs_free_mem(&data); 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return retval; 24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_close(io_channel channel) 24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct test_private_data *data; 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) errcode_t retval = 0; 24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data = (struct test_private_data *) channel->private_data; 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (--channel->refcount > 0) 25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 0; 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (data->real) 25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) retval = io_channel_close(data->real); 25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (data->outfile && data->outfile != stderr) 2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) fclose(data->outfile); 2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ext2fs_free_mem(&channel->private_data); 26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (channel->name) 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ext2fs_free_mem(&channel->name); 2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ext2fs_free_mem(&channel); 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return retval; 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static errcode_t test_set_blksize(io_channel channel, int blksize) 268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){ 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct test_private_data *data; 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) errcode_t retval = 0; 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data = (struct test_private_data *) channel->private_data; 2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (data->real) 2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) retval = io_channel_set_blksize(data->real, blksize); 2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (data->set_blksize) 2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) data->set_blksize(blksize, retval); 2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (data->flags & TEST_FLAG_SET_BLKSIZE) 2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) fprintf(data->outfile, 2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) "Test_io: set_blksize(%d) returned %s\n", 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) blksize, retval ? error_message(retval) : "OK"); 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) channel->block_size = blksize; 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return retval; 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)static errcode_t test_read_blk(io_channel channel, unsigned long block, 2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int count, void *buf) 2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles){ 2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) struct test_private_data *data; 2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) errcode_t retval = 0; 2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) data = (struct test_private_data *) channel->private_data; 2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (data->real) 3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) retval = io_channel_read_blk(data->real, block, count, buf); 3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (data->read_blk) 30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data->read_blk(block, count, retval); 303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (data->flags & TEST_FLAG_READ) 30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) fprintf(data->outfile, 30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "Test_io: read_blk(%lu, %d) returned %s\n", 30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) block, count, retval ? error_message(retval) : "OK"); 30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (data->block && data->block == block) { 30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (data->flags & TEST_FLAG_DUMP) 30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_dump_block(channel, data, block, buf); 31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (--data->read_abort_count == 0) 31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) test_abort(channel, block); 31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return retval; 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)static errcode_t test_write_blk(io_channel channel, unsigned long block, 317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int count, const void *buf) 318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){ 319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct test_private_data *data; 320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) errcode_t retval = 0; 321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) data = (struct test_private_data *) channel->private_data; 3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (data->real) 3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) retval = io_channel_write_blk(data->real, block, count, buf); 328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (data->write_blk) 3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) data->write_blk(block, count, retval); 3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (data->flags & TEST_FLAG_WRITE) 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) fprintf(data->outfile, 332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Test_io: write_blk(%lu, %d) returned %s\n", 333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) block, count, retval ? error_message(retval) : "OK"); 334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (data->block && data->block == block) { 335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (data->flags & TEST_FLAG_DUMP) 336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) test_dump_block(channel, data, block, buf); 3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (--data->write_abort_count == 0) 338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) test_abort(channel, block); 339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return retval; 341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static errcode_t test_write_byte(io_channel channel, unsigned long offset, 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int count, const void *buf) 345{ 346 struct test_private_data *data; 347 errcode_t retval = 0; 348 349 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 350 data = (struct test_private_data *) channel->private_data; 351 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 352 353 if (data->real && data->real->manager->write_byte) 354 retval = io_channel_write_byte(data->real, offset, count, buf); 355 if (data->write_byte) 356 data->write_byte(offset, count, retval); 357 if (data->flags & TEST_FLAG_WRITE) 358 fprintf(data->outfile, 359 "Test_io: write_byte(%lu, %d) returned %s\n", 360 offset, count, retval ? error_message(retval) : "OK"); 361 return retval; 362} 363 364/* 365 * Flush data buffers to disk. 366 */ 367static errcode_t test_flush(io_channel channel) 368{ 369 struct test_private_data *data; 370 errcode_t retval = 0; 371 372 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 373 data = (struct test_private_data *) channel->private_data; 374 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 375 376 if (data->real) 377 retval = io_channel_flush(data->real); 378 379 if (data->flags & TEST_FLAG_FLUSH) 380 fprintf(data->outfile, "Test_io: flush() returned %s\n", 381 retval ? error_message(retval) : "OK"); 382 383 return retval; 384} 385 386static errcode_t test_set_option(io_channel channel, const char *option, 387 const char *arg) 388{ 389 struct test_private_data *data; 390 errcode_t retval = 0; 391 392 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); 393 data = (struct test_private_data *) channel->private_data; 394 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); 395 396 397 if (data->flags & TEST_FLAG_SET_OPTION) 398 fprintf(data->outfile, "Test_io: set_option(%s, %s) ", 399 option, arg); 400 if (data->real && data->real->manager->set_option) { 401 retval = (data->real->manager->set_option)(data->real, 402 option, arg); 403 if (data->flags & TEST_FLAG_SET_OPTION) 404 fprintf(data->outfile, "returned %s\n", 405 retval ? error_message(retval) : "OK"); 406 } else { 407 if (data->flags & TEST_FLAG_SET_OPTION) 408 fprintf(data->outfile, "not implemented\n"); 409 } 410 return retval; 411} 412