uuid_from_string.c revision 330897
155714Skris/*-
255714Skris * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
355714Skris *
455714Skris * Copyright (c) 2002 Marcel Moolenaar
555714Skris * Copyright (c) 2002 Hiten Mahesh Pandya
655714Skris * All rights reserved.
755714Skris *
855714Skris * Redistribution and use in source and binary forms, with or without
955714Skris * modification, are permitted provided that the following conditions
1055714Skris * are met:
1155714Skris * 1. Redistributions of source code must retain the above copyright
1255714Skris *    notice, this list of conditions and the following disclaimer.
1355714Skris * 2. Redistributions in binary form must reproduce the above copyright
1455714Skris *    notice, this list of conditions and the following disclaimer in the
1555714Skris *    documentation and/or other materials provided with the distribution.
1655714Skris *
1755714Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1855714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1955714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2055714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2155714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2255714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23109998Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25109998Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26142425Snectar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27109998Smarkm * SUCH DAMAGE.
28109998Smarkm *
29109998Smarkm * $FreeBSD: stable/11/lib/libc/uuid/uuid_from_string.c 330897 2018-03-14 03:19:51Z eadler $
30109998Smarkm */
31109998Smarkm
32238405Sjkim#include <stdio.h>
33109998Smarkm#include <string.h>
34109998Smarkm#include <uuid.h>
35109998Smarkm
36109998Smarkm/*
37109998Smarkm * uuid_from_string() - convert a string representation of an UUID into
38109998Smarkm *			a binary representation.
39109998Smarkm * See also:
40109998Smarkm *	http://www.opengroup.org/onlinepubs/009629399/uuid_from_string.htm
41109998Smarkm *
42109998Smarkm * NOTE: The sequence field is in big-endian, while the time fields are in
43109998Smarkm *	 native byte order.
44109998Smarkm */
45109998Smarkmvoid
46109998Smarkmuuid_from_string(const char *s, uuid_t *u, uint32_t *status)
47109998Smarkm{
48109998Smarkm	int n;
4955714Skris
5055714Skris	/* Short-circuit 2 special cases: NULL pointer and empty string. */
51205128Ssimon	if (s == NULL || *s == '\0') {
52205128Ssimon		uuid_create_nil(u, status);
53205128Ssimon		return;
54205128Ssimon	}
5555714Skris
5659191Skris	/* Assume the worst. */
5755714Skris	if (status != NULL)
5855714Skris		*status = uuid_s_invalid_string_uuid;
5955714Skris
6055714Skris	/* The UUID string representation has a fixed length. */
6155714Skris	if (strlen(s) != 36)
6255714Skris		return;
6355714Skris
6455714Skris	/*
6555714Skris	 * We only work with "new" UUIDs. New UUIDs have the form:
6655714Skris	 *	01234567-89ab-cdef-0123-456789abcdef
6755714Skris	 * The so called "old" UUIDs, which we don't support, have the form:
6855714Skris	 *	0123456789ab.cd.ef.01.23.45.67.89.ab
6955714Skris	 */
7055714Skris	if (s[8] != '-')
7155714Skris		return;
7255714Skris
7355714Skris	n = sscanf(s,
7455714Skris	    "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
7555714Skris	    &u->time_low, &u->time_mid, &u->time_hi_and_version,
7655714Skris	    &u->clock_seq_hi_and_reserved, &u->clock_seq_low, &u->node[0],
7755714Skris	    &u->node[1], &u->node[2], &u->node[3], &u->node[4], &u->node[5]);
78111147Snectar
79111147Snectar	/* Make sure we have all conversions. */
80111147Snectar	if (n != 11)
81111147Snectar		return;
82111147Snectar
8355714Skris	/* We have a successful scan. Check semantics... */
8455714Skris	n = u->clock_seq_hi_and_reserved;
85160814Ssimon	if ((n & 0x80) != 0x00 &&			/* variant 0? */
8655714Skris	    (n & 0xc0) != 0x80 &&			/* variant 1? */
87160814Ssimon	    (n & 0xe0) != 0xc0) {			/* variant 2? */
88111147Snectar		if (status != NULL)
89111147Snectar			*status = uuid_s_bad_version;
90111147Snectar	} else {
91111147Snectar		if (status != NULL)
92111147Snectar			*status = uuid_s_ok;
93111147Snectar	}
94111147Snectar}
95111147Snectar