From 607fbed2534cb80063395936384f4aef293812fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 14 Aug 2018 20:57:27 +0200 Subject: [PATCH 72/86] fsck.fat: Fix Year 2038 Bug Do not use time_t type and strftime() function which are affected by the Year 2038 Bug. Instead parse date/time directly from DOS format which avoids conversion from DOS to UNIX + conversion from UNIX to string. --- src/check.c | 55 +++++++++++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/src/check.c b/src/check.c index 13a5fd6..76e9721 100644 --- a/src/check.c +++ b/src/check.c @@ -108,44 +108,31 @@ static char *path_name(DOS_FILE * file) return path; } -static const int day_n[] = - { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0 }; -/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ - -/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ - -static time_t date_dos2unix(unsigned short time, unsigned short date) -{ - int month, year; - time_t secs; - - month = ((date >> 5) & 15) - 1; - if (month < 0) { - /* make sure that nothing bad happens if the month bits were zero */ - month = 0; - } - year = date >> 9; - secs = - (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + - 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653); - /* days since 1.1.70 plus 80's leap day */ - return secs; -} +static const char *month_str[] = + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char *file_stat(DOS_FILE * file) { static char temp[100]; - struct tm *tm; - char tmp[40]; - time_t date; - - date = - date_dos2unix(le16toh(file->dir_ent.time), le16toh(file->dir_ent.date)); - tm = localtime(&date); - if (!strftime(tmp, 40, "%H:%M:%S %b %d %Y", tm)) - strcpy(tmp, ""); - sprintf(temp, " Size %u bytes, date %s", le32toh(file->dir_ent.size), tmp); + unsigned int hours, minutes, secs, day, month, year; + unsigned short time, date; + + time = le16toh(file->dir_ent.time); + date = le16toh(file->dir_ent.date); + year = 1980 + (date >> 9); + month = ((date >> 5) & 15); + if (month < 1) month = 1; + else if (month > 12) month = 12; + day = (date & 31); + if (day < 1) day = 1; + hours = (time >> 11); + if (hours > 23) hours = 23; + minutes = ((time >> 5) & 63); + if (minutes > 59) minutes = 59; + secs = (time & 31) * 2; + if (secs > 59) secs = 59; + sprintf(temp, " Size %u bytes, date %02u:%02u:%02u %s %02u %4u", + le32toh(file->dir_ent.size), hours, minutes, secs, month_str[month-1], day, year); return temp; } -- 1.8.3.1