1199767f8SToomas Soome /*-
2199767f8SToomas Soome  * Copyright (c) 2015 M. Warner Losh
3199767f8SToomas Soome  * All rights reserved.
4199767f8SToomas Soome  *
5199767f8SToomas Soome  * Redistribution and use in source and binary forms, with or without
6199767f8SToomas Soome  * modification, are permitted provided that the following conditions
7199767f8SToomas Soome  * are met:
8199767f8SToomas Soome  * 1. Redistributions of source code must retain the above copyright
9199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer.
10199767f8SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12199767f8SToomas Soome  *    documentation and/or other materials provided with the distribution.
13199767f8SToomas Soome  *
14199767f8SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15199767f8SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16199767f8SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17199767f8SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18199767f8SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19199767f8SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20199767f8SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21199767f8SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22199767f8SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23199767f8SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24199767f8SToomas Soome  * SUCH DAMAGE.
25199767f8SToomas Soome  *
26199767f8SToomas Soome  * $FreeBSD$
27199767f8SToomas Soome  */
28199767f8SToomas Soome 
29199767f8SToomas Soome /*
30199767f8SToomas Soome  * Note: some comments taken from lib/libc/uuid/uuid_from_string.c
31199767f8SToomas Soome  * Copyright (c) 2002 Marcel Moolenaar
32199767f8SToomas Soome  * Copyright (c) 2002 Hiten Mahesh Pandya
33199767f8SToomas Soome  */
34199767f8SToomas Soome 
35199767f8SToomas Soome 
36199767f8SToomas Soome #include <stand.h>
37199767f8SToomas Soome #include <uuid.h>
38199767f8SToomas Soome 
39199767f8SToomas Soome static int
hex2int(int ch)40199767f8SToomas Soome hex2int(int ch)
41199767f8SToomas Soome {
42199767f8SToomas Soome 	if (ch >= '0' && ch <= '9')
43199767f8SToomas Soome 		return ch - '0';
44199767f8SToomas Soome 	if (ch >= 'a' && ch <= 'f')
45199767f8SToomas Soome 		return 10 + ch - 'a';
46199767f8SToomas Soome 	if (ch >= 'A' && ch <= 'F')
47199767f8SToomas Soome 		return 10 + ch - 'A';
48199767f8SToomas Soome 	return 16;
49199767f8SToomas Soome }
50199767f8SToomas Soome 
51199767f8SToomas Soome static uint32_t
fromhex(const char * s,int len,int * ok)52199767f8SToomas Soome fromhex(const char *s, int len, int *ok)
53199767f8SToomas Soome {
54199767f8SToomas Soome 	uint32_t v;
55199767f8SToomas Soome 	int i, h;
56199767f8SToomas Soome 
57199767f8SToomas Soome 	if (!*ok)
58199767f8SToomas Soome 		return 0;
59199767f8SToomas Soome 	v = 0;
60dd5bccd7SToomas Soome 	for (i = 0; i < len; i++) {
61199767f8SToomas Soome 		h = hex2int(s[i]);
62199767f8SToomas Soome 		if (h == 16) {
63199767f8SToomas Soome 			*ok = 0;
64199767f8SToomas Soome 			return v;
65199767f8SToomas Soome 		}
66199767f8SToomas Soome 		v = (v << 4) | h;
67199767f8SToomas Soome 	}
68199767f8SToomas Soome 	return v;
69199767f8SToomas Soome }
70199767f8SToomas Soome 
71199767f8SToomas Soome /*
72199767f8SToomas Soome  * uuid_from_string() - convert a string representation of an UUID into
73199767f8SToomas Soome  *			a binary representation.
74199767f8SToomas Soome  * See also:
75199767f8SToomas Soome  *	http://www.opengroup.org/onlinepubs/009629399/uuid_from_string.htm
76199767f8SToomas Soome  *
77199767f8SToomas Soome  * NOTE: The sequence field is in big-endian, while the time fields are in
78199767f8SToomas Soome  *	 native byte order.
79199767f8SToomas Soome  *
80199767f8SToomas Soome  * 01234567-89ab-cdef-0123-456789abcdef
81199767f8SToomas Soome  * 000000000011111111112222222222333333
82199767f8SToomas Soome  * 012345678901234567890123456789012345
83199767f8SToomas Soome  *         -    -    -    -
84199767f8SToomas Soome  * hhhhhhhh-hhhh-hhhh-bbbb-bbbbbbbbbbbb
85199767f8SToomas Soome  *
86199767f8SToomas Soome  */
87199767f8SToomas Soome void
uuid_from_string(const char * s,uuid_t * u,uint32_t * status)88199767f8SToomas Soome uuid_from_string(const char *s, uuid_t *u, uint32_t *status)
89199767f8SToomas Soome {
90199767f8SToomas Soome 	int ok = 1;
91199767f8SToomas Soome 	int n;
92199767f8SToomas Soome 
93199767f8SToomas Soome 	if (s == NULL || *s == '\0') {
94199767f8SToomas Soome 		uuid_create_nil(u, status);
95199767f8SToomas Soome 		return;
96199767f8SToomas Soome 	}
97199767f8SToomas Soome 
98199767f8SToomas Soome 	if (status != NULL)
99199767f8SToomas Soome 		*status = uuid_s_invalid_string_uuid;
100199767f8SToomas Soome 	if (strlen(s) != 36)
101199767f8SToomas Soome 		return;
102199767f8SToomas Soome 	/* Only support new format, check for all the right dashes */
103199767f8SToomas Soome 	if (s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
104199767f8SToomas Soome 		return;
105199767f8SToomas Soome 	/* native byte order */
106199767f8SToomas Soome 	u->time_low                  = fromhex(s     , 8, &ok);
107199767f8SToomas Soome 	u->time_mid                  = fromhex(s +  9, 4, &ok);
108199767f8SToomas Soome 	u->time_hi_and_version       = fromhex(s + 14, 4, &ok);
109199767f8SToomas Soome 	/* Big endian, but presented as a whole number so decode as such */
110199767f8SToomas Soome 	u->clock_seq_hi_and_reserved = fromhex(s + 19, 2, &ok);
111199767f8SToomas Soome 	u->clock_seq_low             = fromhex(s + 21, 2, &ok);
112199767f8SToomas Soome 	u->node[0]                   = fromhex(s + 24, 2, &ok);
113199767f8SToomas Soome 	u->node[1]                   = fromhex(s + 26, 2, &ok);
114199767f8SToomas Soome 	u->node[2]                   = fromhex(s + 28, 2, &ok);
115199767f8SToomas Soome 	u->node[3]                   = fromhex(s + 30, 2, &ok);
116199767f8SToomas Soome 	u->node[4]                   = fromhex(s + 32, 2, &ok);
117199767f8SToomas Soome 	u->node[5]                   = fromhex(s + 34, 2, &ok);
118199767f8SToomas Soome 	if (!ok)
119199767f8SToomas Soome 		return;
120199767f8SToomas Soome 
121199767f8SToomas Soome 	/* We have a successful scan. Check semantics... */
122199767f8SToomas Soome 	n = u->clock_seq_hi_and_reserved;
123199767f8SToomas Soome 	if ((n & 0x80) != 0x00 &&			/* variant 0? */
124199767f8SToomas Soome 	    (n & 0xc0) != 0x80 &&			/* variant 1? */
125199767f8SToomas Soome 	    (n & 0xe0) != 0xc0) {			/* variant 2? */
126199767f8SToomas Soome 		if (status != NULL)
127199767f8SToomas Soome 			*status = uuid_s_bad_version;
128199767f8SToomas Soome 	} else {
129199767f8SToomas Soome 		if (status != NULL)
130199767f8SToomas Soome 			*status = uuid_s_ok;
131199767f8SToomas Soome 	}
132199767f8SToomas Soome }
133