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

Last change on this file since 821 was 821, checked in by Bruno Cornec, 14 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: 7.1 KB
Line 
1/*
2 * image.c --- writes out the critical parts of the filesystem as a
3 *  flat file.
4 *
5 * Copyright (C) 2000 Theodore Ts'o.
6 *
7 * Note: this uses the POSIX IO interfaces, unlike most of the other
8 * functions in this library.  So sue me.
9 *
10 * %Begin-Header%
11 * This file may be redistributed under the terms of the GNU Public
12 * License.
13 * %End-Header%
14 */
15
16#include <stdio.h>
17#include <string.h>
18#if HAVE_UNISTD_H
19#include <unistd.h>
20#endif
21#if HAVE_ERRNO_H
22#include <errno.h>
23#endif
24#include <fcntl.h>
25#include <time.h>
26#if HAVE_SYS_STAT_H
27#include <sys/stat.h>
28#endif
29#if HAVE_SYS_TYPES_H
30#include <sys/types.h>
31#endif
32
33#include "ext2_fs.h"
34#include "ext2fs.h"
35
36#ifndef HAVE_TYPE_SSIZE_T
37typedef int ssize_t;
38#endif
39
40/*
41 * This function returns 1 if the specified block is all zeros
42 */
43static int check_zero_block(char *buf, int blocksize)
44{
45    char    *cp = buf;
46    int left = blocksize;
47
48    while (left > 0) {
49        if (*cp++)
50            return 0;
51        left--;
52    }
53    return 1;
54}
55
56/*
57 * Write the inode table out as a single block.
58 */
59#define BUF_BLOCKS  32
60
61errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
62{
63    unsigned int    group, left, c, d;
64    char        *buf, *cp;
65    blk_t       blk;
66    ssize_t     actual;
67    errcode_t   retval;
68
69    buf = xmalloc(fs->blocksize * BUF_BLOCKS);
70
71    for (group = 0; group < fs->group_desc_count; group++) {
72        blk = fs->group_desc[(unsigned)group].bg_inode_table;
73        if (!blk)
74            return EXT2_ET_MISSING_INODE_TABLE;
75        left = fs->inode_blocks_per_group;
76        while (left) {
77            c = BUF_BLOCKS;
78            if (c > left)
79                c = left;
80            retval = io_channel_read_blk(fs->io, blk, c, buf);
81            if (retval)
82                goto errout;
83            cp = buf;
84            while (c) {
85                if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
86                    d = c;
87                    goto skip_sparse;
88                }
89                /* Skip zero blocks */
90                if (check_zero_block(cp, fs->blocksize)) {
91                    c--;
92                    blk++;
93                    left--;
94                    cp += fs->blocksize;
95                    lseek(fd, fs->blocksize, SEEK_CUR);
96                    continue;
97                }
98                /* Find non-zero blocks */
99                for (d=1; d < c; d++) {
100                    if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
101                        break;
102                }
103            skip_sparse:
104                actual = write(fd, cp, fs->blocksize * d);
105                if (actual == -1) {
106                    retval = errno;
107                    goto errout;
108                }
109                if (actual != (ssize_t) (fs->blocksize * d)) {
110                    retval = EXT2_ET_SHORT_WRITE;
111                    goto errout;
112                }
113                blk += d;
114                left -= d;
115                cp += fs->blocksize * d;
116                c -= d;
117            }
118        }
119    }
120    retval = 0;
121
122errout:
123    free(buf);
124    return retval;
125}
126
127/*
128 * Read in the inode table and stuff it into place
129 */
130errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
131                  int flags EXT2FS_ATTR((unused)))
132{
133    unsigned int    group, c, left;
134    char        *buf;
135    blk_t       blk;
136    ssize_t     actual;
137    errcode_t   retval;
138
139    buf = xmalloc(fs->blocksize * BUF_BLOCKS);
140
141    for (group = 0; group < fs->group_desc_count; group++) {
142        blk = fs->group_desc[(unsigned)group].bg_inode_table;
143        if (!blk) {
144            retval = EXT2_ET_MISSING_INODE_TABLE;
145            goto errout;
146        }
147        left = fs->inode_blocks_per_group;
148        while (left) {
149            c = BUF_BLOCKS;
150            if (c > left)
151                c = left;
152            actual = read(fd, buf, fs->blocksize * c);
153            if (actual == -1) {
154                retval = errno;
155                goto errout;
156            }
157            if (actual != (ssize_t) (fs->blocksize * c)) {
158                retval = EXT2_ET_SHORT_READ;
159                goto errout;
160            }
161            retval = io_channel_write_blk(fs->io, blk, c, buf);
162            if (retval)
163                goto errout;
164
165            blk += c;
166            left -= c;
167        }
168    }
169    retval = ext2fs_flush_icache(fs);
170
171errout:
172    free(buf);
173    return retval;
174}
175
176/*
177 * Write out superblock and group descriptors
178 */
179errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
180                   int flags EXT2FS_ATTR((unused)))
181{
182    char        *buf, *cp;
183    ssize_t     actual;
184    errcode_t   retval;
185
186    buf = xmalloc(fs->blocksize);
187
188    /*
189     * Write out the superblock
190     */
191    memset(buf, 0, fs->blocksize);
192    memcpy(buf, fs->super, SUPERBLOCK_SIZE);
193    actual = write(fd, buf, fs->blocksize);
194    if (actual == -1) {
195        retval = errno;
196        goto errout;
197    }
198    if (actual != (ssize_t) fs->blocksize) {
199        retval = EXT2_ET_SHORT_WRITE;
200        goto errout;
201    }
202
203    /*
204     * Now write out the block group descriptors
205     */
206    cp = (char *) fs->group_desc;
207    actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
208    if (actual == -1) {
209        retval = errno;
210        goto errout;
211    }
212    if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
213        retval = EXT2_ET_SHORT_WRITE;
214        goto errout;
215    }
216
217    retval = 0;
218
219errout:
220    free(buf);
221    return retval;
222}
223
224/*
225 * Read the superblock and group descriptors and overwrite them.
226 */
227errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
228                  int flags EXT2FS_ATTR((unused)))
229{
230    char        *buf;
231    ssize_t     actual, size;
232    errcode_t   retval;
233
234    size = fs->blocksize * (fs->group_desc_count + 1);
235    buf = xmalloc(size);
236
237    /*
238     * Read it all in.
239     */
240    actual = read(fd, buf, size);
241    if (actual == -1) {
242        retval = errno;
243        goto errout;
244    }
245    if (actual != size) {
246        retval = EXT2_ET_SHORT_READ;
247        goto errout;
248    }
249
250    /*
251     * Now copy in the superblock and group descriptors
252     */
253    memcpy(fs->super, buf, SUPERBLOCK_SIZE);
254
255    memcpy(fs->group_desc, buf + fs->blocksize,
256           fs->blocksize * fs->group_desc_count);
257
258    retval = 0;
259
260errout:
261    free(buf);
262    return retval;
263}
264
265/*
266 * Write the block/inode bitmaps.
267 */
268errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
269{
270    char        *ptr;
271    int     c, size;
272    char        zero_buf[1024];
273    ssize_t     actual;
274    errcode_t   retval;
275
276    if (flags & IMAGER_FLAG_INODEMAP) {
277        if (!fs->inode_map) {
278            retval = ext2fs_read_inode_bitmap(fs);
279            if (retval)
280                return retval;
281        }
282        ptr = fs->inode_map->bitmap;
283        size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
284    } else {
285        if (!fs->block_map) {
286            retval = ext2fs_read_block_bitmap(fs);
287            if (retval)
288                return retval;
289        }
290        ptr = fs->block_map->bitmap;
291        size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
292    }
293    size = size * fs->group_desc_count;
294
295    actual = write(fd, ptr, size);
296    if (actual == -1) {
297        retval = errno;
298        goto errout;
299    }
300    if (actual != size) {
301        retval = EXT2_ET_SHORT_WRITE;
302        goto errout;
303    }
304    size = size % fs->blocksize;
305    memset(zero_buf, 0, sizeof(zero_buf));
306    if (size) {
307        size = fs->blocksize - size;
308        while (size) {
309            c = size;
310            if (c > (int) sizeof(zero_buf))
311                c = sizeof(zero_buf);
312            actual = write(fd, zero_buf, c);
313            if (actual == -1) {
314                retval = errno;
315                goto errout;
316            }
317            if (actual != c) {
318                retval = EXT2_ET_SHORT_WRITE;
319                goto errout;
320            }
321            size -= c;
322        }
323    }
324    retval = 0;
325errout:
326    return (retval);
327}
328
329
330/*
331 * Read the block/inode bitmaps.
332 */
333errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
334{
335    char        *ptr, *buf = 0;
336    int     size;
337    ssize_t     actual;
338    errcode_t   retval;
339
340    if (flags & IMAGER_FLAG_INODEMAP) {
341        if (!fs->inode_map) {
342            retval = ext2fs_read_inode_bitmap(fs);
343            if (retval)
344                return retval;
345        }
346        ptr = fs->inode_map->bitmap;
347        size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
348    } else {
349        if (!fs->block_map) {
350            retval = ext2fs_read_block_bitmap(fs);
351            if (retval)
352                return retval;
353        }
354        ptr = fs->block_map->bitmap;
355        size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
356    }
357    size = size * fs->group_desc_count;
358
359    buf = xmalloc(size);
360
361    actual = read(fd, buf, size);
362    if (actual == -1) {
363        retval = errno;
364        goto errout;
365    }
366    if (actual != size) {
367        retval = EXT2_ET_SHORT_WRITE;
368        goto errout;
369    }
370    memcpy(ptr, buf, size);
371
372    retval = 0;
373errout:
374    free(buf);
375    return (retval);
376}
Note: See TracBrowser for help on using the repository browser.