xref: /freebsd/lib/libc/uuid/uuid_from_string.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
165393a86SMarcel Moolenaar /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3d915a14eSPedro F. Giffuni  *
465393a86SMarcel Moolenaar  * Copyright (c) 2002 Marcel Moolenaar
565393a86SMarcel Moolenaar  * Copyright (c) 2002 Hiten Mahesh Pandya
665393a86SMarcel Moolenaar  * All rights reserved.
765393a86SMarcel Moolenaar  *
865393a86SMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
965393a86SMarcel Moolenaar  * modification, are permitted provided that the following conditions
1065393a86SMarcel Moolenaar  * are met:
1165393a86SMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
1265393a86SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
1365393a86SMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
1465393a86SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
1565393a86SMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
1665393a86SMarcel Moolenaar  *
1765393a86SMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1865393a86SMarcel Moolenaar  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1965393a86SMarcel Moolenaar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2065393a86SMarcel Moolenaar  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2165393a86SMarcel Moolenaar  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2265393a86SMarcel Moolenaar  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2365393a86SMarcel Moolenaar  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2465393a86SMarcel Moolenaar  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2565393a86SMarcel Moolenaar  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2665393a86SMarcel Moolenaar  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2765393a86SMarcel Moolenaar  * SUCH DAMAGE.
2865393a86SMarcel Moolenaar  */
2965393a86SMarcel Moolenaar 
3065393a86SMarcel Moolenaar #include <stdio.h>
3165393a86SMarcel Moolenaar #include <string.h>
3265393a86SMarcel Moolenaar #include <uuid.h>
3365393a86SMarcel Moolenaar 
3465393a86SMarcel Moolenaar /*
3565393a86SMarcel Moolenaar  * uuid_from_string() - convert a string representation of an UUID into
3665393a86SMarcel Moolenaar  *			a binary representation.
3765393a86SMarcel Moolenaar  * See also:
3865393a86SMarcel Moolenaar  *	http://www.opengroup.org/onlinepubs/009629399/uuid_from_string.htm
3965393a86SMarcel Moolenaar  *
4065393a86SMarcel Moolenaar  * NOTE: The sequence field is in big-endian, while the time fields are in
4165393a86SMarcel Moolenaar  *	 native byte order.
4265393a86SMarcel Moolenaar  */
4365393a86SMarcel Moolenaar void
uuid_from_string(const char * s,uuid_t * u,uint32_t * status)4465393a86SMarcel Moolenaar uuid_from_string(const char *s, uuid_t *u, uint32_t *status)
4565393a86SMarcel Moolenaar {
4665393a86SMarcel Moolenaar 	int n;
4765393a86SMarcel Moolenaar 
4865393a86SMarcel Moolenaar 	/* Short-circuit 2 special cases: NULL pointer and empty string. */
4965393a86SMarcel Moolenaar 	if (s == NULL || *s == '\0') {
5065393a86SMarcel Moolenaar 		uuid_create_nil(u, status);
5165393a86SMarcel Moolenaar 		return;
5265393a86SMarcel Moolenaar 	}
5365393a86SMarcel Moolenaar 
5465393a86SMarcel Moolenaar 	/* Assume the worst. */
5565393a86SMarcel Moolenaar 	if (status != NULL)
5665393a86SMarcel Moolenaar 		*status = uuid_s_invalid_string_uuid;
5765393a86SMarcel Moolenaar 
5865393a86SMarcel Moolenaar 	/* The UUID string representation has a fixed length. */
5965393a86SMarcel Moolenaar 	if (strlen(s) != 36)
6065393a86SMarcel Moolenaar 		return;
6165393a86SMarcel Moolenaar 
6265393a86SMarcel Moolenaar 	/*
6365393a86SMarcel Moolenaar 	 * We only work with "new" UUIDs. New UUIDs have the form:
6465393a86SMarcel Moolenaar 	 *	01234567-89ab-cdef-0123-456789abcdef
6565393a86SMarcel Moolenaar 	 * The so called "old" UUIDs, which we don't support, have the form:
6665393a86SMarcel Moolenaar 	 *	0123456789ab.cd.ef.01.23.45.67.89.ab
6765393a86SMarcel Moolenaar 	 */
6865393a86SMarcel Moolenaar 	if (s[8] != '-')
6965393a86SMarcel Moolenaar 		return;
7065393a86SMarcel Moolenaar 
7165393a86SMarcel Moolenaar 	n = sscanf(s,
7265393a86SMarcel Moolenaar 	    "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
7365393a86SMarcel Moolenaar 	    &u->time_low, &u->time_mid, &u->time_hi_and_version,
7465393a86SMarcel Moolenaar 	    &u->clock_seq_hi_and_reserved, &u->clock_seq_low, &u->node[0],
7565393a86SMarcel Moolenaar 	    &u->node[1], &u->node[2], &u->node[3], &u->node[4], &u->node[5]);
7665393a86SMarcel Moolenaar 
7765393a86SMarcel Moolenaar 	/* Make sure we have all conversions. */
7865393a86SMarcel Moolenaar 	if (n != 11)
7965393a86SMarcel Moolenaar 		return;
8065393a86SMarcel Moolenaar 
8165393a86SMarcel Moolenaar 	/* We have a successful scan. Check semantics... */
8265393a86SMarcel Moolenaar 	n = u->clock_seq_hi_and_reserved;
8365393a86SMarcel Moolenaar 	if ((n & 0x80) != 0x00 &&			/* variant 0? */
8465393a86SMarcel Moolenaar 	    (n & 0xc0) != 0x80 &&			/* variant 1? */
8565393a86SMarcel Moolenaar 	    (n & 0xe0) != 0xc0) {			/* variant 2? */
8665393a86SMarcel Moolenaar 		if (status != NULL)
8765393a86SMarcel Moolenaar 			*status = uuid_s_bad_version;
8865393a86SMarcel Moolenaar 	} else {
8965393a86SMarcel Moolenaar 		if (status != NULL)
9065393a86SMarcel Moolenaar 			*status = uuid_s_ok;
9165393a86SMarcel Moolenaar 	}
9265393a86SMarcel Moolenaar }
93