diff options
Diffstat (limited to 'fs/fat/misc.c')
-rw-r--r-- | fs/fat/misc.c | 57 |
1 files changed, 15 insertions, 42 deletions
diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 0f55f5cb732f..d3da05f26465 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
12 | #include <linux/time.h> | ||
12 | #include "fat.h" | 13 | #include "fat.h" |
13 | 14 | ||
14 | /* | 15 | /* |
@@ -157,10 +158,6 @@ extern struct timezone sys_tz; | |||
157 | #define SECS_PER_MIN 60 | 158 | #define SECS_PER_MIN 60 |
158 | #define SECS_PER_HOUR (60 * 60) | 159 | #define SECS_PER_HOUR (60 * 60) |
159 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) | 160 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) |
160 | #define UNIX_SECS_1980 315532800L | ||
161 | #if BITS_PER_LONG == 64 | ||
162 | #define UNIX_SECS_2108 4354819200L | ||
163 | #endif | ||
164 | /* days between 1.1.70 and 1.1.80 (2 leap days) */ | 161 | /* days between 1.1.70 and 1.1.80 (2 leap days) */ |
165 | #define DAYS_DELTA (365 * 10 + 2) | 162 | #define DAYS_DELTA (365 * 10 + 2) |
166 | /* 120 (2100 - 1980) isn't leap year */ | 163 | /* 120 (2100 - 1980) isn't leap year */ |
@@ -213,58 +210,35 @@ void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, | |||
213 | void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, | 210 | void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, |
214 | __le16 *time, __le16 *date, u8 *time_cs) | 211 | __le16 *time, __le16 *date, u8 *time_cs) |
215 | { | 212 | { |
216 | time_t second = ts->tv_sec; | 213 | struct tm tm; |
217 | time_t day, leap_day, month, year; | 214 | time_to_tm(ts->tv_sec, sbi->options.tz_utc ? 0 : |
215 | -sys_tz.tz_minuteswest * 60, &tm); | ||
218 | 216 | ||
219 | if (!sbi->options.tz_utc) | 217 | /* FAT can only support year between 1980 to 2107 */ |
220 | second -= sys_tz.tz_minuteswest * SECS_PER_MIN; | 218 | if (tm.tm_year < 1980 - 1900) { |
221 | |||
222 | /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ | ||
223 | if (second < UNIX_SECS_1980) { | ||
224 | *time = 0; | 219 | *time = 0; |
225 | *date = cpu_to_le16((0 << 9) | (1 << 5) | 1); | 220 | *date = cpu_to_le16((0 << 9) | (1 << 5) | 1); |
226 | if (time_cs) | 221 | if (time_cs) |
227 | *time_cs = 0; | 222 | *time_cs = 0; |
228 | return; | 223 | return; |
229 | } | 224 | } |
230 | #if BITS_PER_LONG == 64 | 225 | if (tm.tm_year > 2107 - 1900) { |
231 | if (second >= UNIX_SECS_2108) { | ||
232 | *time = cpu_to_le16((23 << 11) | (59 << 5) | 29); | 226 | *time = cpu_to_le16((23 << 11) | (59 << 5) | 29); |
233 | *date = cpu_to_le16((127 << 9) | (12 << 5) | 31); | 227 | *date = cpu_to_le16((127 << 9) | (12 << 5) | 31); |
234 | if (time_cs) | 228 | if (time_cs) |
235 | *time_cs = 199; | 229 | *time_cs = 199; |
236 | return; | 230 | return; |
237 | } | 231 | } |
238 | #endif | ||
239 | 232 | ||
240 | day = second / SECS_PER_DAY - DAYS_DELTA; | 233 | /* from 1900 -> from 1980 */ |
241 | year = day / 365; | 234 | tm.tm_year -= 80; |
242 | leap_day = (year + 3) / 4; | 235 | /* 0~11 -> 1~12 */ |
243 | if (year > YEAR_2100) /* 2100 isn't leap year */ | 236 | tm.tm_mon++; |
244 | leap_day--; | 237 | /* 0~59 -> 0~29(2sec counts) */ |
245 | if (year * 365 + leap_day > day) | 238 | tm.tm_sec >>= 1; |
246 | year--; | ||
247 | leap_day = (year + 3) / 4; | ||
248 | if (year > YEAR_2100) /* 2100 isn't leap year */ | ||
249 | leap_day--; | ||
250 | day -= year * 365 + leap_day; | ||
251 | |||
252 | if (IS_LEAP_YEAR(year) && day == days_in_year[3]) { | ||
253 | month = 2; | ||
254 | } else { | ||
255 | if (IS_LEAP_YEAR(year) && day > days_in_year[3]) | ||
256 | day--; | ||
257 | for (month = 1; month < 12; month++) { | ||
258 | if (days_in_year[month + 1] > day) | ||
259 | break; | ||
260 | } | ||
261 | } | ||
262 | day -= days_in_year[month]; | ||
263 | 239 | ||
264 | *time = cpu_to_le16(((second / SECS_PER_HOUR) % 24) << 11 | 240 | *time = cpu_to_le16(tm.tm_hour << 11 | tm.tm_min << 5 | tm.tm_sec); |
265 | | ((second / SECS_PER_MIN) % 60) << 5 | 241 | *date = cpu_to_le16(tm.tm_year << 9 | tm.tm_mon << 5 | tm.tm_mday); |
266 | | (second % SECS_PER_MIN) >> 1); | ||
267 | *date = cpu_to_le16((year << 9) | (month << 5) | (day + 1)); | ||
268 | if (time_cs) | 242 | if (time_cs) |
269 | *time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000; | 243 | *time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000; |
270 | } | 244 | } |
@@ -285,4 +259,3 @@ int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) | |||
285 | } | 259 | } |
286 | return err; | 260 | return err; |
287 | } | 261 | } |
288 | |||