/* squash4.c - SquashFS */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <minilzo.h>
#include "xz.h"
#include "xz_stream.h"
GRUB_MOD_LICENSE ("GPLv3+");
/*
object format Pointed by
superblock RAW Fixed offset (0)
data RAW ? Fixed offset (60)
inode table Chunk superblock
dir table Chunk superblock
fragment table Chunk unk1
unk1 RAW, Chunk superblock
unk2 RAW superblock
exttblptr RAW superblock
unk1 contains pointer to fragment table followed by some chunk.
unk2 containts one uint64_t
*/
struct grub_squash_super
{
} __attribute__ ((packed));
/* Chunk-based */
struct grub_squash_inode
{
/* Same values as direlem types. */
union
{
struct {
struct {
struct {
struct {
struct {
char name[0];
} __attribute__ ((packed));
} __attribute__ ((packed));
struct grub_squash_cache_inode
{
};
/* Chunk-based. */
struct grub_squash_dirent_header
{
/* Actually the value is the number of elements - 1. */
} __attribute__ ((packed));
struct grub_squash_dirent
{
/* Actually the value is the length of name - 1. */
char name[0];
} __attribute__ ((packed));
enum
{
};
struct grub_squash_frag_desc
{
} __attribute__ ((packed));
enum
{
};
enum
{
};
enum
{
};
struct grub_squash_data
{
int log2_blksz;
struct grub_squash_data *data);
char *xzbuf;
};
struct grub_fshelp_node
{
};
static grub_err_t
{
while (len > 0)
{
while (1)
{
sizeof (d), &d);
if (err)
return err;
if (offset < SQUASH_CHUNK_SIZE)
break;
}
if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED)
{
a & (GRUB_DISK_SECTOR_SIZE - 1),
if (err)
return err;
}
else
{
char *tmp;
if (!tmp)
return grub_errno;
/* FIXME: buffer uncompressed data. */
a & (GRUB_DISK_SECTOR_SIZE - 1),
if (err)
{
return err;
}
{
return grub_errno;
}
}
}
return GRUB_ERR_NONE;
}
static grub_ssize_t
{
}
static grub_ssize_t
{
if (!udata)
return -1;
{
return -1;
}
return len;
}
static grub_ssize_t
{
while (len)
{
{
return -1;
}
{
grub_size_t l;
if (outoff >= 0)
{
if (l > len)
l = len;
}
else
{
if (l > len)
l = len;
}
ret += l;
len -= l;
}
if (xzret == XZ_STREAM_END)
break;
}
return ret;
}
static struct grub_squash_data *
{
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
if (err)
return NULL;
|| sb.block_size == 0
{
return NULL;
}
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
if (err)
return NULL;
if (!data)
return NULL;
switch (sb.compression)
{
break;
break;
{
return NULL;
}
{
return NULL;
}
break;
default:
return NULL;
}
for (data->log2_blksz = 0;
data->log2_blksz++);
return data;
}
static char *
{
char *ret;
if (err)
{
return NULL;
}
return ret;
}
static int
int NESTED_FUNC_ATTR
enum grub_fshelp_filetype filetype,
{
unsigned i;
/* FIXME: why - 3 ? */
{
break;
break;
default:
return 0;
}
{
if (err)
return 0;
{
char *buf;
int r;
if (err)
return 0;
if (err)
return 0;
if (!buf)
return 0;
if (err)
return 0;
if (! node)
return 0;
if (r)
return r;
}
}
return 0;
}
static grub_err_t
{
}
static void
{
}
static grub_err_t
const struct grub_dirhook_info *info))
{
enum grub_fshelp_filetype filetype,
enum grub_fshelp_filetype filetype,
{
}
if (! data)
return grub_errno;
if (err)
return err;
if (!grub_errno)
return grub_errno;
}
static grub_err_t
{
if (! data)
return grub_errno;
if (err)
return err;
if (grub_errno)
{
return grub_errno;
}
{
break;
break;
default:
{
}
}
return GRUB_ERR_NONE;
}
static grub_ssize_t
struct grub_squash_cache_inode *ino,
{
grub_uint64_t a = 0;
grub_size_t i;
{
break;
break;
}
if (!ino->block_sizes)
{
{
break;
break;
}
* sizeof (ino->block_sizes[0]));
* sizeof (ino->cumulated_block_sizes[0]));
{
ino->block_sizes = 0;
ino->cumulated_block_sizes = 0;
return -1;
}
if (err)
{
ino->block_sizes = 0;
ino->cumulated_block_sizes = 0;
return -1;
}
ino->cumulated_block_sizes[0] = 0;
for (i = 1; i < total_blocks; i++)
}
if (a == 0)
a = sizeof (struct grub_squash_super);
{
if (!(ino->block_sizes[i]
{
char *block;
if (!block)
return -1;
(ino->cumulated_block_sizes[i] + a)
(ino->cumulated_block_sizes[i] + a)
& (GRUB_DISK_SECTOR_SIZE - 1),
if (err)
{
return -1;
}
!= (grub_ssize_t) read)
{
if (!grub_errno)
return -1;
}
}
else
& (GRUB_DISK_SECTOR_SIZE - 1),
if (err)
return -1;
i++;
}
return origlen;
}
static grub_ssize_t
struct grub_squash_cache_inode *ino,
{
grub_uint64_t a = 0, b;
int compressed = 0;
{
break;
break;
}
if (fragment == 0xffffffff)
if (err)
return -1;
else
/* FIXME: cache uncompressed chunks. */
if (compressed)
{
char *block;
if (!block)
return -1;
a >> GRUB_DISK_SECTOR_BITS,
a & (GRUB_DISK_SECTOR_SIZE - 1),
if (err)
{
return -1;
}
!= (grub_ssize_t) len)
{
if (!grub_errno)
return -1;
}
}
else
{
if (err)
return -1;
}
return len;
}
static grub_ssize_t
{
}
static grub_err_t
{
return GRUB_ERR_NONE;
}
static grub_err_t
{
if (! data)
return grub_errno;
return GRUB_ERR_NONE;
}
{
.name = "squash4",
.dir = grub_squash_dir,
.open = grub_squash_open,
.read = grub_squash_read,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
.next = 0
};
{
}
{
}