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