/* $Id: cpio.c,v 1.1 2009/02/21 21:25:19 khorben Exp $ */ /* Copyright (c) 2007 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 #include #include #include #include "plugin.h" /* cpio */ /* public */ /* types */ #pragma pack(1) struct cpio_ascii { char magic[6]; char dev[6]; char ino[6]; char mode[6]; char uid[6]; char gid[6]; char nlink[6]; char rdev[6]; char mtime[11]; char namesize[6]; char filesize[11]; }; struct cpio_binary { uint16_t magic; uint16_t dev; uint16_t ino; uint16_t mode; uint16_t uid; uint16_t gid; uint16_t nlink; uint16_t rdev; uint32_t mtime; uint16_t namesize; uint32_t filesize; }; #pragma pack() union cpio { struct cpio_ascii ascii; struct cpio_binary binary; }; enum { CPIO_ASCII = 0, CPIO_BINARY_BIG, CPIO_BINARY_LITTLE, CPIO_TRAILER }; /* variables */ /* magic */ static unsigned char sig_ascii[] = "070707"; static unsigned char sig_binary_big[] = "\x71\xc7"; static unsigned char sig_binary_little[] = "\xc7\x71"; static unsigned char sig_trailer[] = "TRAILER!!"; static PluginMagic cpio_magic[] = { { sizeof(struct cpio_ascii), 0, sig_ascii, sizeof(sig_ascii)-1 }, { sizeof(struct cpio_binary), 0, sig_binary_big, sizeof(sig_binary_big)-1 }, { sizeof(struct cpio_binary), 0, sig_binary_little, sizeof(sig_binary_little)-1 }, { sizeof(union cpio), 0, sig_trailer, sizeof(sig_trailer)-1 }, { 0, 0, NULL, 0 } }; /* functions */ static int cpio_callback(PluginHelper * ph, int signature, FILE * fp); /* plugin */ Plugin plugin = { PT_ARCHIVE, "CPIO", cpio_magic, cpio_callback }; /* private */ /* functions */ static int _cpio_ids(PluginHelper * ph, uid_t uid, gid_t gid); static int _cpio_mtime(PluginHelper * ph, time_t mtime); static int _cpio_binary(PluginHelper * ph, struct cpio_binary * cpio); /* cpio_callback */ static int _callback_ascii(PluginHelper * ph, FILE * fp); static int _callback_binary_big(PluginHelper * ph, FILE * fp); static int _callback_binary_little(PluginHelper * ph, FILE * fp); static int _callback_trailer(PluginHelper * ph); static int cpio_callback(PluginHelper * ph, int signature, FILE * fp) { switch(signature) { case CPIO_ASCII: return _callback_ascii(ph, fp); case CPIO_BINARY_BIG: return _callback_binary_big(ph, fp); case CPIO_BINARY_LITTLE: return _callback_binary_little(ph, fp); case CPIO_TRAILER: return _callback_trailer(ph); } ph->printf(ph, "%s", "not implemented\n"); return 0; } static int _callback_ascii(PluginHelper * ph, FILE * fp) { int score = 0; struct cpio_ascii cpio; char buf[12]; uid_t uid; gid_t gid; time_t mtime; char * p; if(fread(&cpio, sizeof(cpio), 1, fp) != 1) return -1; ph->printf(ph, "%s", "ascii"); memcpy(buf, cpio.uid, sizeof(cpio.uid)); buf[sizeof(cpio.uid)] = '\0'; uid = strtol(buf, &p, 8); if(*buf == '\0' || *p != '\0') ph->printf(ph, "%s", " invalid uid"); else { memcpy(buf, cpio.gid, sizeof(cpio.gid)); buf[sizeof(cpio.gid)] = '\0'; gid = strtol(buf, &p, 8); if(*buf == '\0' || *p != '\0') ph->printf(ph, "%s", ", invalid gid"); else score += _cpio_ids(ph, uid, gid); } memcpy(buf, cpio.mtime, sizeof(cpio.mtime)); buf[sizeof(cpio.mtime)] = '\0'; mtime = strtol(buf, &p, 8); if(*buf == '\0' || *p != '\0') ph->printf(ph, "%s", " invalid time"); else score += _cpio_mtime(ph, mtime); ph->printf(ph, "\n"); return score / 2; } static int _callback_binary_big(PluginHelper * ph, FILE * fp) { struct cpio_binary cpio; if(fread(&cpio, sizeof(cpio), 1, fp) != 1) return -1; ph->printf(ph, "%s", "binary big endian"); cpio.uid = htob16(cpio.uid); cpio.gid = htob16(cpio.gid); cpio.mtime = htob32(cpio.mtime); return _cpio_binary(ph, &cpio); } static int _callback_binary_little(PluginHelper * ph, FILE * fp) { struct cpio_binary cpio; if(fread(&cpio, sizeof(cpio), 1, fp) != 1) return -1; ph->printf(ph, "%s", "binary little endian"); cpio.uid = htol16(cpio.uid); cpio.gid = htol16(cpio.gid); cpio.mtime = htol32(cpio.mtime); return _cpio_binary(ph, &cpio); } static int _callback_trailer(PluginHelper * ph) { ph->printf(ph, "%s", "trailer\n"); return 100; } /* _cpio_ids */ static int _cpio_ids(PluginHelper * ph, uid_t uid, gid_t gid) { ph->printf(ph, "%s%u%s%u", ", uid ", uid, ", gid ", gid); if(uid == gid) return 20; return 0; } /* _cpio_mtime */ static int _cpio_mtime(PluginHelper * ph, time_t mtime) { struct tm tm; char tmp[22] = ""; if(mtime == 0) return 100; 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; } /* _cpio_binary */ static int _cpio_binary(PluginHelper * ph, struct cpio_binary * cpio) { int score = 0; score += _cpio_ids(ph, cpio->uid, cpio->gid); score += _cpio_mtime(ph, cpio->mtime); ph->printf(ph, "\n"); return score / 2; }