]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - lib/ext2fs/inode_io.c
Remove trailing whitespace for the entire source tree
[thirdparty/e2fsprogs.git] / lib / ext2fs / inode_io.c
1 /*
2 * inode_io.c --- This is allows an inode in an ext2 filesystem image
3 * to be accessed via the I/O manager interface.
4 *
5 * Copyright (C) 2002 Theodore Ts'o.
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
13 #include <stdio.h>
14 #include <string.h>
15 #if HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #if HAVE_ERRNO_H
19 #include <errno.h>
20 #endif
21 #include <time.h>
22
23 #include "ext2_fs.h"
24 #include "ext2fs.h"
25
26 /*
27 * For checking structure magic numbers...
28 */
29
30 #define EXT2_CHECK_MAGIC(struct, code) \
31 if ((struct)->magic != (code)) return (code)
32
33 struct inode_private_data {
34 int magic;
35 char name[32];
36 ext2_file_t file;
37 ext2_filsys fs;
38 ext2_ino_t ino;
39 struct ext2_inode inode;
40 int flags;
41 struct inode_private_data *next;
42 };
43
44 #define CHANNEL_HAS_INODE 0x8000
45
46 static struct inode_private_data *top_intern;
47 static int ino_unique = 0;
48
49 static errcode_t inode_open(const char *name, int flags, io_channel *channel);
50 static errcode_t inode_close(io_channel channel);
51 static errcode_t inode_set_blksize(io_channel channel, int blksize);
52 static errcode_t inode_read_blk(io_channel channel, unsigned long block,
53 int count, void *data);
54 static errcode_t inode_write_blk(io_channel channel, unsigned long block,
55 int count, const void *data);
56 static errcode_t inode_flush(io_channel channel);
57 static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
58 int size, const void *data);
59 static errcode_t inode_read_blk64(io_channel channel,
60 unsigned long long block, int count, void *data);
61 static errcode_t inode_write_blk64(io_channel channel,
62 unsigned long long block, int count, const void *data);
63
64 static struct struct_io_manager struct_inode_manager = {
65 EXT2_ET_MAGIC_IO_MANAGER,
66 "Inode I/O Manager",
67 inode_open,
68 inode_close,
69 inode_set_blksize,
70 inode_read_blk,
71 inode_write_blk,
72 inode_flush,
73 inode_write_byte,
74 NULL,
75 NULL,
76 inode_read_blk64,
77 inode_write_blk64
78 };
79
80 io_manager inode_io_manager = &struct_inode_manager;
81
82 errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
83 struct ext2_inode *inode,
84 char **name)
85 {
86 struct inode_private_data *data;
87 errcode_t retval;
88
89 if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
90 &data)))
91 return retval;
92 data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
93 sprintf(data->name, "%u:%d", ino, ino_unique++);
94 data->file = 0;
95 data->fs = fs;
96 data->ino = ino;
97 data->flags = 0;
98 if (inode) {
99 memcpy(&data->inode, inode, sizeof(struct ext2_inode));
100 data->flags |= CHANNEL_HAS_INODE;
101 }
102 data->next = top_intern;
103 top_intern = data;
104 *name = data->name;
105 return 0;
106 }
107
108 errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
109 char **name)
110 {
111 return ext2fs_inode_io_intern2(fs, ino, NULL, name);
112 }
113
114
115 static errcode_t inode_open(const char *name, int flags, io_channel *channel)
116 {
117 io_channel io = NULL;
118 struct inode_private_data *prev, *data = NULL;
119 errcode_t retval;
120 int open_flags;
121
122 if (name == 0)
123 return EXT2_ET_BAD_DEVICE_NAME;
124
125 for (data = top_intern, prev = NULL; data;
126 prev = data, data = data->next)
127 if (strcmp(name, data->name) == 0)
128 break;
129 if (!data)
130 return ENOENT;
131 if (prev)
132 prev->next = data->next;
133 else
134 top_intern = data->next;
135
136 retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
137 if (retval)
138 goto cleanup;
139 memset(io, 0, sizeof(struct struct_io_channel));
140
141 io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
142 io->manager = inode_io_manager;
143 retval = ext2fs_get_mem(strlen(name)+1, &io->name);
144 if (retval)
145 goto cleanup;
146
147 strcpy(io->name, name);
148 io->private_data = data;
149 io->block_size = 1024;
150 io->read_error = 0;
151 io->write_error = 0;
152 io->refcount = 1;
153
154 open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
155 retval = ext2fs_file_open2(data->fs, data->ino,
156 (data->flags & CHANNEL_HAS_INODE) ?
157 &data->inode : 0, open_flags,
158 &data->file);
159 if (retval)
160 goto cleanup;
161
162 *channel = io;
163 return 0;
164
165 cleanup:
166 if (data) {
167 ext2fs_free_mem(&data);
168 }
169 if (io)
170 ext2fs_free_mem(&io);
171 return retval;
172 }
173
174 static errcode_t inode_close(io_channel channel)
175 {
176 struct inode_private_data *data;
177 errcode_t retval = 0;
178
179 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
180 data = (struct inode_private_data *) channel->private_data;
181 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
182
183 if (--channel->refcount > 0)
184 return 0;
185
186 retval = ext2fs_file_close(data->file);
187
188 ext2fs_free_mem(&channel->private_data);
189 if (channel->name)
190 ext2fs_free_mem(&channel->name);
191 ext2fs_free_mem(&channel);
192 return retval;
193 }
194
195 static errcode_t inode_set_blksize(io_channel channel, int blksize)
196 {
197 struct inode_private_data *data;
198
199 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
200 data = (struct inode_private_data *) channel->private_data;
201 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
202
203 channel->block_size = blksize;
204 return 0;
205 }
206
207
208 static errcode_t inode_read_blk64(io_channel channel,
209 unsigned long long block, int count, void *buf)
210 {
211 struct inode_private_data *data;
212 errcode_t retval;
213
214 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
215 data = (struct inode_private_data *) channel->private_data;
216 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
217
218 if ((retval = ext2fs_file_lseek(data->file,
219 block * channel->block_size,
220 EXT2_SEEK_SET, 0)))
221 return retval;
222
223 count = (count < 0) ? -count : (count * channel->block_size);
224
225 return ext2fs_file_read(data->file, buf, count, 0);
226 }
227
228 static errcode_t inode_read_blk(io_channel channel, unsigned long block,
229 int count, void *buf)
230 {
231 return inode_read_blk64(channel, block, count, buf);
232 }
233
234 static errcode_t inode_write_blk64(io_channel channel,
235 unsigned long long block, int count, const void *buf)
236 {
237 struct inode_private_data *data;
238 errcode_t retval;
239
240 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
241 data = (struct inode_private_data *) channel->private_data;
242 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
243
244 if ((retval = ext2fs_file_lseek(data->file,
245 block * channel->block_size,
246 EXT2_SEEK_SET, 0)))
247 return retval;
248
249 count = (count < 0) ? -count : (count * channel->block_size);
250
251 return ext2fs_file_write(data->file, buf, count, 0);
252 }
253
254 static errcode_t inode_write_blk(io_channel channel, unsigned long block,
255 int count, const void *buf)
256 {
257 return inode_write_blk64(channel, block, count, buf);
258 }
259
260 static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
261 int size, const void *buf)
262 {
263 struct inode_private_data *data;
264 errcode_t retval = 0;
265
266 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
267 data = (struct inode_private_data *) channel->private_data;
268 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
269
270 if ((retval = ext2fs_file_lseek(data->file, offset,
271 EXT2_SEEK_SET, 0)))
272 return retval;
273
274 return ext2fs_file_write(data->file, buf, size, 0);
275 }
276
277 /*
278 * Flush data buffers to disk.
279 */
280 static errcode_t inode_flush(io_channel channel)
281 {
282 struct inode_private_data *data;
283
284 EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
285 data = (struct inode_private_data *) channel->private_data;
286 EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
287
288 return ext2fs_file_flush(data->file);
289 }
290