1 /* 2 * uuid_time.c --- Interpret the time field from a uuid. This program 3 * violates the UUID abstraction barrier by reaching into the guts 4 * of a UUID and interpreting it. 5 * 6 * Copyright (C) 1998, 1999 Theodore Ts'o. 7 * 8 * %Begin-Header% 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, and the entire permission notice in its entirety, 14 * including the disclaimer of warranties. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote 19 * products derived from this software without specific prior 20 * written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 25 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 28 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 32 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH 33 * DAMAGE. 34 * %End-Header% 35 */ 36 37 #include <stdio.h> 38 #include <unistd.h> 39 #include <stdlib.h> 40 #include <sys/types.h> 41 #include <sys/time.h> 42 #include <time.h> 43 44 #include "uuidP.h" 45 46 time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) 47 { 48 struct timeval tv; 49 struct uuid uuid; 50 uint32_t high; 51 uint64_t clock_reg; 52 53 uuid_unpack(uu, &uuid); 54 55 high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); 56 clock_reg = uuid.time_low | ((uint64_t) high << 32); 57 58 clock_reg -= (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; 59 tv.tv_sec = clock_reg / 10000000; 60 tv.tv_usec = (clock_reg % 10000000) / 10; 61 62 if (ret_tv) 63 *ret_tv = tv; 64 65 return tv.tv_sec; 66 } 67 68 int uuid_type(const uuid_t uu) 69 { 70 struct uuid uuid; 71 72 uuid_unpack(uu, &uuid); 73 return ((uuid.time_hi_and_version >> 12) & 0xF); 74 } 75 76 int uuid_variant(const uuid_t uu) 77 { 78 struct uuid uuid; 79 int var; 80 81 uuid_unpack(uu, &uuid); 82 var = uuid.clock_seq; 83 84 if ((var & 0x8000) == 0) 85 return UUID_VARIANT_NCS; 86 if ((var & 0x4000) == 0) 87 return UUID_VARIANT_DCE; 88 if ((var & 0x2000) == 0) 89 return UUID_VARIANT_MICROSOFT; 90 return UUID_VARIANT_OTHER; 91 } 92 93 #ifdef DEBUG 94 static const char *variant_string(int variant) 95 { 96 switch (variant) { 97 case UUID_VARIANT_NCS: 98 return "NCS"; 99 case UUID_VARIANT_DCE: 100 return "DCE"; 101 case UUID_VARIANT_MICROSOFT: 102 return "Microsoft"; 103 default: 104 return "Other"; 105 } 106 } 107 108 109 int 110 main(int argc, char **argv) 111 { 112 uuid_t buf; 113 time_t time_reg; 114 struct timeval tv; 115 int type, variant; 116 117 if (argc != 2) { 118 fprintf(stderr, "Usage: %s uuid\n", argv[0]); 119 exit(1); 120 } 121 if (uuid_parse(argv[1], buf)) { 122 fprintf(stderr, "Invalid UUID: %s\n", argv[1]); 123 exit(1); 124 } 125 variant = uuid_variant(buf); 126 type = uuid_type(buf); 127 time_reg = uuid_time(buf, &tv); 128 129 printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); 130 if (variant != UUID_VARIANT_DCE) { 131 printf("Warning: This program only knows how to interpret " 132 "DCE UUIDs.\n\tThe rest of the output is likely " 133 "to be incorrect!!\n"); 134 } 135 printf("UUID type is %d", type); 136 switch (type) { 137 case 1: 138 printf(" (time based)\n"); 139 break; 140 case 2: 141 printf(" (DCE)\n"); 142 break; 143 case 3: 144 printf(" (name-based)\n"); 145 break; 146 case 4: 147 printf(" (random)\n"); 148 break; 149 default: 150 printf("\n"); 151 } 152 if (type != 1) { 153 printf("Warning: not a time-based UUID, so UUID time " 154 "decoding will likely not work!\n"); 155 } 156 printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, (long)tv.tv_usec, 157 ctime(&time_reg)); 158 159 return 0; 160 } 161 #endif 162