Annotation of src/sbin/gpt/recover.c, Revision 1.4.20.1
1.1 christos 1: /*-
2: * Copyright (c) 2002 Marcel Moolenaar
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: *
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
1.4.20.1! snj 27: #if HAVE_NBTOOL_CONFIG_H
! 28: #include "nbtool_config.h"
! 29: #endif
! 30:
1.1 christos 31: #include <sys/cdefs.h>
1.2 christos 32: #ifdef __FBSDID
1.1 christos 33: __FBSDID("$FreeBSD: src/sbin/gpt/recover.c,v 1.8 2005/08/31 01:47:19 marcel Exp $");
1.2 christos 34: #endif
35: #ifdef __RCSID
1.4.20.1! snj 36: __RCSID("$NetBSD: recover.c,v 1.4 2011/08/27 17:38:16 joerg Exp $");
1.2 christos 37: #endif
1.1 christos 38:
39: #include <sys/types.h>
40:
41: #include <err.h>
42: #include <stddef.h>
43: #include <stdio.h>
44: #include <stdlib.h>
45: #include <string.h>
46: #include <unistd.h>
47:
48: #include "map.h"
49: #include "gpt.h"
50:
51: static int recoverable;
52:
1.3 riz 53: const char recovermsg[] = "recover device ...";
54:
1.4 joerg 55: __dead static void
1.1 christos 56: usage_recover(void)
57: {
58:
59: fprintf(stderr,
1.3 riz 60: "usage: %s %s\n", getprogname(), recovermsg);
1.1 christos 61: exit(1);
62: }
63:
64: static void
65: recover(int fd)
66: {
67: off_t last;
68: map_t *gpt, *tpg;
69: map_t *tbl, *lbt;
70: struct gpt_hdr *hdr;
71:
72: if (map_find(MAP_TYPE_MBR) != NULL) {
73: warnx("%s: error: device contains a MBR", device_name);
74: return;
75: }
76:
77: gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
78: tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
79: tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
80: lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
81:
82: if (gpt == NULL && tpg == NULL) {
83: warnx("%s: no primary or secondary GPT headers, can't recover",
84: device_name);
85: return;
86: }
87: if (tbl == NULL && lbt == NULL) {
88: warnx("%s: no primary or secondary GPT tables, can't recover",
89: device_name);
90: return;
91: }
92:
93: last = mediasz / secsz - 1LL;
94:
95: if (tbl != NULL && lbt == NULL) {
96: lbt = map_add(last - tbl->map_size, tbl->map_size,
97: MAP_TYPE_SEC_GPT_TBL, tbl->map_data);
98: if (lbt == NULL) {
99: warnx("%s: adding secondary GPT table failed",
100: device_name);
101: return;
102: }
103: gpt_write(fd, lbt);
104: warnx("%s: recovered secondary GPT table from primary",
105: device_name);
106: } else if (tbl == NULL && lbt != NULL) {
107: tbl = map_add(2LL, lbt->map_size, MAP_TYPE_PRI_GPT_TBL,
108: lbt->map_data);
109: if (tbl == NULL) {
110: warnx("%s: adding primary GPT table failed",
111: device_name);
112: return;
113: }
114: gpt_write(fd, tbl);
115: warnx("%s: recovered primary GPT table from secondary",
116: device_name);
117: }
118:
119: if (gpt != NULL && tpg == NULL) {
120: tpg = map_add(last, 1LL, MAP_TYPE_SEC_GPT_HDR,
121: calloc(1, secsz));
122: if (tpg == NULL) {
123: warnx("%s: adding secondary GPT header failed",
124: device_name);
125: return;
126: }
127: memcpy(tpg->map_data, gpt->map_data, secsz);
128: hdr = tpg->map_data;
129: hdr->hdr_lba_self = htole64(tpg->map_start);
130: hdr->hdr_lba_alt = htole64(gpt->map_start);
131: hdr->hdr_lba_table = htole64(lbt->map_start);
132: hdr->hdr_crc_self = 0;
133: hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
134: gpt_write(fd, tpg);
135: warnx("%s: recovered secondary GPT header from primary",
136: device_name);
137: } else if (gpt == NULL && tpg != NULL) {
138: gpt = map_add(1LL, 1LL, MAP_TYPE_PRI_GPT_HDR,
139: calloc(1, secsz));
140: if (gpt == NULL) {
141: warnx("%s: adding primary GPT header failed",
142: device_name);
143: return;
144: }
145: memcpy(gpt->map_data, tpg->map_data, secsz);
146: hdr = gpt->map_data;
147: hdr->hdr_lba_self = htole64(gpt->map_start);
148: hdr->hdr_lba_alt = htole64(tpg->map_start);
149: hdr->hdr_lba_table = htole64(tbl->map_start);
150: hdr->hdr_crc_self = 0;
151: hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
152: gpt_write(fd, gpt);
153: warnx("%s: recovered primary GPT header from secondary",
154: device_name);
155: }
156: }
157:
158: int
159: cmd_recover(int argc, char *argv[])
160: {
161: int ch, fd;
162:
163: while ((ch = getopt(argc, argv, "r")) != -1) {
164: switch(ch) {
165: case 'r':
166: recoverable = 1;
167: break;
168: default:
169: usage_recover();
170: }
171: }
172:
173: if (argc == optind)
174: usage_recover();
175:
176: while (optind < argc) {
177: fd = gpt_open(argv[optind++]);
178: if (fd == -1) {
179: warn("unable to open device '%s'", device_name);
180: continue;
181: }
182:
183: recover(fd);
184:
185: gpt_close(fd);
186: }
187:
188: return (0);
189: }
CVSweb <webmaster@jp.NetBSD.org>