From f94e753b35cf7a8bdd3a27edb72e094917757334 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Tue, 3 Mar 2020 15:59:49 +0100
Subject: [PATCH] libfdisk: add partition type aliases and shortcuts

Now, the type shortcuts are supported for sfdisk scripts only.

Unfortunately, the current implementation is not generic enough
and it's also fragile as 'E' shortcut is in collision with 0x0E
type for MBR. The another issue is 'L' which makes shortcuts useless
for fdisk where 'L' is used for another purpose in dialogs.

This patch introduces partition type aliases as extension to
shortcuts. The definition of the shortcut is part of the label
definition and it's not more hardcoded in sfdisk script code.

This patch also introduces 'Ex' shortcut as replacement for (now
deprecated) 'E'.

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 libfdisk/src/dos.c         |  16 +++
 libfdisk/src/fdiskP.h      |  17 +++
 libfdisk/src/gpt.c         |  13 ++
 libfdisk/src/libfdisk.h.in |  36 ++++++
 libfdisk/src/libfdisk.sym  |   3 +
 libfdisk/src/parttype.c    | 236 ++++++++++++++++++++++++++++++-------
 libfdisk/src/script.c      |  94 ++-------------
 7 files changed, 291 insertions(+), 124 deletions(-)

diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index ae06e179d..a79912e8b 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -70,6 +70,18 @@ static struct fdisk_parttype dos_parttypes[] = {
 	#include "pt-mbr-partnames.h"
 };
 
+static const struct fdisk_shortcut dos_parttype_cuts[] =
+{
+	{ .shortcut = "L", .alias = "linux",    .data = "83" },
+	{ .shortcut = "S", .alias = "swap",     .data = "82" },
+	{ .shortcut = "E", .alias = "extended", .data = "05", .deprecated = 1 }, /* collision with 0x0e type */
+	{ .shortcut = "Ex",.alias = "extended", .data = "05" }, /* MBR extended */
+	{ .shortcut = "U", .alias = "uefi",     .data = "EF" }, /* UEFI system */
+	{ .shortcut = "R", .alias = "raid",     .data = "FD" }, /* Linux RAID */
+	{ .shortcut = "V", .alias = "lvm",      .data = "8E" }, /* LVM */
+	{ .shortcut = "X", .alias = "linuxex",  .data = "85" }  /* Linux extended */
+};
+
 #define set_hsc(h,s,c,sector) { \
 		s = sector % cxt->geom.sectors + 1;			\
 		sector /= cxt->geom.sectors;				\
@@ -2556,8 +2568,12 @@ struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt __attribute__
 	lb->name = "dos";
 	lb->id = FDISK_DISKLABEL_DOS;
 	lb->op = &dos_operations;
+
 	lb->parttypes = dos_parttypes;
 	lb->nparttypes = ARRAY_SIZE(dos_parttypes) - 1;
+	lb->parttype_cuts = dos_parttype_cuts;
+	lb->nparttype_cuts = ARRAY_SIZE(dos_parttype_cuts);
+
 	lb->fields = dos_fields;
 	lb->nfields = ARRAY_SIZE(dos_fields);
 
diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h
index ec07f1fc8..f291c08b6 100644
--- a/libfdisk/src/fdiskP.h
+++ b/libfdisk/src/fdiskP.h
@@ -123,6 +123,17 @@ enum {
 #define fdisk_parttype_is_invisible(_x)	((_x) && ((_x)->flags & FDISK_PARTTYPE_INVISIBLE))
 #define fdisk_parttype_is_allocated(_x)	((_x) && ((_x)->flags & FDISK_PARTTYPE_ALLOCATED))
 
+/*
+ * Shortcut (used for partition types)
+ */
+struct fdisk_shortcut {
+	const char	*shortcut;	/* shortcut, usually one letter (e.h. "H") */
+	const char	*alias;		/* human readable alias (e.g. "home") */
+	const char	*data;		/* for example partition type */
+
+	unsigned int    deprecated : 1;
+};
+
 struct fdisk_partition {
 	int		refcount;		/* reference counter */
 
@@ -278,6 +289,9 @@ struct fdisk_label {
 	struct fdisk_parttype	*parttypes;	/* supported partitions types */
 	size_t			nparttypes;	/* number of items in parttypes[] */
 
+	const struct fdisk_shortcut *parttype_cuts;	/* partition type shortcuts */
+	size_t			nparttype_cuts;	/* number of items in parttype_cuts */
+
 	size_t			nparts_max;	/* maximal number of partitions */
 	size_t			nparts_cur;	/* number of currently used partitions */
 
@@ -519,4 +533,7 @@ int fdisk_do_wipe(struct fdisk_context *cxt);
 int fdisk_has_wipe_area(struct fdisk_context *cxt, uint64_t start, uint64_t size);
 int fdisk_check_collisions(struct fdisk_context *cxt);
 
+/* parttype.c */
+const char *fdisk_label_translate_type_shortcut(const struct fdisk_label *lb, char *cut);
+
 #endif /* _LIBFDISK_PRIVATE_H */
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c
index 4915b9a37..25555a395 100644
--- a/libfdisk/src/gpt.c
+++ b/libfdisk/src/gpt.c
@@ -156,6 +156,16 @@ static struct fdisk_parttype gpt_parttypes[] =
 	#include "pt-gpt-partnames.h"
 };
 
+static const struct fdisk_shortcut gpt_parttype_cuts[] =
+{
+	{ .shortcut = "L", .alias = "linux", .data = "0FC63DAF-8483-4772-8E79-3D69D8477DE4" }, /* Linux */
+	{ .shortcut = "S", .alias = "swap",  .data = "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F" }, /* Swap */
+	{ .shortcut = "H", .alias = "home",  .data = "933AC7E1-2EB4-4F13-B844-0E14E2AEF915" }, /* Home */
+	{ .shortcut = "U", .alias = "uefi",  .data = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" }, /* UEFI system */
+	{ .shortcut = "R", .alias = "raid",  .data = "A19D880F-05FC-4D3B-A006-743F0F84911E" }, /* Linux RAID */
+	{ .shortcut = "V", .alias = "lvm",   .data = "E6D6D379-F507-44C2-A23C-238F2A3DF928" }  /* LVM */
+};
+
 #define alignment_required(_x)  ((_x)->grain != (_x)->sector_size)
 
 /* gpt_entry macros */
@@ -3134,8 +3144,11 @@ struct fdisk_label *fdisk_new_gpt_label(struct fdisk_context *cxt __attribute__
 	lb->name = "gpt";
 	lb->id = FDISK_DISKLABEL_GPT;
 	lb->op = &gpt_operations;
+
 	lb->parttypes = gpt_parttypes;
 	lb->nparttypes = ARRAY_SIZE(gpt_parttypes);
+	lb->parttype_cuts = gpt_parttype_cuts;
+	lb->nparttype_cuts = ARRAY_SIZE(gpt_parttype_cuts);
 
 	lb->fields = gpt_fields;
 	lb->nfields = ARRAY_SIZE(gpt_fields);
diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in
index 89fad448e..bf05290f9 100644
--- a/libfdisk/src/libfdisk.h.in
+++ b/libfdisk/src/libfdisk.h.in
@@ -264,7 +264,13 @@ int fdisk_parttype_set_typestr(struct fdisk_parttype *t, const char *str);
 int fdisk_parttype_set_code(struct fdisk_parttype *t, int code);
 size_t fdisk_label_get_nparttypes(const struct fdisk_label *lb);
 struct fdisk_parttype *fdisk_label_get_parttype(const struct fdisk_label *lb, size_t n);
+int fdisk_label_get_parttype_shortcut(
+	                        const struct fdisk_label *lb, size_t n,
+		                const char **typestr,
+			        const char **shortcut,
+				const char **alias);
 int fdisk_label_has_code_parttypes(const struct fdisk_label *lb);
+int fdisk_label_has_parttypes_shortcuts(const struct fdisk_label *lb);
 struct fdisk_parttype *fdisk_label_get_parttype_from_code(
 				const struct fdisk_label *lb,
 				unsigned int code);
@@ -277,6 +283,36 @@ struct fdisk_parttype *fdisk_copy_parttype(const struct fdisk_parttype *type);
 struct fdisk_parttype *fdisk_label_parse_parttype(
 				const struct fdisk_label *lb,
 				const char *str);
+struct fdisk_parttype *fdisk_label_advparse_parttype(
+				const struct fdisk_label *lb,
+				const char *str,
+				int flags);
+
+/**
+ * fdisk_parttype_parser_flags:
+ * @FDISK_PARTTYPE_PARSE_DATA: parse hex or UUID from string
+ * @FDISK_PARTTYPE_PARSE_DATALAST: try hex or UUID as the last possibility (don't use!)
+ * @FDISK_PARTTYPE_PARSE_SHORTCUT: try input interpret as type shortcut (e.g 'L' for linux partition)
+ * @FDISK_PARTTYPE_PARSE_ALIAS: try input interpret as type alias (e.g. 'linux' for linux partition)
+ * @FDISK_PARTTYPE_PARSE_DEPRECATED: accept also deprecated aliases and shortcuts
+ * @FDISK_PARTTYPE_PARSE_DEFAULT: recommended flags for new code
+ * @FDISK_PARTTYPE_PARSE_NOUNKNOWN: ignore unknown types
+ */
+enum fdisk_parttype_parser_flags {
+	FDISK_PARTTYPE_PARSE_DATA       = (1 << 1),
+	FDISK_PARTTYPE_PARSE_DATALAST   = (1 << 2),
+	FDISK_PARTTYPE_PARSE_SHORTCUT   = (1 << 3),
+	FDISK_PARTTYPE_PARSE_ALIAS      = (1 << 4),
+	FDISK_PARTTYPE_PARSE_DEPRECATED = (1 << 5),
+	FDISK_PARTTYPE_PARSE_NOUNKNOWN  = (1 << 6),
+	FDISK_PARTTYPE_PARSE_SEQNUM     = (1 << 7),
+
+	FDISK_PARTTYPE_PARSE_DEFAULT = (FDISK_PARTTYPE_PARSE_DATA | \
+				        FDISK_PARTTYPE_PARSE_SHORTCUT | \
+				        FDISK_PARTTYPE_PARSE_ALIAS | \
+					FDISK_PARTTYPE_PARSE_SEQNUM )
+};
+
 const char *fdisk_parttype_get_string(const struct fdisk_parttype *t);
 unsigned int fdisk_parttype_get_code(const struct fdisk_parttype *t);
 const char *fdisk_parttype_get_name(const struct fdisk_parttype *t);
diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym
index 96fcadd..4a5ba0b 100644
--- a/libfdisk/src/libfdisk.sym
+++ b/libfdisk/src/libfdisk.sym
@@ -307,4 +307,7 @@ FDISK_2.33 {
 FDISK_2.35 {
 	fdisk_script_set_table;
 	fdisk_assign_device_by_fd;
+        fdisk_label_has_parttypes_shortcuts;
+        fdisk_label_advparse_parttype;
+        fdisk_label_get_parttype_shortcut;
 } FDISK_2.33;
diff --git a/libfdisk/src/parttype.c b/libfdisk/src/parttype.c
index d5ad434f0..36d12216d 100644
--- a/libfdisk/src/parttype.c
+++ b/libfdisk/src/parttype.c
@@ -145,6 +145,41 @@ struct fdisk_parttype *fdisk_label_get_parttype(const struct fdisk_label *lb, si
 	return &lb->parttypes[n];
 }
 
+/**
+ * fdisk_label_get_parttype_shortcut:
+ * @lb: label
+ * @n: number
+ * @typestr: returns type as string
+ * @shortcut: returns type shortcut string
+ * @alias: returns type alias string
+ *
+ * Returns: return 0 on success, <0 on error, 2 for deprecated alias, 1 for @n out of range
+ *
+ * Since: v2.36
+ */
+int fdisk_label_get_parttype_shortcut(const struct fdisk_label *lb, size_t n,
+		const char **typestr, const char **shortcut, const char **alias)
+{
+	const struct fdisk_shortcut *sc;
+
+	if (!lb)
+		return -EINVAL;
+	if (n >= lb->nparttype_cuts)
+		return 1;
+
+	sc = &lb->parttype_cuts[n];
+	if (typestr)
+		*typestr = sc->data;
+	if (shortcut)
+		*shortcut = sc->shortcut;
+	if (alias)
+		*alias = sc->alias;
+
+	return sc->deprecated == 1 ? 2 : 0;
+
+}
+
+
 /**
  * fdisk_label_has_code_parttypes:
  * @lb: label
@@ -161,6 +196,20 @@ int fdisk_label_has_code_parttypes(const struct fdisk_label *lb)
 	return 1;
 }
 
+/**
+ * fdisk_label_has_parttypes_shortcuts
+ * @lb: label
+ *
+ * Returns: 1 if the label support shortuts/aliases for partition types or 0.
+ *
+ * Since: 2.36
+ */
+int fdisk_label_has_parttypes_shortcuts(const struct fdisk_label *lb)
+{
+	assert(lb);
+	return lb->nparttype_cuts ? 1 : 0;
+}
+
 
 /**
  * fdisk_label_get_parttype_from_code:
@@ -266,79 +315,186 @@ struct fdisk_parttype *fdisk_copy_parttype(const struct fdisk_parttype *type)
 	return t;
 }
 
-/**
- * fdisk_label_parse_parttype:
- * @lb: label
- * @str: string to parse from
- *
- * Parses partition type from @str according to the label. The function returns
- * a pointer to static table of the partition types, or newly allocated
- * partition type for unknown types (see fdisk_parttype_is_unknown(). It's
- * safe to call fdisk_unref_parttype() for all results.
- *
- * Returns: pointer to type or NULL on error.
- */
-struct fdisk_parttype *fdisk_label_parse_parttype(
+static struct fdisk_parttype *parttype_from_data(
 				const struct fdisk_label *lb,
-				const char *str)
+				const char *str,
+				unsigned int *xcode,
+				int use_seqnum)
 {
 	struct fdisk_parttype *types, *ret = NULL;
 	char *end = NULL;
 
 	assert(lb);
+	assert(str);
 
+	if (xcode)
+		*xcode = 0;
 	if (!lb->nparttypes)
 		return NULL;
 
-	DBG(LABEL, ul_debugobj(lb, "parsing '%s' (%s) partition type",
-				str, lb->name));
+	DBG(LABEL, ul_debugobj(lb, " parsing '%s' data", str));
 	types = lb->parttypes;
 
 	if (types[0].typestr == NULL) {
-		unsigned int code = 0;
+		unsigned int code;
 
-		DBG(LABEL, ul_debugobj(lb, " parsing hex"));
+		DBG(LABEL, ul_debugobj(lb, " +hex"));
 
 		errno = 0;
 		code = strtol(str, &end, 16);
 
 		if (errno || *end != '\0') {
-			DBG(LABEL, ul_debugobj(lb, "parsing failed: %m"));
+			DBG(LABEL, ul_debugobj(lb, "  failed: %m"));
 			return NULL;
 		}
+		if (xcode)
+			*xcode = code;
 		ret = fdisk_label_get_parttype_from_code(lb, code);
-		if (ret)
-			goto done;
-
-		ret = fdisk_new_unknown_parttype(code, NULL);
 	} else {
-		int i;
-
-		DBG(LABEL, ul_debugobj(lb, " parsing string"));
+		DBG(LABEL, ul_debugobj(lb, " +string"));
 
 		/* maybe specified by type string (e.g. UUID) */
 		ret = fdisk_label_get_parttype_from_string(lb, str);
-		if (ret)
-			goto done;
 
-		/* maybe specified by order number */
-		errno = 0;
-		i = strtol(str, &end, 0);
-		if (errno == 0 && *end == '\0' && i > 0
-		    && i - 1 < (int) lb->nparttypes) {
-			ret = &types[i - 1];
-			goto done;
-		}
+		if (!ret) {
+			/* maybe specified by order number */
+			int i;
+
+			errno = 0;
+			i = strtol(str, &end, 0);
 
-		ret = fdisk_new_unknown_parttype(0, str);
+			if (use_seqnum && errno == 0
+			    && *end == '\0' && i > 0
+			    && i - 1 < (int) lb->nparttypes)
+				ret = &types[i - 1];
+		}
 	}
 
-done:
-	DBG(PARTTYPE, ul_debugobj(ret, "returns parsed '%s' [%s] partition type",
-				ret->name, ret->typestr ? : ""));
+	if (ret)
+		DBG(PARTTYPE, ul_debugobj(ret, " result '%s'", ret->name));
 	return ret;
 }
 
+static struct fdisk_parttype *parttype_from_shortcut(
+				const struct fdisk_label *lb,
+				const char *str, int deprecated)
+{
+	size_t i;
+
+	DBG(LABEL, ul_debugobj(lb, " parsing '%s' shortcut", str));
+
+	for (i = 0; i < lb->nparttype_cuts; i++) {
+		const struct fdisk_shortcut *sc = &lb->parttype_cuts[i];
+
+		if (sc->deprecated && !deprecated)
+			continue;
+		if (sc->shortcut && strcmp(sc->shortcut, str) == 0)
+			return parttype_from_data(lb, sc->data, NULL, 0);
+	}
+	return NULL;
+}
+
+static struct fdisk_parttype *parttype_from_alias(
+				const struct fdisk_label *lb,
+				const char *str, int deprecated)
+{
+	size_t i;
+
+	DBG(LABEL, ul_debugobj(lb, " parsing '%s' alias", str));
+
+	for (i = 0; i < lb->nparttype_cuts; i++) {
+		const struct fdisk_shortcut *sc = &lb->parttype_cuts[i];
+
+		if (sc->deprecated && !deprecated)
+			continue;
+		if (sc->alias && strcmp(sc->alias, str) == 0)
+			return parttype_from_data(lb, sc->data, NULL, 0);
+	}
+	return NULL;
+}
+
+/**
+ * fdisk_label_advparse_parttype:
+ * @lb: label
+ * @str: string to parse from
+ * @flags: FDISK_PARTTYPE_PARSE_*
+ *
+ * This function is advanced partition types parser. It parses partition type
+ * from @str according to the label. The function returns a pointer to static
+ * table of the partition types, or newly allocated partition type for unknown
+ * types (see fdisk_parttype_is_unknown(). It's safe to call fdisk_unref_parttype()
+ * for all results.
+ *
+ * The @str may be type data (hex code or UUID), alias or shortcut. For GPT
+ * also sequence number of the type in the list of the supported types.
+ *
+ * Returns: pointer to type or NULL on error.
+ */
+struct fdisk_parttype *fdisk_label_advparse_parttype(
+				const struct fdisk_label *lb,
+				const char *str,
+				int flags)
+{
+	struct fdisk_parttype *res = NULL;
+	unsigned int code = 0;
+
+	if (!lb->nparttypes)
+		return NULL;
+
+	DBG(LABEL, ul_debugobj(lb, "parsing '%s' (%s) type", str, lb->name));
+
+	if ((flags & FDISK_PARTTYPE_PARSE_DATA)
+	    && !(flags & FDISK_PARTTYPE_PARSE_DATALAST))
+		res = parttype_from_data(lb, str, &code,
+				flags & FDISK_PARTTYPE_PARSE_SEQNUM);
+
+	if (!res && (flags & FDISK_PARTTYPE_PARSE_ALIAS))
+		res = parttype_from_alias(lb, str,
+				flags & FDISK_PARTTYPE_PARSE_DEPRECATED);
+
+	if (!res && (flags & FDISK_PARTTYPE_PARSE_SHORTCUT))
+		res = parttype_from_shortcut(lb, str,
+				flags & FDISK_PARTTYPE_PARSE_DEPRECATED);
+
+	if (!res && (flags & FDISK_PARTTYPE_PARSE_DATA)
+	    && (flags & FDISK_PARTTYPE_PARSE_DATALAST))
+		res = parttype_from_data(lb, str, &code,
+				flags & FDISK_PARTTYPE_PARSE_SEQNUM);
+
+	if (!res && !(flags & FDISK_PARTTYPE_PARSE_NOUNKNOWN)) {
+		if (lb->parttypes[0].typestr)
+			res = fdisk_new_unknown_parttype(0, str);
+		else
+			res = fdisk_new_unknown_parttype(code, NULL);
+	}
+
+	if (res)
+		DBG(PARTTYPE, ul_debugobj(res, "returns parsed '%s' [%s] partition type",
+				res->name, res->typestr ? : ""));
+	return res;
+}
+
+/**
+ * fdisk_label_parse_parttype:
+ * @lb: label
+ * @str: string to parse from (type name, UUID, etc.)
+ *
+ * Parses partition type from @str according to the label. The function returns
+ * a pointer to static table of the partition types, or newly allocated
+ * partition type for unknown types (see fdisk_parttype_is_unknown(). It's
+ * safe to call fdisk_unref_parttype() for all results.
+ *
+ * Note that for GPT it accepts sequence number of UUID.
+ *
+ * Returns: pointer to type or NULL on error.
+ */
+struct fdisk_parttype *fdisk_label_parse_parttype(
+				const struct fdisk_label *lb,
+				const char *str)
+{
+	return fdisk_label_advparse_parttype(lb, str, FDISK_PARTTYPE_PARSE_DATA);
+}
+
 /**
  * fdisk_parttype_get_string:
  * @t: type
diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c
index 6f66f88b9..e73c8dcdb 100644
--- a/libfdisk/src/script.c
+++ b/libfdisk/src/script.c
@@ -61,9 +61,6 @@ struct fdisk_script {
 				force_label : 1;	/* label: <name> specified */
 };
 
-static struct fdisk_parttype *translate_type_shortcuts(struct fdisk_script *dp, char *str);
-
-
 static void fdisk_script_free_header(struct fdisk_scriptheader *fi)
 {
 	if (!fi)
@@ -969,6 +966,11 @@ static int partno_from_devname(char *s)
 	return pno - 1;
 }
 
+#define FDISK_SCRIPT_PARTTYPE_PARSE_FLAGS \
+	(FDISK_PARTTYPE_PARSE_DATA | FDISK_PARTTYPE_PARSE_DATALAST | \
+	 FDISK_PARTTYPE_PARSE_SHORTCUT | FDISK_PARTTYPE_PARSE_ALIAS | \
+	 FDISK_PARTTYPE_PARSE_DEPRECATED)
+
 /* dump format
  * <device>: start=<num>, size=<num>, type=<string>, ...
  */
@@ -1069,19 +1071,14 @@ static int parse_line_nameval(struct fdisk_script *dp, char *s)
 			if (rc)
 				break;
 
-			pa->type = translate_type_shortcuts(dp, type);
-			if (!pa->type)
-				pa->type = fdisk_label_parse_parttype(
-						script_get_label(dp), type);
+			pa->type = fdisk_label_advparse_parttype(script_get_label(dp),
+					type, FDISK_SCRIPT_PARTTYPE_PARSE_FLAGS);
 			free(type);
 
 			if (!pa->type) {
 				rc = -EINVAL;
-				fdisk_unref_parttype(pa->type);
-				pa->type = NULL;
 				break;
 			}
-
 		} else {
 			DBG(SCRIPT, ul_debugobj(dp, "script parse error: unknown field '%s'", p));
 			rc = -EINVAL;
@@ -1098,71 +1095,6 @@ static int parse_line_nameval(struct fdisk_script *dp, char *s)
 	return rc;
 }
 
-/* original sfdisk supports partition types shortcuts like 'L' = Linux native
- */
-static struct fdisk_parttype *translate_type_shortcuts(struct fdisk_script *dp, char *str)
-{
-	struct fdisk_label *lb;
-	const char *type = NULL;
-
-	if (strlen(str) != 1)
-		return NULL;
-
-	lb = script_get_label(dp);
-	if (!lb)
-		return NULL;
-
-	if (lb->id == FDISK_DISKLABEL_DOS) {
-		switch (*str) {
-		case 'L':	/* Linux */
-			type = "83";
-			break;
-		case 'S':	/* Swap */
-			type = "82";
-			break;
-		case 'E':	/* Dos extended */
-			type = "05";
-			break;
-		case 'X':	/* Linux extended */
-			type = "85";
-			break;
-		case 'U':	/* UEFI system */
-			type = "EF";
-			break;
-		case 'R':	/* Linux RAID */
-			type = "FD";
-			break;
-		case 'V':	/* LVM */
-			type = "8E";
-			break;
-
-		}
-	} else if (lb->id == FDISK_DISKLABEL_GPT) {
-		switch (*str) {
-		case 'L':	/* Linux */
-			type = "0FC63DAF-8483-4772-8E79-3D69D8477DE4";
-			break;
-		case 'S':	/* Swap */
-			type = "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F";
-			break;
-		case 'H':	/* Home */
-			type = "933AC7E1-2EB4-4F13-B844-0E14E2AEF915";
-			break;
-		case 'U':	/* UEFI system */
-			type = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B";
-			break;
-		case 'R':	/* Linux RAID */
-			type = "A19D880F-05FC-4D3B-A006-743F0F84911E";
-			break;
-		case 'V':	/* LVM */
-			type = "E6D6D379-F507-44C2-A23C-238F2A3DF928";
-			break;
-		}
-	}
-
-	return type ? fdisk_label_parse_parttype(lb, type) : NULL;
-}
-
 #define TK_PLUS		1
 #define TK_MINUS	-1
 
@@ -1257,18 +1189,12 @@ static int parse_line_valcommas(struct fdisk_script *dp, char *s)
 			if (rc)
 				break;
 
-			pa->type = translate_type_shortcuts(dp, str);
-			if (!pa->type)
-				pa->type = fdisk_label_parse_parttype(
-						script_get_label(dp), str);
+			pa->type = fdisk_label_advparse_parttype(script_get_label(dp),
+						str, FDISK_SCRIPT_PARTTYPE_PARSE_FLAGS);
 			free(str);
 
-			if (!pa->type) {
+			if (!pa->type)
 				rc = -EINVAL;
-				fdisk_unref_parttype(pa->type);
-				pa->type = NULL;
-				break;
-			}
 			break;
 		case ITEM_BOOTABLE:
 			if (*p == ',' || *p == ';')
