]> git.sven.stormbind.net Git - sven/fuse-exfat.git/blobdiff - libexfat/time.c
releasing package fuse-exfat version 1.4.0-2
[sven/fuse-exfat.git] / libexfat / time.c
index 890930eacbcdca19faef16fca8667458db4940b4..3ab2a1561b8a70ab5e93954e2ad95b3989273ab7 100644 (file)
@@ -2,11 +2,12 @@
        time.c (03.02.12)
        exFAT file system implementation library.
 
        time.c (03.02.12)
        exFAT file system implementation library.
 
-       Copyright (C) 2010-2012  Andrew Nayenko
+       Free exFAT implementation.
+       Copyright (C) 2010-2023  Andrew Nayenko
 
 
-       This program is free software: you can redistribute it and/or modify
+       This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        it under the terms of the GNU General Public License as published by
-       the Free Software Foundation, either version 3 of the License, or
+       the Free Software Foundation, either version 2 of the License, or
        (at your option) any later version.
 
        This program is distributed in the hope that it will be useful,
        (at your option) any later version.
 
        This program is distributed in the hope that it will be useful,
@@ -14,8 +15,9 @@
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
 
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
 
-       You should have received a copy of the GNU General Public License
-       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       You should have received a copy of the GNU General Public License along
+       with this program; if not, write to the Free Software Foundation, Inc.,
+       51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
 #include "exfat.h"
 */
 
 #include "exfat.h"
@@ -51,7 +53,8 @@ static const time_t days_in_year[] =
        0,   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
 };
 
        0,   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
 };
 
-time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec)
+time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec,
+               uint8_t tzoffset)
 {
        time_t unix_time = EPOCH_DIFF_SEC;
        uint16_t ndate = le16_to_cpu(date);
 {
        time_t unix_time = EPOCH_DIFF_SEC;
        uint16_t ndate = le16_to_cpu(date);
@@ -98,13 +101,18 @@ time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec)
        unix_time += centisec / 100;
 
        /* exFAT stores timestamps in local time, so we correct it to UTC */
        unix_time += centisec / 100;
 
        /* exFAT stores timestamps in local time, so we correct it to UTC */
-       unix_time += exfat_timezone;
+       if (tzoffset & 0x80)
+               /* lower 7 bits are signed timezone offset in 15 minute increments */
+               unix_time -= (int8_t)(tzoffset << 1) * 15 * 60 / 2;
+       else
+               /* timezone offset not present, assume our local timezone */
+               unix_time += exfat_timezone;
 
        return unix_time;
 }
 
 void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
 
        return unix_time;
 }
 
 void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
-               uint8_t* centisec)
+               uint8_t* centisec, uint8_t* tzoffset)
 {
        time_t shift = EPOCH_DIFF_SEC + exfat_timezone;
        uint16_t day, month, year;
 {
        time_t shift = EPOCH_DIFF_SEC + exfat_timezone;
        uint16_t day, month, year;
@@ -144,13 +152,22 @@ void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
        *time = cpu_to_le16(twosec | (min << 5) | (hour << 11));
        if (centisec)
                *centisec = (unix_time % 2) * 100;
        *time = cpu_to_le16(twosec | (min << 5) | (hour << 11));
        if (centisec)
                *centisec = (unix_time % 2) * 100;
+
+       /* record our local timezone offset in exFAT (15 minute increment) format */
+       *tzoffset = (uint8_t)(-exfat_timezone / 60 / 15) | 0x80;
 }
 
 void exfat_tzset(void)
 {
        time_t now;
 }
 
 void exfat_tzset(void)
 {
        time_t now;
+       struct tm* utc;
 
        tzset();
        now = time(NULL);
 
        tzset();
        now = time(NULL);
-       exfat_timezone = mktime(gmtime(&now)) - now;
+       utc = gmtime(&now);
+       /* gmtime() always sets tm_isdst to 0 because daylight savings never
+          affect UTC. Setting tm_isdst to -1 makes mktime() to determine whether
+          summer time is in effect. */
+       utc->tm_isdst = -1;
+       exfat_timezone = mktime(utc) - now;
 }
 }