]> git.proxmox.com Git - grub2.git/commitdiff
Various squash4 fixes and LZO and XZ support.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 26 Dec 2011 12:18:01 +0000 (13:18 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 26 Dec 2011 12:18:01 +0000 (13:18 +0100)
* Makefile.util.def (libgrubmods.a): Add xzembed directory to cppflags.
Add xzembed source files.
* grub-core/Makefile.core.def (squash4): Add xzembed and minilzo flags.
* grub-core/fs/squash4.c (grub_squash_super): New field compression.
(grub_squash_inode): New subtype long_dir.
(SQUASH_TYPE_LONG_DIR): New inode type.
(COMPRESSION): New enum.
(XZBUFSIZ): New const.
(grub_squash_data): New fields blksz, decompress, xzdec, xzbuf.
(read_chunk): Use data->decompress.
(zlib_decompress): New function.
(lzo_decompress): Likewise.
(xz_decompress): Likewise.
(squash_mount): Set new data fields.
(grub_squash_iterate_dir): Handle long dir.
(squash_unmount): Free xzdec and xzbuf.
(grub_squash_open): Check ino type.
(direct_read): Stylistic fixes. Use data->decompress.
(grub_squash_read_data): Likewise.
* grub-core/io/gzio.c (grub_gzio): Remove disk_input.
(get_byte): Likewise.
(grub_zlib_disk_read): Removed.
* grub-core/lib/posix_wrap/sys/types.h (ssize_t): New type.
(GRUB_POSIX_BOOL_DEFINED): New define.
* grub-core/lib/posix_wrap/unistd.h: Include sys/types.h.
* grub-core/lib/xzembed/xz.h: Addmissing includes.
[!GRUB_POSIX_BOOL_DEFINED]: Define bool.
* include/grub/deflate.h (grub_zlib_disk_read): Removed.

ChangeLog
Makefile.util.def
grub-core/Makefile.core.def
grub-core/fs/squash4.c
grub-core/io/gzio.c
grub-core/lib/posix_wrap/sys/types.h
grub-core/lib/posix_wrap/unistd.h
grub-core/lib/xzembed/xz.h
include/grub/deflate.h

index 3acd07f972de50cf21c7e4c0ca83d65430a8fdd0..216eb1fc34d2d12b51bab4ba192756a2cd4cc33f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2011-12-26  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Various squash4 fixes and LZO and XZ support.
+
+       * Makefile.util.def (libgrubmods.a): Add xzembed directory to cppflags.
+       Add xzembed source files.
+       * grub-core/Makefile.core.def (squash4): Add xzembed and minilzo flags.
+       * grub-core/fs/squash4.c (grub_squash_super): New field compression.
+       (grub_squash_inode): New subtype long_dir.
+       (SQUASH_TYPE_LONG_DIR): New inode type.
+       (COMPRESSION): New enum.
+       (XZBUFSIZ): New const.
+       (grub_squash_data): New fields blksz, decompress, xzdec, xzbuf.
+       (read_chunk): Use data->decompress.
+       (zlib_decompress): New function.
+       (lzo_decompress): Likewise.
+       (xz_decompress): Likewise.
+       (squash_mount): Set new data fields.
+       (grub_squash_iterate_dir): Handle long dir.
+       (squash_unmount): Free xzdec and xzbuf.
+       (grub_squash_open): Check ino type.
+       (direct_read): Stylistic fixes. Use data->decompress.
+       (grub_squash_read_data): Likewise.
+       * grub-core/io/gzio.c (grub_gzio): Remove disk_input.
+       (get_byte): Likewise.
+       (grub_zlib_disk_read): Removed.
+       * grub-core/lib/posix_wrap/sys/types.h (ssize_t): New type.
+       (GRUB_POSIX_BOOL_DEFINED): New define.
+       * grub-core/lib/posix_wrap/unistd.h: Include sys/types.h.
+       * grub-core/lib/xzembed/xz.h: Addmissing includes.
+       [!GRUB_POSIX_BOOL_DEFINED]: Define bool.
+       * include/grub/deflate.h (grub_zlib_disk_read): Removed.
+
 2011-12-26  Vladimir Serbinenko  <phcoder@gmail.com>
 
        Don't override more informative errors.
index 47aefee32569d3f7180d360179d167ab1456c987..d12d529a6594a07fa3474f62ddea5cdd34d19cc1 100644 (file)
@@ -34,7 +34,7 @@ library = {
 library = {
   name = libgrubmods.a;
   cflags = '$(CFLAGS_POSIX) -Wno-undef';
-  cppflags = '-I$(srcdir)/lib/posix_wrap -I$(top_srcdir)/grub-core/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
+  cppflags = '-I$(top_srcdir)/grub-core/lib/minilzo -I$(srcdir)/grub-core/lib/xzembed -DMINILZO_HAVE_CONFIG_H';
 
   common_nodist = grub_script.tab.c;
   common_nodist = grub_script.yy.c;
@@ -119,6 +119,9 @@ library = {
   common = grub-core/io/lzopio.c;
   common = grub-core/kern/ia64/dl_helper.c;
   common = grub-core/lib/minilzo/minilzo.c;
+  common = grub-core/lib/xzembed/xz_dec_bcj.c;
+  common = grub-core/lib/xzembed/xz_dec_lzma2.c;
+  common = grub-core/lib/xzembed/xz_dec_stream.c;
 };
 
 program = {
index e183f884cc1da8d70c0491f6c861d598d2e69628..21fe41cd2bd6c367b91d737e52f0e81c5b31f840 100644 (file)
@@ -1117,6 +1117,8 @@ module = {
 module = {
   name = squash4;
   common = fs/squash4.c;
+  cflags = '$(CFLAGS_POSIX) -Wno-undef';
+  cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
 };
 
 module = {
index e14df6dbf0557bb20d3e14f1feb164d8089b4ea2..1cbc711e86f8a86e20ab89eb5a64238309c22ca0 100644 (file)
 #include <grub/types.h>
 #include <grub/fshelp.h>
 #include <grub/deflate.h>
+#include <minilzo.h>
+
+#include "xz.h"
+#include "xz_stream.h"
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -53,7 +57,9 @@ struct grub_squash_super
   grub_uint32_t dummy1;
   grub_uint32_t creation_time;
   grub_uint32_t block_size;
-  grub_uint64_t dummy3;
+  grub_uint32_t dummy2;
+  grub_uint16_t compression;
+  grub_uint16_t dummy3;
   grub_uint64_t dummy4;
   grub_uint16_t root_ino_offset;
   grub_uint32_t root_ino_chunk;
@@ -74,39 +80,43 @@ struct grub_squash_inode
   grub_uint16_t type;
   grub_uint16_t dummy[3];
   grub_uint32_t mtime;
+  grub_uint32_t dummy2;
   union
   {
     struct {
-      grub_uint32_t dummy;
       grub_uint32_t chunk;
       grub_uint32_t fragment;
       grub_uint16_t offset;
-      grub_uint16_t dummy2;
+      grub_uint16_t dummy;
       grub_uint32_t size;
       grub_uint32_t block_size[0];
     }  __attribute__ ((packed)) file;
     struct {
-      grub_uint32_t dummy;
       grub_uint64_t chunk;
       grub_uint64_t size;
-      grub_uint32_t dummy2[3];
+      grub_uint32_t dummy1[3];
       grub_uint32_t fragment;
       grub_uint16_t offset;
-      grub_uint16_t dummy3;
-      grub_uint32_t dummy4;
+      grub_uint16_t dummy2;
+      grub_uint32_t dummy3;
       grub_uint32_t block_size[0];
     }  __attribute__ ((packed)) long_file;
     struct {
-      grub_uint32_t dummy1;
       grub_uint32_t chunk;
-      grub_uint32_t dummy2;
+      grub_uint32_t dummy;
       grub_uint16_t size;
       grub_uint16_t offset;
-      grub_uint16_t dummy3;
-      grub_uint16_t dummy4;
     } __attribute__ ((packed)) dir;
     struct {
-      grub_uint64_t dummy;
+      grub_uint32_t dummy1;
+      grub_uint32_t size;
+      grub_uint32_t chunk;
+      grub_uint32_t dummy2;
+      grub_uint16_t dummy3;
+      grub_uint16_t offset;
+    } __attribute__ ((packed)) long_dir;
+    struct {
+      grub_uint32_t dummy;
       grub_uint32_t namelen;
       char name[0];
     } __attribute__ ((packed)) symlink;
@@ -146,6 +156,7 @@ enum
     SQUASH_TYPE_DIR = 1,
     SQUASH_TYPE_REGULAR = 2,
     SQUASH_TYPE_SYMLINK = 3,
+    SQUASH_TYPE_LONG_DIR = 8,
     SQUASH_TYPE_LONG_REGULAR = 9,
   };
 
@@ -169,7 +180,16 @@ enum
     SQUASH_BLOCK_UNCOMPRESSED = 0x1000000
   };
 
+enum
+  {
+    COMPRESSION_ZLIB = 1,
+    COMPRESSION_LZO = 3,
+    COMPRESSION_XZ = 4,
+  };
+
+
 #define SQUASH_CHUNK_SIZE 0x2000
+#define XZBUFSIZ 0x2000
 
 struct grub_squash_data
 {
@@ -178,6 +198,12 @@ struct grub_squash_data
   struct grub_squash_cache_inode ino;
   grub_uint64_t fragments;
   int log2_blksz;
+  grub_size_t blksz;
+  grub_ssize_t (*decompress) (char *inbuf, grub_size_t insize, grub_off_t off,
+                             char *outbuf, grub_size_t outsize,
+                             struct grub_squash_data *data);
+  struct xz_dec *xzdec;
+  char *xzbuf;
 };
 
 struct grub_fshelp_node
@@ -242,8 +268,8 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len,
              return err;
            }
 
-         if (grub_zlib_decompress (tmp, bsize, offset,
-                                   buf, csize) < 0)
+         if (data->decompress (tmp, bsize, offset,
+                               buf, csize, data) < 0)
            {
              grub_free (tmp);
              return grub_errno;
@@ -257,6 +283,94 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len,
   return GRUB_ERR_NONE;
 }
 
+static grub_ssize_t
+zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
+                char *outbuf, grub_size_t outsize,
+                struct grub_squash_data *data __attribute__ ((unused)))
+{
+  return grub_zlib_decompress (inbuf, insize, off, outbuf, outsize);
+}
+
+static grub_ssize_t
+lzo_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
+               char *outbuf, grub_size_t len, struct grub_squash_data *data)
+{
+  lzo_uint usize = data->blksz;
+  grub_uint8_t *udata;
+
+  udata = grub_malloc (data->blksz);
+  if (!udata)
+    return -1;
+
+  if (lzo1x_decompress_safe ((grub_uint8_t *) inbuf,
+                            insize, udata, &usize, NULL) != LZO_E_OK)
+    {
+      grub_free (udata);
+      return -1;
+    }
+  grub_memcpy (outbuf, udata + off, len);
+  grub_free (udata);
+  return len;
+}
+
+static grub_ssize_t
+xz_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
+              char *outbuf, grub_size_t len, struct grub_squash_data *data)
+{
+  grub_size_t ret;
+  grub_off_t pos = 0;
+  struct xz_buf buf;
+
+  xz_dec_reset (data->xzdec);
+  buf.in = (grub_uint8_t *) inbuf;
+  buf.in_pos = 0;
+  buf.in_size = insize;
+  buf.out = (grub_uint8_t *) data->xzbuf;
+  buf.out_pos = 0;
+  buf.out_size = XZBUFSIZ;
+
+  while (len)
+    {
+      enum xz_ret xzret;
+      
+      buf.out_pos = 0;
+
+      xzret = xz_dec_run (data->xzdec, &buf);
+
+      if (xzret != XZ_OK && xzret != XZ_STREAM_END)
+       {
+         grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "invalid xz chunk");
+         return -1;
+       }
+      if (pos + buf.out_pos >= off)
+       {
+         grub_ssize_t outoff = pos - off;
+         grub_size_t l;
+         if (outoff >= 0)
+           {
+             l = buf.out_pos;
+             if (l > len)
+               l = len;
+             grub_memcpy (outbuf + outoff, buf.out, l);
+           }
+         else
+           {
+             outoff = -outoff;
+             l = buf.out_pos - outoff;
+             if (l > len)
+               l = len;
+             grub_memcpy (outbuf, buf.out + outoff, l);
+           }
+         ret += l;
+         len -= l;
+       }
+      pos += buf.out_pos;
+      if (xzret == XZ_STREAM_END)
+       break;
+    }
+  return ret;
+}
+
 static struct grub_squash_data *
 squash_mount (grub_disk_t disk)
 {
@@ -270,10 +384,9 @@ squash_mount (grub_disk_t disk)
     grub_error (GRUB_ERR_BAD_FS, "not a squash4");
   if (err)
     return NULL;
-  if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC
-      || grub_le_to_cpu32 (sb.block_size) == 0
-      || ((grub_le_to_cpu32 (sb.block_size) - 1)
-         & grub_le_to_cpu32 (sb.block_size)))
+  if (sb.magic != grub_cpu_to_le32_compile_time (SQUASH_MAGIC)
+      || sb.block_size == 0
+      || ((sb.block_size - 1) & sb.block_size))
     {
       grub_error (GRUB_ERR_BAD_FS, "not squash4");
       return NULL;
@@ -296,8 +409,40 @@ squash_mount (grub_disk_t disk)
   data->disk = disk;
   data->fragments = grub_le_to_cpu64 (frag);
 
+  switch (sb.compression)
+    {
+    case grub_cpu_to_le16 (COMPRESSION_ZLIB):
+      data->decompress = zlib_decompress;
+      break;
+    case grub_cpu_to_le16 (COMPRESSION_LZO):
+      data->decompress = lzo_decompress;
+      break;
+    case grub_cpu_to_le16 (COMPRESSION_XZ):
+      data->decompress = xz_decompress;
+      data->xzbuf = grub_malloc (XZBUFSIZ);
+      if (!data->xzbuf)
+       {
+         grub_free (data);
+         return NULL;
+       }
+      data->xzdec = xz_dec_init (1 << 16);
+      if (!data->xzdec)
+       {
+         grub_free (data->xzbuf);
+         grub_free (data);
+         return NULL;
+       }
+      break;
+    default:
+      grub_free (data);
+      grub_error (GRUB_ERR_BAD_FS, "unsupported compression %d",
+                 grub_le_to_cpu16 (sb.compression));
+      return NULL;
+    }
+
+  data->blksz = grub_le_to_cpu32 (data->sb.block_size);
   for (data->log2_blksz = 0; 
-       (1U << data->log2_blksz) < grub_le_to_cpu32 (data->sb.block_size);
+       (1U << data->log2_blksz) < data->blksz;
        data->log2_blksz++);
 
   return data;
@@ -332,12 +477,29 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
                                  enum grub_fshelp_filetype filetype,
                                  grub_fshelp_node_t node))
 {
-  grub_uint32_t off = grub_le_to_cpu16 (dir->ino.dir.offset);
+  grub_uint32_t off;
   grub_uint32_t endoff;
+  grub_uint64_t chunk;
   unsigned i;
 
   /* FIXME: why - 3 ? */
-  endoff = grub_le_to_cpu16 (dir->ino.dir.size) + off - 3;
+  switch (dir->ino.type)
+    {
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_DIR):
+      off = grub_le_to_cpu16 (dir->ino.dir.offset);
+      endoff = grub_le_to_cpu16 (dir->ino.dir.size) + off - 3;
+      chunk = grub_le_to_cpu32 (dir->ino.dir.chunk);
+      break;
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_DIR):
+      off = grub_le_to_cpu16 (dir->ino.long_dir.offset);
+      endoff = grub_le_to_cpu16 (dir->ino.long_dir.size) + off - 3;
+      chunk = grub_le_to_cpu32 (dir->ino.long_dir.chunk);
+      break;
+    default:
+      grub_error (GRUB_ERR_BAD_FS, "unexpected ino type 0x%x",
+                 grub_le_to_cpu16 (dir->ino.type));
+      return 0;
+    }
 
   while (off < endoff)
     {
@@ -346,7 +508,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
 
       err = read_chunk (dir->data, &dh, sizeof (dh),
                        grub_le_to_cpu64 (dir->data->sb.diroffset)
-                       + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
+                       + chunk, off);
       if (err)
        return 0;
       off += sizeof (dh);
@@ -361,7 +523,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
 
          err = read_chunk (dir->data, &di, sizeof (di),
                            grub_le_to_cpu64 (dir->data->sb.diroffset)
-                           + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
+                           + chunk, off);
          if (err)
            return 0;
          off += sizeof (di);
@@ -379,7 +541,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
          err = read_chunk (dir->data, buf,
                            grub_le_to_cpu16 (di.namelen) + 1,
                            grub_le_to_cpu64 (dir->data->sb.diroffset)
-                           + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
+                           + chunk, off);
          if (err)
            return 0;
 
@@ -416,13 +578,16 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root)
  
  return read_chunk (data, &root->ino, sizeof (root->ino),
                    grub_le_to_cpu64 (data->sb.inodeoffset) 
-                   + grub_le_to_cpu16 (data->sb.root_ino_chunk),
+                   + grub_le_to_cpu32 (data->sb.root_ino_chunk),
                    grub_cpu_to_le16 (data->sb.root_ino_offset));
 }
 
 static void
 squash_unmount (struct grub_squash_data *data)
 {
+  if (data->xzdec)
+    xz_dec_end (data->xzdec);
+  grub_free (data->xzbuf);
   grub_free (data->ino.cumulated_block_sizes);
   grub_free (data->ino.block_sizes);
   grub_free (data);
@@ -505,11 +670,22 @@ grub_squash_open (struct grub_file *file, const char *name)
   data->ino.ino_chunk = fdiro->ino_chunk;
   data->ino.ino_offset = fdiro->ino_offset;
 
-  if (fdiro->ino.type
-      == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
-    file->size = grub_le_to_cpu64 (fdiro->ino.long_file.size);
-  else
-    file->size = grub_le_to_cpu32 (fdiro->ino.file.size);
+  switch (fdiro->ino.type)
+    {
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR):
+      file->size = grub_le_to_cpu64 (fdiro->ino.long_file.size);
+      break;
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR):
+      file->size = grub_le_to_cpu32 (fdiro->ino.file.size);
+      break;
+    default:
+      {
+       grub_uint16_t type = grub_le_to_cpu16 (fdiro->ino.type);
+       grub_free (fdiro);
+       squash_unmount (data);
+       return grub_error (GRUB_ERR_BAD_FS, "unexpected ino type 0x%x", type);
+      }
+    }
 
   grub_free (fdiro);
 
@@ -527,32 +703,35 @@ direct_read (struct grub_squash_data *data,
   grub_size_t i;
   grub_size_t origlen = len;
 
-  if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
-    a = grub_le_to_cpu64 (ino->ino.long_file.chunk);
-  else
-    a = grub_le_to_cpu32 (ino->ino.file.chunk);
+  switch (ino->ino.type)
+    {
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR):
+      a = grub_le_to_cpu64 (ino->ino.long_file.chunk);
+      break;
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR):
+      a = grub_le_to_cpu32 (ino->ino.file.chunk);
+      break;
+    }
 
   if (!ino->block_sizes)
     {
       grub_off_t total_size;
       grub_size_t total_blocks;
       grub_size_t block_offset;
-      if (ino->ino.type
-         == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
+      switch (ino->ino.type)
        {
+       case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR):
          total_size = grub_le_to_cpu64 (ino->ino.long_file.size);
          block_offset = ((char *) &ino->ino.long_file.block_size
                          - (char *) &ino->ino);
-       }
-      else
-       {
+         break;
+       case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR):
          total_size = grub_le_to_cpu32 (ino->ino.file.size);
          block_offset = ((char *) &ino->ino.file.block_size
                          - (char *) &ino->ino);
+         break;
        }
-      total_blocks = ((total_size
-                     + grub_le_to_cpu32 (data->sb.block_size) - 1)
-                     >> data->log2_blksz);
+      total_blocks = ((total_size + data->blksz - 1) >> data->log2_blksz);
       ino->block_sizes = grub_malloc (total_blocks
                                      * sizeof (ino->block_sizes[0]));
       ino->cumulated_block_sizes = grub_malloc (total_blocks
@@ -587,20 +766,42 @@ direct_read (struct grub_squash_data *data,
   if (a == 0)
     a = sizeof (struct grub_squash_super);
   i = off >> data->log2_blksz;
-  cumulated_uncompressed_size = grub_le_to_cpu32 (data->sb.block_size)
-    * (grub_disk_addr_t) i;
+  cumulated_uncompressed_size = data->blksz * (grub_disk_addr_t) i;
   while (cumulated_uncompressed_size < off + len)
     {
       grub_size_t boff, read;
       boff = off - cumulated_uncompressed_size;
-      read = grub_le_to_cpu32 (data->sb.block_size) - boff;
+      read = data->blksz - boff;
       if (read > len)
        read = len;
       if (!(ino->block_sizes[i]
            & grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED)))
-       err = grub_zlib_disk_read (data->disk,
-                                  ino->cumulated_block_sizes[i] + a,
-                                  boff, buf, read);
+       {
+         char *block;
+         block = grub_malloc (data->blksz);
+         if (!block)
+           return -1;
+         err = grub_disk_read (data->disk,
+                               (ino->cumulated_block_sizes[i] + a)
+                               >> GRUB_DISK_SECTOR_BITS,
+                               (ino->cumulated_block_sizes[i] + a)
+                               & (GRUB_DISK_SECTOR_SIZE - 1),
+                               data->blksz, block);
+         if (err)
+           {
+             grub_free (block);
+             return -1;
+           }
+         if (data->decompress (block, data->blksz, boff, buf, read, data)
+             != (grub_ssize_t) read)
+           {
+             grub_free (block);
+             if (!grub_errno)
+               grub_error (GRUB_ERR_BAD_FS, "incorrect compressed chunk");
+             return -1;
+           }
+         grub_free (block);
+       }
       else
        err = grub_disk_read (data->disk, 
                              (ino->cumulated_block_sizes[i] + a + boff)
@@ -631,15 +832,16 @@ grub_squash_read_data (struct grub_squash_data *data,
   int compressed = 0;
   struct grub_squash_frag_desc frag;
 
-  if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
+  switch (ino->ino.type)
     {
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR):
       a = grub_le_to_cpu64 (ino->ino.long_file.chunk);
       fragment = grub_le_to_cpu32 (ino->ino.long_file.fragment);
-    }
-  else
-    {
+      break;
+    case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR):
       a = grub_le_to_cpu32 (ino->ino.file.chunk);
       fragment = grub_le_to_cpu32 (ino->ino.file.fragment);
+      break;
     }
 
   if (fragment == 0xffffffff)
@@ -658,12 +860,37 @@ grub_squash_read_data (struct grub_squash_data *data,
   
   /* FIXME: cache uncompressed chunks.  */
   if (compressed)
-    err = grub_zlib_disk_read (data->disk, a, b, buf, len);
+    {
+      char *block;
+      block = grub_malloc (data->blksz);
+      if (!block)
+       return -1;
+      err = grub_disk_read (data->disk,
+                           a >> GRUB_DISK_SECTOR_BITS,
+                           a & (GRUB_DISK_SECTOR_SIZE - 1),
+                           data->blksz, block);
+      if (err)
+       {
+         grub_free (block);
+         return -1;
+       }
+      if (data->decompress (block, data->blksz, b, buf, len, data)
+         != (grub_ssize_t) len)
+       {
+         grub_free (block);
+         if (!grub_errno)
+           grub_error (GRUB_ERR_BAD_FS, "incorrect compressed chunk");
+         return -1;
+       }
+      grub_free (block);
+    }
   else
-    err = grub_disk_read (data->disk, (a + b) >> GRUB_DISK_SECTOR_BITS,
+    {
+      err = grub_disk_read (data->disk, (a + b) >> GRUB_DISK_SECTOR_BITS,
                          (a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
-  if (err)
-    return -1;
+      if (err)
+       return -1;
+    }
   return len;
 }
 
index 7380221aac76b8a932559f1412c0b93834c6441a..0d4003cd293ee4c4cc6ca86b61fc6606658a4c3e 100644 (file)
@@ -41,7 +41,6 @@
 #include <grub/fs.h>
 #include <grub/file.h>
 #include <grub/dl.h>
-#include <grub/disk.h>
 #include <grub/deflate.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
@@ -65,9 +64,6 @@ struct grub_gzio
   /* If input is in memory following fields are used instead of file.  */
   grub_size_t mem_input_size, mem_input_off;
   grub_uint8_t *mem_input;
-  grub_disk_addr_t disk_input_off;
-  grub_disk_addr_t disk_input_start;
-  grub_disk_t disk_input;
   /* The offset at which the data starts in the underlying file.  */
   grub_off_t data_offset;
   /* The type of current block.  */
@@ -388,18 +384,6 @@ get_byte (grub_gzio_t gzio)
       return 0;
     }
 
-  if (gzio->disk_input && (gzio->disk_input_off == gzio->data_offset
-                          || gzio->inbuf_d == INBUFSIZ))
-    {
-      grub_disk_addr_t d = gzio->disk_input_start + gzio->disk_input_off;
-      gzio->inbuf_d = 0;
-      grub_disk_read (gzio->disk_input,
-                     d >> GRUB_DISK_SECTOR_BITS,
-                     d & (GRUB_DISK_SECTOR_SIZE - 1),
-                     INBUFSIZ, gzio->inbuf);
-      gzio->disk_input_off += INBUFSIZ;
-    }
-
   if (gzio->file && (grub_file_tell (gzio->file)
                     == (grub_off_t) gzio->data_offset
                     || gzio->inbuf_d == INBUFSIZ))
@@ -422,8 +406,6 @@ gzio_seek (grub_gzio_t gzio, grub_off_t off)
       else
        gzio->mem_input_off = off;
     }
-  else if (gzio->disk_input)
-    gzio->disk_input_off = off;
   else
     grub_file_seek (gzio->file, off);
 }
@@ -1314,34 +1296,6 @@ grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
   return ret;
 }
 
-grub_err_t
-grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart,
-                    grub_off_t off, char *outbuf, grub_size_t outsize)
-{
-  grub_gzio_t gzio = 0;
-  grub_ssize_t ret;
-
-  gzio = grub_zalloc (sizeof (*gzio));
-  if (! gzio)
-    return -1;
-
-  gzio->disk_input_off = 0;
-  gzio->disk_input_start = zlibstart;
-  gzio->disk_input = disk;
-
-  if (!test_zlib_header (gzio))
-    {
-      grub_free (gzio);
-      return -1;
-    }
-
-  ret = grub_gzio_read_real (gzio, off, outbuf, outsize);
-  grub_free (gzio);
-
-  /* FIXME: Check Adler.  */
-  return ret < 0 ? grub_errno : GRUB_ERR_NONE;
-}
-
 \f
 
 static struct grub_fs grub_gzio_fs =
index 0c58d6c44152644e7da0387f25d1cacc1d334a0c..b2181160658aaf1a8e5131cab25d28ea5c8b412f 100644 (file)
 #include <grub/misc.h>
 
 typedef grub_size_t size_t;
+typedef grub_ssize_t ssize_t;
+#ifndef GRUB_POSIX_BOOL_DEFINED
 typedef enum { false = 0, true = 1 } bool;
+#define GRUB_POSIX_BOOL_DEFINED 1
+#endif
 
 typedef grub_uint8_t uint8_t;
 typedef grub_uint16_t uint16_t;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a12c43b15a9ea213d712b87f9f64657b2eab2d32 100644 (file)
@@ -0,0 +1 @@
+#include <sys/types.h>
index f0a7dbbca7435106d85f9774e159d415f8efdb80..fe7158bb29fabf3823082bc60c90d46eade68bd4 100644 (file)
 #define XZ_H
 
 #include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <grub/misc.h>
+
+#ifndef GRUB_POSIX_BOOL_DEFINED
+typedef enum { false = 0, true = 1 } bool;
+#endif
 
 /**
  * enum xz_ret - Return codes
index ae4a1f244d568fa680b59869689352c313d3a625..6ec4eaa998337fa1e0755c1239dfe0a41984a4ed 100644 (file)
@@ -23,8 +23,4 @@ grub_ssize_t
 grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off,
                      char *outbuf, grub_size_t outsize);
 
-grub_err_t
-grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart,
-                    grub_off_t off, char *outbuf, grub_size_t outsize);
-
 #endif