/* $Id: romfs.c,v 1.1 2009/02/21 21:25:20 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 "plugin.h" /* romfs */ /* public */ /* types */ #pragma pack(1) struct romfs { char sig[8]; uint32_t size; uint32_t checksum; }; struct romfh { uint32_t next; uint32_t spec; uint32_t size; uint32_t checksum; }; #pragma pack() /* variables */ /* magic */ static unsigned char sig[] = "-rom1fs-"; static PluginMagic romfs_magic[] = { { sizeof(struct romfs), 0, sig, sizeof(sig)-1 }, { 0, 0, NULL, 0 } }; /* functions */ static int romfs_callback(PluginHelper * ph, int signature, FILE * fp); /* plugin */ Plugin plugin = { PT_ARCHIVE, "ROMFS", romfs_magic, romfs_callback }; /* private */ /* functions */ /* romfs_callback */ static int _callback_members(PluginHelper * ph, FILE * fp, uint32_t size, char buf[1024], size_t len, size_t i); static int romfs_callback(PluginHelper * ph, int signature, FILE * fp) { char buf[1024]; struct romfs * hdr; size_t len; size_t i; if((len = fread(buf, sizeof(char), sizeof(buf), fp)) < sizeof(*hdr)) return -1; hdr = (struct romfs *)buf; hdr->size = htob32(hdr->size); ph->printf(ph, "%s%u", "size ", hdr->size); for(i = sizeof(*hdr); i < len && buf[i] != '\0'; i++); if(i == len) /* no string termination found */ { ph->printf(ph, "%s", ", volume name too long\n"); return 0; } ph->printf(ph, "%s%s%s", ", volume name \"", &buf[sizeof(*hdr)], "\"\n"); i += i % 16 == 0 ? 0 : 16 - (i % 16); /* 16 byte alignment */ return _callback_members(ph, fp, hdr->size, buf, len, i); } static int _callback_members(PluginHelper * ph, FILE * fp, uint32_t size, char buf[1024], size_t len, size_t i) { char * mode[8] = { "hard link", "directory", "regular file", "symbolic link", "block device", "char device", "socket", "fifo" }; struct romfh * fhdr; size_t cnt = 0; while(len >= i) { memmove(buf, &buf[i], len - i); len-=i; if((i = fread(&buf[len], sizeof(char), 1024 - len, fp)) == 0 && len < sizeof(*fhdr)) break; len+=i; fhdr = (struct romfh*)buf; fhdr->next = htob32(fhdr->next); fhdr->size = htob32(fhdr->size); for(i = sizeof(*fhdr); buf[i] != '\0' && i < len; i++); if(i == len) /* no string termination found */ break; if(fhdr->size > size) /* FIXME still too imprecise */ break; ph->printf(ph, "%s%u%s%u%s%s%s%s%s", "member #", cnt++, ": size ", fhdr->size, ", filename \"", &buf[sizeof(*fhdr)], "\", ", mode[fhdr->next & 0x7], "\n"); if((fhdr->next & ~0xf) == 0) break; i += (i % 16 == 0) ? 0 : 16 - (i % 16); /* 16 byte alignment */ if(i + fhdr->size > len) /* next header is past buffer */ { if(fseek(fp, fhdr->size + len - i, SEEK_CUR) != 0) return -1; i = 0; len = 0; } else /* next header starts in current buffer */ i += fhdr->size; /* FIXME 16-byte alignment probably required here */ } return 100; }