• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * e2image.c --- Program which writes an image file backing up
3  * critical metadata for the filesystem.
4  *
5  * Copyright 2000, 2001 by 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 #ifndef _LARGEFILE_SOURCE
14 #define _LARGEFILE_SOURCE
15 #endif
16 #ifndef _LARGEFILE64_SOURCE
17 #define _LARGEFILE64_SOURCE
18 #endif
19 
20 #include "config.h"
21 #include <fcntl.h>
22 #include <grp.h>
23 #ifdef HAVE_GETOPT_H
24 #include <getopt.h>
25 #else
26 extern char *optarg;
27 extern int optind;
28 #endif
29 #include <pwd.h>
30 #include <stdio.h>
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <errno.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <assert.h>
42 #include <signal.h>
43 
44 #include "ext2fs/ext2_fs.h"
45 #include "ext2fs/ext2fs.h"
46 #include "et/com_err.h"
47 #include "uuid/uuid.h"
48 #include "e2p/e2p.h"
49 #include "ext2fs/e2image.h"
50 #include "ext2fs/qcow2.h"
51 
52 #include "support/nls-enable.h"
53 #include "support/plausible.h"
54 #include "../version.h"
55 
56 #define QCOW_OFLAG_COPIED     (1LL << 63)
57 #define NO_BLK ((blk64_t) -1)
58 
59 /* Image types */
60 #define E2IMAGE_RAW	1
61 #define E2IMAGE_QCOW2	2
62 
63 /* Image flags */
64 #define E2IMAGE_INSTALL_FLAG	1
65 #define E2IMAGE_SCRAMBLE_FLAG	2
66 #define E2IMAGE_IS_QCOW2_FLAG	4
67 #define E2IMAGE_CHECK_ZERO_FLAG	8
68 
69 static const char * program_name = "e2image";
70 static char * device_name = NULL;
71 static char all_data;
72 static char output_is_blk;
73 static char nop_flag;
74 /* writing to blk device: don't skip zeroed blocks */
75 static blk64_t source_offset, dest_offset;
76 static char move_mode;
77 static char show_progress;
78 static char *check_buf;
79 static int skipped_blocks;
80 
align_offset(blk64_t offset,unsigned int n)81 static blk64_t align_offset(blk64_t offset, unsigned int n)
82 {
83 	return (offset + n - 1) & ~((blk64_t) n - 1);
84 }
85 
get_bits_from_size(size_t size)86 static int get_bits_from_size(size_t size)
87 {
88 	int res = 0;
89 
90 	if (size == 0)
91 		return -1;
92 
93 	while (size != 1) {
94 		/* Not a power of two */
95 		if (size & 1)
96 			return -1;
97 
98 		size >>= 1;
99 		res++;
100 	}
101 	return res;
102 }
103 
usage(void)104 static void usage(void)
105 {
106 	fprintf(stderr, _("Usage: %s [ -r|Q ] [ -fr ] device image-file\n"),
107 		program_name);
108 	fprintf(stderr, _("       %s -I device image-file\n"), program_name);
109 	fprintf(stderr, _("       %s -ra  [  -cfnp  ] [ -o src_offset ] "
110 			  "[ -O dest_offset ] src_fs [ dest_fs ]\n"),
111 		program_name);
112 	exit (1);
113 }
114 
seek_relative(int fd,int offset)115 static ext2_loff_t seek_relative(int fd, int offset)
116 {
117 	ext2_loff_t ret = ext2fs_llseek(fd, offset, SEEK_CUR);
118 	if (ret < 0) {
119 		perror("seek_relative");
120 		exit(1);
121 	}
122 	return ret;
123 }
124 
seek_set(int fd,ext2_loff_t offset)125 static ext2_loff_t seek_set(int fd, ext2_loff_t offset)
126 {
127 	ext2_loff_t ret = ext2fs_llseek(fd, offset, SEEK_SET);
128 	if (ret < 0) {
129 		perror("seek_set");
130 		exit(1);
131 	}
132 	return ret;
133 }
134 
135 /*
136  * Returns true if the block we are about to write is identical to
137  * what is already on the disk.
138  */
check_block(int fd,void * buf,void * cbuf,int blocksize)139 static int check_block(int fd, void *buf, void *cbuf, int blocksize)
140 {
141 	char *cp = cbuf;
142 	int count = blocksize, ret;
143 
144 	if (cbuf == NULL)
145 		return 0;
146 
147 	while (count > 0) {
148 		ret = read(fd, cp, count);
149 		if (ret < 0) {
150 			perror("check_block");
151 			exit(1);
152 		}
153 		count -= ret;
154 		cp += ret;
155 	}
156 	ret = memcmp(buf, cbuf, blocksize);
157 	seek_relative(fd, -blocksize);
158 	return (ret == 0) ? 1 : 0;
159 }
160 
generic_write(int fd,void * buf,int blocksize,blk64_t block)161 static void generic_write(int fd, void *buf, int blocksize, blk64_t block)
162 {
163 	int count, free_buf = 0;
164 	errcode_t err;
165 
166 	if (!blocksize)
167 		return;
168 
169 	if (!buf) {
170 		free_buf = 1;
171 		err = ext2fs_get_arrayzero(1, blocksize, &buf);
172 		if (err) {
173 			com_err(program_name, err, "%s",
174 				_("while allocating buffer"));
175 			exit(1);
176 		}
177 	}
178 	if (nop_flag) {
179 		printf(_("Writing block %llu\n"), (unsigned long long) block);
180 		if (fd != 1)
181 			seek_relative(fd, blocksize);
182 		goto free_and_return;
183 	}
184 	count = write(fd, buf, blocksize);
185 	if (count != blocksize) {
186 		if (count == -1)
187 			err = errno;
188 		else
189 			err = 0;
190 
191 		if (block)
192 			com_err(program_name, err,
193 				_("error writing block %llu"), block);
194 		else
195 			com_err(program_name, err, "%s",
196 				_("error in generic_write()"));
197 
198 		exit(1);
199 	}
200 free_and_return:
201 	if (free_buf)
202 		ext2fs_free_mem(&buf);
203 }
204 
write_header(int fd,void * hdr,int hdr_size,int wrt_size)205 static void write_header(int fd, void *hdr, int hdr_size, int wrt_size)
206 {
207 	char *header_buf;
208 	int ret;
209 
210 	/* Sanity check */
211 	if (hdr_size > wrt_size) {
212 		fprintf(stderr, "%s",
213 			_("Error: header size is bigger than wrt_size\n"));
214 	}
215 
216 	ret = ext2fs_get_mem(wrt_size, &header_buf);
217 	if (ret) {
218 		fputs(_("Couldn't allocate header buffer\n"), stderr);
219 		exit(1);
220 	}
221 
222 	seek_set(fd, 0);
223 	memset(header_buf, 0, wrt_size);
224 
225 	if (hdr)
226 		memcpy(header_buf, hdr, hdr_size);
227 
228 	generic_write(fd, header_buf, wrt_size, NO_BLK);
229 
230 	ext2fs_free_mem(&header_buf);
231 }
232 
write_image_file(ext2_filsys fs,int fd)233 static void write_image_file(ext2_filsys fs, int fd)
234 {
235 	struct ext2_image_hdr	hdr;
236 	struct stat		st;
237 	errcode_t		retval;
238 
239 	write_header(fd, NULL, sizeof(struct ext2_image_hdr), fs->blocksize);
240 	memset(&hdr, 0, sizeof(struct ext2_image_hdr));
241 
242 	hdr.offset_super = seek_relative(fd, 0);
243 	retval = ext2fs_image_super_write(fs, fd, 0);
244 	if (retval) {
245 		com_err(program_name, retval, "%s",
246 			_("while writing superblock"));
247 		exit(1);
248 	}
249 
250 	hdr.offset_inode = seek_relative(fd, 0);
251 	retval = ext2fs_image_inode_write(fs, fd,
252 				  (fd != 1) ? IMAGER_FLAG_SPARSEWRITE : 0);
253 	if (retval) {
254 		com_err(program_name, retval, "%s",
255 			_("while writing inode table"));
256 		exit(1);
257 	}
258 
259 	hdr.offset_blockmap = seek_relative(fd, 0);
260 	retval = ext2fs_image_bitmap_write(fs, fd, 0);
261 	if (retval) {
262 		com_err(program_name, retval, "%s",
263 			_("while writing block bitmap"));
264 		exit(1);
265 	}
266 
267 	hdr.offset_inodemap = seek_relative(fd, 0);
268 	retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP);
269 	if (retval) {
270 		com_err(program_name, retval, "%s",
271 			_("while writing inode bitmap"));
272 		exit(1);
273 	}
274 
275 	hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE;
276 	strcpy(hdr.magic_descriptor, "Ext2 Image 1.0");
277 	gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname));
278 	strncpy(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name)-1);
279 	hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0;
280 	hdr.fs_blocksize = fs->blocksize;
281 
282 	if (stat(device_name, &st) == 0)
283 		hdr.fs_device = st.st_rdev;
284 
285 	if (fstat(fd, &st) == 0) {
286 		hdr.image_device = st.st_dev;
287 		hdr.image_inode = st.st_ino;
288 	}
289 	memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid));
290 
291 	hdr.image_time = time(0);
292 	write_header(fd, &hdr, sizeof(struct ext2_image_hdr), fs->blocksize);
293 }
294 
295 /*
296  * These set of functions are used to write a RAW image file.
297  */
298 static ext2fs_block_bitmap meta_block_map;
299 static ext2fs_block_bitmap scramble_block_map;	/* Directory blocks to be scrambled */
300 static blk64_t meta_blocks_count;
301 
302 struct process_block_struct {
303 	ext2_ino_t	ino;
304 	int		is_dir;
305 };
306 
307 /*
308  * These subroutines short circuits ext2fs_get_blocks and
309  * ext2fs_check_directory; we use them since we already have the inode
310  * structure, so there's no point in letting the ext2fs library read
311  * the inode again.
312  */
313 static ino_t stashed_ino = 0;
314 static struct ext2_inode *stashed_inode;
315 
meta_get_blocks(ext2_filsys fs EXT2FS_ATTR ((unused)),ext2_ino_t ino,blk_t * blocks)316 static errcode_t meta_get_blocks(ext2_filsys fs EXT2FS_ATTR((unused)),
317 				 ext2_ino_t ino,
318 				 blk_t *blocks)
319 {
320 	int	i;
321 
322 	if ((ino != stashed_ino) || !stashed_inode)
323 		return EXT2_ET_CALLBACK_NOTHANDLED;
324 
325 	for (i=0; i < EXT2_N_BLOCKS; i++)
326 		blocks[i] = stashed_inode->i_block[i];
327 	return 0;
328 }
329 
meta_check_directory(ext2_filsys fs EXT2FS_ATTR ((unused)),ext2_ino_t ino)330 static errcode_t meta_check_directory(ext2_filsys fs EXT2FS_ATTR((unused)),
331 				      ext2_ino_t ino)
332 {
333 	if ((ino != stashed_ino) || !stashed_inode)
334 		return EXT2_ET_CALLBACK_NOTHANDLED;
335 
336 	if (!LINUX_S_ISDIR(stashed_inode->i_mode))
337 		return EXT2_ET_NO_DIRECTORY;
338 	return 0;
339 }
340 
meta_read_inode(ext2_filsys fs EXT2FS_ATTR ((unused)),ext2_ino_t ino,struct ext2_inode * inode)341 static errcode_t meta_read_inode(ext2_filsys fs EXT2FS_ATTR((unused)),
342 				 ext2_ino_t ino,
343 				 struct ext2_inode *inode)
344 {
345 	if ((ino != stashed_ino) || !stashed_inode)
346 		return EXT2_ET_CALLBACK_NOTHANDLED;
347 	*inode = *stashed_inode;
348 	return 0;
349 }
350 
use_inode_shortcuts(ext2_filsys fs,int use_shortcuts)351 static void use_inode_shortcuts(ext2_filsys fs, int use_shortcuts)
352 {
353 	if (use_shortcuts) {
354 		fs->get_blocks = meta_get_blocks;
355 		fs->check_directory = meta_check_directory;
356 		fs->read_inode = meta_read_inode;
357 		stashed_ino = 0;
358 	} else {
359 		fs->get_blocks = 0;
360 		fs->check_directory = 0;
361 		fs->read_inode = 0;
362 	}
363 }
364 
process_dir_block(ext2_filsys fs EXT2FS_ATTR ((unused)),blk64_t * block_nr,e2_blkcnt_t blockcnt EXT2FS_ATTR ((unused)),blk64_t ref_block EXT2FS_ATTR ((unused)),int ref_offset EXT2FS_ATTR ((unused)),void * priv_data EXT2FS_ATTR ((unused)))365 static int process_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)),
366 			     blk64_t *block_nr,
367 			     e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
368 			     blk64_t ref_block EXT2FS_ATTR((unused)),
369 			     int ref_offset EXT2FS_ATTR((unused)),
370 			     void *priv_data EXT2FS_ATTR((unused)))
371 {
372 	struct process_block_struct *p;
373 
374 	p = (struct process_block_struct *) priv_data;
375 
376 	ext2fs_mark_block_bitmap2(meta_block_map, *block_nr);
377 	meta_blocks_count++;
378 	if (scramble_block_map && p->is_dir && blockcnt >= 0)
379 		ext2fs_mark_block_bitmap2(scramble_block_map, *block_nr);
380 	return 0;
381 }
382 
process_file_block(ext2_filsys fs EXT2FS_ATTR ((unused)),blk64_t * block_nr,e2_blkcnt_t blockcnt,blk64_t ref_block EXT2FS_ATTR ((unused)),int ref_offset EXT2FS_ATTR ((unused)),void * priv_data EXT2FS_ATTR ((unused)))383 static int process_file_block(ext2_filsys fs EXT2FS_ATTR((unused)),
384 			      blk64_t *block_nr,
385 			      e2_blkcnt_t blockcnt,
386 			      blk64_t ref_block EXT2FS_ATTR((unused)),
387 			      int ref_offset EXT2FS_ATTR((unused)),
388 			      void *priv_data EXT2FS_ATTR((unused)))
389 {
390 	if (blockcnt < 0 || all_data) {
391 		ext2fs_mark_block_bitmap2(meta_block_map, *block_nr);
392 		meta_blocks_count++;
393 	}
394 	return 0;
395 }
396 
mark_table_blocks(ext2_filsys fs)397 static void mark_table_blocks(ext2_filsys fs)
398 {
399 	blk64_t	first_block, b;
400 	unsigned int	i,j;
401 
402 	first_block = fs->super->s_first_data_block;
403 	/*
404 	 * Mark primary superblock
405 	 */
406 	ext2fs_mark_block_bitmap2(meta_block_map, first_block);
407 	meta_blocks_count++;
408 
409 	/*
410 	 * Mark the primary superblock descriptors
411 	 */
412 	for (j = 0; j < fs->desc_blocks; j++) {
413 		ext2fs_mark_block_bitmap2(meta_block_map,
414 			 ext2fs_descriptor_block_loc2(fs, first_block, j));
415 	}
416 	meta_blocks_count += fs->desc_blocks;
417 
418 	for (i = 0; i < fs->group_desc_count; i++) {
419 		/*
420 		 * Mark the blocks used for the inode table
421 		 */
422 		if ((output_is_blk ||
423 		     !ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT)) &&
424 		    ext2fs_inode_table_loc(fs, i)) {
425 			unsigned int end = (unsigned) fs->inode_blocks_per_group;
426 			/* skip unused blocks */
427 			if (!output_is_blk && ext2fs_has_group_desc_csum(fs))
428 				end -= (ext2fs_bg_itable_unused(fs, i) /
429 					EXT2_INODES_PER_BLOCK(fs->super));
430 			for (j = 0, b = ext2fs_inode_table_loc(fs, i);
431 			     j < end;
432 			     j++, b++) {
433 				ext2fs_mark_block_bitmap2(meta_block_map, b);
434 				meta_blocks_count++;
435 			}
436 		}
437 
438 		/*
439 		 * Mark block used for the block bitmap
440 		 */
441 		if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) &&
442 		    ext2fs_block_bitmap_loc(fs, i)) {
443 			ext2fs_mark_block_bitmap2(meta_block_map,
444 				     ext2fs_block_bitmap_loc(fs, i));
445 			meta_blocks_count++;
446 		}
447 
448 		/*
449 		 * Mark block used for the inode bitmap
450 		 */
451 		if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) &&
452 		    ext2fs_inode_bitmap_loc(fs, i)) {
453 			ext2fs_mark_block_bitmap2(meta_block_map,
454 				 ext2fs_inode_bitmap_loc(fs, i));
455 			meta_blocks_count++;
456 		}
457 	}
458 }
459 
460 /*
461  * This function returns 1 if the specified block is all zeros
462  */
check_zero_block(char * buf,int blocksize)463 static int check_zero_block(char *buf, int blocksize)
464 {
465 	char	*cp = buf;
466 	int	left = blocksize;
467 
468 	if (output_is_blk)
469 		return 0;
470 	while (left > 0) {
471 		if (*cp++)
472 			return 0;
473 		left--;
474 	}
475 	return 1;
476 }
477 
478 static int name_id[256];
479 
480 #define EXT4_MAX_REC_LEN		((1<<16)-1)
481 
scramble_dir_block(ext2_filsys fs,blk64_t blk,char * buf)482 static void scramble_dir_block(ext2_filsys fs, blk64_t blk, char *buf)
483 {
484 	char *p, *end, *cp;
485 	struct ext2_dir_entry_2 *dirent;
486 	unsigned int rec_len;
487 	int id, len;
488 
489 	end = buf + fs->blocksize;
490 	for (p = buf; p < end-8; p += rec_len) {
491 		dirent = (struct ext2_dir_entry_2 *) p;
492 		rec_len = dirent->rec_len;
493 #ifdef WORDS_BIGENDIAN
494 		rec_len = ext2fs_swab16(rec_len);
495 #endif
496 		if (rec_len == EXT4_MAX_REC_LEN || rec_len == 0)
497 			rec_len = fs->blocksize;
498 		else
499 			rec_len = (rec_len & 65532) | ((rec_len & 3) << 16);
500 #if 0
501 		printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len);
502 #endif
503 		if (rec_len < 8 || (rec_len % 4) ||
504 		    (p+rec_len > end)) {
505 			printf(_("Corrupt directory block %llu: "
506 				 "bad rec_len (%d)\n"),
507 			       (unsigned long long) blk, rec_len);
508 			rec_len = end - p;
509 			(void) ext2fs_set_rec_len(fs, rec_len,
510 					(struct ext2_dir_entry *) dirent);
511 #ifdef WORDS_BIGENDIAN
512 			dirent->rec_len = ext2fs_swab16(dirent->rec_len);
513 #endif
514 			continue;
515 		}
516 		if (dirent->name_len + 8U > rec_len) {
517 			printf(_("Corrupt directory block %llu: "
518 				 "bad name_len (%d)\n"),
519 			       (unsigned long long) blk, dirent->name_len);
520 			dirent->name_len = rec_len - 8;
521 			continue;
522 		}
523 		cp = p+8;
524 		len = rec_len - dirent->name_len - 8;
525 		if (len > 0)
526 			memset(cp+dirent->name_len, 0, len);
527 		if (dirent->name_len==1 && cp[0] == '.')
528 			continue;
529 		if (dirent->name_len==2 && cp[0] == '.' && cp[1] == '.')
530 			continue;
531 
532 		memset(cp, 'A', dirent->name_len);
533 		len = dirent->name_len;
534 		id = name_id[len]++;
535 		while ((len > 0) && (id > 0)) {
536 			*cp += id % 26;
537 			id = id / 26;
538 			cp++;
539 			len--;
540 		}
541 	}
542 }
543 
544 static char got_sigint;
545 
sigint_handler(int unused EXT2FS_ATTR ((unused)))546 static void sigint_handler(int unused EXT2FS_ATTR((unused)))
547 {
548 	got_sigint = 1;
549 	signal (SIGINT, SIG_DFL);
550 }
551 
552 #define calc_percent(a, b) ((int) ((100.0 * (((float) (a)) / \
553 					     ((float) (b)))) + 0.5))
554 #define calc_rate(t, b, d) (((float)(t) / ((1024 * 1024) / (b))) / (d))
555 
print_progress(blk64_t num,blk64_t total)556 static int print_progress(blk64_t num, blk64_t total)
557 {
558 	return fprintf(stderr, _("%llu / %llu blocks (%d%%)"), num, total,
559 		      calc_percent(num, total));
560 }
561 
output_meta_data_blocks(ext2_filsys fs,int fd,int flags)562 static void output_meta_data_blocks(ext2_filsys fs, int fd, int flags)
563 {
564 	errcode_t	retval;
565 	blk64_t		blk;
566 	char		*buf, *zero_buf;
567 	int		sparse = 0;
568 	blk64_t		start = 0;
569 	blk64_t		distance = 0;
570 	blk64_t		end = ext2fs_blocks_count(fs->super);
571 	time_t		last_update = 0;
572 	time_t		start_time = 0;
573 	blk64_t		total_written = 0;
574 	int		bscount = 0;
575 
576 	retval = ext2fs_get_mem(fs->blocksize, &buf);
577 	if (retval) {
578 		com_err(program_name, retval, "%s",
579 			_("while allocating buffer"));
580 		exit(1);
581 	}
582 	retval = ext2fs_get_memzero(fs->blocksize, &zero_buf);
583 	if (retval) {
584 		com_err(program_name, retval, "%s",
585 			_("while allocating buffer"));
586 		exit(1);
587 	}
588 	if (show_progress) {
589 		fprintf(stderr, "%s", _("Copying "));
590 		bscount = print_progress(total_written, meta_blocks_count);
591 		fflush(stderr);
592 		last_update = time(NULL);
593 		start_time = time(NULL);
594 	}
595 	/* when doing an in place move to the right, you can't start
596 	   at the beginning or you will overwrite data, so instead
597 	   divide the fs up into distance size chunks and write them
598 	   in reverse. */
599 	if (move_mode && dest_offset > source_offset) {
600 		distance = (dest_offset - source_offset) / fs->blocksize;
601 		if (distance < ext2fs_blocks_count(fs->super))
602 			start = ext2fs_blocks_count(fs->super) - distance;
603 	}
604 	if (move_mode)
605 		signal (SIGINT, sigint_handler);
606 more_blocks:
607 	if (distance)
608 		seek_set(fd, (start * fs->blocksize) + dest_offset);
609 	for (blk = start; blk < end; blk++) {
610 		if (got_sigint) {
611 			if (distance) {
612 				/* moving to the right */
613 				if (distance >= ext2fs_blocks_count(fs->super)||
614 				    start == ext2fs_blocks_count(fs->super) -
615 						distance)
616 					kill(getpid(), SIGINT);
617 			} else {
618 				/* moving to the left */
619 				if (blk < (source_offset - dest_offset) /
620 				    fs->blocksize)
621 					kill(getpid(), SIGINT);
622 			}
623 			if (show_progress)
624 				fputc('\r', stderr);
625 			fprintf(stderr, "%s",
626 				_("Stopping now will destroy the filesystem, "
627 				 "interrupt again if you are sure\n"));
628 			if (show_progress) {
629 				fprintf(stderr, "%s", _("Copying "));
630 				bscount = print_progress(total_written,
631 							 meta_blocks_count);
632 				fflush(stderr);
633 			}
634 
635 			got_sigint = 0;
636 		}
637 		if (show_progress && last_update != time(NULL)) {
638 			time_t duration;
639 			last_update = time(NULL);
640 			while (bscount--)
641 				fputc('\b', stderr);
642 			bscount = print_progress(total_written,
643 						 meta_blocks_count);
644 			duration = time(NULL) - start_time;
645 			if (duration > 5 && total_written) {
646 				time_t est = (duration * meta_blocks_count /
647 					      total_written) - duration;
648 				char buff[30];
649 				strftime(buff, 30, "%T", gmtime(&est));
650 				bscount +=
651 					fprintf(stderr,
652 						_(" %s remaining at %.2f MB/s"),
653 						buff, calc_rate(total_written,
654 								fs->blocksize,
655 								duration));
656 			}
657 			fflush (stderr);
658 		}
659 		if ((blk >= fs->super->s_first_data_block) &&
660 		    ext2fs_test_block_bitmap2(meta_block_map, blk)) {
661 			retval = io_channel_read_blk64(fs->io, blk, 1, buf);
662 			if (retval) {
663 				com_err(program_name, retval,
664 					_("error reading block %llu"), blk);
665 			}
666 			total_written++;
667 			if (scramble_block_map &&
668 			    ext2fs_test_block_bitmap2(scramble_block_map, blk))
669 				scramble_dir_block(fs, blk, buf);
670 			if ((flags & E2IMAGE_CHECK_ZERO_FLAG) &&
671 			    check_zero_block(buf, fs->blocksize))
672 				goto sparse_write;
673 			if (sparse)
674 				seek_relative(fd, sparse);
675 			sparse = 0;
676 			if (check_block(fd, buf, check_buf, fs->blocksize)) {
677 				seek_relative(fd, fs->blocksize);
678 				skipped_blocks++;
679 			} else
680 				generic_write(fd, buf, fs->blocksize, blk);
681 		} else {
682 		sparse_write:
683 			if (fd == 1) {
684 				if (!nop_flag)
685 					generic_write(fd, zero_buf,
686 						      fs->blocksize, blk);
687 				continue;
688 			}
689 			sparse += fs->blocksize;
690 			if (sparse > 1024*1024) {
691 				seek_relative(fd, 1024*1024);
692 				sparse -= 1024*1024;
693 			}
694 		}
695 	}
696 	if (distance && start) {
697 		if (start < distance) {
698 			end = start;
699 			start = 0;
700 		} else {
701 			end -= distance;
702 			start -= distance;
703 			if (end < distance) {
704 				/* past overlap, do rest in one go */
705 				end = start;
706 				start = 0;
707 			}
708 		}
709 		sparse = 0;
710 		goto more_blocks;
711 	}
712 	signal (SIGINT, SIG_DFL);
713 	if (show_progress) {
714 		time_t duration = time(NULL) - start_time;
715 		char buff[30];
716 		fputc('\r', stderr);
717 		strftime(buff, 30, "%T", gmtime(&duration));
718 		fprintf(stderr, _("Copied %llu / %llu blocks (%d%%) in %s "),
719 			total_written, meta_blocks_count,
720 			calc_percent(total_written, meta_blocks_count), buff);
721 		if (duration)
722 			fprintf(stderr, _("at %.2f MB/s"),
723 				calc_rate(total_written, fs->blocksize, duration));
724 		fputs("       \n", stderr);
725 	}
726 #ifdef HAVE_FTRUNCATE64
727 	if (sparse) {
728 		ext2_loff_t offset;
729 		if (distance)
730 			offset = seek_set(fd,
731 					  fs->blocksize * ext2fs_blocks_count(fs->super) + dest_offset);
732 		else
733 			offset = seek_relative(fd, sparse);
734 
735 		if (ftruncate64(fd, offset) < 0) {
736 			seek_relative(fd, -1);
737 			generic_write(fd, zero_buf, 1, NO_BLK);
738 		}
739 	}
740 #else
741 	if (sparse && !distance) {
742 		seek_relative(fd, sparse-1);
743 		generic_write(fd, zero_buf, 1, NO_BLK);
744 	}
745 #endif
746 	ext2fs_free_mem(&zero_buf);
747 	ext2fs_free_mem(&buf);
748 }
749 
init_l1_table(struct ext2_qcow2_image * image)750 static void init_l1_table(struct ext2_qcow2_image *image)
751 {
752 	__u64 *l1_table;
753 	errcode_t ret;
754 
755 	ret = ext2fs_get_arrayzero(image->l1_size, sizeof(__u64), &l1_table);
756 	if (ret) {
757 		com_err(program_name, ret, "%s",
758 			_("while allocating l1 table"));
759 		exit(1);
760 	}
761 
762 	image->l1_table = l1_table;
763 }
764 
init_l2_cache(struct ext2_qcow2_image * image)765 static void init_l2_cache(struct ext2_qcow2_image *image)
766 {
767 	unsigned int count, i;
768 	struct ext2_qcow2_l2_cache *cache;
769 	struct ext2_qcow2_l2_table *table;
770 	errcode_t ret;
771 
772 	ret = ext2fs_get_arrayzero(1, sizeof(struct ext2_qcow2_l2_cache),
773 				   &cache);
774 	if (ret)
775 		goto alloc_err;
776 
777 	count = (image->l1_size > L2_CACHE_PREALLOC) ? L2_CACHE_PREALLOC :
778 		 image->l1_size;
779 
780 	cache->count = count;
781 	cache->free = count;
782 	cache->next_offset = image->l2_offset;
783 
784 	for (i = 0; i < count; i++) {
785 		ret = ext2fs_get_arrayzero(1,
786 				sizeof(struct ext2_qcow2_l2_table), &table);
787 		if (ret)
788 			goto alloc_err;
789 
790 		ret = ext2fs_get_arrayzero(image->l2_size,
791 						   sizeof(__u64), &table->data);
792 		if (ret)
793 			goto alloc_err;
794 
795 		table->next = cache->free_head;
796 		cache->free_head = table;
797 	}
798 
799 	image->l2_cache = cache;
800 	return;
801 
802 alloc_err:
803 	com_err(program_name, ret, "%s", _("while allocating l2 cache"));
804 	exit(1);
805 }
806 
put_l2_cache(struct ext2_qcow2_image * image)807 static void put_l2_cache(struct ext2_qcow2_image *image)
808 {
809 	struct ext2_qcow2_l2_cache *cache = image->l2_cache;
810 	struct ext2_qcow2_l2_table *tmp, *table;
811 
812 	if (!cache)
813 		return;
814 
815 	table = cache->free_head;
816 	cache->free_head = NULL;
817 again:
818 	while (table) {
819 		tmp = table;
820 		table = table->next;
821 		ext2fs_free_mem(&tmp->data);
822 		ext2fs_free_mem(&tmp);
823 	}
824 
825 	if (cache->free != cache->count) {
826 		fprintf(stderr, "%s", _("Warning: There are still tables in "
827 					"the cache while putting the cache, "
828 					"data will be lost so the image may "
829 					"not be valid.\n"));
830 		table = cache->used_head;
831 		cache->used_head = NULL;
832 		goto again;
833 	}
834 
835 	ext2fs_free_mem(&cache);
836 }
837 
init_refcount(struct ext2_qcow2_image * img,blk64_t table_offset)838 static int init_refcount(struct ext2_qcow2_image *img, blk64_t table_offset)
839 {
840 	struct	ext2_qcow2_refcount	*ref;
841 	blk64_t table_clusters;
842 	errcode_t ret;
843 
844 	ref = &(img->refcount);
845 
846 	/*
847 	 * One refcount block addresses 2048 clusters, one refcount table
848 	 * addresses cluster/sizeof(__u64) refcount blocks, and we need
849 	 * to address meta_blocks_count clusters + qcow2 metadata clusters
850 	 * in the worst case.
851 	 */
852 	table_clusters = meta_blocks_count + (table_offset >>
853 					      img->cluster_bits);
854 	table_clusters >>= (img->cluster_bits + 6 - 1);
855 	table_clusters = (table_clusters == 0) ? 1 : table_clusters;
856 
857 	ref->refcount_table_offset = table_offset;
858 	ref->refcount_table_clusters = table_clusters;
859 	ref->refcount_table_index = 0;
860 	ref->refcount_block_index = 0;
861 
862 	/* Allocate refcount table */
863 	ret = ext2fs_get_arrayzero(ref->refcount_table_clusters,
864 				   img->cluster_size, &ref->refcount_table);
865 	if (ret)
866 		return ret;
867 
868 	/* Allocate refcount block */
869 	ret = ext2fs_get_arrayzero(1, img->cluster_size, &ref->refcount_block);
870 	if (ret)
871 		ext2fs_free_mem(&ref->refcount_table);
872 
873 	return ret;
874 }
875 
initialize_qcow2_image(int fd,ext2_filsys fs,struct ext2_qcow2_image * image)876 static int initialize_qcow2_image(int fd, ext2_filsys fs,
877 			    struct ext2_qcow2_image *image)
878 {
879 	struct ext2_qcow2_hdr *header;
880 	blk64_t total_size, offset;
881 	int shift, l2_bits, header_size, l1_size, ret;
882 	int cluster_bits = get_bits_from_size(fs->blocksize);
883 	struct ext2_super_block *sb = fs->super;
884 
885 	/* Allocate header */
886 	ret = ext2fs_get_memzero(sizeof(struct ext2_qcow2_hdr), &header);
887 	if (ret)
888 		return ret;
889 
890 	total_size = ext2fs_blocks_count(sb) << cluster_bits;
891 	image->cluster_size = fs->blocksize;
892 	image->l2_size = 1 << (cluster_bits - 3);
893 	image->cluster_bits = cluster_bits;
894 	image->fd = fd;
895 
896 	header->magic = ext2fs_cpu_to_be32(QCOW_MAGIC);
897 	header->version = ext2fs_cpu_to_be32(QCOW_VERSION);
898 	header->size = ext2fs_cpu_to_be64(total_size);
899 	header->cluster_bits = ext2fs_cpu_to_be32(cluster_bits);
900 
901 	header_size = (sizeof(struct ext2_qcow2_hdr) + 7) & ~7;
902 	offset = align_offset(header_size, image->cluster_size);
903 
904 	header->l1_table_offset = ext2fs_cpu_to_be64(offset);
905 	image->l1_offset = offset;
906 
907 	l2_bits = cluster_bits - 3;
908 	shift = cluster_bits + l2_bits;
909 	l1_size = ((total_size + (1LL << shift) - 1) >> shift);
910 	header->l1_size = ext2fs_cpu_to_be32(l1_size);
911 	image->l1_size = l1_size;
912 
913 	/* Make space for L1 table */
914 	offset += align_offset(l1_size * sizeof(blk64_t), image->cluster_size);
915 
916 	/* Initialize refcounting */
917 	ret = init_refcount(image, offset);
918 	if (ret) {
919 		ext2fs_free_mem(&header);
920 		return ret;
921 	}
922 	header->refcount_table_offset = ext2fs_cpu_to_be64(offset);
923 	header->refcount_table_clusters =
924 		ext2fs_cpu_to_be32(image->refcount.refcount_table_clusters);
925 	offset += image->cluster_size;
926 	offset += image->refcount.refcount_table_clusters <<
927 		image->cluster_bits;
928 
929 	/* Make space for L2 tables */
930 	image->l2_offset = offset;
931 	offset += image->cluster_size;
932 
933 	/* Make space for first refcount block */
934 	image->refcount.refcount_block_offset = offset;
935 
936 	image->hdr = header;
937 	/* Initialize l1 and l2 tables */
938 	init_l1_table(image);
939 	init_l2_cache(image);
940 
941 	return 0;
942 }
943 
free_qcow2_image(struct ext2_qcow2_image * img)944 static void free_qcow2_image(struct ext2_qcow2_image *img)
945 {
946 	if (!img)
947 		return;
948 
949 	if (img->hdr)
950 		ext2fs_free_mem(&img->hdr);
951 
952 	if (img->l1_table)
953 		ext2fs_free_mem(&img->l1_table);
954 
955 	if (img->refcount.refcount_table)
956 		ext2fs_free_mem(&img->refcount.refcount_table);
957 	if (img->refcount.refcount_block)
958 		ext2fs_free_mem(&img->refcount.refcount_block);
959 
960 	put_l2_cache(img);
961 
962 	ext2fs_free_mem(&img);
963 }
964 
965 /**
966  * Put table from used list (used_head) into free list (free_head).
967  * l2_table is used to return pointer to the next used table (used_head).
968  */
put_used_table(struct ext2_qcow2_image * img,struct ext2_qcow2_l2_table ** l2_table)969 static void put_used_table(struct ext2_qcow2_image *img,
970 			  struct ext2_qcow2_l2_table **l2_table)
971 {
972 	struct ext2_qcow2_l2_cache *cache = img->l2_cache;
973 	struct ext2_qcow2_l2_table *table;
974 
975 	table = cache->used_head;
976 	cache->used_head = table->next;
977 
978 	assert(table);
979 	if (!table->next)
980 		cache->used_tail = NULL;
981 
982 	/* Clean the table for case we will need to use it again */
983 	memset(table->data, 0, img->cluster_size);
984 	table->next = cache->free_head;
985 	cache->free_head = table;
986 
987 	cache->free++;
988 
989 	*l2_table = cache->used_head;
990 }
991 
flush_l2_cache(struct ext2_qcow2_image * image)992 static void flush_l2_cache(struct ext2_qcow2_image *image)
993 {
994 	blk64_t seek = 0;
995 	ext2_loff_t offset;
996 	struct ext2_qcow2_l2_cache *cache = image->l2_cache;
997 	struct ext2_qcow2_l2_table *table = cache->used_head;
998 	int fd = image->fd;
999 
1000 	/* Store current position */
1001 	offset = seek_relative(fd, 0);
1002 
1003 	assert(table);
1004 	while (cache->free < cache->count) {
1005 		if (seek != table->offset) {
1006 			seek_set(fd, table->offset);
1007 			seek = table->offset;
1008 		}
1009 
1010 		generic_write(fd, (char *)table->data, image->cluster_size,
1011 			      NO_BLK);
1012 		put_used_table(image, &table);
1013 		seek += image->cluster_size;
1014 	}
1015 
1016 	/* Restore previous position */
1017 	seek_set(fd, offset);
1018 }
1019 
1020 /**
1021  * Get first free table (from free_head) and put it into tail of used list
1022  * (to used_tail).
1023  * l2_table is used to return pointer to moved table.
1024  * Returns 1 if the cache is full, 0 otherwise.
1025  */
get_free_table(struct ext2_qcow2_image * image,struct ext2_qcow2_l2_table ** l2_table)1026 static void get_free_table(struct ext2_qcow2_image *image,
1027 			  struct ext2_qcow2_l2_table **l2_table)
1028 {
1029 	struct ext2_qcow2_l2_table *table;
1030 	struct ext2_qcow2_l2_cache *cache = image->l2_cache;
1031 
1032 	if (0 == cache->free)
1033 		flush_l2_cache(image);
1034 
1035 	table = cache->free_head;
1036 	assert(table);
1037 	cache->free_head = table->next;
1038 
1039 	if (cache->used_tail)
1040 		cache->used_tail->next = table;
1041 	else
1042 		/* First item in the used list */
1043 		cache->used_head = table;
1044 
1045 	cache->used_tail = table;
1046 	cache->free--;
1047 
1048 	*l2_table = table;
1049 }
1050 
add_l2_item(struct ext2_qcow2_image * img,blk64_t blk,blk64_t data,blk64_t next)1051 static int add_l2_item(struct ext2_qcow2_image *img, blk64_t blk,
1052 		       blk64_t data, blk64_t next)
1053 {
1054 	struct ext2_qcow2_l2_cache *cache = img->l2_cache;
1055 	struct ext2_qcow2_l2_table *table = cache->used_tail;
1056 	blk64_t l1_index = blk / img->l2_size;
1057 	blk64_t l2_index = blk & (img->l2_size - 1);
1058 	int ret = 0;
1059 
1060 	/*
1061 	 * Need to create new table if it does not exist,
1062 	 * or if it is full
1063 	 */
1064 	if (!table || (table->l1_index != l1_index)) {
1065 		get_free_table(img, &table);
1066 		table->l1_index = l1_index;
1067 		table->offset = cache->next_offset;
1068 		cache->next_offset = next;
1069 		img->l1_table[l1_index] =
1070 			ext2fs_cpu_to_be64(table->offset | QCOW_OFLAG_COPIED);
1071 		ret++;
1072 	}
1073 
1074 	table->data[l2_index] = ext2fs_cpu_to_be64(data | QCOW_OFLAG_COPIED);
1075 	return ret;
1076 }
1077 
update_refcount(int fd,struct ext2_qcow2_image * img,blk64_t offset,blk64_t rfblk_pos)1078 static int update_refcount(int fd, struct ext2_qcow2_image *img,
1079 			   blk64_t offset, blk64_t rfblk_pos)
1080 {
1081 	struct	ext2_qcow2_refcount	*ref;
1082 	__u32	table_index;
1083 	int ret = 0;
1084 
1085 	ref = &(img->refcount);
1086 	table_index = offset >> (2 * img->cluster_bits - 1);
1087 
1088 	/*
1089 	 * Need to create new refcount block when the offset addresses
1090 	 * another item in the refcount table
1091 	 */
1092 	if (table_index != ref->refcount_table_index) {
1093 
1094 		seek_set(fd, ref->refcount_block_offset);
1095 
1096 		generic_write(fd, (char *)ref->refcount_block,
1097 			      img->cluster_size, NO_BLK);
1098 		memset(ref->refcount_block, 0, img->cluster_size);
1099 
1100 		ref->refcount_table[ref->refcount_table_index] =
1101 			ext2fs_cpu_to_be64(ref->refcount_block_offset);
1102 		ref->refcount_block_offset = rfblk_pos;
1103 		ref->refcount_block_index = 0;
1104 		ref->refcount_table_index = table_index;
1105 		ret++;
1106 	}
1107 
1108 	/*
1109 	 * We are relying on the fact that we are creating the qcow2
1110 	 * image sequentially, hence we will always allocate refcount
1111 	 * block items sequentialy.
1112 	 */
1113 	ref->refcount_block[ref->refcount_block_index] = ext2fs_cpu_to_be16(1);
1114 	ref->refcount_block_index++;
1115 	return ret;
1116 }
1117 
sync_refcount(int fd,struct ext2_qcow2_image * img)1118 static int sync_refcount(int fd, struct ext2_qcow2_image *img)
1119 {
1120 	struct	ext2_qcow2_refcount	*ref;
1121 
1122 	ref = &(img->refcount);
1123 
1124 	ref->refcount_table[ref->refcount_table_index] =
1125 		ext2fs_cpu_to_be64(ref->refcount_block_offset);
1126 	seek_set(fd, ref->refcount_table_offset);
1127 	generic_write(fd, (char *)ref->refcount_table,
1128 		ref->refcount_table_clusters << img->cluster_bits, NO_BLK);
1129 
1130 	seek_set(fd, ref->refcount_block_offset);
1131 	generic_write(fd, (char *)ref->refcount_block, img->cluster_size,
1132 		      NO_BLK);
1133 	return 0;
1134 }
1135 
output_qcow2_meta_data_blocks(ext2_filsys fs,int fd)1136 static void output_qcow2_meta_data_blocks(ext2_filsys fs, int fd)
1137 {
1138 	errcode_t		retval;
1139 	blk64_t			blk, offset, size, end;
1140 	char			*buf;
1141 	struct ext2_qcow2_image	*img;
1142 	unsigned int		header_size;
1143 
1144 	/* allocate  struct ext2_qcow2_image */
1145 	retval = ext2fs_get_mem(sizeof(struct ext2_qcow2_image), &img);
1146 	if (retval) {
1147 		com_err(program_name, retval, "%s",
1148 			_("while allocating ext2_qcow2_image"));
1149 		exit(1);
1150 	}
1151 
1152 	retval = initialize_qcow2_image(fd, fs, img);
1153 	if (retval) {
1154 		com_err(program_name, retval, "%s",
1155 			_("while initializing ext2_qcow2_image"));
1156 		exit(1);
1157 	}
1158 	header_size = align_offset(sizeof(struct ext2_qcow2_hdr),
1159 				   img->cluster_size);
1160 	write_header(fd, img->hdr, sizeof(struct ext2_qcow2_hdr), header_size);
1161 
1162 	/* Refcount all qcow2 related metadata up to refcount_block_offset */
1163 	end = img->refcount.refcount_block_offset;
1164 	seek_set(fd, end);
1165 	blk = end + img->cluster_size;
1166 	for (offset = 0; offset <= end; offset += img->cluster_size) {
1167 		if (update_refcount(fd, img, offset, blk)) {
1168 			blk += img->cluster_size;
1169 			/*
1170 			 * If we create new refcount block, we need to refcount
1171 			 * it as well.
1172 			 */
1173 			end += img->cluster_size;
1174 		}
1175 	}
1176 	seek_set(fd, offset);
1177 
1178 	retval = ext2fs_get_mem(fs->blocksize, &buf);
1179 	if (retval) {
1180 		com_err(program_name, retval, "%s",
1181 			_("while allocating buffer"));
1182 		exit(1);
1183 	}
1184 	/* Write qcow2 data blocks */
1185 	for (blk = 0; blk < ext2fs_blocks_count(fs->super); blk++) {
1186 		if ((blk >= fs->super->s_first_data_block) &&
1187 		    ext2fs_test_block_bitmap2(meta_block_map, blk)) {
1188 			retval = io_channel_read_blk64(fs->io, blk, 1, buf);
1189 			if (retval) {
1190 				com_err(program_name, retval,
1191 					_("error reading block %llu"), blk);
1192 				continue;
1193 			}
1194 			if (scramble_block_map &&
1195 			    ext2fs_test_block_bitmap2(scramble_block_map, blk))
1196 				scramble_dir_block(fs, blk, buf);
1197 			if (check_zero_block(buf, fs->blocksize))
1198 				continue;
1199 
1200 			if (update_refcount(fd, img, offset, offset)) {
1201 				/* Make space for another refcount block */
1202 				offset += img->cluster_size;
1203 				seek_set(fd, offset);
1204 				/*
1205 				 * We have created the new refcount block, this
1206 				 * means that we need to refcount it as well.
1207 				 * So the previous update_refcount refcounted
1208 				 * the block itself and now we are going to
1209 				 * create refcount for data. New refcount
1210 				 * block should not be created!
1211 				 */
1212 				if (update_refcount(fd, img, offset, offset)) {
1213 					fprintf(stderr, "%s",
1214 						_("Programming error: multiple "
1215 						  "sequential refcount blocks "
1216 						  "created!\n"));
1217 					exit(1);
1218 				}
1219 			}
1220 
1221 			generic_write(fd, buf, fs->blocksize, blk);
1222 
1223 			if (add_l2_item(img, blk, offset,
1224 					offset + img->cluster_size)) {
1225 				offset += img->cluster_size;
1226 				if (update_refcount(fd, img, offset,
1227 					offset + img->cluster_size)) {
1228 					offset += img->cluster_size;
1229 					if (update_refcount(fd, img, offset,
1230 							    offset)) {
1231 						fprintf(stderr, "%s",
1232 			_("Programming error: multiple sequential refcount "
1233 			  "blocks created!\n"));
1234 						exit(1);
1235 					}
1236 				}
1237 				offset += img->cluster_size;
1238 				seek_set(fd, offset);
1239 				continue;
1240 			}
1241 
1242 			offset += img->cluster_size;
1243 		}
1244 	}
1245 	update_refcount(fd, img, offset, offset);
1246 	flush_l2_cache(img);
1247 	sync_refcount(fd, img);
1248 
1249 	/* Write l1_table*/
1250 	seek_set(fd, img->l1_offset);
1251 	size = img->l1_size * sizeof(__u64);
1252 	generic_write(fd, (char *)img->l1_table, size, NO_BLK);
1253 
1254 	ext2fs_free_mem(&buf);
1255 	free_qcow2_image(img);
1256 }
1257 
write_raw_image_file(ext2_filsys fs,int fd,int type,int flags)1258 static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags)
1259 {
1260 	struct process_block_struct	pb;
1261 	struct ext2_inode		inode;
1262 	ext2_inode_scan			scan;
1263 	ext2_ino_t			ino;
1264 	errcode_t			retval;
1265 	char *				block_buf;
1266 
1267 	meta_blocks_count = 0;
1268 	retval = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
1269 					      &meta_block_map);
1270 	if (retval) {
1271 		com_err(program_name, retval, "%s",
1272 			_("while allocating block bitmap"));
1273 		exit(1);
1274 	}
1275 
1276 	if (flags & E2IMAGE_SCRAMBLE_FLAG) {
1277 		retval = ext2fs_allocate_block_bitmap(fs, "scramble block map",
1278 						      &scramble_block_map);
1279 		if (retval) {
1280 			com_err(program_name, retval, "%s",
1281 				_("while allocating scramble block bitmap"));
1282 			exit(1);
1283 		}
1284 	}
1285 
1286 	mark_table_blocks(fs);
1287 	if (show_progress)
1288 		fprintf(stderr, "%s", _("Scanning inodes...\n"));
1289 
1290 	retval = ext2fs_open_inode_scan(fs, 0, &scan);
1291 	if (retval) {
1292 		com_err(program_name, retval, "%s",
1293 			_("while opening inode scan"));
1294 		exit(1);
1295 	}
1296 
1297 	retval = ext2fs_get_mem(fs->blocksize * 3, &block_buf);
1298 	if (retval) {
1299 		com_err(program_name, 0, "%s",
1300 			_("Can't allocate block buffer"));
1301 		exit(1);
1302 	}
1303 
1304 	use_inode_shortcuts(fs, 1);
1305 	stashed_inode = &inode;
1306 	while (1) {
1307 		retval = ext2fs_get_next_inode(scan, &ino, &inode);
1308 		if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
1309 			continue;
1310 		if (retval) {
1311 			com_err(program_name, retval, "%s",
1312 				_("while getting next inode"));
1313 			exit(1);
1314 		}
1315 		if (ino == 0)
1316 			break;
1317 		if (!inode.i_links_count)
1318 			continue;
1319 		if (ext2fs_file_acl_block(fs, &inode)) {
1320 			ext2fs_mark_block_bitmap2(meta_block_map,
1321 					ext2fs_file_acl_block(fs, &inode));
1322 			meta_blocks_count++;
1323 		}
1324 		if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
1325 			continue;
1326 
1327 		stashed_ino = ino;
1328 		pb.ino = ino;
1329 		pb.is_dir = LINUX_S_ISDIR(inode.i_mode);
1330 		if (LINUX_S_ISDIR(inode.i_mode) ||
1331 		    (LINUX_S_ISLNK(inode.i_mode) &&
1332 		     ext2fs_inode_has_valid_blocks2(fs, &inode)) ||
1333 		    ino == fs->super->s_journal_inum) {
1334 			retval = ext2fs_block_iterate3(fs, ino,
1335 					BLOCK_FLAG_READ_ONLY, block_buf,
1336 					process_dir_block, &pb);
1337 			if (retval) {
1338 				com_err(program_name, retval,
1339 					_("while iterating over inode %u"),
1340 					ino);
1341 				exit(1);
1342 			}
1343 		} else {
1344 			if ((inode.i_flags & EXT4_EXTENTS_FL) ||
1345 			    inode.i_block[EXT2_IND_BLOCK] ||
1346 			    inode.i_block[EXT2_DIND_BLOCK] ||
1347 			    inode.i_block[EXT2_TIND_BLOCK] || all_data) {
1348 				retval = ext2fs_block_iterate3(fs,
1349 				       ino, BLOCK_FLAG_READ_ONLY, block_buf,
1350 				       process_file_block, &pb);
1351 				if (retval) {
1352 					com_err(program_name, retval,
1353 					_("while iterating over inode %u"), ino);
1354 					exit(1);
1355 				}
1356 			}
1357 		}
1358 	}
1359 	use_inode_shortcuts(fs, 0);
1360 
1361 	if (type & E2IMAGE_QCOW2)
1362 		output_qcow2_meta_data_blocks(fs, fd);
1363 	else
1364 		output_meta_data_blocks(fs, fd, flags);
1365 
1366 	ext2fs_free_mem(&block_buf);
1367 	ext2fs_close_inode_scan(scan);
1368 	ext2fs_free_block_bitmap(meta_block_map);
1369 	if (type & E2IMAGE_SCRAMBLE_FLAG)
1370 		ext2fs_free_block_bitmap(scramble_block_map);
1371 }
1372 
install_image(char * device,char * image_fn,int type)1373 static void install_image(char *device, char *image_fn, int type)
1374 {
1375 	errcode_t retval;
1376 	ext2_filsys fs;
1377 	int open_flag = EXT2_FLAG_IMAGE_FILE | EXT2_FLAG_64BITS |
1378 			EXT2_FLAG_IGNORE_CSUM_ERRORS;
1379 	int fd = 0;
1380 	io_manager	io_ptr;
1381 	io_channel	io;
1382 
1383 	if (type) {
1384 		com_err(program_name, 0, "%s",
1385 			_("Raw and qcow2 images cannot be installed"));
1386 		exit(1);
1387 	}
1388 
1389 #ifdef CONFIG_TESTIO_DEBUG
1390 	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
1391 		io_ptr = test_io_manager;
1392 		test_io_backing_manager = unix_io_manager;
1393 	} else
1394 #endif
1395 		io_ptr = unix_io_manager;
1396 
1397 	retval = ext2fs_open (image_fn, open_flag, 0, 0,
1398 			      io_ptr, &fs);
1399         if (retval) {
1400 		com_err(program_name, retval, _("while trying to open %s"),
1401 			image_fn);
1402 		exit(1);
1403 	}
1404 
1405 	retval = ext2fs_read_bitmaps (fs);
1406 	if (retval) {
1407 		com_err(program_name, retval, "%s", _("error reading bitmaps"));
1408 		exit(1);
1409 	}
1410 
1411 	fd = ext2fs_open_file(image_fn, O_RDONLY, 0);
1412 	if (fd < 0) {
1413 		perror(image_fn);
1414 		exit(1);
1415 	}
1416 
1417 	retval = io_ptr->open(device, IO_FLAG_RW, &io);
1418 	if (retval) {
1419 		com_err(device, 0, "%s", _("while opening device file"));
1420 		exit(1);
1421 	}
1422 
1423 	ext2fs_rewrite_to_io(fs, io);
1424 
1425 	seek_set(fd, fs->image_header->offset_inode);
1426 
1427 	retval = ext2fs_image_inode_read(fs, fd, 0);
1428 	if (retval) {
1429 		com_err(image_fn, 0, "%s",
1430 			_("while restoring the image table"));
1431 		exit(1);
1432 	}
1433 
1434 	close(fd);
1435 	ext2fs_close_free(&fs);
1436 }
1437 
check_qcow2_image(int * fd,char * name)1438 static struct ext2_qcow2_hdr *check_qcow2_image(int *fd, char *name)
1439 {
1440 
1441 	*fd = ext2fs_open_file(name, O_RDONLY, 0600);
1442 	if (*fd < 0)
1443 		return NULL;
1444 
1445 	return qcow2_read_header(*fd);
1446 }
1447 
main(int argc,char ** argv)1448 int main (int argc, char ** argv)
1449 {
1450 	int c;
1451 	errcode_t retval;
1452 	ext2_filsys fs;
1453 	char *image_fn, offset_opt[64];
1454 	struct ext2_qcow2_hdr *header = NULL;
1455 	int open_flag = EXT2_FLAG_64BITS | EXT2_FLAG_IGNORE_CSUM_ERRORS;
1456 	int img_type = 0;
1457 	int flags = 0;
1458 	int mount_flags = 0;
1459 	int qcow2_fd = 0;
1460 	int fd = 0;
1461 	int ret = 0;
1462 	int ignore_rw_mount = 0;
1463 	int check = 0;
1464 	struct stat st;
1465 
1466 #ifdef ENABLE_NLS
1467 	setlocale(LC_MESSAGES, "");
1468 	setlocale(LC_CTYPE, "");
1469 	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
1470 	textdomain(NLS_CAT_NAME);
1471 	set_com_err_gettext(gettext);
1472 #endif
1473 	fprintf (stderr, "e2image %s (%s)\n", E2FSPROGS_VERSION,
1474 		 E2FSPROGS_DATE);
1475 	if (argc && *argv)
1476 		program_name = *argv;
1477 	add_error_table(&et_ext2_error_table);
1478 	while ((c = getopt(argc, argv, "nrsIQafo:O:pc")) != EOF)
1479 		switch (c) {
1480 		case 'I':
1481 			flags |= E2IMAGE_INSTALL_FLAG;
1482 			break;
1483 		case 'Q':
1484 			if (img_type)
1485 				usage();
1486 			img_type |= E2IMAGE_QCOW2;
1487 			break;
1488 		case 'r':
1489 			if (img_type)
1490 				usage();
1491 			img_type |= E2IMAGE_RAW;
1492 			break;
1493 		case 's':
1494 			flags |= E2IMAGE_SCRAMBLE_FLAG;
1495 			break;
1496 		case 'a':
1497 			all_data = 1;
1498 			break;
1499 		case 'f':
1500 			ignore_rw_mount = 1;
1501 			break;
1502 		case 'n':
1503 			nop_flag = 1;
1504 			break;
1505 		case 'o':
1506 			source_offset = strtoull(optarg, NULL, 0);
1507 			break;
1508 		case 'O':
1509 			dest_offset = strtoull(optarg, NULL, 0);
1510 			break;
1511 		case 'p':
1512 			show_progress = 1;
1513 			break;
1514 		case 'c':
1515 			check = 1;
1516 			break;
1517 		default:
1518 			usage();
1519 		}
1520 	if (optind == argc - 1 &&
1521 	    (source_offset || dest_offset))
1522 		    move_mode = 1;
1523 	else if (optind != argc - 2 )
1524 		usage();
1525 
1526 	if (all_data && !img_type) {
1527 		com_err(program_name, 0, "%s", _("-a option can only be used "
1528 						 "with raw or QCOW2 images."));
1529 		exit(1);
1530 	}
1531 	if ((source_offset || dest_offset) && img_type != E2IMAGE_RAW) {
1532 		com_err(program_name, 0, "%s",
1533 			_("Offsets are only allowed with raw images."));
1534 		exit(1);
1535 	}
1536 	if (move_mode && img_type != E2IMAGE_RAW) {
1537 		com_err(program_name, 0, "%s",
1538 			_("Move mode is only allowed with raw images."));
1539 		exit(1);
1540 	}
1541 	if (move_mode && !all_data) {
1542 		com_err(program_name, 0, "%s",
1543 			_("Move mode requires all data mode."));
1544 		exit(1);
1545 	}
1546 	device_name = argv[optind];
1547 	if (move_mode)
1548 		image_fn = device_name;
1549 	else image_fn = argv[optind+1];
1550 
1551 	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
1552 	if (retval) {
1553 		com_err(program_name, retval, "%s", _("checking if mounted"));
1554 		exit(1);
1555 	}
1556 
1557 	if (img_type && !ignore_rw_mount &&
1558 	    (mount_flags & EXT2_MF_MOUNTED) &&
1559 	   !(mount_flags & EXT2_MF_READONLY)) {
1560 		fprintf(stderr, "%s", _("\nRunning e2image on a R/W mounted "
1561 			"filesystem can result in an\n"
1562 			"inconsistent image which will not be useful "
1563 			"for debugging purposes.\n"
1564 			"Use -f option if you really want to do that.\n"));
1565 		exit(1);
1566 	}
1567 
1568 	if (flags & E2IMAGE_INSTALL_FLAG) {
1569 		install_image(device_name, image_fn, img_type);
1570 		exit (0);
1571 	}
1572 
1573 	if (img_type & E2IMAGE_RAW) {
1574 		header = check_qcow2_image(&qcow2_fd, device_name);
1575 		if (header) {
1576 			flags |= E2IMAGE_IS_QCOW2_FLAG;
1577 			goto skip_device;
1578 		}
1579 	}
1580 	sprintf(offset_opt, "offset=%llu", source_offset);
1581 	retval = ext2fs_open2(device_name, offset_opt, open_flag, 0, 0,
1582 			      unix_io_manager, &fs);
1583         if (retval) {
1584 		com_err (program_name, retval, _("while trying to open %s"),
1585 			 device_name);
1586 		fputs(_("Couldn't find valid filesystem superblock.\n"), stdout);
1587 		if (retval == EXT2_ET_BAD_MAGIC)
1588 			check_plausibility(device_name, CHECK_FS_EXIST, NULL);
1589 		exit(1);
1590 	}
1591 
1592 skip_device:
1593 	if (strcmp(image_fn, "-") == 0)
1594 		fd = 1;
1595 	else {
1596 		int o_flags = O_CREAT|O_RDWR;
1597 
1598 		if (img_type != E2IMAGE_RAW)
1599 			o_flags |= O_TRUNC;
1600 		if (access(image_fn, F_OK) != 0)
1601 			flags |= E2IMAGE_CHECK_ZERO_FLAG;
1602 		fd = ext2fs_open_file(image_fn, o_flags, 0600);
1603 		if (fd < 0) {
1604 			com_err(program_name, errno,
1605 				_("while trying to open %s"), image_fn);
1606 			exit(1);
1607 		}
1608 	}
1609 	if (dest_offset)
1610 		seek_set(fd, dest_offset);
1611 
1612 	if ((img_type & E2IMAGE_QCOW2) && (fd == 1)) {
1613 		com_err(program_name, 0, "%s",
1614 			_("QCOW2 image can not be written to the stdout!\n"));
1615 		exit(1);
1616 	}
1617 	if (fd != 1) {
1618 		if (fstat(fd, &st)) {
1619 			com_err(program_name, 0, "%s",
1620 				_("Can not stat output\n"));
1621 			exit(1);
1622 		}
1623 		if (S_ISBLK(st.st_mode))
1624 			output_is_blk = 1;
1625 	}
1626 	if (flags & E2IMAGE_IS_QCOW2_FLAG) {
1627 		ret = qcow2_write_raw_image(qcow2_fd, fd, header);
1628 		if (ret) {
1629 			if (ret == -QCOW_COMPRESSED)
1630 				fprintf(stderr, _("Image (%s) is compressed\n"),
1631 					image_fn);
1632 			if (ret == -QCOW_ENCRYPTED)
1633 				fprintf(stderr, _("Image (%s) is encrypted\n"),
1634 					image_fn);
1635 			com_err(program_name, ret,
1636 				_("while trying to convert qcow2 image"
1637 				  " (%s) into raw image (%s)"),
1638 				device_name, image_fn);
1639 		}
1640 		goto out;
1641 	}
1642 
1643 	if (check) {
1644 		if (img_type != E2IMAGE_RAW) {
1645 			fprintf(stderr, "%s", _("The -c option only supported "
1646 						"in raw mode\n"));
1647 			exit(1);
1648 		}
1649 		if (fd == 1) {
1650 			fprintf(stderr, "%s", _("The -c option not supported "
1651 						"when writing to stdout\n"));
1652 			exit(1);
1653 		}
1654 		retval = ext2fs_get_mem(fs->blocksize, &check_buf);
1655 		if (retval) {
1656 			com_err(program_name, retval, "%s",
1657 				_("while allocating check_buf"));
1658 			exit(1);
1659 		}
1660 	}
1661 	if (show_progress && (img_type != E2IMAGE_RAW)) {
1662 		fprintf(stderr, "%s",
1663 			_("The -p option only supported in raw mode\n"));
1664 		exit(1);
1665 	}
1666 	if (img_type)
1667 		write_raw_image_file(fs, fd, img_type, flags);
1668 	else
1669 		write_image_file(fs, fd);
1670 
1671 	ext2fs_close_free(&fs);
1672 	if (check)
1673 		printf(_("%d blocks already contained the data to be copied\n"),
1674 		       skipped_blocks);
1675 
1676 out:
1677 	if (header)
1678 		free(header);
1679 	if (qcow2_fd)
1680 		close(qcow2_fd);
1681 	remove_error_table(&et_ext2_error_table);
1682 	return ret;
1683 }
1684