ÜberWall

UWfirmforce

/* $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 <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#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;
}