ÜberWall

UWfirmforce

/* $Id: squashfs.c,v 1.1 2009/02/21 21:25:20 khorben Exp $ */
/* Parts Copyright (c) 2007 Matthias Wenzel, matthias /at/ mazzoo /dot/ de,
* Parts Copyright (c) 2002-2007 Phillip Lougher, phillip /at/
* lougher.demon.co /dot/ uk
* Parts 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 <time.h>
#include "plugin.h"
/* squashfs */
/* public */
/* variables */
/* magic */
static unsigned char sig1[] = "sqsh";
static unsigned char sig2[] = "hsqs";
static PluginMagic squashfs_magic[] =
{
{ 4, 0, sig1, sizeof(sig1)-1 },
{ 4, 0, sig2, sizeof(sig2)-1 },
{ 0, 0, NULL, 0 }
};
/* functions */
static int squashfs_callback(PluginHelper * ph, int signature, FILE * fp);
/* plugin */
Plugin plugin =
{
PT_ARCHIVE | PT_COMPRESSION,
"SQUASHFS",
squashfs_magic,
squashfs_callback
};
/* private */
/* types */
typedef long long squashfs_inode_t;
#pragma pack(1)
struct squashfs_super_block
{
unsigned int s_magic;
unsigned int inodes;
unsigned int bytes_used_2;
unsigned int uid_start_2;
unsigned int guid_start_2;
unsigned int inode_table_start_2;
unsigned int directory_table_start_2;
unsigned int s_major:16;
unsigned int s_minor:16;
unsigned int block_size_1:16;
unsigned int block_log:16;
unsigned int flags:8;
unsigned int no_uids:8;
unsigned int no_guids:8;
unsigned int mkfs_time /* time of filesystem creation */;
squashfs_inode_t root_inode;
unsigned int block_size;
unsigned int fragments;
unsigned int fragment_table_start_2;
long long bytes_used;
long long uid_start;
long long guid_start;
long long inode_table_start;
long long directory_table_start;
long long fragment_table_start;
long long lookup_table_start;
};
#pragma pack()
/* functions */
/* squashfs_callback */
static void _callback_endian_little(struct squashfs_super_block * buf);
static void _callback_endian_big(struct squashfs_super_block * buf);
static int _callback_version(PluginHelper * ph, unsigned int major,
unsigned int minor);
static int _callback_time(PluginHelper * ph, time_t mtime);
static int squashfs_callback(PluginHelper * ph, int signature, FILE * fp)
{
int score = 0;
struct squashfs_super_block buf;
if(fread(&buf, sizeof(buf), 1, fp) != 1)
return -1;
if(signature == 0)
{
score += 100;
ph->printf(ph, "%s", "big endian");
_callback_endian_big(&buf);
}
else if(signature == 1)
{
score += 100;
ph->printf(ph, "%s", "big endian");
_callback_endian_little(&buf);
}
score += _callback_version(ph, buf.s_major, buf.s_minor);
score += _callback_time(ph, buf.mkfs_time);
ph->printf(ph, ", block size %d", buf.block_size);
ph->printf(ph, "\n");
return score / 3;
}
static void _callback_endian_little(struct squashfs_super_block * buf)
{
buf->s_major = htol16(buf->s_major);
buf->s_minor = htol16(buf->s_minor);
buf->mkfs_time = htol32(buf->mkfs_time);
buf->block_size = htol32(buf->block_size);
}
static void _callback_endian_big(struct squashfs_super_block * buf)
{
buf->s_major = htob16(buf->s_major);
buf->s_minor = htob16(buf->s_minor);
buf->mkfs_time = htob32(buf->mkfs_time);
buf->block_size = htob32(buf->block_size);
}
static int _callback_version(PluginHelper * ph, unsigned int major,
unsigned int minor)
{
ph->printf(ph, ", version %d.%d", major, minor);
return major <= 5 ? 100 : 0;
}
static int _callback_time(PluginHelper * ph, time_t mtime)
{
struct tm tm;
char tmp[22] = "";
if(mtime == 0)
return 0;
if(gmtime_r(&mtime, &tm) == NULL || strftime(tmp, sizeof(tmp),
", %d/%m/%Y %H:%M:%S", &tm) == 0)
{
ph->printf(ph, "%s", ", unknown date");
return 0;
}
ph->printf(ph, "%s", tmp);
/* between Wed May 1 00:00:00 CEST 1996 and now */
return mtime > 830901600 && mtime < time(NULL) ? 100 : 0;
}