1b39be1b3SPoul-Henning Kamp /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 38a36da99SPedro F. Giffuni * 4b39be1b3SPoul-Henning Kamp * Copyright (c) 2006 Poul-Henning Kamp 5b39be1b3SPoul-Henning Kamp * All rights reserved. 6b39be1b3SPoul-Henning Kamp * 7b39be1b3SPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without 8b39be1b3SPoul-Henning Kamp * modification, are permitted provided that the following conditions 9b39be1b3SPoul-Henning Kamp * are met: 10b39be1b3SPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright 11b39be1b3SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer. 12b39be1b3SPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright 13b39be1b3SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the 14b39be1b3SPoul-Henning Kamp * documentation and/or other materials provided with the distribution. 15b39be1b3SPoul-Henning Kamp * 16b39be1b3SPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17b39be1b3SPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18b39be1b3SPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19b39be1b3SPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20b39be1b3SPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21b39be1b3SPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22b39be1b3SPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23b39be1b3SPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24b39be1b3SPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25b39be1b3SPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26b39be1b3SPoul-Henning Kamp * SUCH DAMAGE. 27b39be1b3SPoul-Henning Kamp * 28b39be1b3SPoul-Henning Kamp * Convert MS-DOS FAT format timestamps to and from unix timespecs 29b39be1b3SPoul-Henning Kamp * 30b39be1b3SPoul-Henning Kamp * FAT filestamps originally consisted of two 16 bit integers, encoded like 31b39be1b3SPoul-Henning Kamp * this: 32b39be1b3SPoul-Henning Kamp * 33b39be1b3SPoul-Henning Kamp * yyyyyyymmmmddddd (year - 1980, month, day) 34b39be1b3SPoul-Henning Kamp * 35b39be1b3SPoul-Henning Kamp * hhhhhmmmmmmsssss (hour, minutes, seconds divided by two) 36b39be1b3SPoul-Henning Kamp * 37b39be1b3SPoul-Henning Kamp * Subsequently even Microsoft realized that files could be accessed in less 38b39be1b3SPoul-Henning Kamp * than two seconds and a byte was added containing: 39b39be1b3SPoul-Henning Kamp * 40b39be1b3SPoul-Henning Kamp * sfffffff (second mod two, 100ths of second) 41b39be1b3SPoul-Henning Kamp * 42b39be1b3SPoul-Henning Kamp * FAT timestamps are in the local timezone, with no indication of which 43b39be1b3SPoul-Henning Kamp * timezone much less if daylight savings time applies. 44b39be1b3SPoul-Henning Kamp * 45b39be1b3SPoul-Henning Kamp * Later on again, in Windows NT, timestamps were defined relative to GMT. 46b39be1b3SPoul-Henning Kamp * 47b39be1b3SPoul-Henning Kamp * Purists will point out that UTC replaced GMT for such uses around 4861f26caeSWarner Losh * half a century ago, already then. Ironically "NT" was an abbreviation of 49b39be1b3SPoul-Henning Kamp * "New Technology". Anyway... 50b39be1b3SPoul-Henning Kamp * 517ea93e91SPoul-Henning Kamp * The 'utc' argument determines if the resulting FATTIME timestamp 52beb4f781SKonstantin Belousov * should be on the UTC or local timezone calendar. 53b39be1b3SPoul-Henning Kamp * 546afc7238SIan Lepore * The conversion functions below cut time into four-year leap-year 55b39be1b3SPoul-Henning Kamp * cycles rather than single years and uses table lookups inside those 56b39be1b3SPoul-Henning Kamp * cycles to get the months and years sorted out. 57b39be1b3SPoul-Henning Kamp * 58b39be1b3SPoul-Henning Kamp * Obviously we cannot calculate the correct table index going from 59b39be1b3SPoul-Henning Kamp * a posix seconds count to Y/M/D, but we can get pretty close by 60b39be1b3SPoul-Henning Kamp * dividing the daycount by 32 (giving a too low index), and then 61b39be1b3SPoul-Henning Kamp * adjusting upwards a couple of steps if necessary. 62b39be1b3SPoul-Henning Kamp * 63b39be1b3SPoul-Henning Kamp * FAT timestamps have 7 bits for the year and starts at 1980, so 64b39be1b3SPoul-Henning Kamp * they can represent up to 2107 which means that the non-leap-year 65b39be1b3SPoul-Henning Kamp * 2100 must be handled. 66b39be1b3SPoul-Henning Kamp */ 67b39be1b3SPoul-Henning Kamp 68b39be1b3SPoul-Henning Kamp #include <sys/param.h> 69b39be1b3SPoul-Henning Kamp #include <sys/types.h> 70b39be1b3SPoul-Henning Kamp #include <sys/time.h> 71b39be1b3SPoul-Henning Kamp #include <sys/clock.h> 72b39be1b3SPoul-Henning Kamp 737b8b613dSJosef 'Jeff' Sipek #ifdef TEST_DRIVER 747b8b613dSJosef 'Jeff' Sipek /* stub for testing */ 757b8b613dSJosef 'Jeff' Sipek #define utc_offset() 0 767b8b613dSJosef 'Jeff' Sipek #endif 777b8b613dSJosef 'Jeff' Sipek 78b39be1b3SPoul-Henning Kamp #define DAY (24 * 60 * 60) /* Length of day in seconds */ 79b39be1b3SPoul-Henning Kamp #define YEAR 365 /* Length of normal year */ 80b39be1b3SPoul-Henning Kamp #define LYC (4 * YEAR + 1) /* Length of 4 year leap-year cycle */ 81b39be1b3SPoul-Henning Kamp #define T1980 (10 * 365 + 2) /* Days from 1970 to 1980 */ 829d1396c3SJosef 'Jeff' Sipek #define T2108 (138 * 365 + 33) /* Days from 1970 to 2108 */ 83b39be1b3SPoul-Henning Kamp 84b39be1b3SPoul-Henning Kamp /* End of month is N days from start of (normal) year */ 85b39be1b3SPoul-Henning Kamp #define JAN 31 86b39be1b3SPoul-Henning Kamp #define FEB (JAN + 28) 87b39be1b3SPoul-Henning Kamp #define MAR (FEB + 31) 88b39be1b3SPoul-Henning Kamp #define APR (MAR + 30) 89b39be1b3SPoul-Henning Kamp #define MAY (APR + 31) 90b39be1b3SPoul-Henning Kamp #define JUN (MAY + 30) 91b39be1b3SPoul-Henning Kamp #define JUL (JUN + 31) 92b39be1b3SPoul-Henning Kamp #define AUG (JUL + 31) 93b39be1b3SPoul-Henning Kamp #define SEP (AUG + 30) 94b39be1b3SPoul-Henning Kamp #define OCT (SEP + 31) 95b39be1b3SPoul-Henning Kamp #define NOV (OCT + 30) 96b39be1b3SPoul-Henning Kamp #define DEC (NOV + 31) 97b39be1b3SPoul-Henning Kamp 98b39be1b3SPoul-Henning Kamp /* Table of months in a 4 year leap-year cycle */ 99b39be1b3SPoul-Henning Kamp 100b39be1b3SPoul-Henning Kamp #define ENC(y,m) (((y) << 9) | ((m) << 5)) 101b39be1b3SPoul-Henning Kamp 102b39be1b3SPoul-Henning Kamp static const struct { 103b39be1b3SPoul-Henning Kamp uint16_t days; /* month start in days relative to cycle */ 104b39be1b3SPoul-Henning Kamp uint16_t coded; /* encoded year + month information */ 105b39be1b3SPoul-Henning Kamp } mtab[48] = { 106b39be1b3SPoul-Henning Kamp { 0 + 0 * YEAR, ENC(0, 1) }, 107b39be1b3SPoul-Henning Kamp 108b39be1b3SPoul-Henning Kamp { JAN + 0 * YEAR, ENC(0, 2) }, { FEB + 0 * YEAR + 1, ENC(0, 3) }, 109b39be1b3SPoul-Henning Kamp { MAR + 0 * YEAR + 1, ENC(0, 4) }, { APR + 0 * YEAR + 1, ENC(0, 5) }, 110b39be1b3SPoul-Henning Kamp { MAY + 0 * YEAR + 1, ENC(0, 6) }, { JUN + 0 * YEAR + 1, ENC(0, 7) }, 111b39be1b3SPoul-Henning Kamp { JUL + 0 * YEAR + 1, ENC(0, 8) }, { AUG + 0 * YEAR + 1, ENC(0, 9) }, 112b39be1b3SPoul-Henning Kamp { SEP + 0 * YEAR + 1, ENC(0, 10) }, { OCT + 0 * YEAR + 1, ENC(0, 11) }, 113b39be1b3SPoul-Henning Kamp { NOV + 0 * YEAR + 1, ENC(0, 12) }, { DEC + 0 * YEAR + 1, ENC(1, 1) }, 114b39be1b3SPoul-Henning Kamp 115b39be1b3SPoul-Henning Kamp { JAN + 1 * YEAR + 1, ENC(1, 2) }, { FEB + 1 * YEAR + 1, ENC(1, 3) }, 116b39be1b3SPoul-Henning Kamp { MAR + 1 * YEAR + 1, ENC(1, 4) }, { APR + 1 * YEAR + 1, ENC(1, 5) }, 117b39be1b3SPoul-Henning Kamp { MAY + 1 * YEAR + 1, ENC(1, 6) }, { JUN + 1 * YEAR + 1, ENC(1, 7) }, 118b39be1b3SPoul-Henning Kamp { JUL + 1 * YEAR + 1, ENC(1, 8) }, { AUG + 1 * YEAR + 1, ENC(1, 9) }, 119b39be1b3SPoul-Henning Kamp { SEP + 1 * YEAR + 1, ENC(1, 10) }, { OCT + 1 * YEAR + 1, ENC(1, 11) }, 120b39be1b3SPoul-Henning Kamp { NOV + 1 * YEAR + 1, ENC(1, 12) }, { DEC + 1 * YEAR + 1, ENC(2, 1) }, 121b39be1b3SPoul-Henning Kamp 122b39be1b3SPoul-Henning Kamp { JAN + 2 * YEAR + 1, ENC(2, 2) }, { FEB + 2 * YEAR + 1, ENC(2, 3) }, 123b39be1b3SPoul-Henning Kamp { MAR + 2 * YEAR + 1, ENC(2, 4) }, { APR + 2 * YEAR + 1, ENC(2, 5) }, 124b39be1b3SPoul-Henning Kamp { MAY + 2 * YEAR + 1, ENC(2, 6) }, { JUN + 2 * YEAR + 1, ENC(2, 7) }, 125b39be1b3SPoul-Henning Kamp { JUL + 2 * YEAR + 1, ENC(2, 8) }, { AUG + 2 * YEAR + 1, ENC(2, 9) }, 126b39be1b3SPoul-Henning Kamp { SEP + 2 * YEAR + 1, ENC(2, 10) }, { OCT + 2 * YEAR + 1, ENC(2, 11) }, 127b39be1b3SPoul-Henning Kamp { NOV + 2 * YEAR + 1, ENC(2, 12) }, { DEC + 2 * YEAR + 1, ENC(3, 1) }, 128b39be1b3SPoul-Henning Kamp 129b39be1b3SPoul-Henning Kamp { JAN + 3 * YEAR + 1, ENC(3, 2) }, { FEB + 3 * YEAR + 1, ENC(3, 3) }, 130b39be1b3SPoul-Henning Kamp { MAR + 3 * YEAR + 1, ENC(3, 4) }, { APR + 3 * YEAR + 1, ENC(3, 5) }, 131b39be1b3SPoul-Henning Kamp { MAY + 3 * YEAR + 1, ENC(3, 6) }, { JUN + 3 * YEAR + 1, ENC(3, 7) }, 132b39be1b3SPoul-Henning Kamp { JUL + 3 * YEAR + 1, ENC(3, 8) }, { AUG + 3 * YEAR + 1, ENC(3, 9) }, 133b39be1b3SPoul-Henning Kamp { SEP + 3 * YEAR + 1, ENC(3, 10) }, { OCT + 3 * YEAR + 1, ENC(3, 11) }, 134b39be1b3SPoul-Henning Kamp { NOV + 3 * YEAR + 1, ENC(3, 12) } 135b39be1b3SPoul-Henning Kamp }; 136b39be1b3SPoul-Henning Kamp 137b39be1b3SPoul-Henning Kamp void 138ce75945dSIan Lepore timespec2fattime(const struct timespec *tsp, int utc, uint16_t *ddp, 139ce75945dSIan Lepore uint16_t *dtp, uint8_t *dhp) 140b39be1b3SPoul-Henning Kamp { 141b39be1b3SPoul-Henning Kamp time_t t1; 142b39be1b3SPoul-Henning Kamp unsigned t2, l, m; 143b39be1b3SPoul-Henning Kamp 144b39be1b3SPoul-Henning Kamp t1 = tsp->tv_sec; 1457ea93e91SPoul-Henning Kamp if (!utc) 1467ea93e91SPoul-Henning Kamp t1 -= utc_offset(); 147b39be1b3SPoul-Henning Kamp 148b39be1b3SPoul-Henning Kamp if (dhp != NULL) 149b39be1b3SPoul-Henning Kamp *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000; 150b39be1b3SPoul-Henning Kamp if (dtp != NULL) { 151b39be1b3SPoul-Henning Kamp *dtp = (t1 / 2) % 30; 152b39be1b3SPoul-Henning Kamp *dtp |= ((t1 / 60) % 60) << 5; 153b39be1b3SPoul-Henning Kamp *dtp |= ((t1 / 3600) % 24) << 11; 154b39be1b3SPoul-Henning Kamp } 155b39be1b3SPoul-Henning Kamp if (ddp != NULL) { 156b39be1b3SPoul-Henning Kamp t2 = t1 / DAY; 157b39be1b3SPoul-Henning Kamp if (t2 < T1980) { 158b39be1b3SPoul-Henning Kamp /* Impossible date, truncate to 1980-01-01 */ 159b39be1b3SPoul-Henning Kamp *ddp = 0x0021; 160b39be1b3SPoul-Henning Kamp } else { 161b39be1b3SPoul-Henning Kamp t2 -= T1980; 162b39be1b3SPoul-Henning Kamp 163*0fe60dc6SJosef 'Jeff' Sipek /* 2100 is not a leap year */ 164b39be1b3SPoul-Henning Kamp if (t2 >= ((2100 - 1980) / 4 * LYC + FEB)) 165b39be1b3SPoul-Henning Kamp t2++; 166b39be1b3SPoul-Henning Kamp 167b39be1b3SPoul-Henning Kamp /* Account for full leapyear cycles */ 168b39be1b3SPoul-Henning Kamp l = t2 / LYC; 169b39be1b3SPoul-Henning Kamp *ddp = (l * 4) << 9; 170b39be1b3SPoul-Henning Kamp t2 -= l * LYC; 171b39be1b3SPoul-Henning Kamp 172b39be1b3SPoul-Henning Kamp /* Find approximate table entry */ 173b39be1b3SPoul-Henning Kamp m = t2 / 32; 174b39be1b3SPoul-Henning Kamp 175b39be1b3SPoul-Henning Kamp /* Find correct table entry */ 176b39be1b3SPoul-Henning Kamp while (m < 47 && mtab[m + 1].days <= t2) 177b39be1b3SPoul-Henning Kamp m++; 178b39be1b3SPoul-Henning Kamp 179b39be1b3SPoul-Henning Kamp /* Get year + month from the table */ 180b39be1b3SPoul-Henning Kamp *ddp += mtab[m].coded; 181b39be1b3SPoul-Henning Kamp 182b39be1b3SPoul-Henning Kamp /* And apply the day in the month */ 183b39be1b3SPoul-Henning Kamp t2 -= mtab[m].days - 1; 184b39be1b3SPoul-Henning Kamp *ddp |= t2; 185b39be1b3SPoul-Henning Kamp } 186b39be1b3SPoul-Henning Kamp } 187b39be1b3SPoul-Henning Kamp } 188b39be1b3SPoul-Henning Kamp 189b39be1b3SPoul-Henning Kamp /* 190b39be1b3SPoul-Henning Kamp * Table indexed by the bottom two bits of year + four bits of the month 191b39be1b3SPoul-Henning Kamp * from the FAT timestamp, returning number of days into 4 year long 192b39be1b3SPoul-Henning Kamp * leap-year cycle 193b39be1b3SPoul-Henning Kamp */ 194b39be1b3SPoul-Henning Kamp 195b39be1b3SPoul-Henning Kamp #define DCOD(m, y, l) ((m) + YEAR * (y) + (l)) 196b39be1b3SPoul-Henning Kamp static const uint16_t daytab[64] = { 197b39be1b3SPoul-Henning Kamp 0, DCOD( 0, 0, 0), DCOD(JAN, 0, 0), DCOD(FEB, 0, 1), 198b39be1b3SPoul-Henning Kamp DCOD(MAR, 0, 1), DCOD(APR, 0, 1), DCOD(MAY, 0, 1), DCOD(JUN, 0, 1), 199b39be1b3SPoul-Henning Kamp DCOD(JUL, 0, 1), DCOD(AUG, 0, 1), DCOD(SEP, 0, 1), DCOD(OCT, 0, 1), 200b39be1b3SPoul-Henning Kamp DCOD(NOV, 0, 1), DCOD(DEC, 0, 1), 0, 0, 201b39be1b3SPoul-Henning Kamp 0, DCOD( 0, 1, 1), DCOD(JAN, 1, 1), DCOD(FEB, 1, 1), 202b39be1b3SPoul-Henning Kamp DCOD(MAR, 1, 1), DCOD(APR, 1, 1), DCOD(MAY, 1, 1), DCOD(JUN, 1, 1), 203b39be1b3SPoul-Henning Kamp DCOD(JUL, 1, 1), DCOD(AUG, 1, 1), DCOD(SEP, 1, 1), DCOD(OCT, 1, 1), 204b39be1b3SPoul-Henning Kamp DCOD(NOV, 1, 1), DCOD(DEC, 1, 1), 0, 0, 205b39be1b3SPoul-Henning Kamp 0, DCOD( 0, 2, 1), DCOD(JAN, 2, 1), DCOD(FEB, 2, 1), 206b39be1b3SPoul-Henning Kamp DCOD(MAR, 2, 1), DCOD(APR, 2, 1), DCOD(MAY, 2, 1), DCOD(JUN, 2, 1), 207b39be1b3SPoul-Henning Kamp DCOD(JUL, 2, 1), DCOD(AUG, 2, 1), DCOD(SEP, 2, 1), DCOD(OCT, 2, 1), 208b39be1b3SPoul-Henning Kamp DCOD(NOV, 2, 1), DCOD(DEC, 2, 1), 0, 0, 209b39be1b3SPoul-Henning Kamp 0, DCOD( 0, 3, 1), DCOD(JAN, 3, 1), DCOD(FEB, 3, 1), 210b39be1b3SPoul-Henning Kamp DCOD(MAR, 3, 1), DCOD(APR, 3, 1), DCOD(MAY, 3, 1), DCOD(JUN, 3, 1), 211b39be1b3SPoul-Henning Kamp DCOD(JUL, 3, 1), DCOD(AUG, 3, 1), DCOD(SEP, 3, 1), DCOD(OCT, 3, 1), 212b39be1b3SPoul-Henning Kamp DCOD(NOV, 3, 1), DCOD(DEC, 3, 1), 0, 0 213b39be1b3SPoul-Henning Kamp }; 214b39be1b3SPoul-Henning Kamp 215b39be1b3SPoul-Henning Kamp void 216ce75945dSIan Lepore fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc, 217ce75945dSIan Lepore struct timespec *tsp) 218b39be1b3SPoul-Henning Kamp { 219b39be1b3SPoul-Henning Kamp unsigned day; 220b39be1b3SPoul-Henning Kamp 221b39be1b3SPoul-Henning Kamp /* Unpack time fields */ 222b39be1b3SPoul-Henning Kamp tsp->tv_sec = (dt & 0x1f) << 1; 223b39be1b3SPoul-Henning Kamp tsp->tv_sec += ((dt & 0x7e0) >> 5) * 60; 224b39be1b3SPoul-Henning Kamp tsp->tv_sec += ((dt & 0xf800) >> 11) * 3600; 225b39be1b3SPoul-Henning Kamp tsp->tv_sec += dh / 100; 226b39be1b3SPoul-Henning Kamp tsp->tv_nsec = (dh % 100) * 10000000; 227b39be1b3SPoul-Henning Kamp 228b39be1b3SPoul-Henning Kamp /* Day of month */ 229b39be1b3SPoul-Henning Kamp day = (dd & 0x1f) - 1; 230b39be1b3SPoul-Henning Kamp 231b39be1b3SPoul-Henning Kamp /* Full leap-year cycles */ 232b39be1b3SPoul-Henning Kamp day += LYC * ((dd >> 11) & 0x1f); 233b39be1b3SPoul-Henning Kamp 234b39be1b3SPoul-Henning Kamp /* Month offset from leap-year cycle */ 235b39be1b3SPoul-Henning Kamp day += daytab[(dd >> 5) & 0x3f]; 236b39be1b3SPoul-Henning Kamp 237*0fe60dc6SJosef 'Jeff' Sipek /* 2100 is not a leap year */ 238b39be1b3SPoul-Henning Kamp if (day >= ((2100 - 1980) / 4 * LYC + FEB)) 239b39be1b3SPoul-Henning Kamp day--; 240b39be1b3SPoul-Henning Kamp 241b39be1b3SPoul-Henning Kamp /* Align with time_t epoch */ 242b39be1b3SPoul-Henning Kamp day += T1980; 243b39be1b3SPoul-Henning Kamp 244*0fe60dc6SJosef 'Jeff' Sipek tsp->tv_sec += (time_t) DAY * day; 2457ea93e91SPoul-Henning Kamp if (!utc) 2467ea93e91SPoul-Henning Kamp tsp->tv_sec += utc_offset(); 247b39be1b3SPoul-Henning Kamp } 248b39be1b3SPoul-Henning Kamp 249b39be1b3SPoul-Henning Kamp #ifdef TEST_DRIVER 250b39be1b3SPoul-Henning Kamp 251b39be1b3SPoul-Henning Kamp #include <stdio.h> 252b39be1b3SPoul-Henning Kamp #include <unistd.h> 253b39be1b3SPoul-Henning Kamp #include <stdlib.h> 254b39be1b3SPoul-Henning Kamp 255b39be1b3SPoul-Henning Kamp int 256b39be1b3SPoul-Henning Kamp main(int argc __unused, char **argv __unused) 257b39be1b3SPoul-Henning Kamp { 258b39be1b3SPoul-Henning Kamp int i; 259b39be1b3SPoul-Henning Kamp struct timespec ts; 260b39be1b3SPoul-Henning Kamp struct tm tm; 261b39be1b3SPoul-Henning Kamp double a; 26260ae52f7SEd Schouten uint16_t d, t; 26360ae52f7SEd Schouten uint8_t p; 264b39be1b3SPoul-Henning Kamp char buf[100]; 265b39be1b3SPoul-Henning Kamp 266b39be1b3SPoul-Henning Kamp for (i = 0; i < 10000; i++) { 267b39be1b3SPoul-Henning Kamp do { 2689d1396c3SJosef 'Jeff' Sipek /* 2699d1396c3SJosef 'Jeff' Sipek * 32-bits gets us to 2106-02-07 06:28:15, but we 2709d1396c3SJosef 'Jeff' Sipek * need to get to the end of 2107. So, we generate 2719d1396c3SJosef 'Jeff' Sipek * a 36-bit second count to get us way past 2106. 2729d1396c3SJosef 'Jeff' Sipek */ 2739d1396c3SJosef 'Jeff' Sipek ts.tv_sec = ((time_t) arc4random() << 4) ^ arc4random(); 2749d1396c3SJosef 'Jeff' Sipek } while ((ts.tv_sec < T1980 * 86400) || (ts.tv_sec >= T2108 * 86400ull)); 2759d1396c3SJosef 'Jeff' Sipek 276b39be1b3SPoul-Henning Kamp ts.tv_nsec = random() % 1000000000; 277b39be1b3SPoul-Henning Kamp 2789d1396c3SJosef 'Jeff' Sipek printf("%10jd.%03ld -- ", (intmax_t) ts.tv_sec, ts.tv_nsec / 1000000); 279b39be1b3SPoul-Henning Kamp 280b39be1b3SPoul-Henning Kamp gmtime_r(&ts.tv_sec, &tm); 281b39be1b3SPoul-Henning Kamp strftime(buf, sizeof buf, "%Y %m %d %H %M %S", &tm); 282b39be1b3SPoul-Henning Kamp printf("%s -- ", buf); 283b39be1b3SPoul-Henning Kamp 284b39be1b3SPoul-Henning Kamp a = ts.tv_sec + ts.tv_nsec * 1e-9; 285b39be1b3SPoul-Henning Kamp d = t = p = 0; 2867b8b613dSJosef 'Jeff' Sipek timespec2fattime(&ts, 1, &d, &t, &p); 287b39be1b3SPoul-Henning Kamp printf("%04x %04x %02x -- ", d, t, p); 288b39be1b3SPoul-Henning Kamp printf("%3d %02d %02d %02d %02d %02d -- ", 289b39be1b3SPoul-Henning Kamp ((d >> 9) & 0x7f) + 1980, 290b39be1b3SPoul-Henning Kamp (d >> 5) & 0x0f, 291b39be1b3SPoul-Henning Kamp (d >> 0) & 0x1f, 292b39be1b3SPoul-Henning Kamp (t >> 11) & 0x1f, 293b39be1b3SPoul-Henning Kamp (t >> 5) & 0x3f, 294b39be1b3SPoul-Henning Kamp ((t >> 0) & 0x1f) * 2); 295b39be1b3SPoul-Henning Kamp 296b39be1b3SPoul-Henning Kamp ts.tv_sec = ts.tv_nsec = 0; 2977b8b613dSJosef 'Jeff' Sipek fattime2timespec(d, t, p, 1, &ts); 2989d1396c3SJosef 'Jeff' Sipek printf("%10jd.%03ld == ", (intmax_t) ts.tv_sec, ts.tv_nsec / 1000000); 299b39be1b3SPoul-Henning Kamp gmtime_r(&ts.tv_sec, &tm); 300b39be1b3SPoul-Henning Kamp strftime(buf, sizeof buf, "%Y %m %d %H %M %S", &tm); 301b39be1b3SPoul-Henning Kamp printf("%s -- ", buf); 302b39be1b3SPoul-Henning Kamp a -= ts.tv_sec + ts.tv_nsec * 1e-9; 303b39be1b3SPoul-Henning Kamp printf("%.3f", a); 304b39be1b3SPoul-Henning Kamp printf("\n"); 305b39be1b3SPoul-Henning Kamp } 306b39be1b3SPoul-Henning Kamp return (0); 307b39be1b3SPoul-Henning Kamp } 308b39be1b3SPoul-Henning Kamp 309b39be1b3SPoul-Henning Kamp #endif /* TEST_DRIVER */ 310