/* $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 #include #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; }