1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/*
2587c4b3e94c6ef877137d067d5d0f574f69b1391Mark Wielaard * image.c --- writes out the critical parts of the filesystem as a
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * 	flat file.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Copyright (C) 2000 Theodore Ts'o.
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * Note: this uses the POSIX IO interfaces, unlike most of the other
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * functions in this library.  So sue me.
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard *
10b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * %Begin-Header%
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * This file may be redistributed under the terms of the GNU Library
12361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper * General Public License, version 2.
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * %End-Header%
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard */
15361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard#include <stdio.h>
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard#include <string.h>
18b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if HAVE_UNISTD_H
19b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <unistd.h>
20b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
21b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if HAVE_ERRNO_H
22b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <errno.h>
23b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
24b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <fcntl.h>
25b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <time.h>
26b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if HAVE_SYS_STAT_H
27b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/stat.h>
28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#if HAVE_SYS_TYPES_H
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/types.h>
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "ext2_fs.h"
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "ext2fs.h"
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifndef HAVE_TYPE_SSIZE_T
37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppertypedef int ssize_t;
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
40b337b1fd5f3b3410fe522a690ccee70bce8519eeRoland McGrath/*
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * This function returns 1 if the specified block is all zeros
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper */
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic int check_zero_block(char *buf, int blocksize)
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char	*cp = buf;
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	int	left = blocksize;
471662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while (left > 0) {
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (*cp++)
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			return 0;
51fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich Drepper		left--;
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	return 1;
54fdc93e12a77866cafd1aae4463d89cef2c01d9b1Ulrich Drepper}
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/*
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Write the inode table out as a single block.
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper */
59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#define BUF_BLOCKS	32
600b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
611662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaarderrcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	unsigned int	group, left, c, d;
64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char		*buf, *cp;
65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	blk64_t		blk;
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ssize_t		actual;
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	errcode_t	retval;
684be1524398af8e24011cfdfa77c66832f8654a56Roland McGrath	off_t		r;
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	buf = malloc(fs->blocksize * BUF_BLOCKS);
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (!buf)
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		return ENOMEM;
738f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	for (group = 0; group < fs->group_desc_count; group++) {
758f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath		blk = ext2fs_inode_table_loc(fs, (unsigned)group);
768f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath		if (!blk) {
770b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath			retval = EXT2_ET_MISSING_INODE_TABLE;
780b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath			goto errout;
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		left = fs->inode_blocks_per_group;
811662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		while (left) {
821662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			c = BUF_BLOCKS;
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (c > left)
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				c = left;
858f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath			retval = io_channel_read_blk64(fs->io, blk, c, buf);
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (retval)
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				goto errout;
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			cp = buf;
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			while (c) {
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				if (!(flags & IMAGER_FLAG_SPARSEWRITE)) {
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					d = c;
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					goto skip_sparse;
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				}
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				/* Skip zero blocks */
95b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				if (check_zero_block(cp, fs->blocksize)) {
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					c--;
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					blk++;
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					left--;
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					cp += fs->blocksize;
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					r = lseek(fd, fs->blocksize, SEEK_CUR);
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					if (r < 0) {
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						retval = errno;
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						goto errout;
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					}
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					continue;
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				}
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				/* Find non-zero blocks */
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				for (d=1; d < c; d++) {
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					if (check_zero_block(cp + d*fs->blocksize, fs->blocksize))
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						break;
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				}
1128c4aa0ef998191ed828a37190dc179b91649938aMax Filippov			skip_sparse:
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				actual = write(fd, cp, fs->blocksize * d);
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				if (actual == -1) {
115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					retval = errno;
116cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard					goto errout;
117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				}
1186d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				if (actual != (ssize_t) (fs->blocksize * d)) {
1196d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard					retval = EXT2_ET_SHORT_WRITE;
1206d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard					goto errout;
1216d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				}
1221ccdfb683ad6c7e59793136c3a657ddf131cafd1Mark Wielaard				blk += d;
1236d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				left -= d;
124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				cp += fs->blocksize * d;
1256d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard				c -= d;
1266d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard			}
1276d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard		}
1286d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	}
1296d93c8c46d9b2b381c889e5f176451996845b055Mark Wielaard	retval = 0;
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppererrout:
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free(buf);
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	return retval;
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/*
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Read in the inode table and stuff it into place
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper */
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppererrcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd,
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				  int flags EXT2FS_ATTR((unused)))
141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	unsigned int	group, c, left;
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char		*buf;
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	blk64_t		blk;
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ssize_t		actual;
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	errcode_t	retval;
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	buf = malloc(fs->blocksize * BUF_BLOCKS);
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (!buf)
1500b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath		return ENOMEM;
1510b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
1520b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	for (group = 0; group < fs->group_desc_count; group++) {
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		blk = ext2fs_inode_table_loc(fs, (unsigned)group);
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (!blk) {
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			retval = EXT2_ET_MISSING_INODE_TABLE;
1561662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard			goto errout;
1571662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		}
1581662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard		left = fs->inode_blocks_per_group;
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		while (left) {
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			c = BUF_BLOCKS;
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (c > left)
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				c = left;
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			actual = read(fd, buf, fs->blocksize * c);
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (actual == -1) {
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				retval = errno;
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				goto errout;
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (actual != (ssize_t) (fs->blocksize * c)) {
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				retval = EXT2_ET_SHORT_READ;
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				goto errout;
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			}
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			retval = io_channel_write_blk64(fs->io, blk, c, buf);
173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (retval)
174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				goto errout;
175b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper
176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			blk += c;
177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			left -= c;
178b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper		}
179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	retval = ext2fs_flush_icache(fs);
181b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppererrout:
183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free(buf);
1841662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	return retval;
1851662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard}
1861662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
1871662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard/*
188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Write out superblock and group descriptors
189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper */
190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppererrcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				   int flags EXT2FS_ATTR((unused)))
192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char		*buf, *cp;
194b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ssize_t		actual;
195b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	errcode_t	retval;
196b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
197b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	buf = malloc(fs->blocksize);
198b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (!buf)
199b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		return ENOMEM;
200b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
201b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/*
202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 * Write out the superblock
203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 */
204b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	memset(buf, 0, fs->blocksize);
205b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	memcpy(buf, fs->super, SUPERBLOCK_SIZE);
206b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	actual = write(fd, buf, fs->blocksize);
207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (actual == -1) {
208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		retval = errno;
209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		goto errout;
210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (actual != (ssize_t) fs->blocksize) {
212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		retval = EXT2_ET_SHORT_WRITE;
213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		goto errout;
214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
215b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/*
217b0243863149acde9e42b25688c7c2959830e69a9Ulrich Drepper	 * Now write out the block group descriptors
218b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 */
219b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	cp = (char *) fs->group_desc;
220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	actual = write(fd, cp, fs->blocksize * fs->desc_blocks);
221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (actual == -1) {
2223a64a3087f53ab860c7de04da0e53dabef459520Ulrich Drepper		retval = errno;
223b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		goto errout;
224b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
225b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) {
226b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		retval = EXT2_ET_SHORT_WRITE;
227b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		goto errout;
228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2291c83bf1fd46b74492297694b642df36d18c6e7b5Roland McGrath
230b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	retval = 0;
231b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppererrout:
233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	free(buf);
234b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	return retval;
235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/*
238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Read the superblock and group descriptors and overwrite them.
239b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper */
240b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppererrcode_t ext2fs_image_super_read(ext2_filsys fs, int fd,
241b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				  int flags EXT2FS_ATTR((unused)))
242b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
243b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char		*buf;
244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ssize_t		actual, size;
245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	errcode_t	retval;
246b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
247b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size = fs->blocksize * (fs->group_desc_count + 1);
248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	buf = malloc(size);
249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (!buf)
250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		return ENOMEM;
251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	/*
253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 * Read it all in.
254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 */
255b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	actual = read(fd, buf, size);
256b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (actual == -1) {
257b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		retval = errno;
258b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		goto errout;
259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (actual != size) {
261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		retval = EXT2_ET_SHORT_READ;
262b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		goto errout;
263b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
2641662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard
2651662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	/*
2661662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	 * Now copy in the superblock and group descriptors
2671662bc3880ae5acae6aa2a3013d193223c36f189Mark Wielaard	 */
268b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	memcpy(fs->super, buf, SUPERBLOCK_SIZE);
269b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	memcpy(fs->group_desc, buf + fs->blocksize,
271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	       fs->blocksize * fs->group_desc_count);
2728f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath
2738f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	retval = 0;
2748f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath
2758f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGratherrout:
2768f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	free(buf);
2778f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	return retval;
2788f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath}
2798f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath
2808f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath/*
2818f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath * Write the block/inode bitmaps.
2828f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath */
283b08d5a8fb42f4586d756068065186b5af7e48daUlrich Dreppererrcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
2848f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath{
2858f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath	ext2fs_generic_bitmap	bmap;
286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	errcode_t		retval;
287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ssize_t			actual;
288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	__u32			itr, cnt, size;
2890b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	int			c, total_size;
2900b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	char			buf[1024];
2910b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath
2920b9d1fb534604a9ba19999cd8ce8e7efce28da24Roland McGrath	if (flags & IMAGER_FLAG_INODEMAP) {
293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (!fs->inode_map) {
294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			retval = ext2fs_read_inode_bitmap(fs);
295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (retval)
296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				return retval;
2978f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath		}
2988f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath		bmap = fs->inode_map;
2998f31c2c6f18323daf2a6ce30a24fa4dfe0a70fb3Roland McGrath		itr = 1;
300b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	} else {
303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (!fs->block_map) {
304b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			retval = ext2fs_read_block_bitmap(fs);
305b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (retval)
306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				return retval;
307b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		bmap = fs->block_map;
309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		itr = fs->super->s_first_data_block;
310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
3133425454a10d307fae891fb667cf7969e945cde79Josh Stone	total_size = size * fs->group_desc_count;
3148c4aa0ef998191ed828a37190dc179b91649938aMax Filippov
315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while (cnt > 0) {
316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size = sizeof(buf);
317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (size > (cnt >> 3))
3183425454a10d307fae891fb667cf7969e945cde79Josh Stone			size = (cnt >> 3);
319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
320e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper		retval = ext2fs_get_generic_bmap_range(bmap, itr,
321b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						       size << 3, buf);
322b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (retval)
323b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			return retval;
324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		actual = write(fd, buf, size);
3268c4aa0ef998191ed828a37190dc179b91649938aMax Filippov		if (actual == -1)
3278c4aa0ef998191ed828a37190dc179b91649938aMax Filippov			return errno;
328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (actual != (int) size)
329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			return EXT2_ET_SHORT_READ;
330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
331095a01b14c2562a33615f079f300ac86da95bc56Roland McGrath		itr += size << 3;
332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		cnt -= size << 3;
333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
334e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper
335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	size = total_size % fs->blocksize;
336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	memset(buf, 0, sizeof(buf));
337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (size) {
338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size = fs->blocksize - size;
339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		while (size) {
340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			c = size;
3413425454a10d307fae891fb667cf7969e945cde79Josh Stone			if (c > (int) sizeof(buf))
3423425454a10d307fae891fb667cf7969e945cde79Josh Stone				c = sizeof(buf);
343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			actual = write(fd, buf, c);
344e3f9b7db6c7361579ec5cc5eb5e414f7e93baeb6Ulrich Drepper			if (actual == -1)
345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				return errno;
346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			if (actual != c)
347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				return EXT2_ET_SHORT_WRITE;
348b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			size -= c;
349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	return 0;
352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/*
356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper * Read the block/inode bitmaps.
357095a01b14c2562a33615f079f300ac86da95bc56Roland McGrath */
358095a01b14c2562a33615f079f300ac86da95bc56Roland McGratherrcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ext2fs_generic_bitmap	bmap;
361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	errcode_t		retval;
362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	__u32			itr, cnt;
363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	char			buf[1024];
364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	unsigned int		size;
365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	ssize_t			actual;
366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	if (flags & IMAGER_FLAG_INODEMAP) {
368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (!fs->inode_map) {
369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			retval = ext2fs_read_inode_bitmap(fs);
3708190db6a86a37aec86c81626ab1b083c96aff891Roland McGrath			if (retval)
371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				return retval;
3728190db6a86a37aec86c81626ab1b083c96aff891Roland McGrath		}
373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		bmap = fs->inode_map;
374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		itr = 1;
375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
377cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	} else {
378cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard		if (!fs->block_map) {
379cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard			retval = ext2fs_read_block_bitmap(fs);
380cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard			if (retval)
381cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard				return retval;
382cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard		}
383cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard		bmap = fs->block_map;
384cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard		itr = fs->super->s_first_data_block;
385cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard		cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
386cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard		size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
387cb499c489299de2b77472fc836a6b28ecf5361b9Mark Wielaard	}
388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	while (cnt > 0) {
390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		size = sizeof(buf);
391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (size > (cnt >> 3))
392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			size = (cnt >> 3);
393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		actual = read(fd, buf, size);
395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (actual == -1)
396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			return errno;
397b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (actual != (int) size)
398b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			return EXT2_ET_SHORT_READ;
399b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
400b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		retval = ext2fs_set_generic_bmap_range(bmap, itr,
401b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper						       size << 3, buf);
402b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		if (retval)
403b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			return retval;
404b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
405b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		itr += size << 3;
406b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		cnt -= size << 3;
407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	return 0;
409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
4108c4aa0ef998191ed828a37190dc179b91649938aMax Filippov