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