/* $Id: squashfs.c,v 1.1.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 #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; }