]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - mdrestore/xfs_mdrestore.c
2 * Copyright (c) 2007 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "xfs_metadump.h"
23 int show_progress
= 0;
24 int progress_since_warning
= 0;
27 fatal(const char *msg
, ...)
32 fprintf(stderr
, "%s: ", progname
);
33 vfprintf(stderr
, msg
, args
);
38 print_progress(const char *fmt
, ...)
44 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
46 buf
[sizeof(buf
)-1] = '\0';
48 printf("\r%-59s", buf
);
50 progress_since_warning
= 1;
59 xfs_metablock_t
*metablock
; /* header + index + blocks */
71 * read in first blocks (superblock 0), set "inprogress" flag for it,
72 * read in the rest of the file, and if complete, clear SB 0's
76 if (fread(&tmb
, sizeof(tmb
), 1, src_f
) != 1)
77 fatal("error reading from file: %s\n", strerror(errno
));
79 if (be32_to_cpu(tmb
.mb_magic
) != XFS_MD_MAGIC
)
80 fatal("specified file is not a metadata dump\n");
82 block_size
= 1 << tmb
.mb_blocklog
;
83 max_indicies
= (block_size
- sizeof(xfs_metablock_t
)) / sizeof(__be64
);
85 metablock
= (xfs_metablock_t
*)calloc(max_indicies
+ 1, block_size
);
86 if (metablock
== NULL
)
87 fatal("memory allocation failure\n");
89 mb_count
= be16_to_cpu(tmb
.mb_count
);
90 if (mb_count
== 0 || mb_count
> max_indicies
)
91 fatal("bad block count: %u\n", mb_count
);
93 block_index
= (__be64
*)((char *)metablock
+ sizeof(xfs_metablock_t
));
94 block_buffer
= (char *)metablock
+ block_size
;
96 if (fread(block_index
, block_size
- sizeof(tmb
), 1, src_f
) != 1)
97 fatal("error reading from file: %s\n", strerror(errno
));
99 if (block_index
[0] != 0)
100 fatal("first block is not the primary superblock\n");
103 if (fread(block_buffer
, mb_count
<< tmb
.mb_blocklog
,
105 fatal("error reading from file: %s\n", strerror(errno
));
107 libxfs_sb_from_disk(&sb
, (xfs_dsb_t
*)block_buffer
);
109 if (sb
.sb_magicnum
!= XFS_SB_MAGIC
)
110 fatal("bad magic number for primary superblock\n");
112 if (xfs_sb_version_hascrc(&sb
))
113 fatal("Can't restore CRC enabled filesystems yet.\n");
115 ((xfs_dsb_t
*)block_buffer
)->sb_inprogress
= 1;
117 if (is_target_file
) {
118 /* ensure regular files are correctly sized */
120 if (ftruncate64(dst_fd
, sb
.sb_dblocks
* sb
.sb_blocksize
))
121 fatal("cannot set filesystem image size: %s\n",
124 /* ensure device is sufficiently large enough */
126 char *lb
[XFS_MAX_SECTORSIZE
] = { NULL
};
129 off
= sb
.sb_dblocks
* sb
.sb_blocksize
- sizeof(lb
);
130 if (pwrite64(dst_fd
, lb
, sizeof(lb
), off
) < 0)
131 fatal("failed to write last block, is target too "
132 "small? (error: %s)\n", strerror(errno
));
138 if (show_progress
&& (bytes_read
& ((1 << 20) - 1)) == 0)
139 print_progress("%lld MB read\n", bytes_read
>> 20);
141 for (cur_index
= 0; cur_index
< mb_count
; cur_index
++) {
142 if (pwrite64(dst_fd
, &block_buffer
[cur_index
<<
143 tmb
.mb_blocklog
], block_size
,
144 be64_to_cpu(block_index
[cur_index
]) <<
146 fatal("error writing block %llu: %s\n",
147 be64_to_cpu(block_index
[cur_index
]) << BBSHIFT
,
150 if (mb_count
< max_indicies
)
153 if (fread(metablock
, block_size
, 1, src_f
) != 1)
154 fatal("error reading from file: %s\n", strerror(errno
));
156 mb_count
= be16_to_cpu(metablock
->mb_count
);
159 if (mb_count
> max_indicies
)
160 fatal("bad block count: %u\n", mb_count
);
162 if (fread(block_buffer
, mb_count
<< tmb
.mb_blocklog
,
164 fatal("error reading from file: %s\n", strerror(errno
));
166 bytes_read
+= block_size
;
169 if (progress_since_warning
)
172 memset(block_buffer
, 0, sb
.sb_sectsize
);
173 sb
.sb_inprogress
= 0;
174 libxfs_sb_to_disk((xfs_dsb_t
*)block_buffer
, &sb
, XFS_SB_ALL_BITS
);
175 if (xfs_sb_version_hascrc(&sb
)) {
176 xfs_update_cksum(block_buffer
, sb
.sb_sectsize
,
177 offsetof(struct xfs_sb
, sb_crc
));
180 if (pwrite(dst_fd
, block_buffer
, sb
.sb_sectsize
, 0) < 0)
181 fatal("error writing primary superblock: %s\n", strerror(errno
));
189 fprintf(stderr
, "Usage: %s [-V] [-g] source target\n", progname
);
193 extern int platform_check_ismounted(char *, char *, struct stat64
*, int);
204 struct stat64 statbuf
;
207 progname
= basename(argv
[0]);
209 while ((c
= getopt(argc
, argv
, "gV")) != EOF
) {
215 printf("%s version %s\n", progname
, VERSION
);
222 if (argc
- optind
!= 2)
226 if (strcmp(argv
[optind
], "-") == 0) {
228 if (isatty(fileno(stdin
)))
229 fatal("cannot read from a terminal\n");
231 src_f
= fopen(argv
[optind
], "rb");
233 fatal("cannot open source dump file\n");
237 /* check and open target */
240 if (stat64(argv
[optind
], &statbuf
) < 0) {
241 /* ok, assume it's a file and create it */
242 open_flags
|= O_CREAT
;
244 } else if (S_ISREG(statbuf
.st_mode
)) {
245 open_flags
|= O_TRUNC
;
249 * check to make sure a filesystem isn't mounted on the device
251 if (platform_check_ismounted(argv
[optind
], NULL
, &statbuf
, 0))
252 fatal("a filesystem is mounted on target device \"%s\","
253 " cannot restore to a mounted filesystem.\n",
257 dst_fd
= open(argv
[optind
], open_flags
, 0644);
259 fatal("couldn't open target \"%s\"\n", argv
[optind
]);
261 perform_restore(src_f
, dst_fd
, is_target_file
);