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>