grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Remove nested functions from disk and file read hooks
@ 2013-01-21 12:14 Colin Watson
  2013-02-26 21:57 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 1 reply; 2+ messages in thread
From: Colin Watson @ 2013-01-21 12:14 UTC (permalink / raw)
  To: grub-devel

Part seven.  This particular patch in the set loses some of the
compressed-kernel size we'd gained from earlier patches, but it's still
a good bit smaller than when I started on this work so I'm not worried.
Note that, as a general pattern, I have intentionally not zeroed out
read_hook_data after calling code using a read hook; this is because (a)
the code that calls read hooks only checks whether read_hook is NULL,
(b) every function that sets read_hook to something non-NULL naturally
also sets read_hook_data if it cares about its value, and (c) avoiding
the extra code to zero read_hook_data makes a few bytes of difference to
the size of compressed core images.

  UP:   obj/i386-coreboot/grub-core/kernel.img (27868 < 27876) - change: 8
  UP:   obj/i386-ieee1275/grub-core/kernel.img (48364 < 48372) - change: 8
  UP:   obj/i386-pc/grub-core/kernel.img (28852 < 28860) - change: 8
  UP:   obj/amd64-efi/grub-core/affs.mod (8608 < 8624) - change: 16
  UP:   obj/amd64-efi/grub-core/afs.mod (9280 < 9344) - change: 64
  UP:   obj/amd64-efi/grub-core/bfs.mod (10672 < 10752) - change: 80
  DOWN: obj/amd64-efi/grub-core/blocklist.mod (3096 > 3048) - change: -48
  UP:   obj/amd64-efi/grub-core/exfat.mod (8272 < 8336) - change: 64
  UP:   obj/amd64-efi/grub-core/ext2.mod (9096 < 9112) - change: 16
  UP:   obj/amd64-efi/grub-core/fat.mod (8648 < 8680) - change: 32
  UP:   obj/amd64-efi/grub-core/fshelp.mod (4128 < 4144) - change: 16
  UP:   obj/amd64-efi/grub-core/hfs.mod (10800 < 10816) - change: 16
  UP:   obj/amd64-efi/grub-core/hfsplus.mod (10080 < 10096) - change: 16
  UP:   obj/amd64-efi/grub-core/jfs.mod (9416 < 9448) - change: 32
  DOWN: obj/amd64-efi/grub-core/loadenv.mod (8960 > 8928) - change: -32
  UP:   obj/amd64-efi/grub-core/minix2.mod (6032 < 6064) - change: 32
  UP:   obj/amd64-efi/grub-core/minix2_be.mod (6144 < 6176) - change: 32
  UP:   obj/amd64-efi/grub-core/minix3.mod (6016 < 6048) - change: 32
  UP:   obj/amd64-efi/grub-core/minix3_be.mod (6096 < 6128) - change: 32
  UP:   obj/amd64-efi/grub-core/minix_be.mod (6056 < 6072) - change: 16
  UP:   obj/amd64-efi/grub-core/nilfs2.mod (9976 < 9992) - change: 16
  UP:   obj/amd64-efi/grub-core/ntfs.mod (15600 < 15664) - change: 64
  UP:   obj/amd64-efi/grub-core/reiserfs.mod (14288 < 14304) - change: 16
  UP:   obj/amd64-efi/grub-core/romfs.mod (5784 < 5800) - change: 16
  UP:   obj/amd64-efi/grub-core/sfs.mod (7992 < 8008) - change: 16
  UP:   obj/amd64-efi/grub-core/udf.mod (11240 < 11256) - change: 16
  DOWN: obj/amd64-efi/grub-core/ufs1.mod (8144 > 8128) - change: -16
  UP:   obj/amd64-efi/grub-core/ufs1_be.mod (8256 < 8304) - change: 48
  DOWN: obj/amd64-efi/grub-core/ufs2.mod (8160 > 8144) - change: -16
  UP:   obj/amd64-efi/grub-core/xfs.mod (8968 < 8984) - change: 16
  UP:   obj/i386-coreboot/grub-core/affs.mod (5652 < 5656) - change: 4
  UP:   obj/i386-coreboot/grub-core/afs.mod (6912 < 6936) - change: 24
  UP:   obj/i386-coreboot/grub-core/bfs.mod (7656 < 7680) - change: 24
  DOWN: obj/i386-coreboot/grub-core/blocklist.mod (2076 > 1992) - change: -84
  UP:   obj/i386-coreboot/grub-core/exfat.mod (5296 < 5332) - change: 36
  UP:   obj/i386-coreboot/grub-core/ext2.mod (5976 < 5992) - change: 16
  UP:   obj/i386-coreboot/grub-core/fat.mod (5620 < 5640) - change: 20
  UP:   obj/i386-coreboot/grub-core/fshelp.mod (2812 < 2816) - change: 4
  DOWN: obj/i386-coreboot/grub-core/hdparm.mod (7212 > 7208) - change: -4
  UP:   obj/i386-coreboot/grub-core/hfs.mod (7228 < 7232) - change: 4
  UP:   obj/i386-coreboot/grub-core/hfsplus.mod (6596 < 6620) - change: 24
  UP:   obj/i386-coreboot/grub-core/iso9660.mod (8796 < 8804) - change: 8
  UP:   obj/i386-coreboot/grub-core/jfs.mod (6560 < 6580) - change: 20
  DOWN: obj/i386-coreboot/grub-core/loadenv.mod (5568 > 5544) - change: -24
  UP:   obj/i386-coreboot/grub-core/minix.mod (3768 < 3792) - change: 24
  UP:   obj/i386-coreboot/grub-core/minix2.mod (3836 < 3860) - change: 24
  UP:   obj/i386-coreboot/grub-core/minix2_be.mod (3924 < 3956) - change: 32
  UP:   obj/i386-coreboot/grub-core/minix3.mod (3800 < 3832) - change: 32
  UP:   obj/i386-coreboot/grub-core/minix3_be.mod (3872 < 3920) - change: 48
  UP:   obj/i386-coreboot/grub-core/minix_be.mod (3864 < 3896) - change: 32
  UP:   obj/i386-coreboot/grub-core/nilfs2.mod (6600 < 6616) - change: 16
  UP:   obj/i386-coreboot/grub-core/ntfs.mod (10492 < 10496) - change: 4
  UP:   obj/i386-coreboot/grub-core/reiserfs.mod (8952 < 8964) - change: 12
  UP:   obj/i386-coreboot/grub-core/romfs.mod (4068 < 4076) - change: 8
  UP:   obj/i386-coreboot/grub-core/udf.mod (7644 < 7668) - change: 24
  UP:   obj/i386-coreboot/grub-core/ufs1.mod (5468 < 5500) - change: 32
  UP:   obj/i386-coreboot/grub-core/ufs1_be.mod (5596 < 5632) - change: 36
  UP:   obj/i386-coreboot/grub-core/ufs2.mod (5552 < 5584) - change: 32
  UP:   obj/i386-coreboot/grub-core/xfs.mod (6036 < 6060) - change: 24
  UP:   obj/i386-efi/grub-core/affs.mod (5748 < 5752) - change: 4
  UP:   obj/i386-efi/grub-core/afs.mod (6976 < 7020) - change: 44
  UP:   obj/i386-efi/grub-core/bfs.mod (7780 < 7816) - change: 36
  DOWN: obj/i386-efi/grub-core/blocklist.mod (2128 > 2076) - change: -52
  UP:   obj/i386-efi/grub-core/exfat.mod (5452 < 5476) - change: 24
  UP:   obj/i386-efi/grub-core/ext2.mod (6144 < 6156) - change: 12
  UP:   obj/i386-efi/grub-core/fat.mod (5808 < 5824) - change: 16
  UP:   obj/i386-efi/grub-core/fshelp.mod (2856 < 2860) - change: 4
  UP:   obj/i386-efi/grub-core/hfs.mod (7344 < 7356) - change: 12
  UP:   obj/i386-efi/grub-core/hfsplus.mod (6832 < 6852) - change: 20
  UP:   obj/i386-efi/grub-core/iso9660.mod (9140 < 9148) - change: 8
  UP:   obj/i386-efi/grub-core/jfs.mod (6632 < 6644) - change: 12
  DOWN: obj/i386-efi/grub-core/loadenv.mod (5804 > 5784) - change: -20
  UP:   obj/i386-efi/grub-core/minix.mod (3784 < 3804) - change: 20
  UP:   obj/i386-efi/grub-core/minix2.mod (3880 < 3900) - change: 20
  UP:   obj/i386-efi/grub-core/minix2_be.mod (4004 < 4028) - change: 24
  UP:   obj/i386-efi/grub-core/minix3.mod (3868 < 3892) - change: 24
  UP:   obj/i386-efi/grub-core/minix3_be.mod (3948 < 3972) - change: 24
  UP:   obj/i386-efi/grub-core/minix_be.mod (3920 < 3940) - change: 20
  UP:   obj/i386-efi/grub-core/nilfs2.mod (6712 < 6728) - change: 16
  UP:   obj/i386-efi/grub-core/ntfs.mod (10800 < 10812) - change: 12
  UP:   obj/i386-efi/grub-core/reiserfs.mod (9216 < 9224) - change: 8
  UP:   obj/i386-efi/grub-core/udf.mod (7916 < 7928) - change: 12
  UP:   obj/i386-efi/grub-core/ufs1.mod (5548 < 5592) - change: 44
  UP:   obj/i386-efi/grub-core/ufs1_be.mod (5700 < 5720) - change: 20
  UP:   obj/i386-efi/grub-core/ufs2.mod (5632 < 5652) - change: 20
  UP:   obj/i386-efi/grub-core/xfs.mod (6236 < 6260) - change: 24
  UP:   obj/i386-ieee1275/grub-core/affs.mod (5652 < 5656) - change: 4
  UP:   obj/i386-ieee1275/grub-core/afs.mod (6912 < 6936) - change: 24
  UP:   obj/i386-ieee1275/grub-core/bfs.mod (7656 < 7680) - change: 24
  DOWN: obj/i386-ieee1275/grub-core/blocklist.mod (2076 > 1992) - change: -84
  UP:   obj/i386-ieee1275/grub-core/exfat.mod (5296 < 5332) - change: 36
  UP:   obj/i386-ieee1275/grub-core/ext2.mod (5976 < 5992) - change: 16
  UP:   obj/i386-ieee1275/grub-core/fat.mod (5620 < 5640) - change: 20
  UP:   obj/i386-ieee1275/grub-core/fshelp.mod (2812 < 2816) - change: 4
  DOWN: obj/i386-ieee1275/grub-core/hdparm.mod (7140 > 7136) - change: -4
  UP:   obj/i386-ieee1275/grub-core/hfs.mod (7228 < 7232) - change: 4
  UP:   obj/i386-ieee1275/grub-core/hfsplus.mod (6596 < 6620) - change: 24
  UP:   obj/i386-ieee1275/grub-core/iso9660.mod (8796 < 8804) - change: 8
  UP:   obj/i386-ieee1275/grub-core/jfs.mod (6560 < 6580) - change: 20
  DOWN: obj/i386-ieee1275/grub-core/loadenv.mod (5496 > 5472) - change: -24
  UP:   obj/i386-ieee1275/grub-core/minix.mod (3768 < 3792) - change: 24
  UP:   obj/i386-ieee1275/grub-core/minix2.mod (3836 < 3860) - change: 24
  UP:   obj/i386-ieee1275/grub-core/minix2_be.mod (3924 < 3956) - change: 32
  UP:   obj/i386-ieee1275/grub-core/minix3.mod (3800 < 3832) - change: 32
  UP:   obj/i386-ieee1275/grub-core/minix3_be.mod (3872 < 3920) - change: 48
  UP:   obj/i386-ieee1275/grub-core/minix_be.mod (3864 < 3896) - change: 32
  UP:   obj/i386-ieee1275/grub-core/nilfs2.mod (6600 < 6616) - change: 16
  UP:   obj/i386-ieee1275/grub-core/ntfs.mod (10492 < 10496) - change: 4
  UP:   obj/i386-ieee1275/grub-core/reiserfs.mod (8952 < 8964) - change: 12
  UP:   obj/i386-ieee1275/grub-core/romfs.mod (4068 < 4076) - change: 8
  UP:   obj/i386-ieee1275/grub-core/udf.mod (7644 < 7668) - change: 24
  UP:   obj/i386-ieee1275/grub-core/ufs1.mod (5468 < 5500) - change: 32
  UP:   obj/i386-ieee1275/grub-core/ufs1_be.mod (5596 < 5632) - change: 36
  UP:   obj/i386-ieee1275/grub-core/ufs2.mod (5552 < 5584) - change: 32
  UP:   obj/i386-ieee1275/grub-core/xfs.mod (6036 < 6060) - change: 24
  UP:   obj/i386-pc/grub-core/affs.mod (5652 < 5656) - change: 4
  UP:   obj/i386-pc/grub-core/afs.mod (6912 < 6936) - change: 24
  UP:   obj/i386-pc/grub-core/bfs.mod (7656 < 7680) - change: 24
  DOWN: obj/i386-pc/grub-core/blocklist.mod (2076 > 1992) - change: -84
  UP:   obj/i386-pc/grub-core/exfat.mod (5296 < 5332) - change: 36
  UP:   obj/i386-pc/grub-core/ext2.mod (5976 < 5992) - change: 16
  UP:   obj/i386-pc/grub-core/fat.mod (5620 < 5640) - change: 20
  UP:   obj/i386-pc/grub-core/fshelp.mod (2812 < 2816) - change: 4
  DOWN: obj/i386-pc/grub-core/hdparm.mod (7212 > 7208) - change: -4
  UP:   obj/i386-pc/grub-core/hfs.mod (7228 < 7232) - change: 4
  UP:   obj/i386-pc/grub-core/hfsplus.mod (6596 < 6620) - change: 24
  UP:   obj/i386-pc/grub-core/iso9660.mod (8796 < 8804) - change: 8
  UP:   obj/i386-pc/grub-core/jfs.mod (6560 < 6580) - change: 20
  DOWN: obj/i386-pc/grub-core/loadenv.mod (5568 > 5544) - change: -24
  UP:   obj/i386-pc/grub-core/minix.mod (3768 < 3792) - change: 24
  UP:   obj/i386-pc/grub-core/minix2.mod (3836 < 3860) - change: 24
  UP:   obj/i386-pc/grub-core/minix2_be.mod (3924 < 3956) - change: 32
  UP:   obj/i386-pc/grub-core/minix3.mod (3800 < 3832) - change: 32
  UP:   obj/i386-pc/grub-core/minix3_be.mod (3872 < 3920) - change: 48
  UP:   obj/i386-pc/grub-core/minix_be.mod (3864 < 3896) - change: 32
  UP:   obj/i386-pc/grub-core/nilfs2.mod (6600 < 6616) - change: 16
  UP:   obj/i386-pc/grub-core/ntfs.mod (10492 < 10496) - change: 4
  UP:   obj/i386-pc/grub-core/reiserfs.mod (8952 < 8964) - change: 12
  UP:   obj/i386-pc/grub-core/romfs.mod (4068 < 4076) - change: 8
  UP:   obj/i386-pc/grub-core/udf.mod (7644 < 7668) - change: 24
  UP:   obj/i386-pc/grub-core/ufs1.mod (5468 < 5500) - change: 32
  UP:   obj/i386-pc/grub-core/ufs1_be.mod (5596 < 5632) - change: 36
  UP:   obj/i386-pc/grub-core/ufs2.mod (5552 < 5584) - change: 32
  UP:   obj/i386-pc/grub-core/xfs.mod (6036 < 6060) - change: 24
  UP:   i386-pc core image (biosdisk ext2 part_msdos) (26604 < 26647) - change: 43
  UP:   i386-pc core image (biosdisk ext2 part_msdos lvm mdraid1x) (33959 < 34004) - change: 45

=== modified file 'ChangeLog'
--- ChangeLog	2013-01-21 11:10:25 +0000
+++ ChangeLog	2013-01-21 11:15:16 +0000
@@ -1,5 +1,17 @@
 2013-01-21  Colin Watson  <cjwatson@ubuntu.com>
 
+	Remove nested functions from disk and file read hooks.
+
+	* include/grub/disk.h (grub_disk_read_hook_t): New type.
+	(struct grub_disk): Add read_hook_data member.
+	* include/grub/file.h (struct grub_file): Likewise.
+	* include/grub/fshelp.h (grub_fshelp_read_file): Add read_hook_data
+	argument.
+
+	Update all callers.
+
+2013-01-21  Colin Watson  <cjwatson@ubuntu.com>
+
 	* grub-core/partmap/msdos.c (embed_signatures): Add the signature of
 	an Acer registration utility with several sightings in the wild.
 	Reported by: Rickard Westman.  Fixes Ubuntu bug #987022.

=== modified file 'grub-core/commands/blocklist.c'
--- grub-core/commands/blocklist.c	2012-02-08 18:26:01 +0000
+++ grub-core/commands/blocklist.c	2013-01-21 09:46:39 +0000
@@ -28,58 +28,71 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
-static grub_err_t
-grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
-		    int argc, char **args)
+/* Context for grub_cmd_blocklist.  */
+struct blocklist_ctx
 {
-  grub_file_t file;
-  char buf[GRUB_DISK_SECTOR_SIZE];
-  unsigned long start_sector = 0;
-  unsigned num_sectors = 0;
-  int num_entries = 0;
-  grub_disk_addr_t part_start = 0;
-  auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
-			    unsigned length);
-  auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
-			     unsigned offset, unsigned length);
+  unsigned long start_sector;
+  unsigned num_sectors;
+  int num_entries;
+  grub_disk_addr_t part_start;
+};
+
+/* Helper for grub_cmd_blocklist.  */
+static void
+print_blocklist (grub_disk_addr_t sector, unsigned num,
+		 unsigned offset, unsigned length, struct blocklist_ctx *ctx)
+{
+  if (ctx->num_entries++)
+    grub_printf (",");
+
+  grub_printf ("%llu", (unsigned long long) (sector - ctx->part_start));
+  if (num > 0)
+    grub_printf ("+%u", num);
+  if (offset != 0 || length != 0)
+    grub_printf ("[%u-%u]", offset, offset + length);
+}
+
+/* Helper for grub_cmd_blocklist.  */
+static void
+read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length,
+		void *data)
+{
+  struct blocklist_ctx *ctx = data;
 
-  void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset,
-		       unsigned length)
+  if (ctx->num_sectors > 0)
     {
-      if (num_sectors > 0)
+      if (ctx->start_sector + ctx->num_sectors == sector
+	  && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
 	{
-	  if (start_sector + num_sectors == sector
-	      && offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
-	    {
-	      num_sectors++;
-	      return;
-	    }
-
-	  print_blocklist (start_sector, num_sectors, 0, 0);
-	  num_sectors = 0;
+	  ctx->num_sectors++;
+	  return;
 	}
 
-      if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
-	{
-	  start_sector = sector;
-	  num_sectors++;
-	}
-      else
-	print_blocklist (sector, 0, offset, length);
+      print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx);
+      ctx->num_sectors = 0;
     }
 
-  void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num,
-			unsigned offset, unsigned length)
+  if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE)
     {
-      if (num_entries++)
-	grub_printf (",");
-
-      grub_printf ("%llu", (unsigned long long) (sector - part_start));
-      if (num > 0)
-	grub_printf ("+%u", num);
-      if (offset != 0 || length != 0)
-	grub_printf ("[%u-%u]", offset, offset + length);
+      ctx->start_sector = sector;
+      ctx->num_sectors++;
     }
+  else
+    print_blocklist (sector, 0, offset, length, ctx);
+}
+
+static grub_err_t
+grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
+		    int argc, char **args)
+{
+  grub_file_t file;
+  char buf[GRUB_DISK_SECTOR_SIZE];
+  struct blocklist_ctx ctx = {
+    .start_sector = 0,
+    .num_sectors = 0,
+    .num_entries = 0,
+    .part_start = 0
+  };
 
   if (argc < 1)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -93,15 +106,16 @@ grub_cmd_blocklist (grub_command_t cmd _
     return grub_error (GRUB_ERR_BAD_DEVICE,
 		       "this command is available only for disk devices");
 
-  part_start = grub_partition_get_start (file->device->disk->partition);
+  ctx.part_start = grub_partition_get_start (file->device->disk->partition);
 
   file->read_hook = read_blocklist;
+  file->read_hook_data = &ctx;
 
   while (grub_file_read (file, buf, sizeof (buf)) > 0)
     ;
 
-  if (num_sectors > 0)
-    print_blocklist (start_sector, num_sectors, 0, 0);
+  if (ctx.num_sectors > 0)
+    print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx);
 
   grub_file_close (file);
 

=== modified file 'grub-core/commands/loadenv.c'
--- grub-core/commands/loadenv.c	2012-12-31 17:31:38 +0000
+++ grub-core/commands/loadenv.c	2013-01-21 11:29:26 +0000
@@ -284,44 +284,51 @@ write_blocklists (grub_envblk_t envblk,
   return 1;
 }
 
+/* Context for grub_cmd_save_env.  */
+struct grub_cmd_save_env_ctx
+{
+  struct blocklist *head, *tail;
+};
+
+/* Store blocklists in a linked list.  */
+static void
+save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
+		    void *data)
+{
+  struct grub_cmd_save_env_ctx *ctx = data;
+  struct blocklist *block;
+
+  if (offset + length > GRUB_DISK_SECTOR_SIZE)
+    /* Seemingly a bug.  */
+    return;
+
+  block = grub_malloc (sizeof (*block));
+  if (! block)
+    return;
+
+  block->sector = sector;
+  block->offset = offset;
+  block->length = length;
+
+  /* Slightly complicated, because the list should be FIFO.  */
+  block->next = 0;
+  if (ctx->tail)
+    ctx->tail->next = block;
+  ctx->tail = block;
+  if (! ctx->head)
+    ctx->head = block;
+}
+
 static grub_err_t
 grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
 {
   struct grub_arg_list *state = ctxt->state;
   grub_file_t file;
   grub_envblk_t envblk;
-  struct blocklist *head = 0;
-  struct blocklist *tail = 0;
-
-  /* Store blocklists in a linked list.  */
-  auto void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector,
-                                        unsigned offset,
-                                        unsigned length);
-  void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector,
-                                   unsigned offset, unsigned length)
-    {
-      struct blocklist *block;
-
-      if (offset + length > GRUB_DISK_SECTOR_SIZE)
-        /* Seemingly a bug.  */
-        return;
-
-      block = grub_malloc (sizeof (*block));
-      if (! block)
-        return;
-
-      block->sector = sector;
-      block->offset = offset;
-      block->length = length;
-
-      /* Slightly complicated, because the list should be FIFO.  */
-      block->next = 0;
-      if (tail)
-        tail->next = block;
-      tail = block;
-      if (! head)
-        head = block;
-    }
+  struct grub_cmd_save_env_ctx ctx = {
+    .head = 0,
+    .tail = 0
+  };
 
   if (! argc)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
@@ -336,13 +343,14 @@ grub_cmd_save_env (grub_extcmd_context_t
       return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
     }
 
-  file->read_hook = read_hook;
+  file->read_hook = save_env_read_hook;
+  file->read_hook_data = &ctx;
   envblk = read_envblk_file (file);
   file->read_hook = 0;
   if (! envblk)
     goto fail;
 
-  if (check_blocklists (envblk, head, file))
+  if (check_blocklists (envblk, ctx.head, file))
     goto fail;
 
   while (argc)
@@ -363,12 +371,12 @@ grub_cmd_save_env (grub_extcmd_context_t
       args++;
     }
 
-  write_blocklists (envblk, head, file);
+  write_blocklists (envblk, ctx.head, file);
 
  fail:
   if (envblk)
     grub_envblk_close (envblk);
-  free_blocklists (head);
+  free_blocklists (ctx.head);
   grub_file_close (file);
   return grub_errno;
 }

=== modified file 'grub-core/commands/testload.c'
--- grub-core/commands/testload.c	2012-02-24 11:30:32 +0000
+++ grub-core/commands/testload.c	2013-01-21 09:48:28 +0000
@@ -31,6 +31,17 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
+/* Helper for grub_cmd_testload.  */
+static void
+read_progress (grub_disk_addr_t sector __attribute__ ((unused)),
+	       unsigned offset __attribute__ ((unused)),
+	       unsigned len __attribute__ ((unused)),
+	       void *data __attribute__ ((unused)))
+{
+  grub_xputs (".");
+  grub_refresh ();
+}
+
 static grub_err_t
 grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
 		   int argc, char *argv[])
@@ -39,15 +50,6 @@ grub_cmd_testload (struct grub_command *
   char *buf;
   grub_size_t size;
   grub_off_t pos;
-  auto void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector, unsigned offset, unsigned len);
-
-  void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector __attribute__ ((unused)),
-		  unsigned offset __attribute__ ((unused)),
-		  unsigned len __attribute__ ((unused)))
-    {
-      grub_xputs (".");
-      grub_refresh ();
-    }
 
   if (argc < 1)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -68,7 +70,7 @@ grub_cmd_testload (struct grub_command *
     goto fail;
 
   grub_printf ("Reading %s sequentially", argv[0]);
-  file->read_hook = read_func;
+  file->read_hook = read_progress;
   if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
     goto fail;
   grub_printf (" Done.\n");

=== modified file 'grub-core/fs/affs.c'
--- grub-core/fs/affs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/affs.c	2013-01-21 09:46:14 +0000
@@ -531,7 +531,7 @@ grub_affs_read (grub_file_t file, char *
     (struct grub_affs_data *) file->data;
 
   return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen,
-				file->read_hook,
+				file->read_hook, file->read_hook_data,
 				file->offset, len, buf, grub_affs_read_block,
 				grub_be_to_cpu32 (data->diropen.di.size),
 				data->log_blocksize, 0);

=== modified file 'grub-core/fs/bfs.c'
--- grub-core/fs/bfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/bfs.c	2013-01-21 11:28:53 +0000
@@ -217,9 +217,7 @@ read_bfs_file (grub_disk_t disk,
 	       const struct grub_bfs_superblock *sb,
 	       const struct grub_bfs_inode *ino,
 	       grub_off_t off, void *buf, grub_size_t len,
-	       void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-						   unsigned offset,
-						   unsigned length))
+	       grub_disk_read_hook_t read_hook, void *read_hook_data)
 {
   if (len == 0)
     return GRUB_ERR_NONE;
@@ -245,6 +243,7 @@ read_bfs_file (grub_disk_t disk,
 	      if (read_size > len)
 		read_size = len;
 	      disk->read_hook = read_hook;
+	      disk->read_hook_data = read_hook_data;
 	      err = read_extent (disk, sb, &ino->direct[i], 0, off - pos,
 				 buf, read_size);
 	      disk->read_hook = 0;
@@ -290,6 +289,7 @@ read_bfs_file (grub_disk_t disk,
 	      if (read_size > len)
 		read_size = len;
 	      disk->read_hook = read_hook;
+	      disk->read_hook_data = read_hook_data;
 	      err = read_extent (disk, sb, &entries[i], 0, off - pos,
 				 buf, read_size);
 	      disk->read_hook = 0;
@@ -401,6 +401,7 @@ read_bfs_file (grub_disk_t disk,
 	if (read_size > len)
 	  read_size = len;
 	disk->read_hook = read_hook;
+	disk->read_hook_data = read_hook_data;
 	err = read_extent (disk, sb, &l2_entries[l2n], 0, boff,
 			   buf, read_size);
 	disk->read_hook = 0;
@@ -431,7 +432,7 @@ iterate_in_b_tree (grub_disk_t disk,
   int level;
   grub_uint64_t node_off;
 
-  err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0);
+  err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0);
   if (err)
     return 0;
   node_off = grub_bfs_to_cpu64 (head.root);
@@ -441,7 +442,8 @@ iterate_in_b_tree (grub_disk_t disk,
     {
       struct grub_bfs_btree_node node;
       grub_uint64_t key_value;
-      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
+      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
+			   0, 0);
       if (err)
 	return 0;
       err = read_bfs_file (disk, sb, ino, node_off
@@ -451,7 +453,7 @@ iterate_in_b_tree (grub_disk_t disk,
 				       BTREE_ALIGN) +
 			   grub_bfs_to_cpu_treehead (node.count_keys) *
 			   sizeof (grub_uint16_t), &key_value,
-			   sizeof (grub_uint64_t), 0);
+			   sizeof (grub_uint64_t), 0, 0);
       if (err)
 	return 0;
 
@@ -461,7 +463,8 @@ iterate_in_b_tree (grub_disk_t disk,
   while (1)
     {
       struct grub_bfs_btree_node node;
-      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
+      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
+			   0, 0);
       if (err)
 	return 0;
       {
@@ -473,7 +476,7 @@ iterate_in_b_tree (grub_disk_t disk,
 
 	err =
 	  read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data,
-			 grub_bfs_to_cpu_treehead (node.total_key_len), 0);
+			 grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0);
 	if (err)
 	  return 0;
 	key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0;
@@ -483,7 +486,7 @@ iterate_in_b_tree (grub_disk_t disk,
 					 (node.total_key_len), BTREE_ALIGN),
 			     keylen_idx,
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
-			     sizeof (grub_uint16_t), 0);
+			     sizeof (grub_uint16_t), 0, 0);
 	if (err)
 	  return 0;
 	err = read_bfs_file (disk, sb, ino, node_off
@@ -494,7 +497,7 @@ iterate_in_b_tree (grub_disk_t disk,
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
 			     sizeof (grub_uint16_t), key_values,
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
-			     sizeof (grub_uint64_t), 0);
+			     sizeof (grub_uint64_t), 0, 0);
 	if (err)
 	  return 0;
 
@@ -556,7 +559,7 @@ find_in_b_tree (grub_disk_t disk,
   int level;
   grub_uint64_t node_off;
 
-  err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0);
+  err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0);
   if (err)
     return err;
   node_off = grub_bfs_to_cpu64 (head.root);
@@ -565,7 +568,8 @@ find_in_b_tree (grub_disk_t disk,
   while (1)
     {
       struct grub_bfs_btree_node node;
-      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0);
+      err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node),
+			   0, 0);
       if (err)
 	return err;
       if (node.count_keys == 0)
@@ -578,7 +582,7 @@ find_in_b_tree (grub_disk_t disk,
 	unsigned i;
 	err =
 	  read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data,
-			 grub_bfs_to_cpu_treehead (node.total_key_len), 0);
+			 grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0);
 	if (err)
 	  return err;
 	key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0;
@@ -589,7 +593,7 @@ find_in_b_tree (grub_disk_t disk,
 								 total_key_len),
 				       BTREE_ALIGN), keylen_idx,
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
-			     sizeof (grub_uint16_t), 0);
+			     sizeof (grub_uint16_t), 0, 0);
 	if (err)
 	  return err;
 	err = read_bfs_file (disk, sb, ino, node_off
@@ -600,7 +604,7 @@ find_in_b_tree (grub_disk_t disk,
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
 			     sizeof (grub_uint16_t), key_values,
 			     grub_bfs_to_cpu_treehead (node.count_keys) *
-			     sizeof (grub_uint64_t), 0);
+			     sizeof (grub_uint64_t), 0, 0);
 	if (err)
 	  return err;
 
@@ -771,7 +775,7 @@ find_file (const char *path, grub_disk_t
 		  return grub_errno;
 		}
 	      grub_free (old_alloc);
-	      err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0);
+	      err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0, 0);
 	      if (err)
 		{
 		  grub_free (alloc);
@@ -974,7 +978,8 @@ grub_bfs_read (grub_file_t file, char *b
   struct grub_bfs_data *data = file->data;
 
   err = read_bfs_file (file->device->disk, &data->sb,
-		       data->ino, file->offset, buf, len, file->read_hook);
+		       data->ino, file->offset, buf, len,
+		       file->read_hook, file->read_hook_data);
   if (err)
     return -1;
   return len;
@@ -1056,7 +1061,7 @@ read_bfs_attr (grub_disk_t disk,
       if (read > len)
 	read = len;
 
-      err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0);
+      err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0, 0);
       if (err)
 	return -1;
       return read;

=== modified file 'grub-core/fs/ext2.c'
--- grub-core/fs/ext2.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/ext2.c	2013-01-21 12:02:09 +0000
@@ -525,11 +525,11 @@ grub_ext2_read_block (grub_fshelp_node_t
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_ext2_read_file (grub_fshelp_node_t node,
-		     void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-					unsigned offset, unsigned length),
+		     grub_disk_read_hook_t read_hook, void *read_hook_data,
 		     grub_off_t pos, grub_size_t len, char *buf)
 {
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+  return grub_fshelp_read_file (node->data->disk, node,
+				read_hook, read_hook_data,
 				pos, len, buf, grub_ext2_read_block,
 				grub_cpu_to_le32 (node->inode.size)
 				| (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32),
@@ -676,7 +676,7 @@ grub_ext2_read_symlink (grub_fshelp_node
 		  grub_le_to_cpu32 (diro->inode.size));
   else
     {
-      grub_ext2_read_file (diro, 0, 0,
+      grub_ext2_read_file (diro, 0, 0, 0,
 			   grub_le_to_cpu32 (diro->inode.size),
 			   symlink);
       if (grub_errno)
@@ -709,7 +709,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_
     {
       struct ext2_dirent dirent;
 
-      grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent),
+      grub_ext2_read_file (diro, 0, 0, fpos, sizeof (struct ext2_dirent),
 			   (char *) &dirent);
       if (grub_errno)
 	return 0;
@@ -723,7 +723,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_
 	  struct grub_fshelp_node *fdiro;
 	  enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
 
-	  grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent),
+	  grub_ext2_read_file (diro, 0, 0, fpos + sizeof (struct ext2_dirent),
 			       dirent.namelen, filename);
 	  if (grub_errno)
 	    return 0;
@@ -850,7 +850,8 @@ grub_ext2_read (grub_file_t file, char *
 {
   struct grub_ext2_data *data = (struct grub_ext2_data *) file->data;
 
-  return grub_ext2_read_file (&data->diropen, file->read_hook,
+  return grub_ext2_read_file (&data->diropen,
+			      file->read_hook, file->read_hook_data,
 			      file->offset, len, buf);
 }
 

=== modified file 'grub-core/fs/fat.c'
--- grub-core/fs/fat.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/fat.c	2013-01-21 11:29:18 +0000
@@ -454,8 +454,7 @@ grub_fat_mount (grub_disk_t disk)
 
 static grub_ssize_t
 grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-				       unsigned offset, unsigned length),
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
 		    grub_off_t offset, grub_size_t len, char *buf)
 {
   grub_size_t size;
@@ -561,6 +560,7 @@ grub_fat_read_data (grub_disk_t disk, st
 	size = len;
 
       disk->read_hook = read_hook;
+      disk->read_hook_data = read_hook_data;
       grub_disk_read (disk, sector, offset, size, buf);
       disk->read_hook = 0;
       if (grub_errno)
@@ -630,7 +630,7 @@ grub_fat_iterate_dir_next (grub_disk_t d
 
       ctxt->offset += sizeof (dir);
 
-      if (grub_fat_read_data (disk, data, 0, ctxt->offset, sizeof (dir),
+      if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (dir),
 			      (char *) &dir)
 	   != sizeof (dir))
 	break;
@@ -652,7 +652,7 @@ grub_fat_iterate_dir_next (grub_disk_t d
 	    {
 	      struct grub_fat_dir_entry sec;
 	      ctxt->offset += sizeof (sec);
-	      if (grub_fat_read_data (disk, data, 0,
+	      if (grub_fat_read_data (disk, data, 0, 0,
 				      ctxt->offset, sizeof (sec), (char *) &sec)
 		  != sizeof (sec))
 		break;
@@ -729,7 +729,7 @@ grub_fat_iterate_dir_next (grub_disk_t d
       ctxt->offset += sizeof (ctxt->dir);
 
       /* Read a directory entry.  */
-      if (grub_fat_read_data (disk, data, 0,
+      if (grub_fat_read_data (disk, data, 0, 0,
 			      ctxt->offset, sizeof (ctxt->dir),
 			      (char *) &ctxt->dir)
 	   != sizeof (ctxt->dir) || ctxt->dir.name[0] == 0)
@@ -1031,7 +1031,8 @@ grub_fat_open (grub_file_t file, const c
 static grub_ssize_t
 grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
 {
-  return grub_fat_read_data (file->device->disk, file->data, file->read_hook,
+  return grub_fat_read_data (file->device->disk, file->data,
+			     file->read_hook, file->read_hook_data,
 			     file->offset, len, buf);
 }
 
@@ -1064,7 +1065,7 @@ grub_fat_label (grub_device_t device, ch
     {
       offset += sizeof (dir);
 
-      if (grub_fat_read_data (disk, data, 0,
+      if (grub_fat_read_data (disk, data, 0, 0,
 			       offset, sizeof (dir), (char *) &dir)
 	   != sizeof (dir))
 	break;

=== modified file 'grub-core/fs/fshelp.c'
--- grub-core/fs/fshelp.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/fshelp.c	2013-01-21 11:29:13 +0000
@@ -242,14 +242,13 @@ grub_fshelp_find_file (const char *path,
 
 /* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
    beginning with the block POS.  READ_HOOK should be set before
-   reading a block from the file.  GET_BLOCK is used to translate file
-   blocks to disk blocks.  The file is FILESIZE bytes big and the
+   reading a block from the file.  READ_HOOK_DATA is passed through as
+   the DATA argument to READ_HOOK.  GET_BLOCK is used to translate
+   file blocks to disk blocks.  The file is FILESIZE bytes big and the
    blocks have a size of LOG2BLOCKSIZE (in log2).  */
 grub_ssize_t
 grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
-		       void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-                                                           unsigned offset,
-                                                           unsigned length),
+		       grub_disk_read_hook_t read_hook, void *read_hook_data,
 		       grub_off_t pos, grub_size_t len, char *buf,
 		       grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
                                                       grub_disk_addr_t block),
@@ -301,6 +300,7 @@ grub_fshelp_read_file (grub_disk_t disk,
       if (blknr)
 	{
 	  disk->read_hook = read_hook;
+	  disk->read_hook_data = read_hook_data;
 
 	  grub_disk_read (disk, blknr + blocks_start, skipfirst,
 			  blockend, buf);

=== modified file 'grub-core/fs/hfs.c'
--- grub-core/fs/hfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/hfs.c	2013-01-21 11:28:41 +0000
@@ -243,8 +243,7 @@ grub_hfs_block (struct grub_hfs_data *da
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_hfs_read_file (struct grub_hfs_data *data,
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-				       unsigned offset, unsigned length),
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
 		    grub_off_t pos, grub_size_t len, char *buf)
 {
   grub_off_t i;
@@ -289,6 +288,7 @@ grub_hfs_read_file (struct grub_hfs_data
       if (blknr)
 	{
 	  data->disk->read_hook = read_hook;
+	  data->disk->read_hook_data = read_hook_data;
 	  grub_disk_read (data->disk, blknr, skipfirst,
 			  blockend, buf);
 	  data->disk->read_hook = 0;
@@ -1269,7 +1269,8 @@ grub_hfs_read (grub_file_t file, char *b
   struct grub_hfs_data *data =
     (struct grub_hfs_data *) file->data;
 
-  return grub_hfs_read_file (data, file->read_hook, file->offset, len, buf);
+  return grub_hfs_read_file (data, file->read_hook, file->read_hook_data,
+			     file->offset, len, buf);
 }
 
 

=== modified file 'grub-core/fs/hfsplus.c'
--- grub-core/fs/hfsplus.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/hfsplus.c	2013-01-21 09:46:14 +0000
@@ -375,11 +375,11 @@ grub_hfsplus_read_block (grub_fshelp_nod
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_hfsplus_read_file (grub_fshelp_node_t node,
-			void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-					   unsigned offset, unsigned length),
+			grub_disk_read_hook_t read_hook, void *read_hook_data,
 			grub_off_t pos, grub_size_t len, char *buf)
 {
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+  return grub_fshelp_read_file (node->data->disk, node,
+				read_hook, read_hook_data,
 				pos, len, buf, grub_hfsplus_read_block,
 				node->size,
 				node->data->log2blksize - GRUB_DISK_SECTOR_BITS,
@@ -477,7 +477,7 @@ grub_hfsplus_mount (grub_disk_t disk)
     grub_be_to_cpu64 (data->volheader.extents_file.size);
 
   /* Read the essential information about the trees.  */
-  if (grub_hfsplus_read_file (&data->catalog_tree.file, 0,
+  if (grub_hfsplus_read_file (&data->catalog_tree.file, 0, 0,
 			      sizeof (struct grub_hfsplus_btnode),
 			      sizeof (header), (char *) &header) <= 0)
     goto fail;
@@ -487,14 +487,14 @@ grub_hfsplus_mount (grub_disk_t disk)
   data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) &&
 			  (header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE));
 
-  if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0,
+  if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
 			      sizeof (struct grub_hfsplus_btnode),
 			      sizeof (header), (char *) &header) <= 0)
     goto fail;
 
   data->extoverflow_tree.root = grub_be_to_cpu32 (header.root);
 
-  if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0,
+  if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, 0,
 			      sizeof (node), (char *) &node) <= 0)
     goto fail;
 
@@ -605,7 +605,7 @@ grub_hfsplus_read_symlink (grub_fshelp_n
   if (!symlink)
     return 0;
 
-  numread = grub_hfsplus_read_file (node, 0, 0, node->size, symlink);
+  numread = grub_hfsplus_read_file (node, 0, 0, 0, node->size, symlink);
   if (numread != (grub_ssize_t) node->size)
     {
       grub_free (symlink);
@@ -649,7 +649,7 @@ grub_hfsplus_btree_iterate_node (struct
 	saved_node = first_node->next;
       node_count++;
 
-      if (grub_hfsplus_read_file (&btree->file, 0,
+      if (grub_hfsplus_read_file (&btree->file, 0, 0,
 				  (((grub_disk_addr_t)
 				    grub_be_to_cpu32 (first_node->next))
 				   * btree->nodesize),
@@ -702,7 +702,7 @@ grub_hfsplus_btree_search (struct grub_h
       node_count++;
 
       /* Read a node.  */
-      if (grub_hfsplus_read_file (&btree->file, 0,
+      if (grub_hfsplus_read_file (&btree->file, 0, 0,
 				  (grub_disk_addr_t) currnode
 				  * (grub_disk_addr_t) btree->nodesize,
 				  btree->nodesize, (char *) node) <= 0)
@@ -971,8 +971,9 @@ grub_hfsplus_read (grub_file_t file, cha
   struct grub_hfsplus_data *data =
     (struct grub_hfsplus_data *) file->data;
 
-  return grub_hfsplus_read_file (&data->opened_file, file->read_hook,
-				     file->offset, len, buf);
+  return grub_hfsplus_read_file (&data->opened_file,
+				 file->read_hook, file->read_hook_data,
+				 file->offset, len, buf);
 }
 
 /* Context for grub_hfsplus_dir.  */

=== modified file 'grub-core/fs/iso9660.c'
--- grub-core/fs/iso9660.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/iso9660.c	2013-01-21 12:07:49 +0000
@@ -961,6 +961,7 @@ grub_iso9660_read (grub_file_t file, cha
 
   /* XXX: The file is stored in as a single extent.  */
   data->disk->read_hook = file->read_hook;
+  data->disk->read_hook_data = file->read_hook_data;
   read_node (data->node, file->offset, len, buf);
   data->disk->read_hook = NULL;
 

=== modified file 'grub-core/fs/jfs.c'
--- grub-core/fs/jfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/jfs.c	2013-01-21 11:28:44 +0000
@@ -577,8 +577,7 @@ grub_jfs_getent (struct grub_jfs_diropen
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_jfs_read_file (struct grub_jfs_data *data,
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-				       unsigned offset, unsigned length),
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
 		    grub_off_t pos, grub_size_t len, char *buf)
 {
   grub_off_t i;
@@ -616,6 +615,7 @@ grub_jfs_read_file (struct grub_jfs_data
 	}
 
       data->disk->read_hook = read_hook;
+      data->disk->read_hook_data = read_hook_data;
       grub_disk_read (data->disk,
 		      blknr << (grub_le_to_cpu16 (data->sblock.log2_blksz)
 				- GRUB_DISK_SECTOR_BITS),
@@ -782,7 +782,7 @@ grub_jfs_lookup_symlink (struct grub_jfs
 
   if (size <= sizeof (data->currinode.symlink.path))
     grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size);
-  else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0)
+  else if (grub_jfs_read_file (data, 0, 0, 0, size, symlink) < 0)
     return grub_errno;
 
   symlink[size] = '\0';
@@ -894,7 +894,8 @@ grub_jfs_read (grub_file_t file, char *b
   struct grub_jfs_data *data =
     (struct grub_jfs_data *) file->data;
 
-  return grub_jfs_read_file (data, file->read_hook, file->offset, len, buf);
+  return grub_jfs_read_file (data, file->read_hook, file->read_hook_data,
+			     file->offset, len, buf);
 }
 
 

=== modified file 'grub-core/fs/minix.c'
--- grub-core/fs/minix.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/minix.c	2013-01-21 11:29:15 +0000
@@ -249,8 +249,7 @@ grub_minix_get_file_block (struct grub_m
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_minix_read_file (struct grub_minix_data *data,
-		      void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-					 unsigned offset, unsigned length),
+		      grub_disk_read_hook_t read_hook, void *read_hook_data,
 		      grub_off_t pos, grub_size_t len, char *buf)
 {
   grub_uint32_t i;
@@ -301,6 +300,7 @@ grub_minix_read_file (struct grub_minix_
 	}
 
       data->disk->read_hook = read_hook;
+      data->disk->read_hook_data = read_hook_data;
       grub_disk_read (data->disk,
 		      GRUB_MINIX_ZONE2SECT(blknr),
 		      skipfirst, blockend, buf);
@@ -352,7 +352,7 @@ grub_minix_lookup_symlink (struct grub_m
   if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT)
     return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks"));
 
-  if (grub_minix_read_file (data, 0, 0,
+  if (grub_minix_read_file (data, 0, 0, 0,
 			    GRUB_MINIX_INODE_SIZE (data), symlink) < 0)
     return grub_errno;
 
@@ -409,10 +409,10 @@ grub_minix_find_file (struct grub_minix_
       if (grub_strlen (name) == 0)
 	return GRUB_ERR_NONE;
 
-      if (grub_minix_read_file (data, 0, pos, sizeof (ino),
+      if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino),
 				(char *) &ino) < 0)
 	return grub_errno;
-      if (grub_minix_read_file (data, 0, pos + sizeof (ino),
+      if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino),
 				data->filename_size, (char *) filename)< 0)
 	return grub_errno;
 
@@ -568,11 +568,11 @@ grub_minix_dir (grub_device_t device, co
       grub_memset (&info, 0, sizeof (info));
 
 
-      if (grub_minix_read_file (data, 0, pos, sizeof (ino),
+      if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino),
 				(char *) &ino) < 0)
 	return grub_errno;
 
-      if (grub_minix_read_file (data, 0, pos + sizeof (ino),
+      if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino),
 				data->filename_size,
 				(char *) filename) < 0)
 	return grub_errno;
@@ -649,7 +649,8 @@ grub_minix_read (grub_file_t file, char
   struct grub_minix_data *data =
     (struct grub_minix_data *) file->data;
 
-  return grub_minix_read_file (data, file->read_hook, file->offset, len, buf);
+  return grub_minix_read_file (data, file->read_hook, file->read_hook_data,
+			       file->offset, len, buf);
 }
 
 

=== modified file 'grub-core/fs/nilfs2.c'
--- grub-core/fs/nilfs2.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/nilfs2.c	2013-01-21 09:46:14 +0000
@@ -630,13 +630,11 @@ grub_nilfs2_read_block (grub_fshelp_node
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_nilfs2_read_file (grub_fshelp_node_t node,
-		       void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
-							   sector,
-							   unsigned offset,
-							   unsigned length),
+		       grub_disk_read_hook_t read_hook, void *read_hook_data,
 		       grub_off_t pos, grub_size_t len, char *buf)
 {
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+  return grub_fshelp_read_file (node->data->disk, node,
+				read_hook, read_hook_data,
 				pos, len, buf, grub_nilfs2_read_block,
 				grub_le_to_cpu64 (node->inode.i_size),
 				LOG2_NILFS2_BLOCK_SIZE (node->data), 0);
@@ -856,7 +854,7 @@ grub_nilfs2_read_symlink (grub_fshelp_no
   if (!symlink)
     return 0;
 
-  grub_nilfs2_read_file (diro, 0, 0,
+  grub_nilfs2_read_file (diro, 0, 0, 0,
 			 grub_le_to_cpu64 (diro->inode.i_size), symlink);
   if (grub_errno)
     {
@@ -887,7 +885,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_nod
     {
       struct grub_nilfs2_dir_entry dirent;
 
-      grub_nilfs2_read_file (diro, 0, fpos,
+      grub_nilfs2_read_file (diro, 0, 0, fpos,
 			     sizeof (struct grub_nilfs2_dir_entry),
 			     (char *) &dirent);
       if (grub_errno)
@@ -902,7 +900,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_nod
 	  struct grub_fshelp_node *fdiro;
 	  enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
 
-	  grub_nilfs2_read_file (diro, 0,
+	  grub_nilfs2_read_file (diro, 0, 0,
 				 fpos + sizeof (struct grub_nilfs2_dir_entry),
 				 dirent.name_len, filename);
 	  if (grub_errno)
@@ -1025,7 +1023,8 @@ grub_nilfs2_read (grub_file_t file, char
 {
   struct grub_nilfs2_data *data = (struct grub_nilfs2_data *) file->data;
 
-  return grub_nilfs2_read_file (&data->diropen, file->read_hook,
+  return grub_nilfs2_read_file (&data->diropen,
+				file->read_hook, file->read_hook_data,
 				file->offset, len, buf);
 }
 

=== modified file 'grub-core/fs/ntfs.c'
--- grub-core/fs/ntfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/ntfs.c	2013-01-21 11:28:33 +0000
@@ -91,21 +91,15 @@ static grub_err_t read_mft (struct grub_
 static grub_err_t read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest,
 			     grub_disk_addr_t ofs, grub_size_t len,
 			     int cached,
-			     void
-			     NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
-							    sector,
-							    unsigned offset,
-							    unsigned length));
+			     grub_disk_read_hook_t read_hook,
+			     void *read_hook_data);
 
 static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa,
 			     grub_uint8_t *dest,
 			     grub_disk_addr_t ofs, grub_size_t len,
 			     int cached,
-			     void
-			     NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t
-							    sector,
-							    unsigned offset,
-							    unsigned length));
+			     grub_disk_read_hook_t read_hook,
+			     void *read_hook_data);
 
 static void
 init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
@@ -207,7 +201,7 @@ find_attr (struct grub_ntfs_attr *at, gr
 	  at->edat_buf = grub_malloc (n);
 	  if (!at->edat_buf)
 	    return NULL;
-	  if (read_data (at, pa, at->edat_buf, 0, n, 0, 0))
+	  if (read_data (at, pa, at->edat_buf, 0, n, 0, 0, 0))
 	    {
 	      grub_error (GRUB_ERR_BAD_FS,
 			  "fail to read non-resident attribute list");
@@ -249,7 +243,7 @@ find_attr (struct grub_ntfs_attr *at, gr
 	      if (read_attr
 		  (at, pa + 0x10,
 		   u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
-		   at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0))
+		   at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
 		return NULL;
 	      pa += u16at (pa, 4);
 	    }
@@ -325,9 +319,7 @@ retry:
     {
       if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST))
 	{
-	  void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector,
-					      unsigned offset,
-					      unsigned length);
+	  grub_disk_read_hook_t save_hook;
 
 	  save_hook = ctx->comp.disk->read_hook;
 	  ctx->comp.disk->read_hook = 0;
@@ -379,9 +371,7 @@ grub_ntfs_read_block (grub_fshelp_node_t
 static grub_err_t
 read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
 	   grub_disk_addr_t ofs, grub_size_t len, int cached,
-	   void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-					       unsigned offset,
-					       unsigned length))
+	   grub_disk_read_hook_t read_hook, void *read_hook_data)
 {
   grub_disk_addr_t vcn;
   struct grub_ntfs_rlst cc, *ctx;
@@ -480,7 +470,8 @@ read_data (struct grub_ntfs_attr *at, gr
   if (!(ctx->flags & GRUB_NTFS_RF_COMP))
     {
       grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx,
-			     read_hook, ofs, len, (char *) dest,
+			     read_hook, read_hook_data, ofs, len,
+			     (char *) dest,
 			     grub_ntfs_read_block, ofs + len,
 			     ctx->comp.log_spc, 0);
       return grub_errno;
@@ -495,9 +486,7 @@ read_data (struct grub_ntfs_attr *at, gr
 static grub_err_t
 read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs,
 	   grub_size_t len, int cached,
-	   void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-					       unsigned offset,
-					       unsigned length))
+	   grub_disk_read_hook_t read_hook, void *read_hook_data)
 {
   grub_uint8_t *save_cur;
   grub_uint8_t attr;
@@ -532,7 +521,8 @@ read_attr (struct grub_ntfs_attr *at, gr
     }
   pp = find_attr (at, attr);
   if (pp)
-    ret = read_data (at, pp, dest, ofs, len, cached, read_hook);
+    ret = read_data (at, pp, dest, ofs, len, cached,
+		     read_hook, read_hook_data);
   else
     ret =
       (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS,
@@ -546,7 +536,7 @@ read_mft (struct grub_ntfs_data *data, g
 {
   if (read_attr
       (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR),
-       data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0))
+       data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0))
     return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%X fails", mftno);
   return fixup (buf, data->mft_size, (const grub_uint8_t *) "FILE");
 }
@@ -717,7 +707,7 @@ grub_ntfs_read_symlink (grub_fshelp_node
     }
 
   err = read_attr (&mft->attr, (grub_uint8_t *) &symdesc, 0,
-		   sizeof (struct symlink_descriptor), 1, 0);
+		   sizeof (struct symlink_descriptor), 1, 0, 0);
   if (err)
     return NULL;
 
@@ -743,7 +733,7 @@ grub_ntfs_read_symlink (grub_fshelp_node
   if (!buf16)
     return NULL;
 
-  err = read_attr (&mft->attr, (grub_uint8_t *) buf16, off, len, 1, 0);
+  err = read_attr (&mft->attr, (grub_uint8_t *) buf16, off, len, 1, 0, 0);
   if (err)
     return NULL;
 
@@ -852,7 +842,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_
 	    }
           else
             {
-              if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0))
+              if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0))
                 {
                   grub_error (GRUB_ERR_BAD_FS,
                               "fails to read non-resident $BITMAP");
@@ -899,7 +889,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_
 	    {
 	      if ((read_attr
 		   (at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
-		    (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0))
+		    (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0, 0))
 		  || (fixup (indx, mft->data->idx_size,
 			     (const grub_uint8_t *) "INDX")))
 		goto done;
@@ -1136,7 +1126,7 @@ grub_ntfs_read (grub_file_t file, char *
     mft->attr.save_pos = 1;
 
   read_attr (&mft->attr, (grub_uint8_t *) buf, file->offset, len, 1,
-	     file->read_hook);
+	     file->read_hook, file->read_hook_data);
   return (grub_errno) ? -1 : (grub_ssize_t) len;
 }
 

=== modified file 'grub-core/fs/ntfscomp.c'
--- grub-core/fs/ntfscomp.c	2013-01-11 06:41:05 +0000
+++ grub-core/fs/ntfscomp.c	2013-01-21 11:29:00 +0000
@@ -302,6 +302,7 @@ ntfscomp (struct grub_ntfs_attr *at, gru
   ret = 0;
 
   //ctx->comp.disk->read_hook = read_hook;
+  //ctx->comp.disk->read_hook_data = read_hook_data;
 
   if ((vcn > ctx->target_vcn) &&
       (read_block

=== modified file 'grub-core/fs/reiserfs.c'
--- grub-core/fs/reiserfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/reiserfs.c	2013-01-21 11:29:06 +0000
@@ -240,9 +240,8 @@ struct grub_reiserfs_data
 static grub_ssize_t
 grub_reiserfs_read_real (struct grub_fshelp_node *node,
 			 grub_off_t off, char *buf, grub_size_t len,
-			 void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-							     unsigned offset,
-							     unsigned length));
+			 grub_disk_read_hook_t read_hook,
+			 void *read_hook_data);
 
 /* Internal-only functions. Not to be used outside of this file.  */
 
@@ -674,7 +673,7 @@ grub_reiserfs_read_symlink (grub_fshelp_
   if (! symlink_buffer)
     return 0;
 
-  ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0);
+  ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0, 0);
   if (ret < 0)
     {
       grub_free (symlink_buffer);
@@ -1036,9 +1035,7 @@ grub_reiserfs_open (struct grub_file *fi
 static grub_ssize_t
 grub_reiserfs_read_real (struct grub_fshelp_node *node,
 			 grub_off_t off, char *buf, grub_size_t len,
-			 void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-							     unsigned offset,
-							     unsigned length))
+			 grub_disk_read_hook_t read_hook, void *read_hook_data)
 {
   unsigned int indirect_block, indirect_block_count;
   struct grub_reiserfs_key key;
@@ -1105,6 +1102,7 @@ grub_reiserfs_read_real (struct grub_fsh
                             (unsigned) block, (unsigned) offset,
                             (unsigned) (offset + length));
               found.data->disk->read_hook = read_hook;
+              found.data->disk->read_hook_data = read_hook_data;
               grub_disk_read (found.data->disk,
                               block,
                               offset
@@ -1131,6 +1129,7 @@ grub_reiserfs_read_real (struct grub_fsh
           if (grub_errno)
             goto fail;
           found.data->disk->read_hook = read_hook;
+          found.data->disk->read_hook_data = read_hook_data;
           for (indirect_block = 0;
                indirect_block < indirect_block_count
                  && current_position < final_position;
@@ -1236,7 +1235,7 @@ static grub_ssize_t
 grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
 {
   return grub_reiserfs_read_real (file->data, file->offset, buf, len,
-				  file->read_hook);
+				  file->read_hook, file->read_hook_data);
 }
 
 /* Close the file FILE.  */

=== modified file 'grub-core/fs/romfs.c'
--- grub-core/fs/romfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/romfs.c	2013-01-21 12:08:09 +0000
@@ -399,6 +399,7 @@ grub_romfs_read (grub_file_t file, char
 
   /* XXX: The file is stored in as a single extent.  */
   data->data->disk->read_hook = file->read_hook;
+  data->data->disk->read_hook_data = file->read_hook_data;
   grub_disk_read (data->data->disk,
 		  (data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS,
 		  (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1),		  

=== modified file 'grub-core/fs/sfs.c'
--- grub-core/fs/sfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/sfs.c	2013-01-21 09:46:14 +0000
@@ -345,11 +345,11 @@ grub_sfs_read_block (grub_fshelp_node_t
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_sfs_read_file (grub_fshelp_node_t node,
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-				       unsigned offset, unsigned length),
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
 		    grub_off_t pos, grub_size_t len, char *buf)
 {
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+  return grub_fshelp_read_file (node->data->disk, node,
+				read_hook, read_hook_data,
 				pos, len, buf, grub_sfs_read_block,
 				node->size, node->data->log_blocksize, 0);
 }
@@ -646,7 +646,8 @@ grub_sfs_read (grub_file_t file, char *b
 {
   struct grub_sfs_data *data = (struct grub_sfs_data *) file->data;
 
-  return grub_sfs_read_file (&data->diropen, file->read_hook,
+  return grub_sfs_read_file (&data->diropen,
+			     file->read_hook, file->read_hook_data,
 			     file->offset, len, buf);
 }
 

=== modified file 'grub-core/fs/udf.c'
--- grub-core/fs/udf.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/udf.c	2013-01-21 09:46:14 +0000
@@ -564,9 +564,7 @@ fail:
 
 static grub_ssize_t
 grub_udf_read_file (grub_fshelp_node_t node,
-		    void NESTED_FUNC_ATTR
-		    (*read_hook) (grub_disk_addr_t sector,
-				  unsigned offset, unsigned length),
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
 		    grub_off_t pos, grub_size_t len, char *buf)
 {
   switch (U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK)
@@ -591,10 +589,11 @@ grub_udf_read_file (grub_fshelp_node_t n
       return 0;
     }
 
-  return  grub_fshelp_read_file (node->data->disk, node, read_hook,
-				 pos, len, buf, grub_udf_read_block,
-				 U64 (node->block.fe.file_size),
-				 node->data->lbshift, 0);
+  return grub_fshelp_read_file (node->data->disk, node,
+				read_hook, read_hook_data,
+				pos, len, buf, grub_udf_read_block,
+				U64 (node->block.fe.file_size),
+				node->data->lbshift, 0);
 }
 
 static unsigned sblocklist[] = { 256, 512, 0 };
@@ -861,7 +860,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t
 
   while (offset < U64 (dir->block.fe.file_size))
     {
-      if (grub_udf_read_file (dir, 0, offset, sizeof (dirent),
+      if (grub_udf_read_file (dir, 0, 0, offset, sizeof (dirent),
 			      (char *) &dirent) != sizeof (dirent))
 	return 0;
 
@@ -898,7 +897,7 @@ grub_udf_iterate_dir (grub_fshelp_node_t
 	      if (child->block.fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK)
 		type = GRUB_FSHELP_SYMLINK;
 
-	      if ((grub_udf_read_file (dir, 0, offset,
+	      if ((grub_udf_read_file (dir, 0, 0, offset,
 				       dirent.file_ident_length,
 				       (char *) raw))
 		  != dirent.file_ident_length)
@@ -937,7 +936,7 @@ grub_udf_read_symlink (grub_fshelp_node_
   raw = grub_malloc (sz);
   if (!raw)
     return NULL;
-  if (grub_udf_read_file (node, NULL, 0, sz, (char *) raw) < 0)
+  if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0)
     {
       grub_free (raw);
       return NULL;
@@ -1149,7 +1148,8 @@ grub_udf_read (grub_file_t file, char *b
 {
   struct grub_fshelp_node *node = (struct grub_fshelp_node *) file->data;
 
-  return grub_udf_read_file (node, file->read_hook, file->offset, len, buf);
+  return grub_udf_read_file (node, file->read_hook, file->read_hook_data,
+			     file->offset, len, buf);
 }
 
 static grub_err_t

=== modified file 'grub-core/fs/ufs.c'
--- grub-core/fs/ufs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/ufs.c	2013-01-21 11:28:56 +0000
@@ -331,8 +331,7 @@ grub_ufs_get_file_block (struct grub_ufs
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_ufs_read_file (struct grub_ufs_data *data,
-		    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-				       unsigned offset, unsigned length),
+		    grub_disk_read_hook_t read_hook, void *read_hook_data,
 		    grub_off_t pos, grub_size_t len, char *buf)
 {
   struct grub_ufs_sblock *sblock = &data->sblock;
@@ -380,6 +379,7 @@ grub_ufs_read_file (struct grub_ufs_data
       if (blknr)
 	{
 	  data->disk->read_hook = read_hook;
+	  data->disk->read_hook_data = read_hook_data;
 	  grub_disk_read (data->disk,
 			  blknr << grub_ufs_to_cpu32 (data->sblock.log2_blksz),
 			  skipfirst, blockend, buf);
@@ -455,7 +455,7 @@ grub_ufs_lookup_symlink (struct grub_ufs
       && INODE_SIZE (data) <= sizeof (data->inode.symlink))
     grub_strcpy (symlink, (char *) data->inode.symlink);
   else
-    grub_ufs_read_file (data, 0, 0, INODE_SIZE (data), symlink);
+    grub_ufs_read_file (data, 0, 0, 0, INODE_SIZE (data), symlink);
   symlink[INODE_SIZE (data)] = '\0';
 
   /* The symlink is an absolute path, go back to the root inode.  */
@@ -509,7 +509,7 @@ grub_ufs_find_file (struct grub_ufs_data
       if (grub_strlen (name) == 0)
 	return GRUB_ERR_NONE;
 
-      if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
+      if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent),
 			      (char *) &dirent) < 0)
 	return grub_errno;
 
@@ -521,7 +521,7 @@ grub_ufs_find_file (struct grub_ufs_data
       {
 	char filename[namelen + 1];
 
-	if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
+	if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
 				namelen, filename) < 0)
 	  return grub_errno;
 
@@ -659,7 +659,7 @@ grub_ufs_dir (grub_device_t device, cons
       struct grub_ufs_dirent dirent;
       int namelen;
 
-      if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
+      if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent),
 			      (char *) &dirent) < 0)
 	break;
 
@@ -679,7 +679,7 @@ grub_ufs_dir (grub_device_t device, cons
 
 	grub_memset (&info, 0, sizeof (info));
 
-	if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
+	if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
 				namelen, filename) < 0)
 	  break;
 
@@ -752,7 +752,8 @@ grub_ufs_read (grub_file_t file, char *b
   struct grub_ufs_data *data =
     (struct grub_ufs_data *) file->data;
 
-  return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf);
+  return grub_ufs_read_file (data, file->read_hook, file->read_hook_data,
+			     file->offset, len, buf);
 }
 
 

=== modified file 'grub-core/fs/xfs.c'
--- grub-core/fs/xfs.c	2013-01-21 01:33:46 +0000
+++ grub-core/fs/xfs.c	2013-01-21 09:46:14 +0000
@@ -381,11 +381,11 @@ grub_xfs_read_block (grub_fshelp_node_t
    POS.  Return the amount of read bytes in READ.  */
 static grub_ssize_t
 grub_xfs_read_file (grub_fshelp_node_t node,
-		     void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-					unsigned offset, unsigned length),
+		     grub_disk_read_hook_t read_hook, void *read_hook_data,
 		     grub_off_t pos, grub_size_t len, char *buf)
 {
-  return grub_fshelp_read_file (node->data->disk, node, read_hook,
+  return grub_fshelp_read_file (node->data->disk, node,
+				read_hook, read_hook_data,
 				pos, len, buf, grub_xfs_read_block,
 				grub_be_to_cpu64 (node->inode.size),
 				node->data->sblock.log2_bsize
@@ -412,7 +412,7 @@ grub_xfs_read_symlink (grub_fshelp_node_
 	if (!symlink)
 	  return 0;
 
-	numread = grub_xfs_read_file (node, 0, 0, size, symlink);
+	numread = grub_xfs_read_file (node, 0, 0, 0, size, symlink);
 	if (numread != size)
 	  {
 	    grub_free (symlink);
@@ -594,7 +594,7 @@ grub_xfs_iterate_dir (grub_fshelp_node_t
 	    struct grub_xfs_dirblock_tail *tail;
 	    tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
 
-	    numread = grub_xfs_read_file (dir, 0,
+	    numread = grub_xfs_read_file (dir, 0, 0,
 					  blk << dirblk_log2,
 					  dirblk_size, dirblock);
 	    if (numread != dirblk_size)
@@ -831,8 +831,9 @@ grub_xfs_read (grub_file_t file, char *b
   struct grub_xfs_data *data =
     (struct grub_xfs_data *) file->data;
 
-  return grub_xfs_read_file (&data->diropen, file->read_hook,
-			      file->offset, len, buf);
+  return grub_xfs_read_file (&data->diropen,
+			     file->read_hook, file->read_hook_data,
+			     file->offset, len, buf);
 }
 
 

=== modified file 'grub-core/kern/disk.c'
--- grub-core/kern/disk.c	2013-01-10 07:09:26 +0000
+++ grub-core/kern/disk.c	2013-01-21 09:46:14 +0000
@@ -603,7 +603,7 @@ grub_disk_read (grub_disk_t disk, grub_d
 	  cl = GRUB_DISK_SECTOR_SIZE - o;
 	  if (cl > l)
 	    cl = l;
-	  (disk->read_hook) (s, o, cl);
+	  (disk->read_hook) (s, o, cl, disk->read_hook_data);
 	  s++;
 	  l -= cl;
 	  o = 0;

=== modified file 'include/grub/disk.h'
--- include/grub/disk.h	2013-01-20 15:52:15 +0000
+++ include/grub/disk.h	2013-01-21 09:46:14 +0000
@@ -99,6 +99,10 @@ extern grub_disk_dev_t EXPORT_VAR (grub_
 
 struct grub_partition;
 
+typedef void (*grub_disk_read_hook_t) (grub_disk_addr_t sector,
+				       unsigned offset, unsigned length,
+				       void *data);
+
 /* Disk.  */
 struct grub_disk
 {
@@ -122,8 +126,10 @@ struct grub_disk
 
   /* Called when a sector was read. OFFSET is between 0 and
      the sector size minus 1, and LENGTH is between 0 and the sector size.  */
-  void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-		     unsigned offset, unsigned length);
+  grub_disk_read_hook_t read_hook;
+
+  /* Caller-specific data passed to the read hook.  */
+  void *read_hook_data;
 
   /* Device-specific data.  */
   void *data;

=== modified file 'include/grub/file.h'
--- include/grub/file.h	2013-01-11 20:32:42 +0000
+++ include/grub/file.h	2013-01-21 09:46:14 +0000
@@ -23,6 +23,7 @@
 #include <grub/err.h>
 #include <grub/device.h>
 #include <grub/fs.h>
+#include <grub/disk.h>
 
 /* File description.  */
 struct grub_file
@@ -46,8 +47,10 @@ struct grub_file
   void *data;
 
   /* This is called when a sector is read. Used only for a disk device.  */
-  void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-		     unsigned offset, unsigned length);
+  grub_disk_read_hook_t read_hook;
+
+  /* Caller-specific data passed to the read hook.  */
+  void *read_hook_data;
 };
 typedef struct grub_file *grub_file_t;
 

=== modified file 'include/grub/fshelp.h'
--- include/grub/fshelp.h	2013-01-21 01:33:46 +0000
+++ include/grub/fshelp.h	2013-01-21 09:46:14 +0000
@@ -23,6 +23,7 @@
 #include <grub/types.h>
 #include <grub/symbol.h>
 #include <grub/err.h>
+#include <grub/disk.h>
 
 typedef struct grub_fshelp_node *grub_fshelp_node_t;
 
@@ -68,9 +69,8 @@ EXPORT_FUNC(grub_fshelp_find_file) (cons
    blocks have a size of LOG2BLOCKSIZE (in log2).  */
 grub_ssize_t
 EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node,
-				    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
-                                                                        unsigned offset,
-                                                                        unsigned length),
+				    grub_disk_read_hook_t read_hook,
+				    void *read_hook_data,
 				    grub_off_t pos, grub_size_t len, char *buf,
 				    grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
                                                                    grub_disk_addr_t block),

=== modified file 'util/grub-setup.c'
--- util/grub-setup.c	2013-01-20 15:52:15 +0000
+++ util/grub-setup.c	2013-01-21 09:46:14 +0000
@@ -138,6 +138,70 @@ write_rootdev (grub_device_t root_dev,
 #define BOOT_SECTOR 0
 #endif
 
+/* Helper for setup.  */
+static void
+save_first_sector (grub_disk_addr_t sector, unsigned offset, unsigned length,
+		   void *data)
+{
+  grub_disk_addr_t *first_sector = data;
+  grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>",
+		  sector, offset, length);
+
+  if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
+    grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
+
+  *first_sector = sector;
+}
+
+struct blocklists
+{
+  struct grub_boot_blocklist *first_block, *block;
+#ifdef GRUB_SETUP_BIOS
+  grub_uint16_t current_segment;
+#endif
+  grub_uint16_t last_length;
+};
+
+/* Helper for setup.  */
+static void
+save_blocklists (grub_disk_addr_t sector, unsigned offset, unsigned length,
+		 void *data)
+{
+  struct blocklists *bl = data;
+  struct grub_boot_blocklist *prev = bl->block + 1;
+
+  grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
+		  sector, offset, length);
+
+  if (offset != 0 || bl->last_length != GRUB_DISK_SECTOR_SIZE)
+    grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
+
+  if (bl->block != bl->first_block
+      && (grub_target_to_host64 (prev->start)
+	  + grub_target_to_host16 (prev->len)) == sector)
+    {
+      grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
+      prev->len = grub_host_to_target16 (t);
+    }
+  else
+    {
+      bl->block->start = grub_host_to_target64 (sector);
+      bl->block->len = grub_host_to_target16 (1);
+#ifdef GRUB_SETUP_BIOS
+      bl->block->segment = grub_host_to_target16 (bl->current_segment);
+#endif
+
+      bl->block--;
+      if (bl->block->len)
+	grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
+    }
+
+  bl->last_length = length;
+#ifdef GRUB_SETUP_BIOS
+  bl->current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
+#endif
+}
+
 #ifdef GRUB_SETUP_BIOS
 /* Context for setup/identify_partmap.  */
 struct identify_partmap_ctx
@@ -147,7 +211,7 @@ struct identify_partmap_ctx
   int multiple_partmaps;
 };
 
-/* Helper for setup/identify_partmap.
+/* Helper for setup.
    Unlike root_dev, with dest_dev we're interested in the partition map even
    if dest_dev itself is a whole disk.  */
 static int
@@ -190,73 +254,16 @@ setup (const char *dir,
   grub_uint16_t core_sectors;
 #endif
   grub_device_t root_dev = 0, dest_dev, core_dev;
-  struct grub_boot_blocklist *first_block, *block;
+  struct blocklists bl;
   char *tmp_img;
   grub_disk_addr_t first_sector;
-#ifdef GRUB_SETUP_BIOS
-  grub_uint16_t current_segment
-    = GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
-#endif
-  grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
   FILE *fp;
 
-  auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
-						unsigned offset,
-						unsigned length);
-  auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
-					      unsigned offset,
-					      unsigned length);
-
-  void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector,
-					   unsigned offset,
-					   unsigned length)
-    {
-      grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>",
-		      sector, offset, length);
-
-      if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE)
-	grub_util_error ("%s", _("the first sector of the core file is not sector-aligned"));
-
-      first_sector = sector;
-    }
-
-  void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector,
-					 unsigned offset,
-					 unsigned length)
-    {
-      struct grub_boot_blocklist *prev = block + 1;
-
-      grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>",
-		      sector, offset, length);
-
-      if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE)
-	grub_util_error ("%s", _("non-sector-aligned data is found in the core file"));
-
-      if (block != first_block
-	  && (grub_target_to_host64 (prev->start)
-	      + grub_target_to_host16 (prev->len)) == sector)
-	{
-	  grub_uint16_t t = grub_target_to_host16 (prev->len) + 1;
-	  prev->len = grub_host_to_target16 (t);
-	}
-      else
-	{
-	  block->start = grub_host_to_target64 (sector);
-	  block->len = grub_host_to_target16 (1);
 #ifdef GRUB_SETUP_BIOS
-	  block->segment = grub_host_to_target16 (current_segment);
+  bl.current_segment =
+    GRUB_BOOT_I386_PC_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
 #endif
-
-	  block--;
-	  if (block->len)
-	    grub_util_error ("%s", _("the sectors of the core file are too fragmented"));
-	}
-
-      last_length = length;
-#ifdef GRUB_SETUP_BIOS
-      current_segment += GRUB_DISK_SECTOR_SIZE >> 4;
-#endif
-    }
+  bl.last_length = GRUB_DISK_SECTOR_SIZE;
 
   /* Read the boot image by the OS service.  */
   boot_path = grub_util_get_path (dir, boot_file);
@@ -283,9 +290,9 @@ setup (const char *dir,
   core_img = grub_util_read_image (core_path);
 
   /* Have FIRST_BLOCK to point to the first blocklist.  */
-  first_block = (struct grub_boot_blocklist *) (core_img
-						+ GRUB_DISK_SECTOR_SIZE
-						- sizeof (*block));
+  bl.first_block = (struct grub_boot_blocklist *) (core_img
+						   + GRUB_DISK_SECTOR_SIZE
+						   - sizeof (*bl.block));
   grub_util_info ("root is `%s', dest is `%s'", root, dest);
 
   grub_util_info ("Opening dest");
@@ -511,38 +518,38 @@ setup (const char *dir,
     assert (nsec <= maxsec);
 
     /* Clean out the blocklists.  */
-    block = first_block;
-    while (block->len)
+    bl.block = bl.first_block;
+    while (bl.block->len)
       {
-	grub_memset (block, 0, sizeof (block));
+	grub_memset (bl.block, 0, sizeof (bl.block));
       
-	block--;
+	bl.block--;
 
-	if ((char *) block <= core_img)
+	if ((char *) bl.block <= core_img)
 	  grub_util_error ("%s", _("no terminator in the core image"));
       }
 
     save_first_sector (sectors[0] + grub_partition_get_start (ctx.container),
-		       0, GRUB_DISK_SECTOR_SIZE);
+		       0, GRUB_DISK_SECTOR_SIZE, &first_sector);
 
-    block = first_block;
+    bl.block = bl.first_block;
     for (i = 1; i < nsec; i++)
       save_blocklists (sectors[i] + grub_partition_get_start (ctx.container),
-		       0, GRUB_DISK_SECTOR_SIZE);
+		       0, GRUB_DISK_SECTOR_SIZE, &bl);
 
     /* Make sure that the last blocklist is a terminator.  */
-    if (block == first_block)
-      block--;
-    block->start = 0;
-    block->len = 0;
-    block->segment = 0;
+    if (bl.block == bl.first_block)
+      bl.block--;
+    bl.block->start = 0;
+    bl.block->len = 0;
+    bl.block->segment = 0;
 
     write_rootdev (root_dev, boot_img, first_sector);
 
     core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
-    first_block = (struct grub_boot_blocklist *) (core_img
-						  + GRUB_DISK_SECTOR_SIZE
-						  - sizeof (*block));
+    bl.first_block = (struct grub_boot_blocklist *) (core_img
+						     + GRUB_DISK_SECTOR_SIZE
+						     - sizeof (*bl.block));
 
     grub_size_t no_rs_length;
     grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE
@@ -698,22 +705,22 @@ unable_to_embed:
 #endif
 
   /* Clean out the blocklists.  */
-  block = first_block;
-  while (block->len)
+  bl.block = bl.first_block;
+  while (bl.block->len)
     {
-      block->start = 0;
-      block->len = 0;
+      bl.block->start = 0;
+      bl.block->len = 0;
 #ifdef GRUB_SETUP_BIOS
-      block->segment = 0;
+      bl.block->segment = 0;
 #endif
 
-      block--;
+      bl.block--;
 
-      if ((char *) block <= core_img)
+      if ((char *) bl.block <= core_img)
 	grub_util_error ("%s", _("no terminator in the core image"));
     }
 
-  block = first_block;
+  bl.block = bl.first_block;
 
 #ifdef __linux__
   {
@@ -766,11 +773,11 @@ unable_to_embed:
 		if (i == 0 && j == 0)
 		  save_first_sector (((grub_uint64_t) blk) * mul
 				     + container_start,
-				     0, rest);
+				     0, rest, &first_sector);
 		else
 		  save_blocklists (((grub_uint64_t) blk) * mul + j
 				   + container_start,
-				   0, rest);
+				   0, rest, &bl);
 	      }
 	  }
       }
@@ -806,13 +813,14 @@ unable_to_embed:
 				      >> GRUB_DISK_SECTOR_BITS)
 				     + j + container_start,
 				     fie2->fm_extents[i].fe_physical
-				     & (GRUB_DISK_SECTOR_SIZE - 1), len);
+				     & (GRUB_DISK_SECTOR_SIZE - 1), len,
+				     &first_sector);
 		else
 		  save_blocklists ((fie2->fm_extents[i].fe_physical
 				    >> GRUB_DISK_SECTOR_BITS)
 				   + j + container_start,
 				   fie2->fm_extents[i].fe_physical
-				   & (GRUB_DISK_SECTOR_SIZE - 1), len);
+				   & (GRUB_DISK_SECTOR_SIZE - 1), len, &bl);
 
 
 	      }
@@ -830,12 +838,14 @@ unable_to_embed:
       grub_util_error ("%s", grub_errmsg);
 
     file->read_hook = save_first_sector;
+    file->read_hook_data = &first_sector;
     if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE)
 	!= GRUB_DISK_SECTOR_SIZE)
       grub_util_error ("%s", _("failed to read the first sector of the core image"));
 
-    block = first_block;
+    bl.block = bl.first_block;
     file->read_hook = save_blocklists;
+    file->read_hook_data = &bl;
     if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE)
 	!= (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE)
       grub_util_error ("%s", _("failed to read the rest sectors of the core image"));
@@ -913,11 +923,11 @@ unable_to_embed:
     ptr += GRUB_DISK_SECTOR_SIZE;
     len -= GRUB_DISK_SECTOR_SIZE;
 
-    block = first_block;
-    while (block->len)
+    bl.block = bl.first_block;
+    while (bl.block->len)
       {
-	size_t cur = grub_target_to_host16 (block->len) << GRUB_DISK_SECTOR_BITS;
-	blk = grub_target_to_host64 (block->start);
+	size_t cur = grub_target_to_host16 (bl.block->len) << GRUB_DISK_SECTOR_BITS;
+	blk = grub_target_to_host64 (bl.block->start);
 
 	if (cur > len)
 	  cur = len;
@@ -932,9 +942,9 @@ unable_to_embed:
 
 	ptr += cur;
 	len -= cur;
-	block--;
+	bl.block--;
 	
-	if ((char *) block <= core_img)
+	if ((char *) bl.block <= core_img)
 	  grub_util_error ("%s", _("no terminator in the core image"));
       }
     core_dev->disk->partition = container;

Thanks,

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Remove nested functions from disk and file read hooks
  2013-01-21 12:14 [PATCH] Remove nested functions from disk and file read hooks Colin Watson
@ 2013-02-26 21:57 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 0 replies; 2+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2013-02-26 21:57 UTC (permalink / raw)
  To: The development of GNU GRUB

[-- Attachment #1: Type: text/plain, Size: 928 bytes --]


On 21.01.2013 13:14, Colin Watson wrote:

> Part seven.  This particular patch in the set loses some of the
> compressed-kernel size we'd gained from earlier patches, but it's still
> a good bit smaller than when I started on this work so I'm not worried.
> Note that, as a general pattern, I have intentionally not zeroed out
> read_hook_data after calling code using a read hook; this is because (a)
> the code that calls read hooks only checks whether read_hook is NULL,
> (b) every function that sets read_hook to something non-NULL naturally
> also sets read_hook_data if it cares about its value, and (c) avoiding
> the extra code to zero read_hook_data makes a few bytes of difference to
> the size of compressed core images.


There are some possible improvements that we've discussed on IRC.
Apparently you didn't have time to implement them. They can come in
separately later if needed. Go ahead.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-02-26 21:57 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-21 12:14 [PATCH] Remove nested functions from disk and file read hooks Colin Watson
2013-02-26 21:57 ` Vladimir 'φ-coder/phcoder' Serbinenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).