remove.c revision 1.18 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
27 #if HAVE_NBTOOL_CONFIG_H
28 #include "nbtool_config.h"
29 #endif
30
31 #include <sys/cdefs.h>
32 #ifdef __FBSDID
33 __FBSDID("$FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $");
34 #endif
35 #ifdef __RCSID
36 __RCSID("$NetBSD: remove.c,v 1.18 2015/12/01 09:05:33 christos Exp $");
37 #endif
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 #include "gpt_private.h"
51
52 static int all;
53 static gpt_uuid_t type;
54 static off_t block, size;
55 static unsigned int entry;
56 static uint8_t *label;
57
58 const char removemsg1[] = "remove -a";
59 const char removemsg2[] = "remove [-b blocknr] [-i index] [-L label] "
60 "[-s sectors] [-t type]";
61
62 static int
63 usage_remove(void)
64 {
65
66 fprintf(stderr,
67 "usage: %s %s\n"
68 " %s %s\n",
69 getprogname(), removemsg1, getprogname(), removemsg2);
70 return -1;
71 }
72
73 static int
74 rem(gpt_t gpt)
75 {
76 map_t m;
77 struct gpt_ent *ent;
78 unsigned int i;
79
80 if (gpt_hdr(gpt) == NULL)
81 return -1;
82
83 /* Remove all matching entries in the map. */
84 for (m = map_first(gpt); m != NULL; m = m->map_next) {
85 if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
86 continue;
87 if (entry > 0 && entry != m->map_index)
88 continue;
89 if (block > 0 && block != m->map_start)
90 continue;
91 if (size > 0 && size != m->map_size)
92 continue;
93
94 i = m->map_index - 1;
95
96 ent = gpt_ent_primary(gpt, i);
97
98 if (label != NULL)
99 if (strcmp((char *)label,
100 (char *)utf16_to_utf8(ent->ent_name)) != 0)
101 continue;
102
103 if (!gpt_uuid_is_nil(type) &&
104 !gpt_uuid_equal(type, ent->ent_type))
105 continue;
106
107 /* Remove the primary entry by clearing the partition type. */
108 gpt_uuid_copy(ent->ent_type, gpt_uuid_nil);
109
110 if (gpt_write_primary(gpt) == -1)
111 return -1;
112
113 ent = gpt_ent_backup(gpt, i);
114
115 /* Remove the secondary entry. */
116 gpt_uuid_copy(ent->ent_type, gpt_uuid_nil);
117
118 if (gpt_write_backup(gpt) == -1)
119 return -1;
120 gpt_msg(gpt, "partition %d removed", m->map_index);
121 }
122 return 0;
123 }
124
125 int
126 cmd_remove(gpt_t gpt, int argc, char *argv[])
127 {
128 char *p;
129 int ch;
130 int64_t human_num;
131
132 /* Get the remove options */
133 while ((ch = getopt(argc, argv, "ab:i:L:s:t:")) != -1) {
134 switch(ch) {
135 case 'a':
136 if (all > 0)
137 return usage_remove();
138 all = 1;
139 break;
140 case 'b':
141 if (block > 0)
142 return usage_remove();
143 if (dehumanize_number(optarg, &human_num) < 0)
144 return usage_remove();
145 block = human_num;
146 if (block < 1)
147 return usage_remove();
148 break;
149 case 'i':
150 if (entry > 0)
151 return usage_remove();
152 entry = strtoul(optarg, &p, 10);
153 if (*p != 0 || entry < 1)
154 return usage_remove();
155 break;
156 case 'L':
157 if (label != NULL)
158 return usage_remove();
159 label = (uint8_t *)strdup(optarg);
160 break;
161 case 's':
162 if (size > 0)
163 usage_remove();
164 size = strtoll(optarg, &p, 10);
165 if (*p != 0 || size < 1)
166 return usage_remove();
167 break;
168 case 't':
169 if (!gpt_uuid_is_nil(type))
170 return usage_remove();
171 if (gpt_uuid_parse(optarg, type) != 0)
172 return usage_remove();
173 break;
174 default:
175 return usage_remove();
176 }
177 }
178
179 if (!all ^
180 (block > 0 || entry > 0 || label != NULL || size > 0 ||
181 !gpt_uuid_is_nil(type)))
182 return usage_remove();
183
184 if (argc != optind)
185 return usage_remove();
186
187 return rem(gpt);
188 }
189