1aac2fa20SBagas Sanjaya // SPDX-License-Identifier: LGPL-2.0+ 21da177e4SLinus Torvalds /* Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. 31da177e4SLinus Torvalds This file is part of the GNU C Library. 4aac2fa20SBagas Sanjaya Contributed by Paul Eggert (eggert@twinsun.com). */ 51da177e4SLinus Torvalds 61da177e4SLinus Torvalds /* 74b11111aSMarcin Slusarz * dgb 10/02/98: ripped this from glibc source to help convert timestamps 84b11111aSMarcin Slusarz * to unix time 94b11111aSMarcin Slusarz * 10/04/98: added new table-based lookup after seeing how ugly 104b11111aSMarcin Slusarz * the gnu code is 111da177e4SLinus Torvalds * blf 09/27/99: ripped out all the old code and inserted new table from 121da177e4SLinus Torvalds * John Brockmeyer (without leap second corrections) 131da177e4SLinus Torvalds * rewrote udf_stamp_to_time and fixed timezone accounting in 1428de7948SCyrill Gorcunov * udf_time_to_stamp. 151da177e4SLinus Torvalds */ 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds /* 181da177e4SLinus Torvalds * We don't take into account leap seconds. This may be correct or incorrect. 191da177e4SLinus Torvalds * For more NIST information (especially dealing with leap seconds), see: 201da177e4SLinus Torvalds * http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm 211da177e4SLinus Torvalds */ 221da177e4SLinus Torvalds 2378ace70cSJoe Perches #include "udfdecl.h" 2478ace70cSJoe Perches 251da177e4SLinus Torvalds #include <linux/types.h> 261da177e4SLinus Torvalds #include <linux/kernel.h> 273c399fa4SJan Kara #include <linux/time.h> 281da177e4SLinus Torvalds 290220eddaSDeepa Dinamani void 30c3b9cecdSArnd Bergmann udf_disk_stamp_to_time(struct timespec64 *dest, struct timestamp src) 311da177e4SLinus Torvalds { 3256774805SMarcin Slusarz u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone); 3356774805SMarcin Slusarz u16 year = le16_to_cpu(src.year); 3456774805SMarcin Slusarz uint8_t type = typeAndTimezone >> 12; 351da177e4SLinus Torvalds int16_t offset; 361da177e4SLinus Torvalds 37cb00ea35SCyrill Gorcunov if (type == 1) { 3856774805SMarcin Slusarz offset = typeAndTimezone << 4; 391da177e4SLinus Torvalds /* sign extent offset */ 401da177e4SLinus Torvalds offset = (offset >> 4); 411da177e4SLinus Torvalds if (offset == -2047) /* unspecified offset */ 421da177e4SLinus Torvalds offset = 0; 43cbf5676aSmarcin.slusarz@gmail.com } else 441da177e4SLinus Torvalds offset = 0; 451da177e4SLinus Torvalds 46fd3cfad3SJan Kara dest->tv_sec = mktime64(year, src.month, src.day, src.hour, src.minute, 47fd3cfad3SJan Kara src.second); 48cbf5676aSmarcin.slusarz@gmail.com dest->tv_sec -= offset * 60; 49*3b84adf4SRoman Smirnov 50d5bd8213SJan Kara /* 51d5bd8213SJan Kara * Sanitize nanosecond field since reportedly some filesystems are 52d5bd8213SJan Kara * recorded with bogus sub-second values. 53d5bd8213SJan Kara */ 54*3b84adf4SRoman Smirnov if (src.centiseconds < 100 && src.hundredsOfMicroseconds < 100 && 55*3b84adf4SRoman Smirnov src.microseconds < 100) { 56*3b84adf4SRoman Smirnov dest->tv_nsec = 1000 * (src.centiseconds * 10000 + 57*3b84adf4SRoman Smirnov src.hundredsOfMicroseconds * 100 + src.microseconds); 58*3b84adf4SRoman Smirnov } else { 59*3b84adf4SRoman Smirnov dest->tv_nsec = 0; 60*3b84adf4SRoman Smirnov } 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds 630220eddaSDeepa Dinamani void 64c3b9cecdSArnd Bergmann udf_time_to_disk_stamp(struct timestamp *dest, struct timespec64 ts) 651da177e4SLinus Torvalds { 66c3b9cecdSArnd Bergmann time64_t seconds; 671da177e4SLinus Torvalds int16_t offset; 683c399fa4SJan Kara struct tm tm; 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds offset = -sys_tz.tz_minuteswest; 711da177e4SLinus Torvalds 7256774805SMarcin Slusarz dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF)); 731da177e4SLinus Torvalds 743c399fa4SJan Kara seconds = ts.tv_sec + offset * 60; 753c399fa4SJan Kara time64_to_tm(seconds, 0, &tm); 763c399fa4SJan Kara dest->year = cpu_to_le16(tm.tm_year + 1900); 773c399fa4SJan Kara dest->month = tm.tm_mon + 1; 783c399fa4SJan Kara dest->day = tm.tm_mday; 793c399fa4SJan Kara dest->hour = tm.tm_hour; 803c399fa4SJan Kara dest->minute = tm.tm_min; 813c399fa4SJan Kara dest->second = tm.tm_sec; 821da177e4SLinus Torvalds dest->centiseconds = ts.tv_nsec / 10000000; 834b11111aSMarcin Slusarz dest->hundredsOfMicroseconds = (ts.tv_nsec / 1000 - 844b11111aSMarcin Slusarz dest->centiseconds * 10000) / 100; 8528de7948SCyrill Gorcunov dest->microseconds = (ts.tv_nsec / 1000 - dest->centiseconds * 10000 - 861da177e4SLinus Torvalds dest->hundredsOfMicroseconds * 100); 871da177e4SLinus Torvalds } 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds /* EOF */ 90