OSDN Git Service

Improve timestamps resolution from 2 sec to 1 sec.
authorrelan <relan@users.noreply.github.com>
Sun, 5 Sep 2010 09:10:18 +0000 (09:10 +0000)
committerrelan <relan@users.noreply.github.com>
Mon, 24 Aug 2015 05:26:12 +0000 (08:26 +0300)
libexfat/exfat.h
libexfat/node.c
libexfat/utils.c

index 352ec48..0f9d3e4 100644 (file)
@@ -131,8 +131,9 @@ uint32_t exfat_count_free_clusters(struct exfat* ef);
 
 void exfat_stat(const struct exfat* ef, const struct exfat_node* node,
                struct stat* stbuf);
-time_t exfat_exfat2unix(le16_t date, le16_t time);
-void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time);
+time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec);
+void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
+               uint8_t* centisec);
 void exfat_get_name(const struct exfat_node* node, char* buffer, size_t n);
 uint16_t exfat_start_checksum(const struct exfat_entry_meta1* entry);
 uint16_t exfat_add_checksum(const void* entry, uint16_t sum);
index 28de91d..19bee9c 100644 (file)
@@ -136,8 +136,10 @@ static void init_node_meta1(struct exfat_node* node,
                const struct exfat_entry_meta1* meta1)
 {
        node->flags = le16_to_cpu(meta1->attrib);
-       node->mtime = exfat_exfat2unix(meta1->mdate, meta1->mtime);
-       node->atime = exfat_exfat2unix(meta1->adate, meta1->atime);
+       node->mtime = exfat_exfat2unix(meta1->mdate, meta1->mtime,
+                       meta1->mtime_cs);
+       /* there is no centiseconds field for atime */
+       node->atime = exfat_exfat2unix(meta1->adate, meta1->atime, 0);
 }
 
 static void init_node_meta2(struct exfat_node* node,
@@ -474,8 +476,8 @@ void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
        if (meta1.type != EXFAT_ENTRY_FILE)
                exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
        meta1.attrib = cpu_to_le16(node->flags);
-       exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime);
-       exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime);
+       exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime, &meta1.mtime_cs);
+       exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime, NULL);
 
        exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
        if (meta2.type != EXFAT_ENTRY_FILE_INFO)
@@ -714,7 +716,8 @@ static int write_entry(struct exfat* ef, struct exfat_node* dir,
        meta1.type = EXFAT_ENTRY_FILE;
        meta1.continuations = 1 + name_entries;
        meta1.attrib = cpu_to_le16(attrib);
-       exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime);
+       exfat_unix2exfat(time(NULL), &meta1.crdate, &meta1.crtime,
+                       &meta1.crtime_cs);
        meta1.adate = meta1.mdate = meta1.crdate;
        meta1.atime = meta1.mtime = meta1.crtime;
        /* crtime_cs and mtime_cs contain addition to the time in centiseconds;
index dccb0be..53d4e86 100644 (file)
@@ -69,7 +69,7 @@ static const time_t days_in_year[] =
        0,   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
 };
 
-time_t exfat_exfat2unix(le16_t date, le16_t time)
+time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec)
 {
        time_t unix_time = EPOCH_DIFF_SEC;
        uint16_t ndate = le16_to_cpu(date);
@@ -95,6 +95,11 @@ time_t exfat_exfat2unix(le16_t date, le16_t time)
                                hour, min, twosec * 2);
                return 0;
        }
+       if (centisec > 199)
+       {
+               exfat_error("bad centiseconds count %hhu", centisec);
+               return 0;
+       }
 
        /* every 4th year between 1904 and 2096 is leap */
        unix_time += year * SEC_IN_YEAR + LEAP_YEARS(year) * SEC_IN_DAY;
@@ -108,6 +113,7 @@ time_t exfat_exfat2unix(le16_t date, le16_t time)
        unix_time += min * SEC_IN_MIN;
        /* exFAT represents time with 2 sec granularity */
        unix_time += twosec * 2;
+       unix_time += centisec / 100;
 
        /* exFAT stores timestamps in local time, so we correct it to UTC */
        unix_time += timezone;
@@ -115,7 +121,8 @@ time_t exfat_exfat2unix(le16_t date, le16_t time)
        return unix_time;
 }
 
-void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time)
+void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
+               uint8_t* centisec)
 {
        time_t shift = EPOCH_DIFF_SEC + timezone;
        uint16_t day, month, year;
@@ -153,6 +160,8 @@ void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time)
 
        *date = cpu_to_le16(day | (month << 5) | (year << 9));
        *time = cpu_to_le16(twosec | (min << 5) | (hour << 11));
+       if (centisec)
+               *centisec = (unix_time % 2) * 100;
 }
 
 void exfat_get_name(const struct exfat_node* node, char* buffer, size_t n)