]>
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_indices
= (block_size
- sizeof(xfs_metablock_t
)) / sizeof(__be64
);
85 metablock
= (xfs_metablock_t
*)calloc(max_indices
+ 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_indices
)
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");
113 * Normally the upper bound would be simply XFS_MAX_SECTORSIZE
114 * but the metadump format has a maximum number of BBSIZE blocks
115 * it can store in a single metablock.
117 if (sb
.sb_sectsize
< XFS_MIN_SECTORSIZE
||
118 sb
.sb_sectsize
> XFS_MAX_SECTORSIZE
||
119 sb
.sb_sectsize
> max_indices
* block_size
)
120 fatal("bad sector size %u in metadump image\n", sb
.sb_sectsize
);
122 ((xfs_dsb_t
*)block_buffer
)->sb_inprogress
= 1;
124 if (is_target_file
) {
125 /* ensure regular files are correctly sized */
127 if (ftruncate64(dst_fd
, sb
.sb_dblocks
* sb
.sb_blocksize
))
128 fatal("cannot set filesystem image size: %s\n",
131 /* ensure device is sufficiently large enough */
133 char *lb
[XFS_MAX_SECTORSIZE
] = { NULL
};
136 off
= sb
.sb_dblocks
* sb
.sb_blocksize
- sizeof(lb
);
137 if (pwrite64(dst_fd
, lb
, sizeof(lb
), off
) < 0)
138 fatal("failed to write last block, is target too "
139 "small? (error: %s)\n", strerror(errno
));
145 if (show_progress
&& (bytes_read
& ((1 << 20) - 1)) == 0)
146 print_progress("%lld MB read", bytes_read
>> 20);
148 for (cur_index
= 0; cur_index
< mb_count
; cur_index
++) {
149 if (pwrite64(dst_fd
, &block_buffer
[cur_index
<<
150 tmb
.mb_blocklog
], block_size
,
151 be64_to_cpu(block_index
[cur_index
]) <<
153 fatal("error writing block %llu: %s\n",
154 be64_to_cpu(block_index
[cur_index
]) << BBSHIFT
,
157 if (mb_count
< max_indices
)
160 if (fread(metablock
, block_size
, 1, src_f
) != 1)
161 fatal("error reading from file: %s\n", strerror(errno
));
163 mb_count
= be16_to_cpu(metablock
->mb_count
);
166 if (mb_count
> max_indices
)
167 fatal("bad block count: %u\n", mb_count
);
169 if (fread(block_buffer
, mb_count
<< tmb
.mb_blocklog
,
171 fatal("error reading from file: %s\n", strerror(errno
));
173 bytes_read
+= block_size
+ (mb_count
<< tmb
.mb_blocklog
);
176 if (progress_since_warning
)
179 memset(block_buffer
, 0, sb
.sb_sectsize
);
180 sb
.sb_inprogress
= 0;
181 libxfs_sb_to_disk((xfs_dsb_t
*)block_buffer
, &sb
);
182 if (xfs_sb_version_hascrc(&sb
)) {
183 xfs_update_cksum(block_buffer
, sb
.sb_sectsize
,
184 offsetof(struct xfs_sb
, sb_crc
));
187 if (pwrite(dst_fd
, block_buffer
, sb
.sb_sectsize
, 0) < 0)
188 fatal("error writing primary superblock: %s\n", strerror(errno
));
196 fprintf(stderr
, "Usage: %s [-V] [-g] source target\n", progname
);
200 extern int platform_check_ismounted(char *, char *, struct stat64
*, int);
211 struct stat64 statbuf
;
214 progname
= basename(argv
[0]);
216 while ((c
= getopt(argc
, argv
, "gV")) != EOF
) {
222 printf("%s version %s\n", progname
, VERSION
);
229 if (argc
- optind
!= 2)
233 if (strcmp(argv
[optind
], "-") == 0) {
235 if (isatty(fileno(stdin
)))
236 fatal("cannot read from a terminal\n");
238 src_f
= fopen(argv
[optind
], "rb");
240 fatal("cannot open source dump file\n");
244 /* check and open target */
247 if (stat64(argv
[optind
], &statbuf
) < 0) {
248 /* ok, assume it's a file and create it */
249 open_flags
|= O_CREAT
;
251 } else if (S_ISREG(statbuf
.st_mode
)) {
252 open_flags
|= O_TRUNC
;
256 * check to make sure a filesystem isn't mounted on the device
258 if (platform_check_ismounted(argv
[optind
], NULL
, &statbuf
, 0))
259 fatal("a filesystem is mounted on target device \"%s\","
260 " cannot restore to a mounted filesystem.\n",
264 dst_fd
= open(argv
[optind
], open_flags
, 0644);
266 fatal("couldn't open target \"%s\"\n", argv
[optind
]);
268 perform_restore(src_f
, dst_fd
, is_target_file
);