source: MondoRescue/branches/stable/mindi-busybox/e2fsprogs/ext2fs/inode_io.c @ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 13 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 6.5 KB
Line 
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
33struct 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
46static struct inode_private_data *top_intern;
47static int ino_unique = 0;
48
49static errcode_t inode_open(const char *name, int flags, io_channel *channel);
50static errcode_t inode_close(io_channel channel);
51static errcode_t inode_set_blksize(io_channel channel, int blksize);
52static errcode_t inode_read_blk(io_channel channel, unsigned long block,
53                   int count, void *data);
54static errcode_t inode_write_blk(io_channel channel, unsigned long block,
55                int count, const void *data);
56static errcode_t inode_flush(io_channel channel);
57static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
58                int size, const void *data);
59
60static struct struct_io_manager struct_inode_manager = {
61    EXT2_ET_MAGIC_IO_MANAGER,
62    "Inode I/O Manager",
63    inode_open,
64    inode_close,
65    inode_set_blksize,
66    inode_read_blk,
67    inode_write_blk,
68    inode_flush,
69    inode_write_byte
70};
71
72io_manager inode_io_manager = &struct_inode_manager;
73
74errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
75                  struct ext2_inode *inode,
76                  char **name)
77{
78    struct inode_private_data   *data;
79    errcode_t           retval;
80
81    if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
82                     &data)))
83        return retval;
84    data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
85    sprintf(data->name, "%u:%d", ino, ino_unique++);
86    data->file = 0;
87    data->fs = fs;
88    data->ino = ino;
89    data->flags = 0;
90    if (inode) {
91        memcpy(&data->inode, inode, sizeof(struct ext2_inode));
92        data->flags |= CHANNEL_HAS_INODE;
93    }
94    data->next = top_intern;
95    top_intern = data;
96    *name = data->name;
97    return 0;
98}
99
100errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
101                 char **name)
102{
103    return ext2fs_inode_io_intern2(fs, ino, NULL, name);
104}
105
106
107static errcode_t inode_open(const char *name, int flags, io_channel *channel)
108{
109    io_channel  io = NULL;
110    struct inode_private_data *prev, *data = NULL;
111    errcode_t   retval;
112    int     open_flags;
113
114    if (name == 0)
115        return EXT2_ET_BAD_DEVICE_NAME;
116
117    for (data = top_intern, prev = NULL; data;
118         prev = data, data = data->next)
119        if (strcmp(name, data->name) == 0)
120            break;
121    if (!data)
122        return ENOENT;
123    if (prev)
124        prev->next = data->next;
125    else
126        top_intern = data->next;
127
128    retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
129    if (retval)
130        goto cleanup;
131    memset(io, 0, sizeof(struct struct_io_channel));
132
133    io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
134    io->manager = inode_io_manager;
135    retval = ext2fs_get_mem(strlen(name)+1, &io->name);
136    if (retval)
137        goto cleanup;
138
139    strcpy(io->name, name);
140    io->private_data = data;
141    io->block_size = 1024;
142    io->read_error = 0;
143    io->write_error = 0;
144    io->refcount = 1;
145
146    open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
147    retval = ext2fs_file_open2(data->fs, data->ino,
148                   (data->flags & CHANNEL_HAS_INODE) ?
149                   &data->inode : 0, open_flags,
150                   &data->file);
151    if (retval)
152        goto cleanup;
153
154    *channel = io;
155    return 0;
156
157cleanup:
158    if (data) {
159        ext2fs_free_mem(&data);
160    }
161    if (io)
162        ext2fs_free_mem(&io);
163    return retval;
164}
165
166static errcode_t inode_close(io_channel channel)
167{
168    struct inode_private_data *data;
169    errcode_t   retval = 0;
170
171    EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
172    data = (struct inode_private_data *) channel->private_data;
173    EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
174
175    if (--channel->refcount > 0)
176        return 0;
177
178    retval = ext2fs_file_close(data->file);
179
180    ext2fs_free_mem(&channel->private_data);
181    if (channel->name)
182        ext2fs_free_mem(&channel->name);
183    ext2fs_free_mem(&channel);
184    return retval;
185}
186
187static errcode_t inode_set_blksize(io_channel channel, int blksize)
188{
189    struct inode_private_data *data;
190
191    EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
192    data = (struct inode_private_data *) channel->private_data;
193    EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
194
195    channel->block_size = blksize;
196    return 0;
197}
198
199
200static errcode_t inode_read_blk(io_channel channel, unsigned long block,
201                   int count, void *buf)
202{
203    struct inode_private_data *data;
204    errcode_t   retval;
205
206    EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
207    data = (struct inode_private_data *) channel->private_data;
208    EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
209
210    if ((retval = ext2fs_file_lseek(data->file,
211                    block * channel->block_size,
212                    EXT2_SEEK_SET, 0)))
213        return retval;
214
215    count = (count < 0) ? -count : (count * channel->block_size);
216
217    return ext2fs_file_read(data->file, buf, count, 0);
218}
219
220static errcode_t inode_write_blk(io_channel channel, unsigned long block,
221                int count, const void *buf)
222{
223    struct inode_private_data *data;
224    errcode_t   retval;
225
226    EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
227    data = (struct inode_private_data *) channel->private_data;
228    EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
229
230    if ((retval = ext2fs_file_lseek(data->file,
231                    block * channel->block_size,
232                    EXT2_SEEK_SET, 0)))
233        return retval;
234
235    count = (count < 0) ? -count : (count * channel->block_size);
236
237    return ext2fs_file_write(data->file, buf, count, 0);
238}
239
240static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
241                 int size, const void *buf)
242{
243    struct inode_private_data *data;
244    errcode_t   retval = 0;
245
246    EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
247    data = (struct inode_private_data *) channel->private_data;
248    EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
249
250    if ((retval = ext2fs_file_lseek(data->file, offset,
251                    EXT2_SEEK_SET, 0)))
252        return retval;
253
254    return ext2fs_file_write(data->file, buf, size, 0);
255}
256
257/*
258 * Flush data buffers to disk.
259 */
260static errcode_t inode_flush(io_channel channel)
261{
262    struct inode_private_data *data;
263
264    EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
265    data = (struct inode_private_data *) channel->private_data;
266    EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
267
268    return ext2fs_file_flush(data->file);
269}
270
Note: See TracBrowser for help on using the repository browser.