]> git.ipfire.org Git - thirdparty/util-linux.git/blob - libfdisk/src/parttype.c
712994efb2b35d73a7b938ca3bb06c7184d03249
[thirdparty/util-linux.git] / libfdisk / src / parttype.c
1
2 #include <ctype.h>
3
4 #include "nls.h"
5 #include "fdiskP.h"
6
7 /**
8 * SECTION: parttype
9 * @title: Partition types
10 * @short_description: abstraction to partition types
11 *
12 * There are two basic types of parttypes, string based (e.g. GPT)
13 * and code/hex based (e.g. MBR).
14 */
15
16 /**
17 * fdisk_new_parttype:
18 *
19 * It's recommended to use fdisk_label_get_parttype_from_code() or
20 * fdisk_label_get_parttype_from_string() for well known types rather
21 * than allocate a new instance.
22 *
23 * Returns: new instance.
24 */
25 struct fdisk_parttype *fdisk_new_parttype(void)
26 {
27 struct fdisk_parttype *t = calloc(1, sizeof(*t));
28
29 t->refcount = 1;
30 t->flags = FDISK_PARTTYPE_ALLOCATED;
31 DBG(PARTTYPE, ul_debugobj(t, "alloc"));
32 return t;
33 }
34
35 /**
36 * fdisk_ref_parttype:
37 * @t: partition type
38 *
39 * Incremparts reference counter for allocated types
40 */
41 void fdisk_ref_parttype(struct fdisk_parttype *t)
42 {
43 if (fdisk_parttype_is_allocated(t))
44 t->refcount++;
45 }
46
47 /**
48 * fdisk_unref_parttype
49 * @t: partition pointer
50 *
51 * De-incremparts reference counter, on zero the @t is automatically
52 * deallocated.
53 */
54 void fdisk_unref_parttype(struct fdisk_parttype *t)
55 {
56 if (!fdisk_parttype_is_allocated(t))
57 return;
58
59 t->refcount--;
60 if (t->refcount <= 0) {
61 DBG(PARTTYPE, ul_debugobj(t, "free"));
62 free(t->typestr);
63 free(t->name);
64 free(t);
65 }
66 }
67
68 /**
69 * fdisk_parttype_set_name:
70 * @t: partition type
71 * @str: type name
72 *
73 * Sets type name to allocated partition type, for static types
74 * it returns -EINVAL.
75 *
76 * Return: 0 on success, <0 on error
77 */
78 int fdisk_parttype_set_name(struct fdisk_parttype *t, const char *str)
79 {
80 char *p = NULL;
81
82 if (!t || !fdisk_parttype_is_allocated(t))
83 return -EINVAL;
84 if (str) {
85 p = strdup(str);
86 if (!p)
87 return -ENOMEM;
88 }
89
90 free(t->name);
91 t->name = p;
92 return 0;
93 }
94
95 /**
96 * fdisk_parttype_set_typestr:
97 * @t: partition type
98 * @str: type identificator (e.g. GUID for GPT)
99 *
100 * Sets type string to allocated partition type, for static types
101 * it returns -EINVAL. Don't use this function for MBR, see
102 * fdisk_parttype_set_code().
103 *
104 * Return: 0 on success, <0 on error
105 */
106 int fdisk_parttype_set_typestr(struct fdisk_parttype *t, const char *str)
107 {
108 char *p = NULL;
109
110 if (!t || !fdisk_parttype_is_allocated(t))
111 return -EINVAL;
112 if (str) {
113 p = strdup(str);
114 if (!p)
115 return -ENOMEM;
116 }
117
118 free(t->typestr);
119 t->typestr = p;
120 return 0;
121 }
122
123 /**
124 * fdisk_parttype_set_code:
125 * @t: partition type
126 * @code: type identificator (e.g. MBR type codes)
127 *
128 * Sets type code to allocated partition type, for static types it returns
129 * -EINVAL. Don't use this function for GPT, see fdisk_parttype_set_typestr().
130 *
131 * Return: 0 on success, <0 on error
132 */
133 int fdisk_parttype_set_code(struct fdisk_parttype *t, int code)
134 {
135 if (!t || !fdisk_parttype_is_allocated(t))
136 return -EINVAL;
137 t->code = code;
138 return 0;
139 }
140
141 /**
142 * fdisk_label_get_nparttypes:
143 * @lb: label
144 *
145 * Returns: number of types supported by label.
146 */
147 size_t fdisk_label_get_nparttypes(const struct fdisk_label *lb)
148 {
149 if (!lb)
150 return 0;
151 return lb->nparttypes;
152 }
153
154 /**
155 * fdisk_label_get_parttype:
156 * @lb: label
157 * @n: number
158 *
159 * Returns: return parttype
160 */
161 struct fdisk_parttype *fdisk_label_get_parttype(const struct fdisk_label *lb, size_t n)
162 {
163 if (!lb || n >= lb->nparttypes)
164 return NULL;
165 return &lb->parttypes[n];
166 }
167
168 /**
169 * fdisk_label_has_code_parttypes:
170 * @lb: label
171 *
172 * Returns: 1 if the label uses code as partition type
173 * identifiers (e.g. MBR) or 0.
174 */
175 int fdisk_label_has_code_parttypes(const struct fdisk_label *lb)
176 {
177 assert(lb);
178
179 if (lb->parttypes && lb->parttypes[0].typestr)
180 return 0;
181 return 1;
182 }
183
184
185 /**
186 * fdisk_label_get_parttype_from_code:
187 * @lb: label
188 * @code: code to search for
189 *
190 * Search for partition type in label-specific table. The result
191 * is pointer to static array of label types.
192 *
193 * Returns: partition type or NULL upon failure or invalid @code.
194 */
195 struct fdisk_parttype *fdisk_label_get_parttype_from_code(
196 const struct fdisk_label *lb,
197 unsigned int code)
198 {
199 size_t i;
200
201 assert(lb);
202
203 if (!lb->nparttypes)
204 return NULL;
205
206 for (i = 0; i < lb->nparttypes; i++)
207 if (lb->parttypes[i].code == code)
208 return &lb->parttypes[i];
209 return NULL;
210 }
211
212 /**
213 * fdisk_label_get_parttype_from_string:
214 * @lb: label
215 * @str: string to search for
216 *
217 * Search for partition type in label-specific table. The result
218 * is pointer to static array of label types.
219 *
220 * Returns: partition type or NULL upon failure or invalid @str.
221 */
222 struct fdisk_parttype *fdisk_label_get_parttype_from_string(
223 const struct fdisk_label *lb,
224 const char *str)
225 {
226 size_t i;
227
228 assert(lb);
229
230 if (!lb->nparttypes)
231 return NULL;
232
233 for (i = 0; i < lb->nparttypes; i++)
234 if (lb->parttypes[i].typestr
235 && strcasecmp(lb->parttypes[i].typestr, str) == 0)
236 return &lb->parttypes[i];
237
238 return NULL;
239 }
240
241 /**
242 * fdisk_new_unknown_parttype:
243 * @code: type as number
244 * @typestr: type as string
245
246 * Allocates new 'unknown' partition type. Use fdisk_unref_parttype() to
247 * deallocate.
248 *
249 * Returns: newly allocated partition type, or NULL upon failure.
250 */
251 struct fdisk_parttype *fdisk_new_unknown_parttype(unsigned int code,
252 const char *typestr)
253 {
254 struct fdisk_parttype *t = fdisk_new_parttype();
255
256 if (!t)
257 return NULL;
258
259 fdisk_parttype_set_name(t, _("unknown"));
260 fdisk_parttype_set_code(t, code);
261 fdisk_parttype_set_typestr(t, typestr);
262 t->flags |= FDISK_PARTTYPE_UNKNOWN;
263
264 return t;
265 }
266
267 /**
268 * fdisk_copy_parttype:
269 * @type: type to copy
270 *
271 * Use fdisk_unref_parttype() to deallocate.
272 *
273 * Returns: newly allocated partition type, or NULL upon failure.
274 */
275 struct fdisk_parttype *fdisk_copy_parttype(const struct fdisk_parttype *type)
276 {
277 struct fdisk_parttype *t = fdisk_new_parttype();
278
279 if (!t)
280 return NULL;
281
282 fdisk_parttype_set_name(t, type->name);
283 fdisk_parttype_set_code(t, type->code);
284 fdisk_parttype_set_typestr(t, type->typestr);
285
286 return t;
287 }
288
289 /**
290 * fdisk_label_parse_parttype:
291 * @lb: label
292 * @str: string to parse from
293 *
294 * Parses partition type from @str according to the label. Thefunction returns
295 * a pointer to static table of the partition types, or newly allocated
296 * partition type for unknown types (see fdisk_parttype_is_unknown(). It's
297 * safe to call fdisk_unref_parttype() for all results.
298 *
299 * Returns: pointer to type or NULL on error.
300 */
301 struct fdisk_parttype *fdisk_label_parse_parttype(
302 const struct fdisk_label *lb,
303 const char *str)
304 {
305 struct fdisk_parttype *types, *ret = NULL;
306 char *end = NULL;
307
308 assert(lb);
309
310 if (!lb->nparttypes)
311 return NULL;
312
313 DBG(LABEL, ul_debugobj((void *) lb, "parsing '%s' (%s) partition type",
314 str, lb->name));
315 types = lb->parttypes;
316
317 if (types[0].typestr == NULL && isxdigit(*str)) {
318 unsigned int code = 0;
319
320 errno = 0;
321 code = strtol(str, &end, 16);
322
323 if (errno || *end != '\0') {
324 DBG(LABEL, ul_debugobj((void *) lb, "parsing failed: %m"));
325 return NULL;
326 }
327 ret = fdisk_label_get_parttype_from_code(lb, code);
328 if (ret)
329 goto done;
330
331 ret = fdisk_new_unknown_parttype(code, NULL);
332 } else {
333 int i;
334
335 /* maybe specified by type string (e.g. UUID) */
336 ret = fdisk_label_get_parttype_from_string(lb, str);
337 if (ret)
338 goto done;
339
340 /* maybe specified by order number */
341 errno = 0;
342 i = strtol(str, &end, 0);
343 if (errno == 0 && *end == '\0' && i > 0
344 && i - 1 < (int) lb->nparttypes) {
345 ret = &types[i - 1];
346 goto done;
347 }
348
349 ret = fdisk_new_unknown_parttype(0, str);
350 }
351
352 done:
353 DBG(PARTTYPE, ul_debugobj(ret, "returns parsed '%s' [%s] partition type",
354 ret->name, ret->typestr ? : ""));
355 return ret;
356 }
357
358 /**
359 * fdisk_parttype_get_string:
360 * @t: type
361 *
362 * Returns: partition type string (e.g. GUID for GPT)
363 */
364 const char *fdisk_parttype_get_string(const struct fdisk_parttype *t)
365 {
366 assert(t);
367 return t->typestr && *t->typestr ? t->typestr : NULL;
368 }
369
370 /**
371 * fdisk_parttype_get_code:
372 * @t: type
373 *
374 * Returns: partition type code (e.g. for MBR)
375 */
376 unsigned int fdisk_parttype_get_code(const struct fdisk_parttype *t)
377 {
378 assert(t);
379 return t->code;
380 }
381
382 /**
383 * fdisk_parttype_get_name:
384 * @t: type
385 *
386 * Returns: partition type human readable name
387 */
388 const char *fdisk_parttype_get_name(const struct fdisk_parttype *t)
389 {
390 assert(t);
391 return t->name;
392 }
393
394 /**
395 * fdisk_parttype_is_unknown:
396 * @t: type
397 *
398 * Checks for example result from fdisk_label_parse_parttype().
399 *
400 * Returns: 1 is type is "unknonw" or 0.
401 */
402 int fdisk_parttype_is_unknown(const struct fdisk_parttype *t)
403 {
404 return t && (t->flags & FDISK_PARTTYPE_UNKNOWN) ? 1 : 0;
405 }