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