]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - misc/e2image.c
Fix typo in the summary section of the blkid man page
[thirdparty/e2fsprogs.git] / misc / e2image.c
CommitLineData
72ed1264
TT
1/*
2 * e2image.c --- Program which writes an image file backing up
3 * critical metadata for the filesystem.
4 *
a3827953 5 * Copyright 2000, 2001 by Theodore Ts'o.
72ed1264
TT
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
11 */
12
6304baf2
TT
13#define _LARGEFILE_SOURCE
14#define _LARGEFILE64_SOURCE
15
72ed1264
TT
16#include <fcntl.h>
17#include <grp.h>
18#ifdef HAVE_GETOPT_H
19#include <getopt.h>
20#else
21extern char *optarg;
22extern int optind;
23#endif
24#include <pwd.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <time.h>
29#include <unistd.h>
30#include <fcntl.h>
31#include <errno.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34
54c637d4 35#include "ext2fs/ext2_fs.h"
72ed1264
TT
36#include "ext2fs/ext2fs.h"
37#include "et/com_err.h"
38#include "uuid/uuid.h"
39#include "e2p/e2p.h"
40#include "ext2fs/e2image.h"
41
42#include "../version.h"
43#include "nls-enable.h"
44
3e377db2 45const char * program_name = "e2image";
72ed1264
TT
46char * device_name = NULL;
47
48static void usage(void)
49{
d851ed39
TT
50 fprintf(stderr, _("Usage: %s [-rsI] device image_file\n"),
51 program_name);
72ed1264
TT
52 exit (1);
53}
54
095b459d 55static void write_header(int fd, struct ext2_image_hdr *hdr, int blocksize)
72ed1264 56{
095b459d 57 char *header_buf;
72ed1264
TT
58 int actual;
59
095b459d
TT
60 header_buf = malloc(blocksize);
61 if (!header_buf) {
54434927 62 fputs(_("Couldn't allocate header buffer\n"), stderr);
095b459d
TT
63 exit(1);
64 }
65
72ed1264
TT
66 if (lseek(fd, 0, SEEK_SET) < 0) {
67 perror("lseek while writing header");
68 exit(1);
69 }
095b459d 70 memset(header_buf, 0, blocksize);
72ed1264
TT
71
72 if (hdr)
73 memcpy(header_buf, hdr, sizeof(struct ext2_image_hdr));
74
095b459d 75 actual = write(fd, header_buf, blocksize);
72ed1264
TT
76 if (actual < 0) {
77 perror("write header");
78 exit(1);
79 }
095b459d 80 if (actual != blocksize) {
ddc32a04 81 fprintf(stderr, _("short write (only %d bytes) for "
72ed1264
TT
82 "writing image header"), actual);
83 exit(1);
84 }
095b459d 85 free(header_buf);
72ed1264
TT
86}
87
6304baf2 88static void write_image_file(ext2_filsys fs, int fd)
72ed1264 89{
6304baf2
TT
90 struct ext2_image_hdr hdr;
91 struct stat st;
92 errcode_t retval;
72ed1264 93
095b459d 94 write_header(fd, NULL, fs->blocksize);
72ed1264 95 memset(&hdr, 0, sizeof(struct ext2_image_hdr));
6304baf2 96
72ed1264
TT
97 hdr.offset_super = lseek(fd, 0, SEEK_CUR);
98 retval = ext2fs_image_super_write(fs, fd, 0);
99 if (retval) {
100 com_err(program_name, retval, _("while writing superblock"));
101 exit(1);
102 }
103
104 hdr.offset_inode = lseek(fd, 0, SEEK_CUR);
6304baf2
TT
105 retval = ext2fs_image_inode_write(fs, fd,
106 (fd != 1) ? IMAGER_FLAG_SPARSEWRITE : 0);
72ed1264
TT
107 if (retval) {
108 com_err(program_name, retval, _("while writing inode table"));
109 exit(1);
110 }
111
112 hdr.offset_blockmap = lseek(fd, 0, SEEK_CUR);
113 retval = ext2fs_image_bitmap_write(fs, fd, 0);
114 if (retval) {
115 com_err(program_name, retval, _("while writing block bitmap"));
116 exit(1);
117 }
118
119 hdr.offset_inodemap = lseek(fd, 0, SEEK_CUR);
120 retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP);
121 if (retval) {
122 com_err(program_name, retval, _("while writing inode bitmap"));
123 exit(1);
124 }
c5423c5b
TT
125
126 hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE;
127 strcpy(hdr.magic_descriptor, "Ext2 Image 1.0");
128 gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname));
095b459d
TT
129 strncat(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name));
130 hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0;
131 hdr.fs_blocksize = fs->blocksize;
132
c5423c5b
TT
133 if (stat(device_name, &st) == 0)
134 hdr.fs_device = st.st_rdev;
135
136 if (fstat(fd, &st) == 0) {
137 hdr.image_device = st.st_dev;
138 hdr.image_inode = st.st_ino;
139 }
140 memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid));
141
142 hdr.image_time = time(0);
095b459d 143 write_header(fd, &hdr, fs->blocksize);
6304baf2
TT
144}
145
146/*
147 * These set of functions are used to write a RAW image file.
148 */
149ext2fs_block_bitmap meta_block_map;
d851ed39 150ext2fs_block_bitmap scramble_block_map; /* Directory blocks to be scrambled */
6304baf2
TT
151
152struct process_block_struct {
153 ext2_ino_t ino;
d851ed39 154 int is_dir;
6304baf2
TT
155};
156
157/*
158 * These subroutines short circuits ext2fs_get_blocks and
159 * ext2fs_check_directory; we use them since we already have the inode
160 * structure, so there's no point in letting the ext2fs library read
161 * the inode again.
162 */
163static ino_t stashed_ino = 0;
164static struct ext2_inode *stashed_inode;
165
54434927
TT
166static errcode_t meta_get_blocks(ext2_filsys fs EXT2FS_ATTR((unused)),
167 ext2_ino_t ino,
168 blk_t *blocks)
6304baf2
TT
169{
170 int i;
171
172 if ((ino != stashed_ino) || !stashed_inode)
173 return EXT2_ET_CALLBACK_NOTHANDLED;
174
175 for (i=0; i < EXT2_N_BLOCKS; i++)
176 blocks[i] = stashed_inode->i_block[i];
177 return 0;
178}
179
54434927
TT
180static errcode_t meta_check_directory(ext2_filsys fs EXT2FS_ATTR((unused)),
181 ext2_ino_t ino)
4ea7bd04
TT
182{
183 if ((ino != stashed_ino) || !stashed_inode)
184 return EXT2_ET_CALLBACK_NOTHANDLED;
185
186 if (!LINUX_S_ISDIR(stashed_inode->i_mode))
187 return EXT2_ET_NO_DIRECTORY;
188 return 0;
189}
190
54434927
TT
191static errcode_t meta_read_inode(ext2_filsys fs EXT2FS_ATTR((unused)),
192 ext2_ino_t ino,
6304baf2
TT
193 struct ext2_inode *inode)
194{
195 if ((ino != stashed_ino) || !stashed_inode)
196 return EXT2_ET_CALLBACK_NOTHANDLED;
197 *inode = *stashed_inode;
198 return 0;
199}
200
4ea7bd04
TT
201static void use_inode_shortcuts(ext2_filsys fs, int bool)
202{
203 if (bool) {
204 fs->get_blocks = meta_get_blocks;
205 fs->check_directory = meta_check_directory;
206 fs->read_inode = meta_read_inode;
207 stashed_ino = 0;
208 } else {
209 fs->get_blocks = 0;
210 fs->check_directory = 0;
211 fs->read_inode = 0;
212 }
213}
214
54434927
TT
215static int process_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)),
216 blk_t *block_nr,
217 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
218 blk_t ref_block EXT2FS_ATTR((unused)),
219 int ref_offset EXT2FS_ATTR((unused)),
220 void *priv_data EXT2FS_ATTR((unused)))
6304baf2 221{
d851ed39
TT
222 struct process_block_struct *p;
223
224 p = (struct process_block_struct *) priv_data;
225
6304baf2 226 ext2fs_mark_block_bitmap(meta_block_map, *block_nr);
d851ed39
TT
227 if (scramble_block_map && p->is_dir && blockcnt >= 0)
228 ext2fs_mark_block_bitmap(scramble_block_map, *block_nr);
6304baf2
TT
229 return 0;
230}
231
54434927
TT
232static int process_file_block(ext2_filsys fs EXT2FS_ATTR((unused)),
233 blk_t *block_nr,
234 e2_blkcnt_t blockcnt,
235 blk_t ref_block EXT2FS_ATTR((unused)),
236 int ref_offset EXT2FS_ATTR((unused)),
237 void *priv_data EXT2FS_ATTR((unused)))
6304baf2
TT
238{
239 if (blockcnt < 0) {
240 ext2fs_mark_block_bitmap(meta_block_map, *block_nr);
241 }
242 return 0;
243}
244
245static void mark_table_blocks(ext2_filsys fs)
246{
bb1a46a4 247 blk_t first_block, b;
54434927 248 unsigned int i,j;
6304baf2 249
bb1a46a4 250 first_block = fs->super->s_first_data_block;
6304baf2
TT
251 /*
252 * Mark primary superblock
253 */
bb1a46a4 254 ext2fs_mark_block_bitmap(meta_block_map, first_block);
6304baf2
TT
255
256 /*
257 * Mark the primary superblock descriptors
258 */
259 for (j = 0; j < fs->desc_blocks; j++) {
260 ext2fs_mark_block_bitmap(meta_block_map,
bb1a46a4 261 ext2fs_descriptor_block_loc(fs, first_block, j));
6304baf2
TT
262 }
263
264 for (i = 0; i < fs->group_desc_count; i++) {
265 /*
266 * Mark the blocks used for the inode table
267 */
268 if (fs->group_desc[i].bg_inode_table) {
269 for (j = 0, b = fs->group_desc[i].bg_inode_table;
54434927 270 j < (unsigned) fs->inode_blocks_per_group;
6304baf2
TT
271 j++, b++)
272 ext2fs_mark_block_bitmap(meta_block_map, b);
273 }
274
275 /*
276 * Mark block used for the block bitmap
277 */
278 if (fs->group_desc[i].bg_block_bitmap) {
279 ext2fs_mark_block_bitmap(meta_block_map,
280 fs->group_desc[i].bg_block_bitmap);
281 }
282
283 /*
284 * Mark block used for the inode bitmap
285 */
286 if (fs->group_desc[i].bg_inode_bitmap) {
287 ext2fs_mark_block_bitmap(meta_block_map,
288 fs->group_desc[i].bg_inode_bitmap);
289 }
6304baf2
TT
290 }
291}
292
293/*
294 * This function returns 1 if the specified block is all zeros
295 */
296static int check_zero_block(char *buf, int blocksize)
297{
298 char *cp = buf;
299 int left = blocksize;
300
301 while (left > 0) {
302 if (*cp++)
303 return 0;
304 left--;
305 }
306 return 1;
307}
308
e3ef3502
TT
309static void write_block(int fd, char *buf, int sparse_offset,
310 int blocksize, blk_t block)
6304baf2
TT
311{
312 int count;
313 errcode_t err;
314
e3ef3502
TT
315 if (sparse_offset) {
316#ifdef HAVE_LSEEK64
317 if (lseek64(fd, sparse_offset, SEEK_CUR) < 0)
318 perror("lseek");
319#else
320 if (lseek(fd, sparse_offset, SEEK_CUR) < 0)
321 perror("lseek");
322#endif
323 }
324 if (blocksize) {
325 count = write(fd, buf, blocksize);
326 if (count != blocksize) {
327 if (count == -1)
328 err = errno;
329 else
330 err = 0;
8deb80a5 331 com_err(program_name, err, "error writing block %u",
e3ef3502
TT
332 block);
333 }
6304baf2
TT
334 }
335}
336
d851ed39
TT
337int name_id[256];
338
339static void scramble_dir_block(ext2_filsys fs, blk_t blk, char *buf)
340{
341 char *p, *end, *cp;
342 struct ext2_dir_entry_2 *dirent;
343 int rec_len, id, len;
344
d851ed39
TT
345 end = buf + fs->blocksize;
346 for (p = buf; p < end-8; p += rec_len) {
347 dirent = (struct ext2_dir_entry_2 *) p;
348 rec_len = dirent->rec_len;
349#ifdef EXT2FS_ENABLE_SWAPFS
350 if (fs->flags & EXT2_FLAG_SWAP_BYTES)
351 rec_len = ext2fs_swab16(rec_len);
352#endif
353#if 0
354 printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len);
355#endif
356 if (rec_len < 8 || (rec_len % 4) ||
357 (p+rec_len > end)) {
358 printf("Corrupt directory block %lu: "
9b9a780f
TT
359 "bad rec_len (%d)\n", (unsigned long) blk,
360 rec_len);
d851ed39
TT
361 rec_len = end - p;
362#ifdef EXT2FS_ENABLE_SWAPFS
363 if (fs->flags & EXT2_FLAG_SWAP_BYTES)
364 dirent->rec_len = ext2fs_swab16(rec_len);
365#endif
366 continue;
367 }
368 if (dirent->name_len + 8 > rec_len) {
369 printf("Corrupt directory block %lu: "
9b9a780f
TT
370 "bad name_len (%d)\n", (unsigned long) blk,
371 dirent->name_len);
d851ed39
TT
372 dirent->name_len = rec_len - 8;
373 continue;
374 }
d851ed39 375 cp = p+8;
d851ed39
TT
376 len = rec_len - dirent->name_len - 8;
377 if (len > 0)
378 memset(cp+dirent->name_len, 0, len);
79fc2a99
TT
379 if (dirent->name_len==1 && cp[0] == '.')
380 continue;
381 if (dirent->name_len==2 && cp[0] == '.' && cp[1] == '.')
382 continue;
383
384 memset(cp, 'A', dirent->name_len);
d851ed39
TT
385 len = dirent->name_len;
386 id = name_id[len]++;
387 while ((len > 0) && (id > 0)) {
388 *cp += id % 26;
389 id = id / 26;
390 cp++;
391 len--;
392 }
393 }
394}
395
4ea7bd04 396static void output_meta_data_blocks(ext2_filsys fs, int fd)
6304baf2
TT
397{
398 errcode_t retval;
399 blk_t blk;
d851ed39 400 char *buf, *zero_buf;
e3ef3502 401 int sparse = 0;
6304baf2 402
d851ed39
TT
403 buf = malloc(fs->blocksize);
404 if (!buf) {
405 com_err(program_name, ENOMEM, "while allocating buffer");
406 exit(1);
407 }
408 zero_buf = malloc(fs->blocksize);
409 if (!zero_buf) {
410 com_err(program_name, ENOMEM, "while allocating buffer");
411 exit(1);
412 }
413 memset(zero_buf, 0, fs->blocksize);
6304baf2
TT
414 for (blk = 0; blk < fs->super->s_blocks_count; blk++) {
415 if ((blk >= fs->super->s_first_data_block) &&
416 ext2fs_test_block_bitmap(meta_block_map, blk)) {
417 retval = io_channel_read_blk(fs->io, blk, 1, buf);
418 if (retval) {
419 com_err(program_name, retval,
d0ff90d5 420 "error reading block %u", blk);
6304baf2 421 }
d851ed39
TT
422 if (scramble_block_map &&
423 ext2fs_test_block_bitmap(scramble_block_map, blk))
424 scramble_dir_block(fs, blk, buf);
6304baf2
TT
425 if ((fd != 1) && check_zero_block(buf, fs->blocksize))
426 goto sparse_write;
e3ef3502
TT
427 write_block(fd, buf, sparse, fs->blocksize, blk);
428 sparse = 0;
6304baf2
TT
429 } else {
430 sparse_write:
431 if (fd == 1) {
e3ef3502
TT
432 write_block(fd, zero_buf, 0,
433 fs->blocksize, blk);
6304baf2
TT
434 continue;
435 }
e3ef3502
TT
436 sparse += fs->blocksize;
437 if (sparse >= 1024*1024) {
438 write_block(fd, 0, sparse, 0, 0);
439 sparse = 0;
440 }
6304baf2
TT
441 }
442 }
e3ef3502 443 write_block(fd, zero_buf, sparse, 1, -1);
248c2f9c
BB
444 free(zero_buf);
445 free(buf);
6304baf2
TT
446}
447
d851ed39 448static void write_raw_image_file(ext2_filsys fs, int fd, int scramble_flag)
6304baf2
TT
449{
450 struct process_block_struct pb;
451 struct ext2_inode inode;
452 ext2_inode_scan scan;
453 ext2_ino_t ino;
454 errcode_t retval;
455 char * block_buf;
456
457 retval = ext2fs_allocate_block_bitmap(fs, "in-use block map",
458 &meta_block_map);
459 if (retval) {
460 com_err(program_name, retval, "while allocating block bitmap");
461 exit(1);
462 }
d851ed39
TT
463
464 if (scramble_flag) {
465 retval = ext2fs_allocate_block_bitmap(fs, "scramble block map",
466 &scramble_block_map);
467 if (retval) {
468 com_err(program_name, retval,
469 "while allocating scramble block bitmap");
470 exit(1);
471 }
472 }
6304baf2
TT
473
474 mark_table_blocks(fs);
475
476 retval = ext2fs_open_inode_scan(fs, 0, &scan);
477 if (retval) {
478 com_err(program_name, retval, _("while opening inode scan"));
479 exit(1);
480 }
481
482 block_buf = malloc(fs->blocksize * 3);
483 if (!block_buf) {
484 com_err(program_name, 0, "Can't allocate block buffer");
485 exit(1);
486 }
487
4ea7bd04 488 use_inode_shortcuts(fs, 1);
6304baf2
TT
489 stashed_inode = &inode;
490 while (1) {
491 retval = ext2fs_get_next_inode(scan, &ino, &inode);
3432a916
TT
492 if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
493 continue;
6304baf2
TT
494 if (retval) {
495 com_err(program_name, retval,
496 _("while getting next inode"));
497 exit(1);
498 }
499 if (ino == 0)
500 break;
ed909bbe
TT
501 if (!inode.i_links_count)
502 continue;
503 if (inode.i_file_acl) {
504 ext2fs_mark_block_bitmap(meta_block_map,
505 inode.i_file_acl);
506 }
507 if (!ext2fs_inode_has_valid_blocks(&inode))
6304baf2
TT
508 continue;
509
510 stashed_ino = ino;
d851ed39
TT
511 pb.ino = ino;
512 pb.is_dir = LINUX_S_ISDIR(inode.i_mode);
1c1e0049 513 if (LINUX_S_ISDIR(inode.i_mode) ||
eca53e3c
TT
514 (LINUX_S_ISLNK(inode.i_mode) &&
515 ext2fs_inode_has_valid_blocks(&inode)) ||
1c1e0049 516 ino == fs->super->s_journal_inum) {
6304baf2
TT
517 retval = ext2fs_block_iterate2(fs, ino, 0,
518 block_buf, process_dir_block, &pb);
519 if (retval) {
520 com_err(program_name, retval,
d0ff90d5 521 "while iterating over inode %u",
6304baf2
TT
522 ino);
523 exit(1);
524 }
525 } else {
526 if (inode.i_block[EXT2_IND_BLOCK] ||
527 inode.i_block[EXT2_DIND_BLOCK] ||
528 inode.i_block[EXT2_TIND_BLOCK]) {
529 retval = ext2fs_block_iterate2(fs,
530 ino, 0, block_buf,
531 process_file_block, &pb);
532 if (retval) {
533 com_err(program_name, retval,
d0ff90d5 534 "while iterating over inode %u", ino);
6304baf2
TT
535 exit(1);
536 }
537 }
6304baf2
TT
538 }
539 }
4ea7bd04 540 use_inode_shortcuts(fs, 0);
6304baf2 541 output_meta_data_blocks(fs, fd);
d7eee829 542 free(block_buf);
6304baf2
TT
543}
544
6e82cd7e 545static void install_image(char *device, char *image_fn, int raw_flag)
8c6b6483 546{
8c6b6483
TT
547 errcode_t retval;
548 ext2_filsys fs;
549 int open_flag = EXT2_FLAG_IMAGE_FILE;
550 int fd = 0;
551 io_manager io_ptr;
552 io_channel io, image_io;
553
554 if (raw_flag) {
555 com_err(program_name, 0, "Raw images cannot be installed");
556 exit(1);
557 }
558
559#ifdef CONFIG_TESTIO_DEBUG
560 io_ptr = test_io_manager;
561 test_io_backing_manager = unix_io_manager;
562#else
563 io_ptr = unix_io_manager;
564#endif
565
566 retval = ext2fs_open (image_fn, open_flag, 0, 0,
567 io_ptr, &fs);
568 if (retval) {
569 com_err (program_name, retval, _("while trying to open %s"),
570 image_fn);
571 exit(1);
572 }
573
574 retval = ext2fs_read_bitmaps (fs);
575 if (retval) {
576 com_err(program_name, retval, "error reading bitmaps");
577 exit(1);
578 }
579
580
581 fd = open(image_fn, O_RDONLY);
582 if (fd < 0) {
583 perror(image_fn);
584 exit(1);
585 }
586
6e82cd7e 587 retval = io_ptr->open(device, IO_FLAG_RW, &io);
8c6b6483 588 if (retval) {
6e82cd7e 589 com_err(device, 0, "while opening device file");
8c6b6483
TT
590 exit(1);
591 }
592
593 image_io = fs->io;
594
595 ext2fs_rewrite_to_io(fs, io);
596
597 if (lseek(fd, fs->image_header->offset_inode, SEEK_SET) < 0) {
598 perror("lseek");
599 exit(1);
600 }
601
602 retval = ext2fs_image_inode_read(fs, fd, 0);
603 if (retval) {
604 com_err(image_fn, 0, "while restoring the image table");
605 exit(1);
606 }
607
608 ext2fs_close (fs);
609 exit (0);
610}
611
6304baf2
TT
612int main (int argc, char ** argv)
613{
614 int c;
615 errcode_t retval;
616 ext2_filsys fs;
8c6b6483 617 char *image_fn;
6304baf2
TT
618 int open_flag = 0;
619 int raw_flag = 0;
8c6b6483 620 int install_flag = 0;
d851ed39 621 int scramble_flag = 0;
6304baf2
TT
622 int fd = 0;
623
624#ifdef ENABLE_NLS
625 setlocale(LC_MESSAGES, "");
14308a53 626 setlocale(LC_CTYPE, "");
6304baf2
TT
627 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
628 textdomain(NLS_CAT_NAME);
629#endif
0f8973fb
TT
630 fprintf (stderr, "e2image %s (%s)\n", E2FSPROGS_VERSION,
631 E2FSPROGS_DATE);
6304baf2
TT
632 if (argc && *argv)
633 program_name = *argv;
a6d8302b 634 add_error_table(&et_ext2_error_table);
d851ed39 635 while ((c = getopt (argc, argv, "rsI")) != EOF)
6304baf2
TT
636 switch (c) {
637 case 'r':
638 raw_flag++;
639 break;
d851ed39
TT
640 case 's':
641 scramble_flag++;
642 break;
8c6b6483
TT
643 case 'I':
644 install_flag++;
645 break;
6304baf2
TT
646 default:
647 usage();
648 }
649 if (optind != argc - 2 )
650 usage();
651 device_name = argv[optind];
8c6b6483
TT
652 image_fn = argv[optind+1];
653
654 if (install_flag) {
655 install_image(device_name, image_fn, raw_flag);
6e82cd7e 656 exit (0);
8c6b6483
TT
657 }
658
6304baf2
TT
659 retval = ext2fs_open (device_name, open_flag, 0, 0,
660 unix_io_manager, &fs);
661 if (retval) {
662 com_err (program_name, retval, _("while trying to open %s"),
663 device_name);
54434927 664 fputs(_("Couldn't find valid filesystem superblock.\n"), stdout);
6304baf2
TT
665 exit(1);
666 }
667
8c6b6483 668 if (strcmp(image_fn, "-") == 0)
1c1e0049
TT
669 fd = 1;
670 else {
6304baf2 671#ifdef HAVE_OPEN64
8c6b6483 672 fd = open64(image_fn, O_CREAT|O_TRUNC|O_WRONLY, 0600);
6304baf2 673#else
8c6b6483 674 fd = open(image_fn, O_CREAT|O_TRUNC|O_WRONLY, 0600);
6304baf2 675#endif
1c1e0049
TT
676 if (fd < 0) {
677 com_err(program_name, errno,
678 _("while trying to open %s"), argv[optind+1]);
679 exit(1);
680 }
6304baf2
TT
681 }
682
683 if (raw_flag)
d851ed39 684 write_raw_image_file(fs, fd, scramble_flag);
6304baf2
TT
685 else
686 write_image_file(fs, fd);
c5423c5b 687
72ed1264 688 ext2fs_close (fs);
a6d8302b 689 remove_error_table(&et_ext2_error_table);
72ed1264
TT
690 exit (0);
691}