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