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 <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   
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         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
131 cleanup:
132         if (io)
133                 free(io);
134         if (data)
135                 free(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                 free(channel->private_data);
156         if (channel->name)
157                 free(channel->name);
158         free(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         
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