Whamcloud - gitweb
Many files:
[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 #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   
41 struct 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
49 static errcode_t test_open(const char *name, int flags, io_channel *channel);
50 static errcode_t test_close(io_channel channel);
51 static errcode_t test_set_blksize(io_channel channel, int blksize);
52 static errcode_t test_read_blk(io_channel channel, unsigned long block,
53                                int count, void *data);
54 static errcode_t test_write_blk(io_channel channel, unsigned long block,
55                                 int count, const void *data);
56 static errcode_t test_flush(io_channel channel);
57
58 static 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
69 io_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  */
75 io_manager test_io_backing_manager = 0;
76 void (*test_io_cb_read_blk)
77         (unsigned long block, int count, errcode_t err) = 0;
78 void (*test_io_cb_write_blk)
79         (unsigned long block, int count, errcode_t err) = 0;
80 void (*test_io_cb_set_blksize)
81         (int blksize, errcode_t err) = 0;
82
83 static 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         retval = ext2fs_get_mem(sizeof(struct struct_io_channel),
92                                 (void **) &io);
93         if (retval)
94                 return retval;
95         memset(io, 0, sizeof(struct struct_io_channel));
96         io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
97         retval = ext2fs_get_mem(sizeof(struct test_private_data),
98                                 (void **) &data);
99         if (retval) {
100                 retval = EXT2_ET_NO_MEMORY;
101                 goto cleanup;
102         }
103         io->manager = test_io_manager;
104         retval = ext2fs_get_mem(strlen(name)+1, (void **) &io->name);
105         if (retval)
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
131 cleanup:
132         if (io)
133                 ext2fs_free_mem((void **) &io);
134         if (data)
135                 ext2fs_free_mem((void **) &data);
136         return retval;
137 }
138
139 static 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                 ext2fs_free_mem((void **) &channel->private_data);
156         if (channel->name)
157                 ext2fs_free_mem((void **) &channel->name);
158         ext2fs_free_mem((void **) &channel);
159         return retval;
160 }
161
162 static 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
182 static 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
202 static 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  */
225 static errcode_t test_flush(io_channel channel)
226 {
227         struct test_private_data *data;
228         errcode_t       retval = 0;
229         
230         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
231         data = (struct test_private_data *) channel->private_data;
232         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
233
234         if (data->real)
235                 retval = io_channel_flush(data->real);
236         
237         printf("Test_io: flush() returned %s\n",
238                        retval ? error_message(retval) : "OK");
239         
240         return retval;
241 }
242