ÜberWall

UWfirmforce

/* $Id: cramfs.c,v 1.1 2009/02/21 21:25:19 khorben Exp $ */
/* Copyright (c) 2008 khorben of UberWall */
/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <stdint.h>
#include <string.h>
#include "plugin.h"
/* cramfs */
/* public */
/* types */
struct cramfs
{
uint32_t magic;
uint32_t size;
uint32_t flags;
uint32_t padding;
char signature[16];
uint32_t crc;
uint32_t edition;
uint32_t blocks;
uint32_t files;
char name[16];
};
/* constants */
#define CRAMFS_MAGIC 0x28cd3d45
#define CRAMFS_SIGNATURE "Compressed ROMFS"
/* flags */
#define CRAMFS_FLAG_FSID_VERSION_2 0x00000001 /* fsid version #2 */
#define CRAMFS_FLAG_SORTED_DIRS 0x00000002 /* sorted dirs */
#define CRAMFS_FLAG_HOLES 0x00000100 /* support for holes */
#define CRAMFS_FLAG_WRONG_SIGNATURE 0x00000200 /* reserved */
#define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET 0x00000400 /* shifted root fs */
#define CRAMFS_SUPPORTED_FLAGS ( 0x000000ff \
| CRAMFS_FLAG_HOLES \
| CRAMFS_FLAG_WRONG_SIGNATURE \
| CRAMFS_FLAG_SHIFTED_ROOT_OFFSET )
/* variables */
/* magic */
static unsigned char sig1[] = "\x45\x3d\xcd\x28";
static unsigned char sig2[] = "\x28\xcd\x3d\x45";
static unsigned char sig3[] = CRAMFS_SIGNATURE;
static PluginMagic cramfs_magic[] =
{
{ sizeof(struct cramfs), 0, sig1, sizeof(sig1)-1 },
{ sizeof(struct cramfs), 0, sig2, sizeof(sig2)-1 },
{ sizeof(struct cramfs), 16, sig3, sizeof(sig3)-1 },
{ 0, 0, NULL, 0 }
};
/* functions */
static int cramfs_callback(PluginHelper * ph, int signature, FILE * fp);
/* plugin */
Plugin plugin =
{
PT_ARCHIVE | PT_COMPRESSION,
"CRAMFS",
cramfs_magic,
cramfs_callback
};
/* private */
/* functions */
/* cramfs_callback */
static void _callback_endian_little(struct cramfs * hdr);
static void _callback_endian_big(struct cramfs * hdr);
static int _callback_flags(PluginHelper * ph, uint32_t flags);
static int cramfs_callback(PluginHelper * ph, int signature, FILE * fp)
{
int score = 0;
struct cramfs buf;
char name[sizeof(buf.name) + 1];
if(fread(&buf, sizeof(buf), 1, fp) != 1)
return -1;
if(signature == 0 || htol32(buf.magic) == CRAMFS_MAGIC)
{
score+=100;
ph->printf(ph, "%s", "little endian");
_callback_endian_little(&buf);
}
else if(signature == 1 || htob32(buf.magic) == CRAMFS_MAGIC)
{
score+=100;
ph->printf(ph, "%s", "big endian");
_callback_endian_big(&buf);
}
if(strncmp(buf.signature, CRAMFS_SIGNATURE, sizeof(buf.signature) - 1)
== 0)
score+=100;
strncpy(name, buf.name, sizeof(buf.name));
name[sizeof(buf.name)] = '\0';
ph->printf(ph, "%s%u", ", size ", buf.size);
score+=_callback_flags(ph, buf.flags);
ph->printf(ph, "%s%u%s%u%s%s%s", ", ", buf.blocks, " blocks, ",
buf.files, " files, name \"", name, "\"\n");
return score / 3;
}
/* one of these two helpers is eventually useless */
static void _callback_endian_little(struct cramfs * hdr)
{
hdr->magic = htol32(hdr->magic);
hdr->size = htol32(hdr->size);
hdr->flags = htol32(hdr->flags);
hdr->padding = htol32(hdr->padding);
hdr->crc = htol32(hdr->crc);
hdr->edition = htol32(hdr->edition);
hdr->blocks = htol32(hdr->blocks);
hdr->files = htol32(hdr->files);
}
static void _callback_endian_big(struct cramfs * hdr)
{
hdr->magic = htob32(hdr->magic);
hdr->size = htob32(hdr->size);
hdr->flags = htob32(hdr->flags);
hdr->padding = htob32(hdr->padding);
hdr->crc = htob32(hdr->crc);
hdr->edition = htob32(hdr->edition);
hdr->blocks = htob32(hdr->blocks);
hdr->files = htob32(hdr->files);
}
static int _callback_flags(PluginHelper * ph, uint32_t flags)
{
char sep = ' ';
if(flags & ~CRAMFS_SUPPORTED_FLAGS)
{
ph->printf(ph, "%s", ", invalid flags");
return 0;
}
ph->printf(ph, "%s", ", flags");
if(flags & CRAMFS_FLAG_FSID_VERSION_2)
{
ph->printf(ph, "%c%s", sep, "VERSION_2");
sep = '|';
}
if(flags & CRAMFS_FLAG_SORTED_DIRS)
{
ph->printf(ph, "%c%s", sep, "SORTED_DIRS");
sep = '|';
}
if(flags & CRAMFS_FLAG_HOLES)
{
ph->printf(ph, "%c%s", sep, "HOLES");
sep = '|';
}
if(flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET)
{
ph->printf(ph, "%c%s", sep, "SHIFTED_ROOT_OFFSET");
sep = '|';
}
if(sep == ' ')
ph->printf(ph, "%s", " NONE");
return 100;
}