From db64f5b16769168329c3269d5907acca7328de6c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 08:42:40 +0100 Subject: [PATCH 01/26] mtime support for cpio and tar --- grub-core/fs/cpio.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index c087b4f90..486d8215c 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -78,7 +78,7 @@ static grub_dl_t my_mod; static grub_err_t grub_cpio_find_file (struct grub_cpio_data *data, char **name, - grub_uint32_t * ofs) + grub_int32_t *mtime, grub_uint32_t * ofs) { #ifndef MODE_USTAR struct head hd; @@ -91,6 +91,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; + if (mtime) + *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2; if (hd.namesize & 1) hd.namesize++; @@ -139,6 +141,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & ~(GRUB_DISK_SECTOR_SIZE - 1)); + if (mtime) + *mtime = grub_strtoul (hd.mtime, NULL, 8); #endif return GRUB_ERR_NONE; } @@ -204,7 +208,9 @@ grub_cpio_dir (grub_device_t device, const char *path, data->hofs = 0; while (1) { - if (grub_cpio_find_file (data, &name, &ofs)) + grub_int32_t mtime; + + if (grub_cpio_find_file (data, &name, &mtime, &ofs)) goto fail; if (!ofs) @@ -227,6 +233,8 @@ grub_cpio_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = (p != NULL); + info.mtime = mtime; + info.mtimeset = 1; hook (name + len, &info); if (prev) @@ -269,7 +277,7 @@ grub_cpio_open (grub_file_t file, const char *name) data->hofs = 0; while (1) { - if (grub_cpio_find_file (data, &fn, &ofs)) + if (grub_cpio_find_file (data, &fn, NULL, &ofs)) goto fail; if (!ofs) From a2de6bf6ed9b2e3e4dcc9347f6d780608e11e95c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 10:32:50 +0100 Subject: [PATCH 02/26] filesystem mtime support for iso9660 --- grub-core/fs/iso9660.c | 130 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 6dc465f25..96753ac69 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -27,6 +27,7 @@ #include #include #include +#include #define GRUB_ISO9660_FSTYPE_DIR 0040000 #define GRUB_ISO9660_FSTYPE_REG 0100000 @@ -153,6 +154,108 @@ struct grub_fshelp_node static grub_dl_t my_mod; +#define SECPERMIN 60 +#define SECPERHOUR (60*SECPERMIN) +#define SECPERDAY (24*SECPERHOUR) +#define SECPERYEAR (365*SECPERDAY) +#define SECPER4YEARS (4*SECPERYEAR+SECPERDAY) + +static grub_err_t +grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) +{ + grub_int32_t ret; + int y4, ay; + grub_uint16_t monthssum[12] + = { 0, + 31, + 31 + 28, + 31 + 28 + 31, + 31 + 28 + 31 + 30, + 31 + 28 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30}; + grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (datetime->year > 2038 || datetime->year < 1902) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); + if (datetime->month > 12 || datetime->month < 1) + return grub_error (GRUB_ERR_BAD_NUMBER, "not a valid month"); + + /* In the period of validity of unixtime all years divisible by 4 + are bissextile*/ + /* Convenience: let's have 3 consecutive non-bissextile years + at the beginning of the epoch. So count from 1973 instead of 1970 */ + ret = 3*SECPERYEAR + SECPERDAY; + + /* Transform C divisions and modulos to mathematical ones */ + y4 = (datetime->year - 1973) / 4; + if (datetime->year < 1973) + y4--; + ay = datetime->year - 1973 - 4 * y4; + ret += y4 * SECPER4YEARS; + ret += ay * SECPERYEAR; + + ret += monthssum[datetime->month - 1] * SECPERDAY; + if (ay == 0 && datetime->month >= 3) + ret += SECPERDAY; + + ret += (datetime->day - 1) * SECPERDAY; + if ((datetime->day > months[datetime->month - 1] + && (!ay || datetime->month != 2 || datetime->day != 29)) + || datetime->day < 1) + return grub_error (GRUB_ERR_BAD_NUMBER, "invalid day"); + + ret += datetime->hour * SECPERHOUR; + if (datetime->hour > 23) + return grub_error (GRUB_ERR_BAD_NUMBER, "invalid hour"); + ret += datetime->minute * 60; + if (datetime->minute > 59) + return grub_error (GRUB_ERR_BAD_NUMBER, "invalid minute"); + + ret += datetime->second; + /* Accept leap seconds. */ + if (datetime->second > 60) + return grub_error (GRUB_ERR_BAD_NUMBER, "invalid second"); + + if ((datetime->year > 1980 && ret < 0) + || (datetime->year < 1960 && ret > 0)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); + *nix = ret; + return GRUB_ERR_NONE; +} + +static grub_err_t +iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) +{ + grub_err_t err; + struct grub_datetime datetime; + + if (! i->year[0] && ! i->year[1] + && ! i->year[2] && ! i->year[3] + && ! i->month[0] && ! i->month[1] + && ! i->day[0] && ! i->day[1] + && ! i->hour[0] && ! i->hour[1] + && ! i->minute[0] && ! i->minute[1] + && ! i->second[0] && ! i->second[1] + && ! i->hundredth[0] && ! i->hundredth[1]) + return grub_error (GRUB_ERR_BAD_NUMBER, "empty date"); + datetime.year = (i->year[0] - '0') * 1000 + (i->year[1] - '0') * 100 + + (i->year[2] - '0') * 10 + (i->year[3] - '0'); + datetime.month = (i->month[0] - '0') * 10 + (i->month[1] - '0'); + datetime.day = (i->day[0] - '0') * 10 + (i->day[1] - '0'); + datetime.hour = (i->hour[0] - '0') * 10 + (i->hour[1] - '0'); + datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0'); + datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0'); + + err = grub_datetime2unixtime (&datetime, nix); + *nix -= i->offset * 60 * 15; + return err; +} + /* Iterate over the susp entries, starting with block SUA_BLOCK on the offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for every entry. */ @@ -871,6 +974,32 @@ grub_iso9660_uuid (grub_device_t device, char **uuid) return grub_errno; } +/* Get writing time of filesystem. */ +static grub_err_t +grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf) +{ + struct grub_iso9660_data *data; + grub_disk_t disk = device->disk; + grub_err_t err; + + grub_dl_ref (my_mod); + + data = grub_iso9660_mount (disk); + if (!data) + { + grub_dl_unref (my_mod); + return grub_errno; + } + err = iso9660_to_unixtime (&data->voldesc.modified, timebuf); + + grub_dl_unref (my_mod); + + grub_free (data); + + return err; +} + + static struct grub_fs grub_iso9660_fs = @@ -882,6 +1011,7 @@ static struct grub_fs grub_iso9660_fs = .close = grub_iso9660_close, .label = grub_iso9660_label, .uuid = grub_iso9660_uuid, + .mtime = grub_iso9660_mtime, .next = 0 }; From c50d99c5e531a6a7cedebd6de51d98fcfda5f694 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 11:12:59 +0100 Subject: [PATCH 03/26] file mtime support for iso9660 --- grub-core/fs/iso9660.c | 60 +++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 96753ac69..03bfd3e92 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -54,6 +54,17 @@ struct grub_iso9660_voldesc grub_uint8_t version; } __attribute__ ((packed)); +struct grub_iso9660_date2 +{ + grub_uint8_t year; + grub_uint8_t month; + grub_uint8_t day; + grub_uint8_t hour; + grub_uint8_t minute; + grub_uint8_t second; + grub_uint8_t offset; +} __attribute__ ((packed)); + /* A directory entry. */ struct grub_iso9660_dir { @@ -63,7 +74,7 @@ struct grub_iso9660_dir grub_uint32_t first_sector_be; grub_uint32_t size; grub_uint32_t size_be; - grub_uint8_t unused1[7]; + struct grub_iso9660_date2 mtime; grub_uint8_t flags; grub_uint8_t unused2[6]; grub_uint8_t namelen; @@ -145,6 +156,7 @@ struct grub_iso9660_data struct grub_fshelp_node { struct grub_iso9660_data *data; + struct grub_iso9660_dir dirent; unsigned int size; unsigned int blk; unsigned int dir_blk; @@ -188,14 +200,14 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) /* In the period of validity of unixtime all years divisible by 4 are bissextile*/ /* Convenience: let's have 3 consecutive non-bissextile years - at the beginning of the epoch. So count from 1973 instead of 1970 */ - ret = 3*SECPERYEAR + SECPERDAY; + at the beginning of the epoch. So count from 1971 instead of 1970 */ + ret = SECPERYEAR + SECPERDAY; /* Transform C divisions and modulos to mathematical ones */ - y4 = (datetime->year - 1973) / 4; - if (datetime->year < 1973) + y4 = (datetime->year - 1971) / 4; + if (datetime->year < 1971) y4--; - ay = datetime->year - 1973 - 4 * y4; + ay = datetime->year - 1971 - 4 * y4; ret += y4 * SECPER4YEARS; ret += ay * SECPERYEAR; @@ -256,6 +268,24 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) return err; } +static grub_err_t +iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) +{ + grub_err_t err; + struct grub_datetime datetime; + + datetime.year = i->year + 1900; + datetime.month = i->month; + datetime.day = i->day; + datetime.hour = i->hour; + datetime.minute = i->minute; + datetime.second = i->second; + + err = grub_datetime2unixtime (&datetime, nix); + *nix -= i->offset * 60 * 15; + return err; +} + /* Iterate over the susp entries, starting with block SUA_BLOCK on the offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for every entry. */ @@ -467,7 +497,6 @@ grub_iso9660_mount (grub_disk_t disk) static char * grub_iso9660_read_symlink (grub_fshelp_node_t node) { - struct grub_iso9660_dir dirent; int sua_off; int sua_size; char *symlink = 0; @@ -545,13 +574,10 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node) return 0; } - if (grub_disk_read (node->data->disk, node->dir_blk, node->dir_off, - sizeof (dirent), (char *) &dirent)) - return 0; - - sua_off = (sizeof (dirent) + dirent.namelen + 1 - (dirent.namelen % 2) + sua_off = (sizeof (node->dirent) + node->dirent.namelen + 1 + - (node->dirent.namelen % 2) + node->data->susp_skip); - sua_size = dirent.len - sua_off; + sua_size = node->dirent.len - sua_off; symlink = grub_malloc (1); if (!symlink) @@ -748,6 +774,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, filename_alloc = 1; } + node->dirent = dirent; if (hook (filename, type, node)) { if (filename_alloc) @@ -784,8 +811,15 @@ grub_iso9660_dir (grub_device_t device, const char *path, grub_fshelp_node_t node) { struct grub_dirhook_info info; + grub_err_t err; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + err = iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime); + if (err) + grub_errno = GRUB_ERR_NONE; + else + info.mtimeset = 1; + grub_free (node); return hook (filename, &info); } From 3b95531920bdd3bd96706ef6fb01ee6a0cfab8f1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 15:04:12 +0100 Subject: [PATCH 04/26] fix unix range --- grub-core/fs/iso9660.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 03bfd3e92..3b0da5e53 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -192,7 +192,7 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30}; grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - if (datetime->year > 2038 || datetime->year < 1902) + if (datetime->year > 2038 || datetime->year < 1901) return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); if (datetime->month > 12 || datetime->month < 1) return grub_error (GRUB_ERR_BAD_NUMBER, "not a valid month"); From 5706da04438db67180e6b08a3f62aa4ba0b58b75 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 16:19:24 +0100 Subject: [PATCH 05/26] mtime support for xfs --- grub-core/fs/xfs.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 9dffe31d1..966bade1b 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -98,13 +98,22 @@ struct grub_xfs_btree_root grub_uint64_t keys[1]; } __attribute__ ((packed)); +struct grub_xfs_time +{ + grub_uint32_t sec; + grub_uint32_t nanosec; +} __attribute__ ((packed)); + struct grub_xfs_inode { grub_uint8_t magic[2]; grub_uint16_t mode; grub_uint8_t version; grub_uint8_t format; - grub_uint8_t unused2[50]; + grub_uint8_t unused2[26]; + struct grub_xfs_time atime; + struct grub_xfs_time mtime; + struct grub_xfs_time ctime; grub_uint64_t size; grub_uint64_t nblocks; grub_uint32_t extsize; @@ -643,6 +652,11 @@ grub_xfs_dir (grub_device_t device, const char *path, { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); + } info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); grub_free (node); return hook (filename, &info); From f22c12e8524f69b3482f6965d8d9b3480b8a9588 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 17:37:32 +0100 Subject: [PATCH 06/26] mtime for UDF support --- grub-core/fs/iso9660.c | 97 ++++------------------------------------- grub-core/fs/udf.c | 29 ++++++++++++ include/grub/datetime.h | 73 +++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 88 deletions(-) diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 3b0da5e53..f2f4b5a97 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -166,84 +166,9 @@ struct grub_fshelp_node static grub_dl_t my_mod; -#define SECPERMIN 60 -#define SECPERHOUR (60*SECPERMIN) -#define SECPERDAY (24*SECPERHOUR) -#define SECPERYEAR (365*SECPERDAY) -#define SECPER4YEARS (4*SECPERYEAR+SECPERDAY) - -static grub_err_t -grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) -{ - grub_int32_t ret; - int y4, ay; - grub_uint16_t monthssum[12] - = { 0, - 31, - 31 + 28, - 31 + 28 + 31, - 31 + 28 + 31 + 30, - 31 + 28 + 31 + 30 + 31, - 31 + 28 + 31 + 30 + 31 + 30, - 31 + 28 + 31 + 30 + 31 + 30 + 31, - 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, - 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, - 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, - 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30}; - grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - if (datetime->year > 2038 || datetime->year < 1901) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); - if (datetime->month > 12 || datetime->month < 1) - return grub_error (GRUB_ERR_BAD_NUMBER, "not a valid month"); - - /* In the period of validity of unixtime all years divisible by 4 - are bissextile*/ - /* Convenience: let's have 3 consecutive non-bissextile years - at the beginning of the epoch. So count from 1971 instead of 1970 */ - ret = SECPERYEAR + SECPERDAY; - - /* Transform C divisions and modulos to mathematical ones */ - y4 = (datetime->year - 1971) / 4; - if (datetime->year < 1971) - y4--; - ay = datetime->year - 1971 - 4 * y4; - ret += y4 * SECPER4YEARS; - ret += ay * SECPERYEAR; - - ret += monthssum[datetime->month - 1] * SECPERDAY; - if (ay == 0 && datetime->month >= 3) - ret += SECPERDAY; - - ret += (datetime->day - 1) * SECPERDAY; - if ((datetime->day > months[datetime->month - 1] - && (!ay || datetime->month != 2 || datetime->day != 29)) - || datetime->day < 1) - return grub_error (GRUB_ERR_BAD_NUMBER, "invalid day"); - - ret += datetime->hour * SECPERHOUR; - if (datetime->hour > 23) - return grub_error (GRUB_ERR_BAD_NUMBER, "invalid hour"); - ret += datetime->minute * 60; - if (datetime->minute > 59) - return grub_error (GRUB_ERR_BAD_NUMBER, "invalid minute"); - - ret += datetime->second; - /* Accept leap seconds. */ - if (datetime->second > 60) - return grub_error (GRUB_ERR_BAD_NUMBER, "invalid second"); - - if ((datetime->year > 1980 && ret < 0) - || (datetime->year < 1960 && ret > 0)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "outside of UNIX epoch"); - *nix = ret; - return GRUB_ERR_NONE; -} - static grub_err_t iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) { - grub_err_t err; struct grub_datetime datetime; if (! i->year[0] && ! i->year[1] @@ -263,17 +188,17 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0'); datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0'); - err = grub_datetime2unixtime (&datetime, nix); + if (!grub_datetime2unixtime (&datetime, nix)) + return grub_error (GRUB_ERR_BAD_NUMBER, "incorrect date"); *nix -= i->offset * 60 * 15; - return err; + return GRUB_ERR_NONE; } -static grub_err_t +static int iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) { - grub_err_t err; struct grub_datetime datetime; - + datetime.year = i->year + 1900; datetime.month = i->month; datetime.day = i->day; @@ -281,9 +206,10 @@ iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) datetime.minute = i->minute; datetime.second = i->second; - err = grub_datetime2unixtime (&datetime, nix); + if (!grub_datetime2unixtime (&datetime, nix)) + return 0; *nix -= i->offset * 60 * 15; - return err; + return 1; } /* Iterate over the susp entries, starting with block SUA_BLOCK on the @@ -811,14 +737,9 @@ grub_iso9660_dir (grub_device_t device, const char *path, grub_fshelp_node_t node) { struct grub_dirhook_info info; - grub_err_t err; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - err = iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime); - if (err) - grub_errno = GRUB_ERR_NONE; - else - info.mtimeset = 1; + info.mtimeset = !!iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime); grub_free (node); return hook (filename, &info); diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 7041e619e..0c5da996e 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -26,6 +26,7 @@ #include #include #include +#include #define GRUB_UDF_MAX_PDS 2 #define GRUB_UDF_MAX_PMS 6 @@ -904,8 +905,36 @@ grub_udf_dir (grub_device_t device, const char *path, grub_fshelp_node_t node) { struct grub_dirhook_info info; + const struct grub_udf_timestamp *tstamp = NULL; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) + tstamp = &node->fe.modification_time; + else if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE) + tstamp = &node->efe.modification_time; + + if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000) + { + grub_int16_t tz; + struct grub_datetime datetime; + + datetime.year = U16 (tstamp->year); + datetime.month = tstamp->month; + datetime.day = tstamp->day; + datetime.hour = tstamp->hour; + datetime.minute = tstamp->minute; + datetime.second = tstamp->second; + + tz = U16 (tstamp->type_and_timezone) & 0xfff; + if (tz & 0x800) + tz |= 0xf000; + if (tz == -2047) + tz = 0; + + info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime); + + info.mtime -= 60 * tz; + } grub_free (node); return hook (filename, &info); } diff --git a/include/grub/datetime.h b/include/grub/datetime.h index e721e89af..c20fc8c36 100644 --- a/include/grub/datetime.h +++ b/include/grub/datetime.h @@ -51,5 +51,78 @@ char *grub_get_weekday_name (struct grub_datetime *datetime); void grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime); +static inline int +grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) +{ + grub_int32_t ret; + int y4, ay; + const grub_uint16_t monthssum[12] + = { 0, + 31, + 31 + 28, + 31 + 28 + 31, + 31 + 28 + 31 + 30, + 31 + 28 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30}; + const grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; + const int SECPERMIN = 60; + const int SECPERHOUR = 60 * SECPERMIN; + const int SECPERDAY = 24 * SECPERHOUR; + const int SECPERYEAR = 365 * SECPERDAY; + const int SECPER4YEARS = 4 * SECPERYEAR + SECPERDAY; + + if (datetime->year > 2038 || datetime->year < 1901) + return 0; + if (datetime->month > 12 || datetime->month < 1) + return 0; + + /* In the period of validity of unixtime all years divisible by 4 + are bissextile*/ + /* Convenience: let's have 3 consecutive non-bissextile years + at the beginning of the epoch. So count from 1971 instead of 1970 */ + ret = SECPERYEAR + SECPERDAY; + + /* Transform C divisions and modulos to mathematical ones */ + y4 = (datetime->year - 1971) / 4; + if (datetime->year < 1971) + y4--; + ay = datetime->year - 1971 - 4 * y4; + ret += y4 * SECPER4YEARS; + ret += ay * SECPERYEAR; + + ret += monthssum[datetime->month - 1] * SECPERDAY; + if (ay == 0 && datetime->month >= 3) + ret += SECPERDAY; + + ret += (datetime->day - 1) * SECPERDAY; + if ((datetime->day > months[datetime->month - 1] + && (!ay || datetime->month != 2 || datetime->day != 29)) + || datetime->day < 1) + return 0; + + ret += datetime->hour * SECPERHOUR; + if (datetime->hour > 23) + return 0; + ret += datetime->minute * 60; + if (datetime->minute > 59) + return 0; + + ret += datetime->second; + /* Accept leap seconds. */ + if (datetime->second > 60) + return 0; + + if ((datetime->year > 1980 && ret < 0) + || (datetime->year < 1960 && ret > 0)) + return 0; + *nix = ret; + return 1; +} #endif /* ! KERNEL_DATETIME_HEADER */ From f8e2e451e6e19fa94b9e7cc331104eae9b29135d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 10 Dec 2010 18:34:46 +0100 Subject: [PATCH 07/26] handle UTF16 UDF label --- grub-core/fs/udf.c | 68 ++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 0c5da996e..aaf1565f7 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -789,6 +789,43 @@ fail: return 0; } +static char * +read_string (grub_uint8_t *raw, grub_size_t sz) +{ + grub_uint16_t *utf16; + char *ret; + grub_size_t utf16len = 0; + + if (raw[0] != 8 && raw[0] != 16) + return NULL; + + if (raw[0] == 8) + { + unsigned i; + utf16len = sz - 1; + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) + utf16[i] = raw[i + 1]; + } + if (raw[0] == 16) + { + unsigned i; + utf16len = (sz - 1) / 2; + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) + utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; + } + ret = grub_malloc (utf16len * 3 + 1); + if (ret) + *grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0'; + grub_free (utf16); + return ret; +} + static int grub_udf_iterate_dir (grub_fshelp_node_t dir, int NESTED_FUNC_ATTR @@ -842,10 +879,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, else { enum grub_fshelp_filetype type; + char *filename; grub_uint8_t raw[dirent.file_ident_length]; - grub_uint16_t utf16[dirent.file_ident_length - 1]; - grub_uint8_t filename[dirent.file_ident_length * 2]; - grub_size_t utf16len = 0; type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); @@ -856,27 +891,14 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, != dirent.file_ident_length) return 0; - if (raw[0] == 8) - { - unsigned i; - utf16len = dirent.file_ident_length - 1; - for (i = 0; i < utf16len; i++) - utf16[i] = raw[i + 1]; - } - if (raw[0] == 16) - { - unsigned i; - utf16len = (dirent.file_ident_length - 1) / 2; - for (i = 0; i < utf16len; i++) - utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; - } - if (raw[0] == 8 || raw[0] == 16) - { - *grub_utf16_to_utf8 (filename, utf16, utf16len) = '\0'; + filename = read_string (raw, dirent.file_ident_length); - if (hook ((char *) filename, type, child)) - return 1; + if (filename && hook (filename, type, child)) + { + grub_free (filename); + return 1; } + grub_free (filename); } } @@ -1033,7 +1055,7 @@ grub_udf_label (grub_device_t device, char **label) if (data) { - *label = grub_strdup ((char *) &data->lvd.ident[1]); + *label = read_string (data->lvd.ident, sizeof (data->lvd.ident)); grub_free (data); } else From 591baceb34e93e0ebef73f24f581414472804548 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 06:04:21 +0100 Subject: [PATCH 08/26] UDF symlink support --- grub-core/fs/udf.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index aaf1565f7..48aeca3c8 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -884,6 +884,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); + if (child->fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK) + type = GRUB_FSHELP_SYMLINK; if ((grub_udf_read_file (dir, 0, offset, dirent.file_ident_length, @@ -909,6 +911,25 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, return 0; } +static char * +grub_ufs_read_symlink (grub_fshelp_node_t node) +{ + grub_size_t sz = U64 (node->fe.file_size); + grub_uint8_t *raw; + char *ret; + + if (sz < 4) + return NULL; + raw = grub_malloc (sz - 4); + if (!raw) + return NULL; + if (grub_udf_read_file (node, NULL, 4, sz - 4, (char *) raw) < 0) + return NULL; + ret = read_string (raw, sz - 4); + grub_free (raw); + return ret; +} + static grub_err_t grub_udf_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, @@ -972,7 +993,8 @@ grub_udf_dir (grub_device_t device, const char *path, if (grub_fshelp_find_file (path, &rootnode, &foundnode, - grub_udf_iterate_dir, 0, GRUB_FSHELP_DIR)) + grub_udf_iterate_dir, grub_ufs_read_symlink, + GRUB_FSHELP_DIR)) goto fail; grub_udf_iterate_dir (foundnode, iterate); @@ -1006,7 +1028,8 @@ grub_udf_open (struct grub_file *file, const char *name) if (grub_fshelp_find_file (name, &rootnode, &foundnode, - grub_udf_iterate_dir, 0, GRUB_FSHELP_REG)) + grub_udf_iterate_dir, grub_ufs_read_symlink, + GRUB_FSHELP_REG)) goto fail; file->data = foundnode; From 88db5b694a1fe9772fb21afe24d1dadbb6a1254f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 06:23:33 +0100 Subject: [PATCH 09/26] file mtime support for reiserfs --- grub-core/fs/reiserfs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index e92279554..443d71b6f 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -222,6 +222,7 @@ struct grub_fshelp_node grub_uint32_t block_number; /* 0 if node is not found. */ grub_uint16_t block_position; grub_uint64_t next_offset; + grub_int32_t mtime; enum grub_reiserfs_item_type type; /* To know how to read the header. */ struct grub_reiserfs_item_header header; }; @@ -868,6 +869,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, entry_v1_stat.rdev, entry_v1_stat.first_direct_byte); #endif + entry_item->mtime = grub_le_to_cpu32 (entry_v1_stat.mtime); if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK) == S_IFLNK) entry_type = GRUB_FSHELP_SYMLINK; @@ -914,6 +916,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, entry_v2_stat.blocks, entry_v2_stat.first_direct_byte); #endif + entry_item->mtime = grub_le_to_cpu32 (entry_v2_stat.mtime); if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK) == S_IFLNK) entry_type = GRUB_FSHELP_SYMLINK; @@ -1276,6 +1279,8 @@ grub_reiserfs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = node->mtime; grub_free (node); return hook (filename, &info); } From ebec6850b9a62caa24cc886bdaf647c5a731f4b2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 07:00:31 +0100 Subject: [PATCH 10/26] HFS filesystem mtime support --- grub-core/fs/hfs.c | 18 ++++++++++++++++++ include/grub/hfs.h | 4 +++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index cef856326..a40171dbd 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -1072,6 +1072,23 @@ grub_hfs_label (grub_device_t device, char **label) return grub_errno; } +static grub_err_t +grub_hfs_mtime (grub_device_t device, grub_int32_t *tm) +{ + struct grub_hfs_data *data; + + data = grub_hfs_mount (device->disk); + + if (data) + *tm = grub_be_to_cpu32 (data->sblock.mtime) - 2082844800; + else + *tm = 0; + + grub_free (data); + return grub_errno; +} + + static grub_err_t grub_hfs_uuid (grub_device_t device, char **uuid) { @@ -1107,6 +1124,7 @@ static struct grub_fs grub_hfs_fs = .close = grub_hfs_close, .label = grub_hfs_label, .uuid = grub_hfs_uuid, + .mtime = grub_hfs_mtime, .next = 0 }; diff --git a/include/grub/hfs.h b/include/grub/hfs.h index d93b9a2c9..bf98610d9 100644 --- a/include/grub/hfs.h +++ b/include/grub/hfs.h @@ -39,7 +39,9 @@ typedef struct grub_hfs_extent grub_hfs_datarecord_t[3]; struct grub_hfs_sblock { grub_uint16_t magic; - grub_uint8_t unused[18]; + grub_uint32_t ctime; + grub_uint32_t mtime; + grub_uint8_t unused[10]; grub_uint32_t blksz; grub_uint8_t unused2[4]; grub_uint16_t first_block; From 58fa13fc7c03fdc605103e9a476267dcc3fe7190 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 07:15:44 +0100 Subject: [PATCH 11/26] HFS mtime support --- grub-core/fs/hfs.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index a40171dbd..e4cc23c17 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -131,6 +131,8 @@ struct grub_hfs_dirrec grub_uint8_t type; grub_uint8_t unused[5]; grub_uint32_t dirid; + grub_uint32_t ctime; + grub_uint32_t mtime; } __attribute__ ((packed)); /* Information about a file. */ @@ -142,7 +144,9 @@ struct grub_hfs_filerec grub_uint32_t fileid; grub_uint8_t unused2[2]; grub_uint32_t size; - grub_uint8_t unused3[44]; + grub_uint8_t unused3[18]; + grub_uint32_t mtime; + grub_uint8_t unused4[22]; /* The first 3 extents of the file. The other extents can be found in the extent overflow file. */ @@ -951,19 +955,29 @@ grub_hfs_dir (grub_device_t device, const char *path, int dir_hook (struct grub_hfs_record *rec) { char fname[32] = { 0 }; - char *filetype = rec->data; + struct grub_hfs_dirrec *drec = rec->data; + struct grub_hfs_filerec *frec = rec->data; struct grub_hfs_catalog_key *ckey = rec->key; struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); grub_strncpy (fname, (char *) (ckey->str), ckey->strlen); - if (*filetype == GRUB_HFS_FILETYPE_DIR - || *filetype == GRUB_HFS_FILETYPE_FILE) + if (drec->type == GRUB_HFS_FILETYPE_DIR) { - info.dir = (*filetype == GRUB_HFS_FILETYPE_DIR); + info.dir = 1; + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800; return hook (fname, &info); } + if (frec->type == GRUB_HFS_FILETYPE_FILE) + { + info.dir = 0; + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800; + return hook (fname, &info); + } + return 0; } @@ -1088,7 +1102,6 @@ grub_hfs_mtime (grub_device_t device, grub_int32_t *tm) return grub_errno; } - static grub_err_t grub_hfs_uuid (grub_device_t device, char **uuid) { From 7ac6c4842d57817bd35c74d49668422c9f43ba7a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 14:26:34 +0100 Subject: [PATCH 12/26] JFS mtime support --- grub-core/fs/jfs.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 76ef2e540..9e45f56d2 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -153,6 +153,12 @@ struct grub_jfs_leaf_next_dirent grub_uint16_t namepart[15]; } __attribute__ ((packed)); +struct grub_jfs_time +{ + grub_int32_t sec; + grub_int32_t nanosec; +} __attribute__ ((packed)); + struct grub_jfs_inode { grub_uint32_t stamp; @@ -162,7 +168,10 @@ struct grub_jfs_inode grub_uint64_t size; grub_uint8_t unused2[20]; grub_uint32_t mode; - grub_uint8_t unused3[72]; + struct grub_jfs_time atime; + struct grub_jfs_time ctime; + struct grub_jfs_time mtime; + grub_uint8_t unused3[48]; grub_uint8_t unused4[96]; union @@ -751,6 +760,8 @@ grub_jfs_dir (grub_device_t device, const char *path, info.dir = (grub_le_to_cpu32 (inode.mode) & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR; + info.mtimeset = 1; + info.mtime = grub_le_to_cpu32 (inode.mtime.sec); if (hook (diro->name, &info)) goto fail; } From f5ff296240e8575a35b14fc3ec8ca8263b6161c4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 17:46:16 +0100 Subject: [PATCH 13/26] minix mtime support --- grub-core/fs/minix.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 679e1ec51..e0ca09bd7 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -480,6 +480,13 @@ grub_minix_dir (grub_device_t device, const char *path, grub_minix_read_inode (data, grub_le_to_cpu16 (ino)); info.dir = ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR); + info.mtimeset = 1; +#ifndef MODE_MINIX2 + info.mtime = grub_le_to_cpu32 (data->inode.ctime); +#else + info.mtime = grub_le_to_cpu32 (data->inode.mtime); +#endif + if (hook (filename, &info) ? 1 : 0) break; From 80113a62583c1c1622a1ed2d7ea73dfe2b72e4ce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 18:21:39 +0100 Subject: [PATCH 14/26] declare AFFS, CPIO, TAR and XFS as non-installable explicitly --- grub-core/fs/affs.c | 3 +++ grub-core/fs/cpio.c | 3 +++ grub-core/fs/xfs.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 3dc80752d..27e03c0c4 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -535,6 +535,9 @@ static struct grub_fs grub_affs_fs = .read = grub_affs_read, .close = grub_affs_close, .label = grub_affs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 486d8215c..a6c7a1261 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -362,6 +362,9 @@ static struct grub_fs grub_cpio_fs = { .open = grub_cpio_open, .read = grub_cpio_read, .close = grub_cpio_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif }; #ifdef MODE_USTAR diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 966bade1b..dbe957470 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -822,6 +822,9 @@ static struct grub_fs grub_xfs_fs = .close = grub_xfs_close, .label = grub_xfs_label, .uuid = grub_xfs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; From 9959c6a70b7bd4d5cccad712a747f90f33f85fa9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 21:15:25 +0100 Subject: [PATCH 15/26] Fix AFFS rootblock detection --- grub-core/fs/affs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 27e03c0c4..40be4b2f6 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -208,7 +208,7 @@ grub_affs_mount (grub_disk_t disk) rblock = (struct grub_affs_rblock *) rootblock; /* Read the rootblock. */ - grub_disk_read (disk, (disk->total_sectors >> 1) + blocksize, 0, + grub_disk_read (disk, grub_be_to_cpu32 (data->bblock.rootblock), 0, GRUB_DISK_SECTOR_SIZE * 16, rootblock); if (grub_errno) goto fail; @@ -240,7 +240,7 @@ grub_affs_mount (grub_disk_t disk) data->disk = disk; data->htsize = grub_be_to_cpu32 (rblock->htsize); data->diropen.data = data; - data->diropen.block = (disk->total_sectors >> 1); + data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); grub_free (rootblock); @@ -507,7 +507,7 @@ grub_affs_label (grub_device_t device, char **label) { /* The rootblock maps quite well on a file header block, it's something we can use here. */ - grub_disk_read (data->disk, disk->total_sectors >> 1, + grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock), data->blocksize * (GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION), sizeof (file), &file); From e21c35641397325aa9411b41239e4779212ebe0e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 21:59:22 +0100 Subject: [PATCH 16/26] restructure AFFS fshelp_node-related code --- grub-core/fs/affs.c | 84 ++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 40be4b2f6..343af6681 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -50,12 +50,20 @@ struct grub_affs_rblock grub_uint32_t hashtable[1]; } __attribute__ ((packed)); +struct grub_affs_time +{ + grub_int32_t day; + grub_uint32_t min; + grub_uint32_t fractions_of_sec; +} __attribute__ ((packed)); + /* The second part of a file header block. */ struct grub_affs_file { grub_uint8_t unused1[12]; grub_uint32_t size; - grub_uint8_t unused2[104]; + grub_uint8_t unused2[92]; + struct grub_affs_time mtime; grub_uint8_t namelen; grub_uint8_t name[30]; grub_uint8_t unused3[33]; @@ -85,9 +93,9 @@ struct grub_affs_file struct grub_fshelp_node { struct grub_affs_data *data; - int block; - int size; - int parent; + grub_disk_addr_t block; + struct grub_fshelp_node *parent; + struct grub_affs_file di; }; /* Information about a "mounted" affs filesystem. */ @@ -154,7 +162,7 @@ grub_affs_read_file (grub_fshelp_node_t node, { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_affs_read_block, - node->size, 0); + grub_be_to_cpu32 (node->di.size), 0); } @@ -241,6 +249,8 @@ grub_affs_mount (grub_disk_t disk) data->htsize = grub_be_to_cpu32 (rblock->htsize); data->diropen.data = data; data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); + data->diropen.parent = NULL; + grub_memcpy (&data->diropen.di, rootblock, sizeof (data->diropen.di)); grub_free (rootblock); @@ -291,12 +301,15 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, struct grub_affs_data *data = dir->data; grub_uint32_t *hashtable; - auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block, - int size, int type); + auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, + grub_disk_addr_t block, + const struct grub_affs_file *fil); - int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block, - int size, int type) + int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, + grub_disk_addr_t block, + const struct grub_affs_file *fil) { + int type; node = grub_malloc (sizeof (*node)); if (!node) { @@ -304,10 +317,19 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, return 1; } + if ((int) grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR) + type = GRUB_FSHELP_REG; + else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG) + type = GRUB_FSHELP_DIR; + else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK) + type = GRUB_FSHELP_SYMLINK; + else + type = GRUB_FSHELP_UNKNOWN; + node->data = data; - node->size = size; node->block = block; - node->parent = grub_be_to_cpu32 (file.parent); + node->di = *fil; + node->parent = dir; if (hook (name, type, node)) { @@ -317,6 +339,24 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, return 0; } + /* Create the directory entries for `.' and `..'. */ + node = grub_malloc (sizeof (*node)); + if (!node) + return 1; + + *node = *dir; + if (hook (".", GRUB_FSHELP_DIR, node)) + return 1; + if (dir->parent) + { + node = grub_malloc (sizeof (*node)); + if (!node) + return 1; + *node = *dir->parent; + if (hook ("..", GRUB_FSHELP_DIR, node)) + return 1; + } + hashtable = grub_malloc (data->htsize * sizeof (*hashtable)); if (!hashtable) return 1; @@ -326,16 +366,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (grub_errno) goto fail; - /* Create the directory entries for `.' and `..'. */ - if (grub_affs_create_node (".", dir->block, dir->size, GRUB_FSHELP_DIR)) - return 1; - if (grub_affs_create_node ("..", dir->parent ? dir->parent : dir->block, - dir->size, GRUB_FSHELP_DIR)) - return 1; - for (i = 0; i < data->htsize; i++) { - enum grub_fshelp_filetype type; grub_uint64_t next; if (!hashtable[i]) @@ -356,17 +388,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, file.name[file.namelen] = '\0'; - if ((int) grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_DIR) - type = GRUB_FSHELP_REG; - else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_REG) - type = GRUB_FSHELP_DIR; - else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_SYMLINK) - type = GRUB_FSHELP_SYMLINK; - else - type = GRUB_FSHELP_UNKNOWN; - - if (grub_affs_create_node ((char *) (file.name), next, - grub_be_to_cpu32 (file.size), type)) + if (grub_affs_create_node ((char *) (file.name), next, &file)) return 1; next = grub_be_to_cpu32 (file.next); @@ -401,7 +423,7 @@ grub_affs_open (struct grub_file *file, const char *name) if (grub_errno) goto fail; - file->size = fdiro->size; + file->size = grub_be_to_cpu32 (fdiro->di.size); data->diropen = *fdiro; grub_free (fdiro); From 790aaa8c9f63a151c3cf45ea5d907c10174a2940 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 22:02:22 +0100 Subject: [PATCH 17/26] AFFS mtime support --- grub-core/fs/affs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 343af6681..e4b487a7e 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -54,7 +54,7 @@ struct grub_affs_time { grub_int32_t day; grub_uint32_t min; - grub_uint32_t fractions_of_sec; + grub_uint32_t hz; } __attribute__ ((packed)); /* The second part of a file header block. */ @@ -487,6 +487,11 @@ grub_affs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_be_to_cpu32 (node->di.mtime.day) * 86400 + + grub_be_to_cpu32 (node->di.mtime.min) * 60 + + grub_be_to_cpu32 (node->di.mtime.hz) / 50 + + 8 * 365 * 86400 + 86400 * 2; grub_free (node); return hook (filename, &info); } From bd1de4341b4bc6cc1e616674a3fc1ff1c12120fc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 22:33:34 +0100 Subject: [PATCH 18/26] explicitly declare SFS as not installable --- grub-core/fs/sfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index 4a5005908..b49420de1 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -579,6 +579,9 @@ static struct grub_fs grub_sfs_fs = .read = grub_sfs_read, .close = grub_sfs_close, .label = grub_sfs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; From 7b32d83d7834b4f36fbbbff7c526a07f1879c5b0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 22:48:29 +0100 Subject: [PATCH 19/26] SFS mtime support --- grub-core/fs/sfs.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index b49420de1..dc4fbd45c 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -66,7 +66,7 @@ struct grub_sfs_obj grub_uint32_t dir_objc; } dir __attribute__ ((packed)); } file_dir; - grub_uint8_t unused3[4]; + grub_uint32_t mtime; grub_uint8_t type; grub_uint8_t filename[1]; grub_uint8_t comment[1]; @@ -119,6 +119,7 @@ struct grub_fshelp_node struct grub_sfs_data *data; int block; int size; + grub_uint32_t mtime; }; /* Information about a "mounted" sfs filesystem. */ @@ -355,10 +356,12 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, int pos; auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block, - int size, int type); + int size, int type, + grub_uint32_t mtime); int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block, - int size, int type) + int size, int type, + grub_uint32_t mtime) { node = grub_malloc (sizeof (*node)); if (!node) @@ -367,6 +370,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, node->data = data; node->size = size; node->block = block; + node->mtime = mtime; return hook (name, type, node); } @@ -426,7 +430,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, if (grub_sfs_create_node (filename, block, grub_be_to_cpu32 (obj->file_dir.file.size), - type)) + type, grub_be_to_cpu32 (obj->mtime))) { grub_free (objc_data); return 1; @@ -525,6 +529,8 @@ grub_sfs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2; + info.mtimeset = 1; grub_free (node); return hook (filename, &info); } From 0e5507c411c63bdbddd2fcf1c6628a8ec29c87a4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Dec 2010 01:00:33 +0100 Subject: [PATCH 20/26] mtime support for ntfs --- grub-core/fs/ntfs.c | 8 ++++++++ include/grub/ntfs.h | 1 + 2 files changed, 9 insertions(+) diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index 414f6513d..7a5e2b158 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -610,6 +610,10 @@ list_file (struct grub_ntfs_file *diro, char *pos, fdiro->data = diro->data; fdiro->ino = u32at (pos, 0); + if (u64at (pos, 0x20) > u64at (pos, 0x28)) + fdiro->mtime = u64at (pos, 0x20); + else + fdiro->mtime = u64at (pos, 0x28); ustr = grub_malloc (ns * 4 + 1); if (ustr == NULL) @@ -880,6 +884,10 @@ grub_ntfs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_divmod64 (node->mtime, 10000000, 0) + - 86400ULL * 365 * (1970 - 1601) + - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); grub_free (node); return hook (filename, &info); } diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h index 31b99398b..0a089b3c0 100644 --- a/include/grub/ntfs.h +++ b/include/grub/ntfs.h @@ -135,6 +135,7 @@ struct grub_fshelp_node struct grub_ntfs_data *data; char *buf; grub_uint64_t size; + grub_uint64_t mtime; grub_uint32_t ino; int inode_read; struct grub_ntfs_attr attr; From e872a2dd82c6bfc27a870aff9088dfccaaa4fc02 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 18 Dec 2010 22:47:50 +0100 Subject: [PATCH 21/26] * util/grub-mkfont.c (main): Handle errors from FT_Set_Pixel_Sizes. --- ChangeLog | 4 ++++ util/grub-mkfont.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3f15bcc7b..de0a5690a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-12-18 Vladimir Serbinenko + + * util/grub-mkfont.c (main): Handle errors from FT_Set_Pixel_Sizes. + 2010-12-18 Colin Watson * grub-core/normal/term.c (print_more): Make \r or \n scroll one diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c index 3e24380d1..fff6a619e 100644 --- a/util/grub-mkfont.c +++ b/util/grub-mkfont.c @@ -1170,7 +1170,8 @@ main (int argc, char *argv[]) font_info.style = ft_face->style_flags; font_info.size = size; - FT_Set_Pixel_Sizes (ft_face, size, size); + if (FT_Set_Pixel_Sizes (ft_face, size, size)) + grub_util_error ("can't set %dx%d font size", size, size); add_font (&font_info, ft_face, file_format != PF2); FT_Done_Face (ft_face); } From e6533ae1547169a4ef4dd2861bd6c56a8efdc5cc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 00:43:41 +0100 Subject: [PATCH 22/26] Fix handling of UTF-16 UDF labels. * grub-core/fs/udf.c (grub_udf_iterate_dir): Move string-parsing part (read_string): .. here. (grub_udf_label): Use read_string. --- ChangeLog | 8 ++++++ grub-core/fs/udf.c | 70 +++++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index de0a5690a..effab30eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-12-19 Vladimir Serbinenko + + Fix handling of UTF-16 UDF labels. + + * grub-core/fs/udf.c (grub_udf_iterate_dir): Move string-parsing part + (read_string): .. here. + (grub_udf_label): Use read_string. + 2010-12-18 Vladimir Serbinenko * util/grub-mkfont.c (main): Handle errors from FT_Set_Pixel_Sizes. diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 7041e619e..51726edf3 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -788,6 +788,43 @@ fail: return 0; } +static char * +read_string (grub_uint8_t *raw, grub_size_t sz) +{ + grub_uint16_t *utf16; + char *ret; + grub_size_t utf16len = 0; + + if (raw[0] != 8 && raw[0] != 16) + return NULL; + + if (raw[0] == 8) + { + unsigned i; + utf16len = sz - 1; + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) + utf16[i] = raw[i + 1]; + } + if (raw[0] == 16) + { + unsigned i; + utf16len = (sz - 1) / 2; + utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + if (!utf16) + return NULL; + for (i = 0; i < utf16len; i++) + utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; + } + ret = grub_malloc (utf16len * 3 + 1); + if (ret) + *grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0'; + grub_free (utf16); + return ret; +} + static int grub_udf_iterate_dir (grub_fshelp_node_t dir, int NESTED_FUNC_ATTR @@ -841,10 +878,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, else { enum grub_fshelp_filetype type; + char *filename; grub_uint8_t raw[dirent.file_ident_length]; - grub_uint16_t utf16[dirent.file_ident_length - 1]; - grub_uint8_t filename[dirent.file_ident_length * 2]; - grub_size_t utf16len = 0; type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); @@ -855,27 +890,16 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, != dirent.file_ident_length) return 0; - if (raw[0] == 8) - { - unsigned i; - utf16len = dirent.file_ident_length - 1; - for (i = 0; i < utf16len; i++) - utf16[i] = raw[i + 1]; - } - if (raw[0] == 16) - { - unsigned i; - utf16len = (dirent.file_ident_length - 1) / 2; - for (i = 0; i < utf16len; i++) - utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; - } - if (raw[0] == 8 || raw[0] == 16) - { - *grub_utf16_to_utf8 (filename, utf16, utf16len) = '\0'; + filename = read_string (raw, dirent.file_ident_length); + if (!filename) + grub_print_error (); - if (hook ((char *) filename, type, child)) - return 1; + if (filename && hook (filename, type, child)) + { + grub_free (filename); + return 1; } + grub_free (filename); } } @@ -1004,7 +1028,7 @@ grub_udf_label (grub_device_t device, char **label) if (data) { - *label = grub_strdup ((char *) &data->lvd.ident[1]); + *label = read_string (data->lvd.ident, sizeof (data->lvd.ident)); grub_free (data); } else From b85812b06f6806f988c9c57ca52f01c4eb110114 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 00:49:52 +0100 Subject: [PATCH 23/26] * grub-core/fs/affs.c (grub_affs_fs) [GRUB_UTIL]: Explicitly set reserved_first_sector to 0. * grub-core/fs/cpio.c (grub_cpio_fs) [GRUB_UTIL]: Likewise. * grub-core/fs/sfs.c (grub_sfs_fs) [GRUB_UTIL]: Likewise. * grub-core/fs/xfs.c (grub_xfs_fs) [GRUB_UTIL]: Likewise. --- ChangeLog | 8 ++++++++ grub-core/fs/affs.c | 3 +++ grub-core/fs/cpio.c | 3 +++ grub-core/fs/sfs.c | 3 +++ grub-core/fs/xfs.c | 3 +++ 5 files changed, 20 insertions(+) diff --git a/ChangeLog b/ChangeLog index effab30eb..cc3f65c86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-12-19 Vladimir Serbinenko + + * grub-core/fs/affs.c (grub_affs_fs) [GRUB_UTIL]: Explicitly set + reserved_first_sector to 0. + * grub-core/fs/cpio.c (grub_cpio_fs) [GRUB_UTIL]: Likewise. + * grub-core/fs/sfs.c (grub_sfs_fs) [GRUB_UTIL]: Likewise. + * grub-core/fs/xfs.c (grub_xfs_fs) [GRUB_UTIL]: Likewise. + 2010-12-19 Vladimir Serbinenko Fix handling of UTF-16 UDF labels. diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 3dc80752d..27e03c0c4 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -535,6 +535,9 @@ static struct grub_fs grub_affs_fs = .read = grub_affs_read, .close = grub_affs_close, .label = grub_affs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index c087b4f90..2c92404c3 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -354,6 +354,9 @@ static struct grub_fs grub_cpio_fs = { .open = grub_cpio_open, .read = grub_cpio_read, .close = grub_cpio_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif }; #ifdef MODE_USTAR diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index 4a5005908..b49420de1 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -579,6 +579,9 @@ static struct grub_fs grub_sfs_fs = .read = grub_sfs_read, .close = grub_sfs_close, .label = grub_sfs_label, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 9dffe31d1..3d773856e 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -808,6 +808,9 @@ static struct grub_fs grub_xfs_fs = .close = grub_xfs_close, .label = grub_xfs_label, .uuid = grub_xfs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, +#endif .next = 0 }; From b070525d039783869b96e0223c8142a055fffc0f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 00:52:18 +0100 Subject: [PATCH 24/26] * grub-core/fs/affs.c (grub_affs_mount): Read data->bblock.rootblock rather than assuming than rootblock is exactly in the middle. (grub_affs_label): Likewise. --- ChangeLog | 6 ++++++ grub-core/fs/affs.c | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index cc3f65c86..8f459f198 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-12-19 Vladimir Serbinenko + + * grub-core/fs/affs.c (grub_affs_mount): Read data->bblock.rootblock + rather than assuming than rootblock is exactly in the middle. + (grub_affs_label): Likewise. + 2010-12-19 Vladimir Serbinenko * grub-core/fs/affs.c (grub_affs_fs) [GRUB_UTIL]: Explicitly set diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 27e03c0c4..40be4b2f6 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -208,7 +208,7 @@ grub_affs_mount (grub_disk_t disk) rblock = (struct grub_affs_rblock *) rootblock; /* Read the rootblock. */ - grub_disk_read (disk, (disk->total_sectors >> 1) + blocksize, 0, + grub_disk_read (disk, grub_be_to_cpu32 (data->bblock.rootblock), 0, GRUB_DISK_SECTOR_SIZE * 16, rootblock); if (grub_errno) goto fail; @@ -240,7 +240,7 @@ grub_affs_mount (grub_disk_t disk) data->disk = disk; data->htsize = grub_be_to_cpu32 (rblock->htsize); data->diropen.data = data; - data->diropen.block = (disk->total_sectors >> 1); + data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); grub_free (rootblock); @@ -507,7 +507,7 @@ grub_affs_label (grub_device_t device, char **label) { /* The rootblock maps quite well on a file header block, it's something we can use here. */ - grub_disk_read (data->disk, disk->total_sectors >> 1, + grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock), data->blocksize * (GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION), sizeof (file), &file); From b9cd13659cce5dd2414e962c02042c9ece90b918 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 31 Dec 2010 15:22:36 +0100 Subject: [PATCH 25/26] Simplify the AFFS checksum computation. --- grub-core/fs/affs.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index e4b487a7e..e05c166a9 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -174,7 +174,6 @@ grub_affs_mount (grub_disk_t disk) struct grub_affs_rblock *rblock; int checksum = 0; - int checksumr = 0; int blocksize = 0; data = grub_malloc (sizeof (struct grub_affs_data)); @@ -224,8 +223,6 @@ grub_affs_mount (grub_disk_t disk) /* The filesystem blocksize is not stored anywhere in the filesystem itself. One way to determine it is reading blocks for the rootblock until the checksum is correct. */ - checksumr = grub_be_to_cpu32 (rblock->checksum); - rblock->checksum = 0; for (blocksize = 0; blocksize < 8; blocksize++) { grub_uint32_t *currblock = rootblock + GRUB_DISK_SECTOR_SIZE * blocksize; @@ -234,10 +231,10 @@ grub_affs_mount (grub_disk_t disk) for (i = 0; i < GRUB_DISK_SECTOR_SIZE / sizeof (*currblock); i++) checksum += grub_be_to_cpu32 (currblock[i]); - if (checksumr == -checksum) + if (checksum == 0) break; } - if (-checksum != checksumr) + if (checksum != 0) { grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined"); goto fail; From fb17547ca89991f33d269cc01af711e198ab1eb0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 31 Dec 2010 15:23:06 +0100 Subject: [PATCH 26/26] Check amiga partmap checksum --- grub-core/partmap/amiga.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/grub-core/partmap/amiga.c b/grub-core/partmap/amiga.c index 1e0f23402..803e2e14f 100644 --- a/grub-core/partmap/amiga.c +++ b/grub-core/partmap/amiga.c @@ -37,7 +37,7 @@ struct grub_amiga_rdsk grub_uint32_t partitionlst; grub_uint32_t fslst; - /* The other information is not important for us. */ + grub_uint32_t unused[128 - 9]; } __attribute__ ((packed)); struct grub_amiga_partition @@ -65,12 +65,24 @@ struct grub_amiga_partition grub_uint32_t highcyl; grub_uint32_t firstcyl; + grub_uint32_t unused[128 - 44]; } __attribute__ ((packed)); static struct grub_partition_map grub_amiga_partition_map; +static grub_uint32_t +amiga_partition_map_checksum (void *buf, grub_size_t sz) +{ + grub_uint32_t *ptr = buf; + grub_uint32_t r = 0; + sz /= sizeof (grub_uint32_t); + for (; sz; sz--, ptr++) + r += grub_be_to_cpu32 (*ptr); + return r; +} + static grub_err_t amiga_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, @@ -90,7 +102,8 @@ amiga_partition_map_iterate (grub_disk_t disk, return grub_errno; if (grub_memcmp (rdsk.magic, GRUB_AMIGA_RDSK_MAGIC, - sizeof (rdsk.magic)) == 0) + sizeof (rdsk.magic)) == 0 + && amiga_partition_map_checksum (&rdsk, sizeof (rdsk)) == 0) { /* Found the first PART block. */ next = grub_be_to_cpu32 (rdsk.partitionlst); @@ -112,7 +125,8 @@ amiga_partition_map_iterate (grub_disk_t disk, return grub_errno; if (grub_memcmp (apart.magic, GRUB_AMIGA_PART_MAGIC, - sizeof (apart.magic)) == 0) + sizeof (apart.magic)) == 0 + && amiga_partition_map_checksum (&apart, sizeof (apart)) == 0) /* Calculate the first block and the size of the partition. */ part.start = (grub_be_to_cpu32 (apart.lowcyl)