e2image.c revision c5423c5b3ea549d96d1b3315a96b5b58beca75cd
1/*
2 * e2image.c --- Program which writes an image file backing up
3 * critical metadata for the filesystem.
4 *
5 * Copyright 2000 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#include <fcntl.h>
14#include <grp.h>
15#ifdef HAVE_GETOPT_H
16#include <getopt.h>
17#else
18extern char *optarg;
19extern int optind;
20#endif
21#include <pwd.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <time.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <errno.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31
32#include <linux/ext2_fs.h>
33
34#include "ext2fs/ext2fs.h"
35#include "et/com_err.h"
36#include "uuid/uuid.h"
37#include "e2p/e2p.h"
38#include "ext2fs/e2image.h"
39
40#include "../version.h"
41#include "nls-enable.h"
42
43const char * program_name = "e2image";
44char * device_name = NULL;
45
46static void usage(void)
47{
48	fprintf(stderr, _("Usage: %s device file\n"), program_name);
49	exit (1);
50}
51
52static void write_header(int fd, struct ext2_image_hdr *hdr)
53{
54	char header_buf[4096];
55	int actual;
56
57	if (lseek(fd, 0, SEEK_SET) < 0) {
58		perror("lseek while writing header");
59		exit(1);
60	}
61	memset(header_buf, 0, sizeof(header_buf));
62
63	if (hdr)
64		memcpy(header_buf, hdr, sizeof(struct ext2_image_hdr));
65
66	actual = write(fd, header_buf, sizeof(header_buf));
67	if (actual < 0) {
68		perror("write header");
69		exit(1);
70	}
71	if (actual != sizeof(header_buf)) {
72		fprintf(stderr, _("short write (only %d bytes) for"
73				  "writing image header"), actual);
74		exit(1);
75	}
76}
77
78
79int main (int argc, char ** argv)
80{
81	int c;
82	errcode_t retval;
83	ext2_filsys fs;
84	int open_flag = 0;
85	int raw_flag = 0;
86	int fd = 0;
87	struct ext2_image_hdr hdr;
88	struct stat st;
89
90#ifdef ENABLE_NLS
91	setlocale(LC_MESSAGES, "");
92	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
93	textdomain(NLS_CAT_NAME);
94#endif
95	fprintf (stderr, _("e2image %s, %s for EXT2 FS %s, %s\n"),
96		 E2FSPROGS_VERSION, E2FSPROGS_DATE,
97		 EXT2FS_VERSION, EXT2FS_DATE);
98	if (argc && *argv)
99		program_name = *argv;
100	initialize_ext2_error_table();
101	while ((c = getopt (argc, argv, "r")) != EOF)
102		switch (c) {
103		case 'r':
104			raw_flag++;
105			break;
106		default:
107			usage();
108		}
109	if (optind != argc - 2 )
110		usage();
111	device_name = argv[optind];
112	retval = ext2fs_open (device_name, open_flag, 0, 0,
113			      unix_io_manager, &fs);
114        if (retval) {
115		com_err (program_name, retval, _("while trying to open %s"),
116			 device_name);
117		printf(_("Couldn't find valid filesystem superblock.\n"));
118		exit(1);
119	}
120
121	fd = open(argv[optind+1], O_CREAT|O_RDWR, 0600);
122	if (fd < 0) {
123		com_err(program_name, errno, _("while trying to open %s"),
124			argv[optind+1]);
125		exit(1);
126	}
127
128	write_header(fd, NULL);
129	memset(&hdr, 0, sizeof(struct ext2_image_hdr));
130
131	hdr.offset_super = lseek(fd, 0, SEEK_CUR);
132	retval = ext2fs_image_super_write(fs, fd, 0);
133	if (retval) {
134		com_err(program_name, retval, _("while writing superblock"));
135		exit(1);
136	}
137
138	hdr.offset_inode = lseek(fd, 0, SEEK_CUR);
139	retval = ext2fs_image_inode_write(fs, fd, IMAGER_FLAG_SPARSEWRITE);
140	if (retval) {
141		com_err(program_name, retval, _("while writing inode table"));
142		exit(1);
143	}
144
145	hdr.offset_blockmap = lseek(fd, 0, SEEK_CUR);
146	retval = ext2fs_image_bitmap_write(fs, fd, 0);
147	if (retval) {
148		com_err(program_name, retval, _("while writing block bitmap"));
149		exit(1);
150	}
151
152	hdr.offset_inodemap = lseek(fd, 0, SEEK_CUR);
153	retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP);
154	if (retval) {
155		com_err(program_name, retval, _("while writing inode bitmap"));
156		exit(1);
157	}
158
159	hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE;
160	strcpy(hdr.magic_descriptor, "Ext2 Image 1.0");
161	gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname));
162
163	if (stat(device_name, &st) == 0)
164		hdr.fs_device = st.st_rdev;
165
166	if (fstat(fd, &st) == 0) {
167		hdr.image_device = st.st_dev;
168		hdr.image_inode = st.st_ino;
169	}
170	memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid));
171
172	hdr.image_time = time(0);
173	write_header(fd, &hdr);
174
175	ext2fs_close (fs);
176	exit (0);
177}
178
179
180