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