From 6468c26257577441bc2f69b7558eb850b06c4aa6 Mon Sep 17 00:00:00 2001 From: kre Date: Tue, 26 Sep 2023 15:55:46 +0000 Subject: [PATCH] When extracting the attributes (to printable form), avoid simply ignoring any attribute bits which are unknown, print them as a hex value. This avoids "Attributes: " for most windows filesystem types, which all seem to have but 63 set (which is supposed to mean "don't assign a drive letter" which is akin to "noauto" in fstab - except it is set even on partitions which do get mounted, so must mean something subtly different). These upper 16 attribute bits are supposed to be file system type speficic (in practice, they seem to be common to all filesystem types from one vendor) but we don't have the info (yet anyway) to treat them like that. ChromeOS seems to treat some of the bits as bit fields containing numeric values - add #if 0'd (but compile tested) code to deal with those (maybe, compile tested - but not execution tested) should someone ever get an environment where these things occur, and could add the missing definitions to actually test this. --- sbin/gpt/gpt.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/sbin/gpt/gpt.c b/sbin/gpt/gpt.c index 222ee4c42672..8ebc3f78e29a 100644 --- a/sbin/gpt/gpt.c +++ b/sbin/gpt/gpt.c @@ -35,7 +35,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: gpt.c,v 1.84 2022/11/22 00:25:52 mlelstv Exp $"); +__RCSID("$NetBSD: gpt.c,v 1.85 2023/09/26 15:55:46 kre Exp $"); #endif #include @@ -1239,13 +1239,62 @@ const char * gpt_attr_list(char *buf, size_t len, uint64_t attributes) { size_t i; + /* + * a uint64_t (attributes) has at most 16 hex digits + * in its representation, add 2 for "0x", and 2 more + * for surrounding [ ], plus one for a trailing \0, + * and we need 21 bytes, round that up to 24 + */ + char xbuf[24]; + strlcpy(buf, "", len); - for (i = 0; i < __arraycount(gpt_attr); i++) + for (i = 0; i < __arraycount(gpt_attr); i++) { + /* + * if the attribute is specified in one of bits + * 48..63, it should depend upon the defining + * partition type for that attribute. Currently + * we have no idea what that is, so... + * + * Also note that for some partition types, these + * fields are not a single bit boolean, but several + * bits to form a numeric value. That we could handle. + */ + if (attributes & gpt_attr[i].mask) { strlcat(buf, buf[0] ? ", " : "", len); strlcat(buf, gpt_attr[i].name, len); +#if 0 + /* + * there are none currently defined, so this is untestable + * (it does build however). + */ + if (gpt_attr[i].mask & (gpt_attr[i].mask - 1)) { + /* This only happens in bits 46..63 */ + + /* + * xbuf is big enough for "=65535\0" + * which is the biggest possible value + */ + snprintf(xbuf, sizeof xbuf, "=%ju", + (uintmax_t) ( + (attributes & gpt_attr[i].mask) >> + (ffs((int)(gpt_attr[i].mask >> 48)) + 47) + )); + + strlcat(buf, xbuf, len); + } +#endif + attributes &=~ gpt_attr[i].mask; } + } + + if (attributes != 0) { + snprintf(xbuf, sizeof xbuf, "[%#jx]", (uintmax_t)attributes); + strlcat(buf, buf[0] ? ", " : "", len); + strlcat(buf, xbuf, len); + } + return buf; }