]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
fs: Use 64-bit type for filesystem timestamp
authorCarlos Maiolino <cmaiolino@redhat.com>
Mon, 24 May 2021 17:40:05 +0000 (19:40 +0200)
committerDaniel Kiper <daniel.kiper@oracle.com>
Tue, 1 Jun 2021 15:19:13 +0000 (17:19 +0200)
Some filesystems nowadays use 64-bit types for timestamps. So, update
grub_dirhook_info struct to use an grub_int64_t type to store mtime.
This also updates the grub_unixtime2datetime() function to receive
a 64-bit timestamp argument and do 64-bit-safe divisions.

All the remaining conversion from 32-bit to 64-bit should be safe, as
32-bit to 64-bit attributions will be implicitly casted. The most
critical part in the 32-bit to 64-bit conversion is in the function
grub_unixtime2datetime() where it needs to deal with the 64-bit type.
So, for that, the grub_divmod64() helper has been used.

These changes enables the GRUB to support dates beyond y2038.

Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
16 files changed:
grub-core/fs/affs.c
grub-core/fs/ext2.c
grub-core/fs/fat.c
grub-core/fs/hfs.c
grub-core/fs/hfsplus.c
grub-core/fs/iso9660.c
grub-core/fs/nilfs2.c
grub-core/fs/squash4.c
grub-core/fs/ufs.c
grub-core/fs/zfs/zfs.c
grub-core/lib/datetime.c
grub-core/net/bootp.c
grub-core/normal/misc.c
grub-core/tests/sleep_test.c
include/grub/datetime.h
include/grub/fs.h

index 230e26af0f8d95520a0ab020274c5d9eda9e595b..cafcd0fba916d4df59541967af55dc85322f3f10 100644 (file)
@@ -641,7 +641,7 @@ grub_affs_label (grub_device_t device, char **label)
 }
 
 static grub_err_t
-grub_affs_mtime (grub_device_t device, grub_int32_t *t)
+grub_affs_mtime (grub_device_t device, grub_int64_t *t)
 {
   struct grub_affs_data *data;
   grub_disk_t disk = device->disk;
index 848bf939dba70e5117cdb80f55ca0aefa9da2e68..e7dd78e66358138bb1496bd3d036182787b6b49e 100644 (file)
@@ -1055,7 +1055,7 @@ grub_ext2_uuid (grub_device_t device, char **uuid)
 
 /* Get mtime.  */
 static grub_err_t
-grub_ext2_mtime (grub_device_t device, grub_int32_t *tm)
+grub_ext2_mtime (grub_device_t device, grub_int64_t *tm)
 {
   struct grub_ext2_data *data;
   grub_disk_t disk = device->disk;
index 7f775a17038b83d52482389c39a4a2f3f07db263..dd82e4ee35d0af9188dbbc92e947a7c663084483 100644 (file)
@@ -737,7 +737,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node,
  * https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification
  */
 static int
-grub_exfat_timestamp (grub_uint32_t field, grub_uint8_t msec, grub_int32_t *nix) {
+grub_exfat_timestamp (grub_uint32_t field, grub_uint8_t msec, grub_int64_t *nix) {
   struct grub_datetime datetime = {
     .year   = (field >> 25) + 1980,
     .month  = (field & 0x01E00000) >> 21,
@@ -891,7 +891,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node,
  * https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-107.pdf
  */
 static int
-grub_fat_timestamp (grub_uint16_t time, grub_uint16_t date, grub_int32_t *nix) {
+grub_fat_timestamp (grub_uint16_t time, grub_uint16_t date, grub_int64_t *nix) {
   struct grub_datetime datetime = {
     .year   = (date >> 9) + 1980,
     .month  = (date & 0x01E0) >> 5,
index 9a5b7bbe906586e56000f9902129775c65c8644a..f419965d154fcbab080165f7aab26c2e929a8856 100644 (file)
@@ -1374,7 +1374,7 @@ grub_hfs_label (grub_device_t device, char **label)
 }
 
 static grub_err_t
-grub_hfs_mtime (grub_device_t device, grub_int32_t *tm)
+grub_hfs_mtime (grub_device_t device, grub_int64_t *tm)
 {
   struct grub_hfs_data *data;
 
index 2a69055c7ec7b7e4836cfce18b9f69f47232dd6e..19c7b3367987ea890916893234fe13a9fceb9cdf 100644 (file)
@@ -1083,7 +1083,7 @@ grub_hfsplus_label (grub_device_t device, char **label)
 
 /* Get mtime.  */
 static grub_err_t
-grub_hfsplus_mtime (grub_device_t device, grub_int32_t *tm)
+grub_hfsplus_mtime (grub_device_t device, grub_int64_t *tm)
 {
   struct grub_hfsplus_data *data;
   grub_disk_t disk = device->disk;
index 5ec4433b8f87a53053b058fa0127a12b1fd5daa8..ac011950a64f095ba29b7c0e3780e148236a2717 100644 (file)
@@ -178,7 +178,7 @@ static grub_dl_t my_mod;
 \f
 
 static grub_err_t
-iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix)
+iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int64_t *nix)
 {
   struct grub_datetime datetime;
   
@@ -206,7 +206,7 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix)
 }
 
 static int
-iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix)
+iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int64_t *nix)
 {
   struct grub_datetime datetime;
 
@@ -1107,7 +1107,7 @@ grub_iso9660_uuid (grub_device_t device, char **uuid)
 
 /* Get writing time of filesystem. */
 static grub_err_t 
-grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf)
+grub_iso9660_mtime (grub_device_t device, grub_int64_t *timebuf)
 {
   struct grub_iso9660_data *data;
   grub_disk_t disk = device->disk;
index 9b76982b3b08de2c53fed017355062017541433f..3c248a910b420937a910e22c17e6b12e8144a362 100644 (file)
@@ -1186,7 +1186,7 @@ grub_nilfs2_uuid (grub_device_t device, char **uuid)
 
 /* Get mtime.  */
 static grub_err_t
-grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm)
+grub_nilfs2_mtime (grub_device_t device, grub_int64_t * tm)
 {
   struct grub_nilfs2_data *data;
   grub_disk_t disk = device->disk;
index a5f35c10e2f83efdff29bf5c9c4282fd1cbd17b1..6dd731e231ee6dc8c7db176446af585ad7b98063 100644 (file)
@@ -1003,7 +1003,7 @@ grub_squash_close (grub_file_t file)
 }
 
 static grub_err_t
-grub_squash_mtime (grub_device_t dev, grub_int32_t *tm)
+grub_squash_mtime (grub_device_t dev, grub_int64_t *tm)
 {
   struct grub_squash_data *data = 0;
 
index fca46baa19d4f2e24a2cb95ceeb1ac617bbb8b88..34a698b71b8d9d5cf085d510963b6d9b4229327b 100644 (file)
@@ -837,7 +837,7 @@ grub_ufs_uuid (grub_device_t device, char **uuid)
 
 /* Get mtime.  */
 static grub_err_t
-grub_ufs_mtime (grub_device_t device, grub_int32_t *tm)
+grub_ufs_mtime (grub_device_t device, grub_int64_t *tm)
 {
   struct grub_ufs_data *data = 0;
 
index f9e755197c58d9cc96eee08a6d8199ab98fd9fc8..cf4d2ab189a5e2bd5cdb9bddc05e8769792f5c58 100644 (file)
@@ -3771,7 +3771,7 @@ zfs_uuid (grub_device_t device, char **uuid)
 }
 
 static grub_err_t 
-zfs_mtime (grub_device_t device, grub_int32_t *mt)
+zfs_mtime (grub_device_t device, grub_int64_t *mt)
 {
   struct grub_zfs_data *data;
   grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN;
index 95b8c9ff5e37a4e1cf316cd593469e23d96af9e7..9120128cadf354307c630886b1013a0ea7b6e353 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <grub/datetime.h>
 #include <grub/i18n.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
 
 static const char *const grub_weekday_names[] =
 {
@@ -60,7 +62,7 @@ grub_get_weekday_name (struct grub_datetime *datetime)
 
 
 void
-grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime)
+grub_unixtime2datetime (grub_int64_t nix, struct grub_datetime *datetime)
 {
   int i;
   grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
@@ -73,11 +75,17 @@ grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime)
   unsigned days;
   /* Seconds into current day.  */
   unsigned secs_in_day;
+
   /* Transform C divisions and modulos to mathematical ones */
   if (nix < 0)
-    days_epoch = -(((unsigned) (SECPERDAY-nix-1)) / SECPERDAY);
+    /*
+     * The result of division here shouldn't be larger than GRUB_INT_MAX.
+     * So, it's safe to store the result back in an int.
+     */
+    days_epoch = -(grub_divmod64 (((grub_int64_t) (SECPERDAY) - nix - 1), SECPERDAY, NULL));
   else
-    days_epoch = ((unsigned) nix) / SECPERDAY;
+    days_epoch = grub_divmod64 (nix, SECPERDAY, NULL);
+
   secs_in_day = nix - days_epoch * SECPERDAY;
   days = days_epoch + 69 * DAYSPERYEAR + 17;
 
index e33be51f83bb26797ece44554c33c14ec59dbd86..6fb5627025d240163ba13872757704b2aad4dcbc 100644 (file)
@@ -468,7 +468,7 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface)
   grub_err_t err;
   struct grub_net_bootp_packet *pack;
   struct grub_datetime date;
-  grub_int32_t t = 0;
+  grub_int64_t t = 0;
   struct grub_net_buff *nb;
   struct udphdr *udph;
   grub_net_network_level_address_t target;
index 8bb6da31fb303070ff5572561b30fcb885fd4df4..f7e9e3ac4a13e5204d077e38f0cbb34ad5d449ca 100644 (file)
@@ -136,7 +136,7 @@ grub_normal_print_device_info (const char *name)
            }
          if (fs->fs_mtime)
            {
-             grub_int32_t tm;
+             grub_int64_t tm;
              struct grub_datetime datetime;
              (fs->fs_mtime) (dev, &tm);
              if (grub_errno == GRUB_ERR_NONE)
index 3d11c717cb7a1a0ce8bb79045f7ba53c1db2168d..ffb268114fd048809151893cf3cec22b19d8a486 100644 (file)
@@ -32,7 +32,7 @@ static void
 sleep_test (void)
 {
   struct grub_datetime st, en;
-  grub_int32_t stu = 0, enu = 0;
+  grub_int64_t stu = 0, enu = 0;
   int is_delayok;
   grub_test_assert (!grub_get_datetime (&st), "Couldn't retrieve start time");
   grub_millisleep (10000);
@@ -45,8 +45,7 @@ sleep_test (void)
   if (enu - stu >= 15 && enu - stu <= 17)
     is_delayok = 1;
 #endif
-  grub_test_assert (is_delayok, "Interval out of range: %d", enu-stu);
-
+  grub_test_assert (is_delayok, "Interval out of range: %" PRIdGRUB_INT64_T, enu - stu);
 }
 
 GRUB_FUNCTIONAL_TEST (sleep_test, sleep_test);
index fef281404d7d60988e3f948d9b0e879cb8af087f..23ae0791ced811b7691a24dd2f3796d90be37a61 100644 (file)
@@ -48,11 +48,11 @@ grub_err_t grub_set_datetime (struct grub_datetime *datetime);
 int grub_get_weekday (struct grub_datetime *datetime);
 const char *grub_get_weekday_name (struct grub_datetime *datetime);
 
-void grub_unixtime2datetime (grub_int32_t nix,
+void grub_unixtime2datetime (grub_int64_t nix,
                             struct grub_datetime *datetime);
 
 static inline int
-grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix)
+grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int64_t *nix)
 {
   grub_int32_t ret;
   int y4, ay;
index 302e48d4b50dddbde96f2187932db09654af23d0..026bc3bb8615c0a15676672a087c930e6b39e48f 100644 (file)
@@ -39,7 +39,7 @@ struct grub_dirhook_info
   unsigned mtimeset:1;
   unsigned case_insensitive:1;
   unsigned inodeset:1;
-  grub_int32_t mtime;
+  grub_int64_t mtime;
   grub_uint64_t inode;
 };
 
@@ -81,7 +81,7 @@ struct grub_fs
   grub_err_t (*fs_uuid) (grub_device_t device, char **uuid);
 
   /* Get writing time of filesystem. */
-  grub_err_t (*fs_mtime) (grub_device_t device, grub_int32_t *timebuf);
+  grub_err_t (*fs_mtime) (grub_device_t device, grub_int64_t *timebuf);
 
 #ifdef GRUB_UTIL
   /* Determine sectors available for embedding.  */