type.c revision 1.8 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: type.c,v 1.8 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, newtype;
54 static off_t block, size;
55 static unsigned int entry;
56 static uint8_t *label;
57
58 const char typemsg1[] = "type -a -T newtype";
59 const char typemsg2[] = "type [-b blocknr] [-i index] [-L label] "
60 "[-s sectors] [-t type]";
61 const char typemsg3[] = " -T newtype";
62
63 static int
64 usage_type(void)
65 {
66
67 fprintf(stderr,
68 "usage: %s %s\n"
69 " %s %s\n"
70 " %*s %s\n", getprogname(), typemsg1,
71 getprogname(), typemsg2, (int)strlen(getprogname()), "", typemsg3);
72 return -1;
73 }
74
75 static int
76 chtype(gpt_t gpt)
77 {
78 map_t m;
79 struct gpt_ent *ent;
80 unsigned int i;
81
82 if (gpt_hdr(gpt) == NULL)
83 return -1;
84
85 /* Change type of all matching entries in the map. */
86 for (m = map_first(gpt); m != NULL; m = m->map_next) {
87 if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
88 continue;
89 if (entry > 0 && entry != m->map_index)
90 continue;
91 if (block > 0 && block != m->map_start)
92 continue;
93 if (size > 0 && size != m->map_size)
94 continue;
95
96 i = m->map_index - 1;
97
98 ent = gpt_ent_primary(gpt, i);
99
100 if (label != NULL)
101 if (strcmp((char *)label,
102 (char *)utf16_to_utf8(ent->ent_name)) != 0)
103 continue;
104
105 if (!gpt_uuid_is_nil(type) &&
106 !gpt_uuid_equal(type, ent->ent_type))
107 continue;
108
109 /* Change the primary entry. */
110 gpt_uuid_copy(ent->ent_type, newtype);
111
112 if (gpt_write_primary(gpt) == -1)
113 return -1;
114
115 ent = gpt_ent_backup(gpt, i);
116
117 /* Change the secondary entry. */
118 gpt_uuid_copy(ent->ent_type, newtype);
119
120 if (gpt_write_backup(gpt) == -1)
121 return -1;
122
123 gpt_msg(gpt, "Partition %d type changed", m->map_index);
124 }
125 return 0;
126 }
127
128 int
129 cmd_type(gpt_t gpt, int argc, char *argv[])
130 {
131 char *p;
132 int ch;
133 int64_t human_num;
134
135 /* Get the type options */
136 while ((ch = getopt(argc, argv, "ab:i:L:s:t:T:")) != -1) {
137 switch(ch) {
138 case 'a':
139 if (all > 0)
140 return usage_type();
141 all = 1;
142 break;
143 case 'b':
144 if (block > 0)
145 return usage_type();
146 if (dehumanize_number(optarg, &human_num) < 0)
147 return usage_type();
148 block = human_num;
149 if (block < 1)
150 return usage_type();
151 break;
152 case 'i':
153 if (entry > 0)
154 return usage_type();
155 entry = strtoul(optarg, &p, 10);
156 if (*p != 0 || entry < 1)
157 return usage_type();
158 break;
159 case 'L':
160 if (label != NULL)
161 return usage_type();
162 label = (uint8_t *)strdup(optarg);
163 break;
164 case 's':
165 if (size > 0)
166 return usage_type();
167 size = strtoll(optarg, &p, 10);
168 if (*p != 0 || size < 1)
169 return usage_type();
170 break;
171 case 't':
172 if (!gpt_uuid_is_nil(type))
173 return usage_type();
174 if (gpt_uuid_parse(optarg, type) != 0)
175 return usage_type();
176 break;
177 case 'T':
178 if (!gpt_uuid_is_nil(newtype))
179 return usage_type();
180 if (gpt_uuid_parse(optarg, newtype) != 0)
181 return usage_type();
182 break;
183 default:
184 return usage_type();
185 }
186 }
187
188 if (!all ^
189 (block > 0 || entry > 0 || label != NULL || size > 0 ||
190 !gpt_uuid_is_nil(type)))
191 return usage_type();
192 if (gpt_uuid_is_nil(newtype))
193 return usage_type();
194
195 if (argc != optind)
196 return usage_type();
197
198 return chtype(gpt);
199 }
200