// // aegis - project change supervisor // Copyright (C) 2005, 2006, 2008, 2012 Peter Miller // Copyright (C) 2004, 2008 Walter Franzini; // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published // by the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include #include #include #include #include #include #include #include #include #include static string_ty * make_uuid_random(void) { static const char charset[] = "0123456789abcdef"; char buffer[36]; size_t i; // // Generate a random UUID as per // http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt // for (i = 0; i < 36; ++i) { switch (i) { case 8: case 13: case 18: case 23: buffer[i] = '-'; break; case 14: case 19: // see below break; default: buffer[i] = charset[r250() & 15]; break; } } // version buffer[14] = '4'; // top 2 bits are invariant buffer[19] = charset[8 | (r250() & 3)]; return str_n_from_c(buffer, 36); } #if HAVE_UUID_CREATE && HAVE_UUID_MAKE && HAVE_UUID_EXPORT static string_ty * make_uuid(void) { uuid_t *uuid = 0; uuid_rc_t u_rc = uuid_create(&uuid); if (u_rc != UUID_RC_OK) { failed: return make_uuid_random(); } u_rc = uuid_make(uuid, UUID_MAKE_V4); if (u_rc != UUID_RC_OK) goto failed; void *vp = NULL; u_rc = uuid_export(uuid, UUID_FMT_STR, &vp, NULL); if (u_rc != UUID_RC_OK) goto failed; assert(NULL != vp); string_ty *s1 = str_n_from_c((char *)vp, UUID_LEN_STR); uuid_destroy(uuid); free(vp); string_ty *s2 = str_downcase(s1); str_free(s1); return s2; } #elif HAVE_UUID_GENERATE && HAVE_UUID_UNPARSE static string_ty * make_uuid(void) { uuid_t uuid; char uu[37]; uu[0] = '\0'; uuid_generate(uuid); uuid_unparse(uuid, uu); assert(*uu); if (!*uu) return make_uuid_random(); string_ty *s1 = str_n_from_c(uu, 36); string_ty *s2 = str_downcase(s1); str_free(s1); return s2; } #elif HAVE_DCE_UUID_H && HAVE_UUID_CREATE && HAVE_UUID_TO_STRING static string_ty * make_uuid(void) { uuid_t uu_identifier; uint32_t status; char *uu; uu = 0; uuid_create(&uu_identifier, &status); switch (status) { case uuid_s_ok: uuid_to_string(&uu_identifier, &uu, &status); if (uuid_s_ok != status) { do_it_ourselves: return make_uuid_random(); } break; case uuid_s_bad_version: case uuid_s_invalid_string_uuid: case uuid_s_no_memory: goto do_it_ourselves; } if (!uu || !*uu) goto do_it_ourselves; string_ty *s1 = str_n_from_c(uu, 36); // // From // http://www.opengroup.org/onlinepubs/9629399/uuid_to_string.htm // // Note: The RPC run-time system allocates memory for the // string returned in string_uuid. To deallocate the // memory, the application calls the rpc_string_free() // routine. // int ignore; rpc_string_free(&uu, &ignore); string_ty *s2 = str_downcase(s1); str_free(s1); return s2; } #elif defined(UUID_IS_LINUX) static string_ty * make_uuid(void) { int fd; char buffer[36]; fd = open(LINUX_UUID_FILENAME, O_RDONLY); if (fd < 0) { failed: return make_uuid_random(); } if (read(fd, buffer, 36) != 36) { close(fd); goto failed; } close(fd); string_ty *s1 = str_n_from_c(buffer, 36); string_ty *s2 = str_downcase(s1); str_free(s1); return s2; } #else static string_ty * make_uuid(void) { return make_uuid_random(); } #endif string_ty * universal_unique_identifier(void) { string_ty *ret; ret = make_uuid(); assert(ret); return ret; } static const char uuid_charset[] = "0123456789abcdefABCDEF"; bool universal_unique_identifier_valid(string_ty *uuid) { return universal_unique_identifier_valid(nstring(uuid)); } bool universal_unique_identifier_valid(const nstring &uuid) { return ( uuid.size() == 36 && universal_unique_identifier_valid_partial(uuid) ); } bool universal_unique_identifier_valid_partial(string_ty *uuid) { return universal_unique_identifier_valid_partial(nstring(uuid)); } bool universal_unique_identifier_valid_partial(const nstring &uuid) { if (uuid.size() < 4 || uuid.size() > 36) return false; // // Syntax check // for (size_t i = 0; i < uuid.size(); ++i) { switch (i) { case 8: case 13: case 18: case 23: if (uuid[i] != '-') return false; break; default: if (0 == strchr(uuid_charset, uuid[i])) return false; break; } } return true; } // vim: set ts=8 sw=4 et :