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