rc.d/devfs: Add missing line termination.
[dragonfly.git] / sbin / gpt / remove.c
1 /*-
2  * Copyright (c) 2004 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  * $FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $
27  * $DragonFly: src/sbin/gpt/remove.c,v 1.2 2007/06/17 08:34:59 dillon Exp $
28  */
29
30 #include <sys/types.h>
31
32 #include <err.h>
33 #include <stddef.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #include "map.h"
40 #include "gpt.h"
41
42 static int all;
43 static uuid_t type;
44 static off_t block, size;
45 static unsigned int entry = NOENTRY;
46
47 static void
48 usage_remove(void)
49 {
50
51         fprintf(stderr,
52             "usage: %s -a device ...\n"
53             "       %s [-b lba] [-i index] [-s lba] [-t uuid] device ...\n",
54             getprogname(), getprogname());
55         exit(1);
56 }
57
58 static void
59 rem(int fd)
60 {
61         uuid_t uuid;
62         map_t *gpt, *tpg;
63         map_t *tbl, *lbt;
64         map_t *m;
65         struct gpt_hdr *hdr;
66         struct gpt_ent *ent;
67         unsigned int i;
68
69         gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
70         if (gpt == NULL) {
71                 warnx("%s: error: no primary GPT header; run create or recover",
72                     device_name);
73                 return;
74         }
75
76         tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
77         if (tpg == NULL) {
78                 warnx("%s: error: no secondary GPT header; run recover",
79                     device_name);
80                 return;
81         }
82
83         tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
84         lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
85         if (tbl == NULL || lbt == NULL) {
86                 warnx("%s: error: run recover -- trust me", device_name);
87                 return;
88         }
89
90         /* Remove all matching entries in the map. */
91         for (m = map_first(); m != NULL; m = m->map_next) {
92                 if (m->map_type != MAP_TYPE_GPT_PART || m->map_index == NOENTRY)
93                         continue;
94                 if (entry != NOENTRY && entry != m->map_index)
95                         continue;
96                 if (block > 0 && block != m->map_start)
97                         continue;
98                 if (size > 0 && size != m->map_size)
99                         continue;
100
101                 i = m->map_index;
102
103                 hdr = gpt->map_data;
104                 ent = (void*)((char*)tbl->map_data + i *
105                     le32toh(hdr->hdr_entsz));
106                 le_uuid_dec(&ent->ent_type, &uuid);
107                 if (!uuid_is_nil(&type, NULL) &&
108                     !uuid_equal(&type, &uuid, NULL))
109                         continue;
110
111                 /* Remove the primary entry by clearing the partition type. */
112                 uuid_create_nil(&ent->ent_type, NULL);
113
114                 hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
115                     le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
116                 hdr->hdr_crc_self = 0;
117                 hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
118
119                 gpt_write(fd, gpt);
120                 gpt_write(fd, tbl);
121
122                 hdr = tpg->map_data;
123                 ent = (void*)((char*)lbt->map_data + i *
124                     le32toh(hdr->hdr_entsz));
125
126                 /* Remove the secundary entry. */
127                 uuid_create_nil(&ent->ent_type, NULL);
128
129                 hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
130                     le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
131                 hdr->hdr_crc_self = 0;
132                 hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
133
134                 gpt_write(fd, lbt);
135                 gpt_write(fd, tpg);
136
137                 printf("%ss%u removed\n", device_name, m->map_index);
138         }
139 }
140
141 int
142 cmd_remove(int argc, char *argv[])
143 {
144         char *p;
145         int ch, fd;
146
147         /* Get the remove options */
148         while ((ch = getopt(argc, argv, "ab:i:s:t:")) != -1) {
149                 switch(ch) {
150                 case 'a':
151                         if (all > 0)
152                                 usage_remove();
153                         all = 1;
154                         break;
155                 case 'b':
156                         if (block > 0)
157                                 usage_remove();
158                         block = strtoll(optarg, &p, 10);
159                         if (*p != 0 || block < 1)
160                                 usage_remove();
161                         break;
162                 case 'i':
163                         if (entry != NOENTRY)
164                                 usage_remove();
165                         entry = strtoul(optarg, &p, 10);
166                         if (*p != 0 || entry == NOENTRY)
167                                 usage_remove();
168                         break;
169                 case 's':
170                         if (size > 0)
171                                 usage_remove();
172                         size = strtoll(optarg, &p, 10);
173                         if (*p != 0 || size < 1)
174                                 usage_remove();
175                         break;
176                 case 't':
177                         if (!uuid_is_nil(&type, NULL))
178                                 usage_remove();
179                         if (parse_uuid(optarg, &type) != 0)
180                                 usage_remove();
181                         break;
182                 default:
183                         usage_remove();
184                 }
185         }
186
187         if (!all ^
188             (block > 0 || entry != NOENTRY || size > 0 ||
189              !uuid_is_nil(&type, NULL)))
190                 usage_remove();
191
192         if (argc == optind)
193                 usage_remove();
194
195         while (optind < argc) {
196                 fd = gpt_open(argv[optind++]);
197                 if (fd == -1) {
198                         warn("unable to open device '%s'", device_name);
199                         continue;
200                 }
201
202                 rem(fd);
203
204                 gpt_close(fd);
205         }
206
207         return (0);
208 }