Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 May 2002 19:43:17 -0700 (PDT)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 11995 for review
Message-ID:  <200205280243.g4S2hHw86540@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://people.freebsd.org/~peter/p4db/chv.cgi?CH=11995

Change 11995 by marcel@marcel_vaio on 2002/05/27 19:42:30

	Round of cleanups:
	o  Give uuidgen() the correct prototype in syscalls.master
	o  Define struct uuid according to DCE 1.1 in sys/uuid.h
	o  Use struct uuid instead of uuid_t. The latter is defined
	   in sys/uuid.h but should not be used in kernel land.
	o  Add snprintf_uuid(), printf_uuid() and sbuf_printf_uuid()
	   to kern_uuid.c for use in the kernel (currently geom_gpt.c).
	o  Rename the non-standard struct uuid in kern/kern_uuid.c
	   to struct uuid_private and give it a slightly better definition
	   for better byte-order handling. See below.
	o  In sys/gpt.h, fix the broken uuid definitions to match the now
	   compliant struct uuid definition. See below.
	o  In usr.bin/uuidgen/uuidgen.c catch up with struct uuid change.
	
	A note about byte-order:
		The standard failed to provide a non-conflicting and
	unambiguous definition for the binary representation. My initial
	implementation always wrote the timestamp as a 64-bit little-endian
	(2s-complement) integral. The clock sequence was always written
	as a 16-bit big-endian (2s-complement) integral. After a good
	nights sleep and couple of Pan Galactic Gargle Blasters (not
	necessarily in that order :-) I reread the spec and came to the
	conclusion that the time fields are always written in the native
	by order, provided the the low, mid and hi chopping still occurs.
	The spec mentions that you "might need to swap bytes if you talk
	to a machine that has a different byte-order". The clock sequence
	is always written in big-endian order (as is the IEEE 802 address)
	because its division is resulting in bytes, making the ordering
	unambiguous.
	
	Note that the change is mostly a no-op, but it did expose the
	broken UUIDs in sys/gpt.h. The clock-sequence was defined as a
	16-bit integral, but in such a way that it was only valid when
	written as big-endian. This was not the case. Strangely enough
	EFI still matched its UUID, even though it was wrong. Maybe they
	mask out the clock sequence? We at least don't, so I had to
	repartition my disk to be able to find the slice again...

Affected files ...

... //depot/projects/ia64/sys/geom/geom_gpt.c#2 edit
... //depot/projects/ia64/sys/kern/kern_uuid.c#2 edit
... //depot/projects/ia64/sys/kern/syscalls.master#9 edit
... //depot/projects/ia64/sys/sys/gpt.h#2 edit
... //depot/projects/ia64/sys/sys/sysproto.h#10 edit
... //depot/projects/ia64/sys/sys/uuid.h#2 edit
... //depot/projects/ia64/usr.bin/uuidgen/uuidgen.c#3 edit

Differences ...

==== //depot/projects/ia64/sys/geom/geom_gpt.c#2 (text+ko) ====

@@ -158,7 +158,7 @@
 static int
 g_gpt_start(struct bio *bp)
 {
-	uuid_t freebsd = GPT_ENT_TYPE_FREEBSD;
+	struct uuid freebsd = GPT_ENT_TYPE_FREEBSD;
 	struct g_provider *pp = bp->bio_to;
 	struct g_geom *gp = pp->geom;
 	struct g_slicer *gsp = gp->softc;
@@ -178,7 +178,7 @@
 	 * emulate a MBR class :-/
 	 */
 	type = (memcmp(&gs->part[pp->index]->ent_type, &freebsd,
-	    sizeof(uuid_t))) ? 0 : 165;
+	    sizeof(freebsd))) ? 0 : 165;
 	return ((g_haveattr_int(bp, "MBR::type", type)) ? 1 : 0);
 }
 
@@ -188,18 +188,15 @@
 {
 	struct g_slicer *gsp = gp->softc;
 	struct g_gpt_softc *gs = gsp->softc;
-	uuid_t *uuid;
+	struct uuid *uuid;
 
 	g_slice_dumpconf(sb, indent, gp, cp, pp);
 
 	if (pp != NULL) {
 		uuid = &gs->part[pp->index]->ent_type;
-		sbuf_printf(sb,
-"%s<type>%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x</type>\n",
-		    indent, le32toh(uuid->time_low), le16toh(uuid->time_med),
-		    le16toh(uuid->time_hi), be16toh(uuid->seq), uuid->node[0],
-		    uuid->node[1], uuid->node[2], uuid->node[3], uuid->node[4],
-		    uuid->node[5]);
+		sbuf_printf(sb, "%s<type>", indent);
+		sbuf_printf_uuid(sb, uuid);
+		sbuf_printf(sb, "</type>\n");
 	}
 }
 
@@ -279,11 +276,11 @@
 	gsp->frontstuff = hdr->hdr_lba_start * secsz;
 
 	for (i = 0; i < hdr->hdr_entries; i++) {
-		uuid_t unused = GPT_ENT_TYPE_UNUSED;
+		struct uuid unused = GPT_ENT_TYPE_UNUSED;
 		if (i >= GPT_MAX_SLICES)
 			break;
 		ent = (void*)(buf + i * hdr->hdr_entsz);
-		if (!memcmp(&ent->ent_type, &unused, sizeof(uuid_t)))
+		if (!memcmp(&ent->ent_type, &unused, sizeof(unused)))
 			continue;
 		gs->part[i] = g_malloc(hdr->hdr_entsz, M_WAITOK);
 		if (gs->part[i] == NULL)

==== //depot/projects/ia64/sys/kern/kern_uuid.c#2 (text+ko) ====

@@ -31,8 +31,10 @@
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
+#include <sys/sbuf.h>
 #include <sys/socket.h>
 #include <sys/sysproto.h>
+#include <sys/uuid.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -41,26 +43,33 @@
 /*
  * See also:
  *	http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
+ *	http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
+ *
+ * Note that the generator state is itself an UUID, but the time and clock
+ * sequence fields are written in the native byte order.
  */
 
-#define	IEEE_ADDR_LEN	6
+CTASSERT(sizeof(struct uuid) == 16);
 
-union ieee_addr {
-	uint16_t	word[IEEE_ADDR_LEN >> 1];
-	uint8_t		byte[IEEE_ADDR_LEN];
+/* We use an alternative, more convenient representation in the generator. */
+struct uuid_private {
+	union {
+		uint64_t	ll;		/* internal. */
+		struct {
+			uint32_t	low;
+			uint16_t	mid;
+			uint16_t	hi;
+		} x;
+	} time;
+	uint16_t	seq;			/* Big-endian. */
+	uint16_t	node[UUID_NODE_LEN>>1];
 };
 
-struct uuid {
-	uint64_t	time;
-	uint16_t	seq;
-	union ieee_addr	node;
-};
+CTASSERT(sizeof(struct uuid_private) == 16);
 
-CTASSERT(sizeof(struct uuid) == 16);
+static struct uuid_private uuid_last;
 
-static struct uuid	uuid_last;
-static struct mtx	uuid_mutex;
-
+static struct mtx uuid_mutex;
 MTX_SYSINIT(uuid_lock, &uuid_mutex, "UUID generator mutex lock", MTX_DEF);
 
 /*
@@ -74,13 +83,14 @@
  * scan and safely return the MAC address we returned before.
  */
 static void
-uuid_node(union ieee_addr *addr)
+uuid_node(uint16_t *node)
 {
 	struct ifnet *ifp;
 	struct ifaddr *ifa;
 	struct sockaddr_dl *sdl;
 	int i;
 
+	/* XXX: lock ifnet. */
 	TAILQ_FOREACH(ifp, &ifnet, if_link) {
 		/* Walk the address list */
 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
@@ -88,15 +98,17 @@
 			if (sdl != NULL && sdl->sdl_family == AF_LINK &&
 			    sdl->sdl_type == IFT_ETHER) {
 				/* Got a MAC address. */
-				bcopy(LLADDR(sdl), addr->byte, IEEE_ADDR_LEN);
+				bcopy(LLADDR(sdl), node, UUID_NODE_LEN);
+				/* XXX: unlock ifnet. */
 				return;
 			}
 		}
 	}
+	/* XXX: unlock ifnet. */
 
-	for (i = 0; i < 3; i++)
-		addr->word[i] = (uint16_t)arc4random();
-	addr->byte[0] |= 0x80;
+	for (i = 0; i < (UUID_NODE_LEN>>1); i++)
+		node[i] = (uint16_t)arc4random();
+	*((uint8_t*)node) |= 0x80;
 }
 
 /*
@@ -119,14 +131,14 @@
 
 #ifndef _SYS_SYSPROTO_H_
 struct uuidgen_args {
-	void	*store;
+	struct uuid *store;
 	int	count;
 };
 #endif
 
 int uuidgen(struct thread *td, struct uuidgen_args *uap)
 {
-	struct uuid uuid;
+	struct uuid_private uuid;
 	uint64_t time;
 	int error;
 
@@ -139,39 +151,72 @@
 	if (uap->count < 1 || uap->count > 2048)
 		return (EINVAL);
 
-	/* XXX validate accessibility to the whole of the UUID store? */
+	/* XXX: pre-validate accessibility to the whole of the UUID store? */
 
 	mtx_lock(&uuid_mutex);
 
-	uuid_node(&uuid.node);
+	uuid_node(uuid.node);
 	time = uuid_time();
 
-	if (uuid_last.time == 0LL ||
-	    uuid_last.node.word[0] != uuid.node.word[0] ||
-	    uuid_last.node.word[1] != uuid.node.word[1] ||
-	    uuid_last.node.word[2] != uuid.node.word[2])
+	if (uuid_last.time.ll == 0LL || uuid_last.node[0] != uuid.node[0] ||
+	    uuid_last.node[1] != uuid.node[1] ||
+	    uuid_last.node[2] != uuid.node[2])
 		uuid.seq = (uint16_t)arc4random() & 0x3fff;
-	else if (uuid_last.time >= time)
+	else if (uuid_last.time.ll >= time)
 		uuid.seq = (uuid_last.seq + 1) & 0x3fff;
 	else
 		uuid.seq = uuid_last.seq;
 
 	uuid_last = uuid;
-	uuid_last.time = (time + uap->count - 1) & ((1LL << 60) - 1LL);
+	uuid_last.time.ll = (time + uap->count - 1) & ((1LL << 60) - 1LL);
 
 	mtx_unlock(&uuid_mutex);
 
 	/* Set sequence and variant and deal with byte order. */
 	uuid.seq = htobe16(uuid.seq | 0x8000);
 
-	/* XXX this should copyout larger chunks at a time. */
+	/* XXX: this should copyout larger chunks at a time. */
 	do {
-		uuid.time = htole64((time++ & ((1LL << 60) - 1LL)) |
-		    (1LL << 60));
+		/* Set time and version (=1) and deal with byte order. */
+		uuid.time.x.low = (uint32_t)time;
+		uuid.time.x.mid = (uint16_t)(time >> 32);
+		uuid.time.x.hi = ((uint16_t)(time >> 48) & 0xfff) | (1 << 12);
 		error = copyout(&uuid, uap->store, sizeof(uuid));
-		uap->store = (struct uuid*)(uap->store) + 1;
+		uap->store++;
 		uap->count--;
+		time++;
 	} while (uap->count > 0 && !error);
 
 	return (error);
 }
+
+int
+snprintf_uuid(char *buf, size_t sz, struct uuid *uuid)
+{
+	struct uuid_private *id;
+	int cnt;
+
+	id = (struct uuid_private *)uuid;
+	cnt = snprintf(buf, sz, "%08x-%04x-%04x-%04x-%04x%04x%04x",
+	    id->time.x.low, id->time.x.mid, id->time.x.hi, be16toh(id->seq),
+	    be16toh(id->node[0]), be16toh(id->node[1]), be16toh(id->node[2]));
+	return (cnt);
+}
+
+int
+printf_uuid(struct uuid *uuid)
+{
+	char buf[38];
+
+	snprintf_uuid(buf, sizeof(buf), uuid);
+	return (printf("%s", buf));
+}
+
+int
+sbuf_printf_uuid(struct sbuf *sb, struct uuid *uuid)
+{
+	char buf[38];
+
+	snprintf_uuid(buf, sizeof(buf), uuid);
+	return (sbuf_printf(sb, "%s", buf));
+}

==== //depot/projects/ia64/sys/kern/syscalls.master#9 (text+ko) ====

@@ -562,4 +562,4 @@
 390	STD	BSD	{ int kenv(int what, const char *name, char *value, \
 			    int len); }
 391	STD	BSD	{ int lchflags(const char *path, int flags); }
-392	STD	BSD	{ int uuidgen(void *store, int count); }
+392	STD	BSD	{ int uuidgen(struct uuid *store, int count); }

==== //depot/projects/ia64/sys/sys/gpt.h#2 (text+ko) ====

@@ -41,7 +41,7 @@
 	uint64_t	hdr_lba_alt;
 	uint64_t	hdr_lba_start;
 	uint64_t	hdr_lba_end;
-	uuid_t		hdr_uuid;
+	struct uuid	hdr_uuid;
 	uint64_t	hdr_lba_table;
 	uint32_t	hdr_entries;
 	uint32_t	hdr_entsz;
@@ -49,8 +49,8 @@
 };
 
 struct gpt_ent {
-	uuid_t		ent_type;
-	uuid_t		ent_uuid;
+	struct uuid	ent_type;
+	struct uuid	ent_uuid;
 	uint64_t	ent_lba_start;
 	uint64_t	ent_lba_end;
 	uint64_t	ent_attr;
@@ -59,20 +59,20 @@
 };
 
 #define	GPT_ENT_TYPE_UNUSED		\
-	{0x00000000,0x0000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00}}
+	{0x00000000,0x0000,0x0000,0x00,0x00,{0x00,0x00,0x00,0x00,0x00,0x00}}
 #define	GPT_ENT_TYPE_EFI		\
-	{0xc12a7328,0xf81f,0x11d2,0xba4b,{0x00,0xa0,0xc9,0x3e,0xc9,0x3b}}
+	{0xc12a7328,0xf81f,0x11d2,0xba,0x4b,{0x00,0xa0,0xc9,0x3e,0xc9,0x3b}}
 #define	GPT_ENT_TYPE_MBR		\
-	{0x024dee41,0x33e7,0x11d3,0x9d69,{0x00,0x08,0xc7,0x81,0xf3,0x9f}}
+	{0x024dee41,0x33e7,0x11d3,0x9d,0x69,{0x00,0x08,0xc7,0x81,0xf3,0x9f}}
 #define	GPT_ENT_TYPE_FREEBSD		\
-	{0x516e7cb4,0x6ecf,0x11d6,0x8ff8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
+	{0x516e7cb4,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
 #define	GPT_ENT_TYPE_FREEBSD_SWAP	\
-	{0x516e7cb5,0x6ecf,0x11d6,0x8ff8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
+	{0x516e7cb5,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
 #define	GPT_ENT_TYPE_FREEBSD_UFS	\
-	{0x516e7cb6,0x6ecf,0x11d6,0x8ff8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
+	{0x516e7cb6,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
 #define	GPT_ENT_TYPE_FREEBSD_UFS2	\
-	{0x516e7cb7,0x6ecf,0x11d6,0x8ff8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
+	{0x516e7cb7,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
 #define	GPT_ENT_TYPE_FREEBSD_VINUM	\
-	{0x516e7cb8,0x6ecf,0x11d6,0x8ff8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
+	{0x516e7cb8,0x6ecf,0x11d6,0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}}
 
 #endif /* _SYS_GPT_H_ */

==== //depot/projects/ia64/sys/sys/sysproto.h#10 (text+ko) ====

@@ -1116,7 +1116,7 @@
 	char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
 };
 struct uuidgen_args {
-	char store_l_[PADL_(void *)]; void * store; char store_r_[PADR_(void *)];
+	char store_l_[PADL_(struct uuid *)]; struct uuid * store; char store_r_[PADR_(struct uuid *)];
 	char count_l_[PADL_(int)]; int count; char count_r_[PADR_(int)];
 };
 int	nosys(struct thread *, struct nosys_args *);

==== //depot/projects/ia64/sys/sys/uuid.h#2 (text+ko) ====

@@ -26,22 +26,43 @@
  * $FreeBSD$
  */
 
+#ifndef _SYS_UUID_H_
+#define	_SYS_UUID_H_
+
+/* Length of a node address (an IEEE 802 address). */
+#define	_UUID_NODE_LEN		6
+
 /*
  * See also:
- *	http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
+ *      http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
+ *      http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
+ *
+ * A DCE 1.1 compatible source representation of UUIDs.
  */
+struct uuid {
+	uint32_t	time_low;
+	uint16_t	time_mid;
+	uint16_t	time_hi_and_version;
+	uint8_t		clock_seq_hi_and_reserved;
+	uint8_t		clock_seq_low;
+	uint8_t		node[_UUID_NODE_LEN];
+};
 
-#ifndef _SYS_UUID_H_
-#define	_SYS_UUID_H_
+#ifdef _KERNEL
+
+#define	UUID_NODE_LEN	_UUID_NODE_LEN
+
+int snprintf_uuid(char *, size_t, struct uuid *);
+int printf_uuid(struct uuid *);
+int sbuf_printf_uuid(struct sbuf *, struct uuid *);
+
+#else	/* _KERNEL */
+
+/* XXX namespace pollution? */
+typedef struct uuid uuid_t;
 
-typedef struct {
-	uint32_t	time_low;
-	uint16_t	time_med;
-	uint16_t	time_hi;
-	uint16_t	seq;		/* Big-endian. */
-	uint8_t		node[6];
-} uuid_t;
+int	uuidgen(struct uuid *, int);
 
-int	uuidgen(uuid_t *store, int count);
+#endif	/* _KERNEL */
 
 #endif /* _SYS_UUID_H_ */

==== //depot/projects/ia64/usr.bin/uuidgen/uuidgen.c#3 (text+ko) ====

@@ -47,9 +47,9 @@
 
 void uuid_print(uuid_t *uuid)
 {
-	printf("%08x-%04x-%04x-%04x-", le32toh(uuid->time_low),
-	    le16toh(uuid->time_med), le16toh(uuid->time_hi),
-	    be16toh(uuid->seq));
+	printf("%08x-%04x-%04x-%02x%02x-", uuid->time_low, uuid->time_mid,
+	    uuid->time_hi_and_version, uuid->clock_seq_hi_and_reserved,
+	    uuid->clock_seq_low);
 	printf("%02x%02x%02x%02x%02x%02x\n", uuid->node[0], uuid->node[1],
 	    uuid->node[2], uuid->node[3], uuid->node[4], uuid->node[5]);
 }

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe p4-projects" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200205280243.g4S2hHw86540>