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 * This file may be redistributed under the terms of the GNU 10 * Library General Public License. 11 * %End-Header% 12 */ 13 14#include <stdio.h> 15#include <unistd.h> 16#include <stdlib.h> 17#include <sys/types.h> 18#include <sys/time.h> 19#include <time.h> 20 21#include "uuidP.h" 22 23time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) 24{ 25 struct uuid uuid; 26 __u32 high; 27 struct timeval tv; 28 unsigned long long clock_reg; 29 30 uuid_unpack(uu, &uuid); 31 32 high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); 33 clock_reg = uuid.time_low | ((unsigned long long) high << 32); 34 35 clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; 36 tv.tv_sec = clock_reg / 10000000; 37 tv.tv_usec = (clock_reg % 10000000) / 10; 38 39 if (ret_tv) 40 *ret_tv = tv; 41 42 return tv.tv_sec; 43} 44 45int uuid_type(const uuid_t uu) 46{ 47 struct uuid uuid; 48 49 uuid_unpack(uu, &uuid); 50 return ((uuid.time_hi_and_version >> 12) & 0xF); 51} 52 53int uuid_variant(const uuid_t uu) 54{ 55 struct uuid uuid; 56 int var; 57 58 uuid_unpack(uu, &uuid); 59 var = uuid.clock_seq; 60 61 if ((var & 0x8000) == 0) 62 return UUID_VARIANT_NCS; 63 if ((var & 0x4000) == 0) 64 return UUID_VARIANT_DCE; 65 if ((var & 0x2000) == 0) 66 return UUID_VARIANT_MICROSOFT; 67 return UUID_VARIANT_OTHER; 68} 69 70#ifdef DEBUG 71static const char *variant_string(int variant) 72{ 73 switch (variant) { 74 case UUID_VARIANT_NCS: 75 return "NCS"; 76 case UUID_VARIANT_DCE: 77 return "DCE"; 78 case UUID_VARIANT_MICROSOFT: 79 return "Microsoft"; 80 default: 81 return "Other"; 82 } 83} 84 85 86int 87main(int argc, char **argv) 88{ 89 uuid_t buf; 90 time_t time_reg; 91 struct timeval tv; 92 int type, variant; 93 94 if (argc != 2) { 95 fprintf(stderr, "Usage: %s uuid\n", argv[0]); 96 exit(1); 97 } 98 if (uuid_parse(argv[1], buf)) { 99 fprintf(stderr, "Invalid UUID: %s\n", argv[1]); 100 exit(1); 101 } 102 variant = uuid_variant(buf); 103 type = uuid_type(buf); 104 time_reg = uuid_time(buf, &tv); 105 106 printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); 107 if (variant != UUID_VARIANT_DCE) { 108 printf("Warning: This program only knows how to interpret " 109 "DCE UUIDs.\n\tThe rest of the output is likely " 110 "to be incorrect!!\n"); 111 } 112 printf("UUID type is %d", type); 113 switch (type) { 114 case 1: 115 printf(" (time based)\n"); 116 break; 117 case 2: 118 printf(" (DCE)\n"); 119 break; 120 case 3: 121 printf(" (name-based)\n"); 122 break; 123 case 4: 124 printf(" (random)\n"); 125 break; 126 default: 127 printf("\n"); 128 } 129 if (type != 1) { 130 printf("Warning: not a time-based UUID, so UUID time " 131 "decoding will likely not work!\n"); 132 } 133 printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec, 134 ctime(&time_reg)); 135 136 return 0; 137} 138#endif 139