OSDN Git Service

Many files:
[android-x86/external-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         io->refcount = 1;
108
109         memset(data, 0, sizeof(struct test_private_data));
110         data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL;
111         if (test_io_backing_manager) {
112                 retval = test_io_backing_manager->open(name, flags,
113                                                        &data->real);
114                 if (retval)
115                         goto cleanup;
116         } else
117                 data->real = 0;
118         data->read_blk =        test_io_cb_read_blk;
119         data->write_blk =       test_io_cb_write_blk;
120         data->set_blksize =     test_io_cb_set_blksize;
121         
122         *channel = io;
123         return 0;
124
125 cleanup:
126         if (io)
127                 free(io);
128         if (data)
129                 free(data);
130         return retval;
131 }
132
133 static errcode_t test_close(io_channel channel)
134 {
135         struct test_private_data *data;
136         errcode_t       retval = 0;
137
138         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
139         data = (struct test_private_data *) channel->private_data;
140         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
141
142         if (--channel->refcount > 0)
143                 return 0;
144         
145         if (data->real)
146                 retval = io_channel_close(data->real);
147         
148         if (channel->private_data)
149                 free(channel->private_data);
150         if (channel->name)
151                 free(channel->name);
152         free(channel);
153         return retval;
154 }
155
156 static errcode_t test_set_blksize(io_channel channel, int blksize)
157 {
158         struct test_private_data *data;
159         errcode_t       retval = 0;
160
161         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
162         data = (struct test_private_data *) channel->private_data;
163         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
164
165         if (data->real)
166                 retval = io_channel_set_blksize(data->real, blksize);
167         if (data->set_blksize)
168                 data->set_blksize(blksize, retval);
169         else
170                 printf("Test_io: set_blksize(%d) returned %s\n",
171                        blksize, retval ? error_message(retval) : "OK");
172         return retval;
173 }
174
175
176 static errcode_t test_read_blk(io_channel channel, unsigned long block,
177                                int count, void *buf)
178 {
179         struct test_private_data *data;
180         errcode_t       retval = 0;
181
182         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
183         data = (struct test_private_data *) channel->private_data;
184         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
185
186         if (data->real)
187                 retval = io_channel_read_blk(data->real, block, count, buf);
188         if (data->read_blk)
189                 data->read_blk(block, count, retval);
190         else
191                 printf("Test_io: read_blk(%lu, %d) returned %s\n",
192                        block, count, retval ? error_message(retval) : "OK");
193         return retval;
194 }
195
196 static errcode_t test_write_blk(io_channel channel, unsigned long block,
197                                int count, const void *buf)
198 {
199         struct test_private_data *data;
200         errcode_t       retval = 0;
201
202         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
203         data = (struct test_private_data *) channel->private_data;
204         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
205
206         if (data->real)
207                 retval = io_channel_write_blk(data->real, block, count, buf);
208         if (data->write_blk)
209                 data->write_blk(block, count, retval);
210         else
211                 printf("Test_io: write_blk(%lu, %d) returned %s\n",
212                        block, count, retval ? error_message(retval) : "OK");
213         return retval;
214 }
215
216 /*
217  * Flush data buffers to disk.
218  */
219 static errcode_t test_flush(io_channel channel)
220 {
221         struct test_private_data *data;
222         
223         EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
224         data = (struct test_private_data *) channel->private_data;
225         EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
226
227         if (data->real)
228                 return io_channel_flush(data->real);
229         return 0;
230 }
231