| 1 | |
| 2 | |
| 3 | This file is part of the GNU C Library.
|
| 4 | Contributed by Paul Eggert ([email protected]).
|
| 5 |
|
| 6 | |
| 7 | * dgb 10/02/98: ripped this from glibc source to help convert timestamps
|
| 8 | * to unix time
|
| 9 | * 10/04/98: added new table-based lookup after seeing how ugly
|
| 10 | * the gnu code is
|
| 11 | * blf 09/27/99: ripped out all the old code and inserted new table from
|
| 12 | * John Brockmeyer (without leap second corrections)
|
| 13 | * rewrote udf_stamp_to_time and fixed timezone accounting in
|
| 14 | * udf_time_to_stamp.
|
| 15 |
|
| 16 |
|
| 17 | |
| 18 | * We don't take into account leap seconds. This may be correct or incorrect.
|
| 19 | * For more NIST information (especially dealing with leap seconds), see:
|
| 20 | * http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm
|
| 21 |
|
| 22 |
|
| 23 | #include "udfdecl.h"
|
| 24 |
|
| 25 | #include <linux/types.h>
|
| 26 | #include <linux/kernel.h>
|
| 27 | #include <linux/time.h>
|
| 28 |
|
| 29 | void
|
| 30 | udf_disk_stamp_to_time(struct timespec64 *dest, struct timestamp src)
|
| 31 | {
|
| 32 | u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone);
|
| 33 | u16 year = le16_to_cpu(src.year);
|
| 34 | uint8_t type = typeAndTimezone >> 12;
|
| 35 | int16_t offset;
|
| 36 |
|
| 37 | if (type == 1) {
|
| 38 | offset = typeAndTimezone << 4;
|
| 39 |
|
| 40 | offset = (offset >> 4);
|
| 41 | if (offset == -2047)
|
| 42 | offset = 0;
|
| 43 | } else
|
| 44 | offset = 0;
|
| 45 |
|
| 46 | dest->tv_sec = mktime64(year, src.month, src.day, src.hour, src.minute,
|
| 47 | src.second);
|
| 48 | dest->tv_sec -= offset * 60;
|
| 49 |
|
| 50 | |
| 51 | * Sanitize nanosecond field since reportedly some filesystems are
|
| 52 | * recorded with bogus sub-second values.
|
| 53 |
|
| 54 | if (src.centiseconds < 100 && src.hundredsOfMicroseconds < 100 &&
|
| 55 | src.microseconds < 100) {
|
| 56 | dest->tv_nsec = 1000 * (src.centiseconds * 10000 +
|
| 57 | src.hundredsOfMicroseconds * 100 + src.microseconds);
|
| 58 | } else {
|
| 59 | dest->tv_nsec = 0;
|
| 60 | }
|
| 61 | }
|
| 62 |
|
| 63 | void
|
| 64 | udf_time_to_disk_stamp(struct timestamp *dest, struct timespec64 ts)
|
| 65 | {
|
| 66 | time64_t seconds;
|
| 67 | int16_t offset;
|
| 68 | struct tm tm;
|
| 69 |
|
| 70 | offset = -sys_tz.tz_minuteswest;
|
| 71 |
|
| 72 | dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF));
|
| 73 |
|
| 74 | seconds = ts.tv_sec + offset * 60;
|
| 75 | time64_to_tm(seconds, 0, &tm);
|
| 76 | dest->year = cpu_to_le16(tm.tm_year + 1900);
|
| 77 | dest->month = tm.tm_mon + 1;
|
| 78 | dest->day = tm.tm_mday;
|
| 79 | dest->hour = tm.tm_hour;
|
| 80 | dest->minute = tm.tm_min;
|
| 81 | dest->second = tm.tm_sec;
|
| 82 | dest->centiseconds = ts.tv_nsec / 10000000;
|
| 83 | dest->hundredsOfMicroseconds = (ts.tv_nsec / 1000 -
|
| 84 | dest->centiseconds * 10000) / 100;
|
| 85 | dest->microseconds = (ts.tv_nsec / 1000 - dest->centiseconds * 10000 -
|
| 86 | dest->hundredsOfMicroseconds * 100);
|
| 87 | }
|
| 88 |
|
| 89 |
|