Coverage Report

Created: 2026-01-20 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsfat/libfsfat/libfsfat_date_time.c
Line
Count
Source
1
/*
2
 * Date time functions
3
 *
4
 * Copyright (C) 2021-2025, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <types.h>
24
25
#include "libfsfat_libcerror.h"
26
27
/* Determines the FAT timestamp of FAT date and time values
28
 * The timestamp is an unsigned 64-bit integer containing the 10 milli seconds intervals since January 1, 1980
29
 * Returns 1 if successful or -1 on error
30
 */
31
int libfsfat_date_time_get_timestamp(
32
     uint16_t fat_date,
33
     uint16_t fat_time,
34
     uint16_t fat_time_fraction,
35
     uint16_t fat_time_utc_offset,
36
     uint64_t *fat_timestamp,
37
     libcerror_error_t **error )
38
0
{
39
0
  static char *function       = "libfsfat_date_time_get_timestamp";
40
0
  uint64_t safe_fat_timestamp = 0;
41
0
  uint16_t year               = 0;
42
0
  uint8_t day_of_month        = 0;
43
0
  uint8_t hours               = 0;
44
0
  uint8_t month               = 0;
45
0
  uint8_t minutes             = 0;
46
0
  uint8_t seconds             = 0;
47
48
0
  if( fat_timestamp == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid FAT timestamp.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
  /* The year value is stored in bits 9 - 15 of the date (7 bits)
60
   * A year value of 0 represents 1980
61
   */
62
0
  year = (uint16_t) ( 1980 + ( ( fat_date >> 9 ) & 0x7f ) );
63
64
  /* The month value is stored in bits 5 - 8 of the date (4 bits)
65
   * A month value of 1 represents January
66
   */
67
0
  month = (uint8_t) ( ( fat_date >> 5 ) & 0x0f );
68
69
  /* The day value is stored in bits 0 - 4 of the date (5 bits)
70
   */
71
0
  day_of_month = (uint8_t) ( fat_date & 0x1f );
72
73
  /* The hours value is stored in bits 11 - 15 of the time (5 bits)
74
   */
75
0
  hours = (uint8_t) ( ( fat_time >> 11 ) & 0x1f );
76
77
  /* The minutes value is stored in bits 5 - 10 of the time (6 bits)
78
   */
79
0
  minutes = (uint8_t) ( ( fat_time >> 5 ) & 0x3f );
80
81
  /* The seconds value is stored in bits 0 - 4 of the time (5 bits)
82
   * The seconds are stored as 2 second intervals
83
   */
84
0
  seconds = (uint8_t) ( fat_time & 0x1f ) * 2;
85
86
0
  safe_fat_timestamp = day_of_month;
87
88
0
  while( month > 0 )
89
0
  {
90
    /* February (2)
91
     */
92
0
    if( month == 2 )
93
0
    {
94
0
      if( ( ( ( year % 4 ) == 0 )
95
0
        &&  ( ( year % 100 ) != 0 ) )
96
0
       || ( ( year % 400 ) == 0 ) )
97
0
      {
98
0
        safe_fat_timestamp += 29;
99
0
      }
100
0
      else
101
0
      {
102
0
        safe_fat_timestamp += 28;
103
0
      }
104
0
    }
105
    /* April (4), June (6), September (9), November (11)
106
     */
107
0
    else if( ( month == 4 )
108
0
          || ( month == 6 )
109
0
          || ( month == 9 )
110
0
          || ( month == 11 ) )
111
0
    {
112
0
      safe_fat_timestamp += 30;
113
0
    }
114
    /* January (1), March (3), May (5), July (7), August (8), October (10), December (12)
115
     */
116
0
    else if( ( month == 1 )
117
0
          || ( month == 3 )
118
0
          || ( month == 5 )
119
0
          || ( month == 7 )
120
0
          || ( month == 8 )
121
0
          || ( month == 10 )
122
0
          || ( month == 12 ) )
123
0
    {
124
0
      safe_fat_timestamp += 31;
125
0
    }
126
0
    month--;
127
0
  }
128
0
  while( year > 1980 )
129
0
  {
130
0
    if( ( ( ( year % 4 ) == 0 )
131
0
      &&  ( ( year % 100 ) != 0 ) )
132
0
     || ( ( year % 400 ) == 0 ) )
133
0
    {
134
0
      safe_fat_timestamp += 366;
135
0
    }
136
0
    else
137
0
    {
138
0
      safe_fat_timestamp += 365;
139
0
    }
140
0
    year--;
141
0
  }
142
0
  safe_fat_timestamp *= 24;
143
0
  safe_fat_timestamp += hours;
144
0
  safe_fat_timestamp *= 60;
145
0
  safe_fat_timestamp += minutes;
146
147
0
  if( ( fat_time_utc_offset & 0x80 ) != 0 )
148
0
  {
149
0
    fat_time_utc_offset &= 0x7f;
150
151
0
    if( fat_time_utc_offset < 0x40 )
152
0
    {
153
0
      safe_fat_timestamp += (uint64_t) fat_time_utc_offset * 15;
154
0
    }
155
0
    else
156
0
    {
157
0
      safe_fat_timestamp -= (uint64_t) ( 0x80 - fat_time_utc_offset ) * 15;
158
0
    }
159
0
  }
160
0
  safe_fat_timestamp *= 60;
161
0
  safe_fat_timestamp += seconds;
162
0
  safe_fat_timestamp *= 100;
163
0
  safe_fat_timestamp += fat_time_fraction;
164
165
0
  *fat_timestamp = safe_fat_timestamp;
166
167
0
  return( 1 );
168
0
}
169