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