All pastes #44344 Raw Edit

Untitled

public c v1 · immutable
#44344 ·published 2006-03-03 15:57 UTC
rendered paste body
/*       * iroffer by David Johnson (PMG)  * Copyright (C) 1998-2005 David Johnson  *  * By using this file, you agree to the terms and conditions set * forth in the GNU General Public License.  More information is     * available in the README file. *  * If you received this file without documentation, it can be * downloaded from http://iroffer.org/ *  * @(#) iroffer_statefile.c 1.20@(#) * pmg@wellington.i202.centerclick.org|src/iroffer_statefile.c|20050116225130|20716 *  *//* include the headers */#include "iroffer_config.h"#include "iroffer_defines.h"#include "iroffer_headers.h"#include "iroffer_globals.h"/* *      ******  FILE FORMAT  ****** * * Word size:     4 Bytes * Byte order:    Network Order * * == OVERALL == * Word 0:        Magic * Word 1:        Version * Word 2..n-4:   TLV Data * Word n-3..n:   md5sum * * == TLV Format == * Word 0:        Tag * Word 1:        Length in Bytes (Tag+Length+Value, but not Padding) * Word 2..n-1:   Value * Word n:        Value + Zero Padding * * Some tags are compound, some are not.  Compound tags contain TLV * data of their own. * */typedef enum{  STATEFILE_TAG_IROFFER_VERSION      =  1 << 8,  STATEFILE_TAG_TIMESTAMP,    STATEFILE_TAG_XFR_RECORD           =  2 << 8,  STATEFILE_TAG_SENT_RECORD,  STATEFILE_TAG_TOTAL_SENT,  STATEFILE_TAG_TOTAL_UPTIME,  STATEFILE_TAG_LAST_LOGROTATE,    STATEFILE_TAG_IGNORE               = 10 << 8, /* compound */  STATEFILE_TAG_IGNORE_FLAGS,  STATEFILE_TAG_IGNORE_BUCKET,  STATEFILE_TAG_IGNORE_LASTCONTACT,  STATEFILE_TAG_IGNORE_HOSTMASK,    STATEFILE_TAG_MSGLOG               = 11 << 8, /* compound */  STATEFILE_TAG_MSGLOG_WHEN,  STATEFILE_TAG_MSGLOG_HOSTMASK,  STATEFILE_TAG_MSGLOG_MESSAGE,    STATEFILE_TAG_XDCCS                = 12 << 8, /* compound */  STATEFILE_TAG_XDCCS_FILE,  STATEFILE_TAG_XDCCS_DESC,  STATEFILE_TAG_XDCCS_NOTE,  STATEFILE_TAG_XDCCS_GETS,  STATEFILE_TAG_XDCCS_MINSPEED,  STATEFILE_TAG_XDCCS_MAXSPEED,  STATEFILE_TAG_XDCCS_MD5SUM_INFO,  } statefile_tag_t;typedef struct{  statefile_tag_t tag;  ir_int32 length; /* includes header */} statefile_hdr_t;#define STATEFILE_MAGIC (('I' << 24) | ('R' << 16) | ('F' << 8) | 'R')#define STATEFILE_VERSION 1typedef struct{  ir_uint32 upper;  ir_uint32 lower;} statefile_uint64_t;typedef struct{  statefile_hdr_t hdr;  time_t g_time;} statefile_item_generic_time_t;typedef struct{  statefile_hdr_t hdr;  ir_int32 g_int;} statefile_item_generic_int_t;typedef struct{  statefile_hdr_t hdr;  ir_uint32 g_uint;} statefile_item_generic_uint_t;typedef struct{  statefile_hdr_t hdr;  statefile_uint64_t g_ullint;} statefile_item_generic_ullint_t;typedef struct{  statefile_hdr_t hdr;  float g_float;} statefile_item_generic_float_t;typedef struct{  statefile_hdr_t hdr;  statefile_uint64_t st_size;  statefile_uint64_t st_dev;  statefile_uint64_t st_ino;  time_t mtime;  MD5Digest md5sum;} statefile_item_md5sum_info_t;static int write_statefile_item(ir_boutput_t *bout, void *item){  int callval;  statefile_hdr_t *hdr = (statefile_hdr_t*)item;  ir_int32 length = hdr->length;  unsigned char dummy[4] = {};    hdr->tag = htonl(hdr->tag);  hdr->length = htonl(hdr->length);    callval = ir_boutput_write(bout, item, length);    if (callval != length)    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Write To State File (%d != %d) %s",               callval, length, strerror(errno));      return -1;    }    if (length & 3)    {      length = 4 - (length & 3);      callval = ir_boutput_write(bout, dummy, length);            if (callval != length)        {          outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Write To State File (%d != %d) %s",                   callval, length, strerror(errno));          return -1;        }    }    return 0;}void write_statefile(void){  char *statefile_tmp, *statefile_bkup;  int fd;  int callval;  statefile_hdr_t *hdr;  ir_int32 length;  ir_boutput_t bout;    updatecontext();    if (gdata.statefile == NULL)    {      return;    }    statefile_tmp = mycalloc(strlen(gdata.statefile)+5);  statefile_bkup = mycalloc(strlen(gdata.statefile)+2);    sprintf(statefile_tmp,  "%s.tmp", gdata.statefile);  sprintf(statefile_bkup, "%s~",    gdata.statefile);    if (gdata.debug > 0)    {      ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,              COLOR_NO_COLOR, "Saving State File... ");    }    fd = open(statefile_tmp,            O_WRONLY | O_CREAT | O_TRUNC | ADDED_OPEN_FLAGS,            CREAT_PERMISSIONS);    if (fd < 0)    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Create State File '%s': %s",               statefile_tmp, strerror(errno));      goto error_out;    }    ir_boutput_init(&bout, fd, BOUTPUT_MD5SUM | BOUTPUT_NO_LIMIT);    /*** write ***/    {    ir_uint32 magic = htonl(STATEFILE_MAGIC);    callval = ir_boutput_write(&bout, &magic, sizeof(magic));    if (callval != sizeof(magic))      {        outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Write To State File (%d != %d) %s",                 callval, (int)sizeof(magic), strerror(errno));      }  }    {    ir_uint32 version = htonl(STATEFILE_VERSION);    callval = ir_boutput_write(&bout, &version, sizeof(version));    if (callval != sizeof(version))      {        outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Write To State File (%d != %d) %s",                 callval, (int)sizeof(version), strerror(errno));      }  }    {    unsigned char *data;    unsigned char *next;        length = sizeof(statefile_hdr_t) + maxtextlength;        data = mycalloc(length);        /* header */    hdr = (statefile_hdr_t*)data;    hdr->tag = STATEFILE_TAG_IROFFER_VERSION;    hdr->length = sizeof(statefile_hdr_t);    next = (unsigned char*)(&hdr[1]);        length = snprintf(next, maxtextlength-1,                      "iroffer v" VERSIONLONG ", %s", gdata.osstring);        if ((length < 0) || (length >= maxtextlength))      {       outerror(OUTERROR_TYPE_WARN_LOUD, "Version too long! %d",                 length);      }    else      {        hdr->length += ceiling(length+1, 4);        write_statefile_item(&bout, data);      }        mydelete(data);  }    {    statefile_item_generic_time_t item_timestamp;    item_timestamp.hdr.tag = STATEFILE_TAG_TIMESTAMP;    item_timestamp.hdr.length = sizeof(statefile_item_generic_time_t);    item_timestamp.g_time = htonl(gdata.curtime);    write_statefile_item(&bout, &item_timestamp);  }    {    statefile_item_generic_float_t item_xfr_record;    item_xfr_record.hdr.tag = STATEFILE_TAG_XFR_RECORD;    item_xfr_record.hdr.length = sizeof(statefile_item_generic_float_t);    item_xfr_record.g_float = gdata.record;    write_statefile_item(&bout, &item_xfr_record);  }    {    statefile_item_generic_float_t item_sent_record;    item_sent_record.hdr.tag = STATEFILE_TAG_SENT_RECORD;    item_sent_record.hdr.length = sizeof(statefile_item_generic_float_t);    item_sent_record.g_float = gdata.sentrecord;    write_statefile_item(&bout, &item_sent_record);  }    {    statefile_item_generic_ullint_t item_total_sent;    item_total_sent.hdr.tag = STATEFILE_TAG_TOTAL_SENT;    item_total_sent.hdr.length = sizeof(statefile_item_generic_ullint_t);    item_total_sent.g_ullint.upper = htonl(gdata.totalsent >> 32);    item_total_sent.g_ullint.lower = htonl(gdata.totalsent & 0xFFFFFFFF);    write_statefile_item(&bout, &item_total_sent);  }    {    statefile_item_generic_int_t item_total_uptime;    item_total_uptime.hdr.tag = STATEFILE_TAG_TOTAL_UPTIME;    item_total_uptime.hdr.length = sizeof(statefile_item_generic_int_t);    item_total_uptime.g_int = htonl(gdata.totaluptime);    write_statefile_item(&bout, &item_total_uptime);  }    {    statefile_item_generic_time_t item_last_logrotate;    item_last_logrotate.hdr.tag = STATEFILE_TAG_LAST_LOGROTATE;    item_last_logrotate.hdr.length = sizeof(statefile_item_generic_int_t);    item_last_logrotate.g_time = htonl(gdata.last_logrotate);    write_statefile_item(&bout, &item_last_logrotate);  }    {    unsigned char *data;    unsigned char *next;    igninfo *ignore;    statefile_item_generic_int_t *g_int;    statefile_item_generic_uint_t *g_uint;    statefile_item_generic_time_t *g_time;        ignore = irlist_get_head(&gdata.ignorelist);        while (ignore)      {        if (ignore->flags & IGN_IGNORING)          {            /*             * need room to write:             *  flags         uint             *  bucket        int             *  lastcontact   time_t             *  hostmask      string             */            length = sizeof(statefile_hdr_t) +              sizeof(statefile_item_generic_uint_t) +               sizeof(statefile_item_generic_int_t) +               sizeof(statefile_item_generic_time_t) +               sizeof(statefile_hdr_t) + ceiling(strlen(ignore->hostmask) + 1, 4);                        data = mycalloc(length);                        /* outter header */            hdr = (statefile_hdr_t*)data;            hdr->tag = STATEFILE_TAG_IGNORE;            hdr->length = length;            next = (unsigned char*)(&hdr[1]);                        /* flags */            g_uint = (statefile_item_generic_uint_t*)next;            g_uint->hdr.tag = htonl(STATEFILE_TAG_IGNORE_FLAGS);            g_uint->hdr.length = htonl(sizeof(*g_uint));            g_uint->g_uint = htonl(ignore->flags);            next = (unsigned char*)(&g_uint[1]);                        /* bucket */            g_int = (statefile_item_generic_int_t*)next;            g_int->hdr.tag = htonl(STATEFILE_TAG_IGNORE_BUCKET);            g_int->hdr.length = htonl(sizeof(*g_int));            g_int->g_int = htonl(ignore->bucket);            next = (unsigned char*)(&g_int[1]);                        /* lastcontact */            g_time = (statefile_item_generic_time_t*)next;            g_time->hdr.tag = htonl(STATEFILE_TAG_IGNORE_LASTCONTACT);            g_time->hdr.length = htonl(sizeof(*g_time));            g_time->g_time = htonl(ignore->lastcontact);            next = (unsigned char*)(&g_time[1]);                        /* hostmask */            hdr = (statefile_hdr_t*)next;            hdr->tag = htonl(STATEFILE_TAG_IGNORE_HOSTMASK);            hdr->length = htonl(sizeof(statefile_hdr_t) + strlen(ignore->hostmask) + 1);            next = (unsigned char*)(&hdr[1]);            strcpy(next, ignore->hostmask);            next += ceiling(strlen(ignore->hostmask) + 1, 4);                    write_statefile_item(&bout, data);                        mydelete(data);          }        ignore = irlist_get_next(ignore);      }  }    {    unsigned char *data;    unsigned char *next;    msglog_t *msglog;    statefile_item_generic_time_t *g_time;        msglog = irlist_get_head(&gdata.msglog);        while (msglog)      {        /*         * need room to write:         *  when          time_t         *  hostmask      string         *  message       string         */        length = sizeof(statefile_hdr_t) +          sizeof(statefile_item_generic_time_t) +           sizeof(statefile_hdr_t) + ceiling(strlen(msglog->hostmask) + 1, 4) +          sizeof(statefile_hdr_t) + ceiling(strlen(msglog->message) + 1, 4);                data = mycalloc(length);                /* outter header */        hdr = (statefile_hdr_t*)data;        hdr->tag = STATEFILE_TAG_MSGLOG;        hdr->length = length;        next = (unsigned char*)(&hdr[1]);                /* when */        g_time = (statefile_item_generic_time_t*)next;        g_time->hdr.tag = htonl(STATEFILE_TAG_MSGLOG_WHEN);        g_time->hdr.length = htonl(sizeof(*g_time));        g_time->g_time = htonl(msglog->when);        next = (unsigned char*)(&g_time[1]);                /* hostmask */        hdr = (statefile_hdr_t*)next;        hdr->tag = htonl(STATEFILE_TAG_MSGLOG_HOSTMASK);        hdr->length = htonl(sizeof(statefile_hdr_t) + strlen(msglog->hostmask) + 1);        next = (unsigned char*)(&hdr[1]);        strcpy(next, msglog->hostmask);        next += ceiling(strlen(msglog->hostmask) + 1, 4);                /* message */        hdr = (statefile_hdr_t*)next;        hdr->tag = htonl(STATEFILE_TAG_MSGLOG_MESSAGE);        hdr->length = htonl(sizeof(statefile_hdr_t) + strlen(msglog->message) + 1);        next = (unsigned char*)(&hdr[1]);        strcpy(next, msglog->message);        next += ceiling(strlen(msglog->message) + 1, 4);                write_statefile_item(&bout, data);                mydelete(data);        msglog = irlist_get_next(msglog);      }  }    {    unsigned char *data;    unsigned char *next;    xdcc *xd;    statefile_item_generic_int_t *g_int;    statefile_item_generic_float_t *g_float;    statefile_item_md5sum_info_t *md5sum_info;        xd = irlist_get_head(&gdata.xdccs);        while (xd)      {        /*         * need room to write:         *  file          string         *  desc          string         *  note          string         *  gets          int         *  minspeed      float         *  maxspeed      float         */        length = sizeof(statefile_hdr_t) +          sizeof(statefile_hdr_t) + ceiling(strlen(xd->file) + 1, 4) +          sizeof(statefile_hdr_t) + ceiling(strlen(xd->desc) + 1, 4) +          sizeof(statefile_hdr_t) + ceiling(strlen(xd->note) + 1, 4) +          sizeof(statefile_item_generic_int_t) +           sizeof(statefile_item_generic_float_t) +           sizeof(statefile_item_generic_float_t);                if (xd->has_md5sum)          {            length += ceiling(sizeof(statefile_item_md5sum_info_t), 4);          }                data = mycalloc(length);                /* outter header */        hdr = (statefile_hdr_t*)data;        hdr->tag = STATEFILE_TAG_XDCCS;        hdr->length = length;        next = (unsigned char*)(&hdr[1]);                /* file */        hdr = (statefile_hdr_t*)next;        hdr->tag = htonl(STATEFILE_TAG_XDCCS_FILE);        hdr->length = htonl(sizeof(statefile_hdr_t) + strlen(xd->file) + 1);        next = (unsigned char*)(&hdr[1]);        strcpy(next, xd->file);        next += ceiling(strlen(xd->file) + 1, 4);                /* desc */        hdr = (statefile_hdr_t*)next;        hdr->tag = htonl(STATEFILE_TAG_XDCCS_DESC);        hdr->length = htonl(sizeof(statefile_hdr_t) + strlen(xd->desc) + 1);        next = (unsigned char*)(&hdr[1]);        strcpy(next, xd->desc);        next += ceiling(strlen(xd->desc) + 1, 4);                /* note */        hdr = (statefile_hdr_t*)next;        hdr->tag = htonl(STATEFILE_TAG_XDCCS_NOTE);        hdr->length = htonl(sizeof(statefile_hdr_t) + strlen(xd->note) + 1);        next = (unsigned char*)(&hdr[1]);        strcpy(next, xd->note);        next += ceiling(strlen(xd->note) + 1, 4);                /* gets */        g_int = (statefile_item_generic_int_t*)next;        g_int->hdr.tag = htonl(STATEFILE_TAG_XDCCS_GETS);        g_int->hdr.length = htonl(sizeof(*g_int));        g_int->g_int = htonl(xd->gets);        next = (unsigned char*)(&g_int[1]);                /* minspeed */        g_float = (statefile_item_generic_float_t*)next;        g_float->hdr.tag = htonl(STATEFILE_TAG_XDCCS_MINSPEED);        g_float->hdr.length = htonl(sizeof(*g_float));        if (gdata.transferminspeed == xd->minspeed)          {            g_float->g_float = 0;          }        else          {            g_float->g_float = xd->minspeed;          }        next = (unsigned char*)(&g_float[1]);                /* maxspeed */        g_float = (statefile_item_generic_float_t*)next;        g_float->hdr.tag = htonl(STATEFILE_TAG_XDCCS_MAXSPEED);        g_float->hdr.length = htonl(sizeof(*g_float));        if (gdata.transfermaxspeed == xd->maxspeed)          {            g_float->g_float = 0;          }        else          {            g_float->g_float = xd->maxspeed;          }        next = (unsigned char*)(&g_float[1]);                if (xd->has_md5sum)          {            /* md5sum */            md5sum_info = (statefile_item_md5sum_info_t*)next;            md5sum_info->hdr.tag = htonl(STATEFILE_TAG_XDCCS_MD5SUM_INFO);            md5sum_info->hdr.length = htonl(sizeof(*md5sum_info));            md5sum_info->st_size.upper = htonl(((ir_uint64)xd->st_size) >> 32);            md5sum_info->st_size.lower = htonl(xd->st_size & 0xFFFFFFFF);            md5sum_info->st_dev.upper  = htonl(((ir_uint64)xd->st_dev) >> 32);            md5sum_info->st_dev.lower  = htonl(xd->st_dev & 0xFFFFFFFF);            md5sum_info->st_ino.upper  = htonl(((ir_uint64)xd->st_ino) >> 32);            md5sum_info->st_ino.lower  = htonl(xd->st_ino & 0xFFFFFFFF);            md5sum_info->mtime         = htonl(xd->mtime);            memcpy(md5sum_info->md5sum, xd->md5sum, sizeof(MD5Digest));            next = (unsigned char*)(&md5sum_info[1]);          }                write_statefile_item(&bout, data);                mydelete(data);        xd = irlist_get_next(xd);      }  }    {    MD5Digest digest = {};        ir_boutput_get_md5sum(&bout, digest);        callval = ir_boutput_write(&bout, &digest, sizeof(digest));    if (callval != sizeof(digest))      {        outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Write md5sum To State File (%d != %d) %s",                 callval, (int)sizeof(digest), strerror(errno));      }  }    /*** end write ***/    ir_boutput_set_flags(&bout, 0);    callval = ir_boutput_attempt_flush(&bout);  if (callval < 0)    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Write to State File: %s",               strerror(errno));    }    if (bout.count_dropped || (bout.count_written != bout.count_flushed))    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Write failed to State File: %d/%d/%d",               bout.count_written,               bout.count_flushed,               bout.count_dropped);    }    ir_boutput_delete(&bout);  close(fd);    /* remove old bkup */  callval = unlink(statefile_bkup);  if ((callval < 0) && (errno != ENOENT))    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Remove Old State File '%s': %s",               statefile_bkup, strerror(errno));      /* ignore, continue */    }    /* backup old -> bkup */  callval = link(gdata.statefile, statefile_bkup);  if ((callval < 0) && (errno != ENOENT))    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Backup Old State File '%s' -> '%s': %s",               gdata.statefile, statefile_bkup, strerror(errno));      /* ignore, continue */    }    /* rename new -> current */  callval = rename(statefile_tmp, gdata.statefile);  if (callval < 0)    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Save New State File '%s': %s",               gdata.statefile, strerror(errno));      /* ignore, continue */    }    if (gdata.debug > 0)    {      ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,              COLOR_NO_COLOR, "Done");    }   error_out:    mydelete(statefile_tmp);  mydelete(statefile_bkup);  return;}static statefile_hdr_t* read_statefile_item(ir_uint32 **buffer, int *buffer_len){  statefile_hdr_t *all;    if (*buffer_len < sizeof(statefile_hdr_t))    {      return NULL;    }    all = (statefile_hdr_t*)*buffer;    all->tag = ntohl(all->tag);  all->length = ntohl(all->length);    if (*buffer_len < all->length)    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Bad Header From State File (%d < %d)",               *buffer_len, all->length);      return NULL;    }    *buffer += ceiling(all->length, 4) / sizeof(ir_uint32);  *buffer_len -= ceiling(all->length, 4);    return all;}void read_statefile(void){  int fd;  ir_uint32 *buffer, *buffer_begin;  int buffer_len;  struct MD5Context md5sum;  MD5Digest digest;  struct stat st;  statefile_hdr_t *hdr;  int callval;  time_t timestamp = 0;    updatecontext();    if (gdata.statefile == NULL)    {      return;    }    ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,          COLOR_NO_COLOR, "Loading State File... ");    fd = open(gdata.statefile,            O_RDONLY | O_CREAT | ADDED_OPEN_FLAGS,            CREAT_PERMISSIONS );    if (fd < 0)    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Access State File '%s': %s",               gdata.statefile, strerror(errno));      return;    }    if ((fstat(fd, &st) < 0) || (st.st_size < ((sizeof(ir_uint32) * 2) + sizeof(MD5Digest))))    {      ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,              COLOR_NO_COLOR, "State File: Too small, Skipping");      close(fd);      return;    }    buffer_len = st.st_size;  buffer_begin = buffer = mycalloc(buffer_len);    callval = read(fd, buffer, buffer_len);  close(fd);  if (callval != buffer_len)    {      outerror(OUTERROR_TYPE_WARN_LOUD, "Cant Read State File (%d != %d) %s",               callval, buffer_len, strerror(errno));      goto error_out;    }    /* verify md5sum */  buffer_len -= sizeof(MD5Digest);    MD5Init(&md5sum);  MD5Update(&md5sum, (md5byte*)buffer, buffer_len);  MD5Final(digest, &md5sum);    if (memcmp(digest, buffer+(buffer_len/sizeof(ir_uint32)), sizeof(MD5Digest)))    {      outerror(OUTERROR_TYPE_CRASH,               "\"%s\" Appears corrupt or is not an iroffer state file",               gdata.statefile);      goto error_out;    }    /* read */    if (ntohl(*buffer) != STATEFILE_MAGIC)    {      outerror(OUTERROR_TYPE_CRASH,               "\"%s\" Does not appear to be an iroffer state file",               gdata.statefile);      goto error_out;    }  buffer++;  buffer_len -= sizeof(ir_uint32);    if (gdata.debug > 0)    {      ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,              COLOR_NO_COLOR, "  [Version %lu State File]", (unsigned long)ntohl(*buffer));    }  buffer++;  buffer_len -= sizeof(ir_uint32);    while ((hdr = read_statefile_item(&buffer, &buffer_len)))    {      switch (hdr->tag)        {        case STATEFILE_TAG_TIMESTAMP:          if (hdr->length == sizeof(statefile_item_generic_time_t))            {              char *tempstr;              statefile_item_generic_time_t *g_time = (statefile_item_generic_time_t*)hdr;              timestamp = ntohl(g_time->g_time);                            tempstr = mycalloc(maxtextlength);              getdatestr(tempstr, timestamp, maxtextlength);                            ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,                      COLOR_NO_COLOR, "  [Written on %s]", tempstr);              mydelete(tempstr);            }          else            {              outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Timestamp Tag (len = %d)",                       hdr->length);            }          break;                  case STATEFILE_TAG_XFR_RECORD:          if (hdr->length == sizeof(statefile_item_generic_float_t))            {              statefile_item_generic_float_t *g_float = (statefile_item_generic_float_t*)hdr;              gdata.record = g_float->g_float;                            if (gdata.debug > 0)                {                  ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,                          COLOR_NO_COLOR, "  2,1•[12Record:00 %1.1fKB/s 02]•·", gdata.record);                }            }          else            {              outerror(OUTERROR_TYPE_WARN, "Ignoring Bad xfr Record Tag (len = %d)",                       hdr->length);            }          break;                  case STATEFILE_TAG_SENT_RECORD:          if (hdr->length == sizeof(statefile_item_generic_float_t))            {              statefile_item_generic_float_t *g_float = (statefile_item_generic_float_t*)hdr;              gdata.sentrecord = g_float->g_float;                            if (gdata.debug > 0)                {                  ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,                          COLOR_NO_COLOR, "  2,1•[12Record:00 %1.1fKB/s 02]•·", gdata.sentrecord);                }            }          else            {              outerror(OUTERROR_TYPE_WARN, "Ignoring Bad sent Record Tag (len = %d)",                       hdr->length);            }          break;                  case STATEFILE_TAG_TOTAL_SENT:          if (hdr->length == sizeof(statefile_item_generic_ullint_t))            {              statefile_item_generic_ullint_t *g_ullint = (statefile_item_generic_ullint_t*)hdr;              gdata.totalsent = (((ir_uint64)ntohl(g_ullint->g_ullint.upper)) << 32) | ((ir_uint64)ntohl(g_ullint->g_ullint.lower));                            if (gdata.debug > 0)                {                  ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,                          COLOR_NO_COLOR, "  2,1·•[12 Total Offered:00 %1.2f %cB 02]",                          (gdata.totalsent/1024/1024) > 1024 ? ( (gdata.totalsent/1024/1024/1024) > 1024 ? ((float)gdata.totalsent)/1024/1024/1024/1024                                                                 : ((float)gdata.totalsent)/1024/1024/1024 ) : ((float)gdata.totalsent)/1024/1024 ,                          (gdata.totalsent/1024/1024) > 1024 ? ( (gdata.totalsent/1024/1024/1024) > 1024 ? 'T' : 'G' ) : 'M');                }            }          else            {              outerror(OUTERROR_TYPE_WARN, "Ignoring Bad sent Record Tag (len = %d)",                       hdr->length);            }          break;                  case STATEFILE_TAG_TOTAL_UPTIME:          if (hdr->length == sizeof(statefile_item_generic_int_t))            {              char *tempstr;              statefile_item_generic_int_t *g_int = (statefile_item_generic_int_t*)hdr;              gdata.totaluptime = ntohl(g_int->g_int);                            if (gdata.debug > 0)                {                  tempstr = mycalloc(maxtextlength);                  getuptime(tempstr, 0, gdata.curtime-gdata.totaluptime, maxtextlength);                  ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,                          COLOR_NO_COLOR, "  [Total Runtime %s]",                          tempstr);                  mydelete(tempstr);                }            }          else            {              outerror(OUTERROR_TYPE_WARN, "Ignoring Bad sent Record Tag (len = %d)",                       hdr->length);            }          break;                  case STATEFILE_TAG_LAST_LOGROTATE:          if (hdr->length == sizeof(statefile_item_generic_time_t))            {              char *tempstr;              statefile_item_generic_time_t *g_time = (statefile_item_generic_time_t*)hdr;              gdata.last_logrotate = ntohl(g_time->g_time);                            if (gdata.debug > 0)                {                  tempstr = mycalloc(maxtextlength);                  getdatestr(tempstr, gdata.last_logrotate, maxtextlength);                                    ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,                          COLOR_NO_COLOR, "  [Last Log Rotate %s]", tempstr);                  mydelete(tempstr);                }            }          else            {              outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Last Log Rotate Tag (len = %d)",                       hdr->length);            }          break;                  case STATEFILE_TAG_IROFFER_VERSION:          if (hdr->length > sizeof(statefile_hdr_t))            {              char *iroffer_version = (char*)(&hdr[1]);              iroffer_version[hdr->length-sizeof(statefile_hdr_t)-1] = '\0';                            if (gdata.debug > 0)                {                  ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,                          COLOR_NO_COLOR, "  [Written by %s]", iroffer_version);                }            }          else            {              outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Iroffer Version Tag (len = %d)",                       hdr->length);            }          break;                  case STATEFILE_TAG_IGNORE:          {            igninfo *ignore;            char *tempr;            statefile_hdr_t *ihdr;            ignore = irlist_add(&gdata.ignorelist, sizeof(igninfo));                        hdr->length -= sizeof(*hdr);            ihdr = &hdr[1];                        while (hdr->length >= sizeof(*hdr))              {                ihdr->tag = ntohl(ihdr->tag);                ihdr->length = ntohl(ihdr->length);                switch (ihdr->tag)                  {                  case STATEFILE_TAG_IGNORE_FLAGS:                    if (ihdr->length == sizeof(statefile_item_generic_uint_t))                      {                        statefile_item_generic_uint_t *g_uint = (statefile_item_generic_uint_t*)ihdr;                        ignore->flags = ntohl(g_uint->g_uint);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Ignore Flags Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_IGNORE_BUCKET:                    if (ihdr->length == sizeof(statefile_item_generic_int_t))                      {                        statefile_item_generic_int_t *g_int = (statefile_item_generic_int_t*)ihdr;                        ignore->bucket = ntohl(g_int->g_int);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Ignore Bucket Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_IGNORE_LASTCONTACT:                    if (ihdr->length == sizeof(statefile_item_generic_time_t))                      {                        statefile_item_generic_time_t *g_time = (statefile_item_generic_time_t*)ihdr;                        ignore->lastcontact = ntohl(g_time->g_time);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Ignore Lastcontact Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_IGNORE_HOSTMASK:                    if (ihdr->length > sizeof(statefile_hdr_t))                      {                        char *hostmask = (char*)(&ihdr[1]);                        hostmask[ihdr->length-sizeof(statefile_hdr_t)-1] = '\0';                        ignore->hostmask = mycalloc(strlen(hostmask)+1);                        strcpy(ignore->hostmask,hostmask);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Ignore Hostmask Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      default:                    outerror(OUTERROR_TYPE_WARN, "Ignoring Unknown Ignore Tag 0x%X (len=%d)",                             ihdr->tag, ihdr->length);                  }                hdr->length -= ceiling(ihdr->length, 4);                ihdr = (statefile_hdr_t*)(((char*)ihdr) + ceiling(ihdr->length, 4));              }                        if ((!ignore->lastcontact) || (!ignore->hostmask))              {                outerror(OUTERROR_TYPE_WARN, "Ignoring Incomplete Ignore Tag");                                mydelete(ignore->hostmask);                irlist_delete(&gdata.ignorelist, ignore);              }            else              {                ignore->bucket -= (gdata.curtime - timestamp)/IGN_TL;                                ignore->regexp = mycalloc(sizeof(regex_t));                tempr = hostmasktoregex(ignore->hostmask);                if (regcomp(ignore->regexp,tempr,REG_ICASE|REG_NOSUB))                  {                    ignore->regexp = NULL;                  }                mydelete(tempr);              }          }                    break;                  case STATEFILE_TAG_MSGLOG:          {            msglog_t *msglog;            statefile_hdr_t *ihdr;            msglog = irlist_add(&gdata.msglog, sizeof(msglog_t));                        hdr->length -= sizeof(*hdr);            ihdr = &hdr[1];                        while (hdr->length >= sizeof(*hdr))              {                ihdr->tag = ntohl(ihdr->tag);                ihdr->length = ntohl(ihdr->length);                switch (ihdr->tag)                  {                  case STATEFILE_TAG_MSGLOG_WHEN:                    if (ihdr->length == sizeof(statefile_item_generic_time_t))                      {                        statefile_item_generic_time_t *g_time = (statefile_item_generic_time_t*)ihdr;                        msglog->when = ntohl(g_time->g_time);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Msglog When Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_MSGLOG_HOSTMASK:                    if (ihdr->length > sizeof(statefile_hdr_t))                      {                        char *hostmask = (char*)(&ihdr[1]);                        hostmask[ihdr->length-sizeof(statefile_hdr_t)-1] = '\0';                        msglog->hostmask = mycalloc(strlen(hostmask)+1);                        strcpy(msglog->hostmask,hostmask);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Msglog Hostmask Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_MSGLOG_MESSAGE:                    if (ihdr->length > sizeof(statefile_hdr_t))                      {                        char *message = (char*)(&ihdr[1]);                        message[ihdr->length-sizeof(statefile_hdr_t)-1] = '\0';                        msglog->message = mycalloc(strlen(message)+1);                        strcpy(msglog->message,message);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Msglog Message Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      default:                    outerror(OUTERROR_TYPE_WARN, "Ignoring Unknown Msglog Tag 0x%X (len=%d)",                             ihdr->tag, ihdr->length);                  }                hdr->length -= ceiling(ihdr->length, 4);                ihdr = (statefile_hdr_t*)(((char*)ihdr) + ceiling(ihdr->length, 4));              }                        if ((!msglog->when) || (!msglog->hostmask) || (!msglog->message))              {                outerror(OUTERROR_TYPE_WARN, "Ignoring Incomplete Msglog Tag");                                mydelete(msglog->hostmask);                mydelete(msglog->message);                irlist_delete(&gdata.msglog, msglog);              }          }                    break;                  case STATEFILE_TAG_XDCCS:          {            xdcc *xd;            statefile_hdr_t *ihdr;                        xd = irlist_add(&gdata.xdccs, sizeof(xdcc));                        xd->minspeed = gdata.transferminspeed;            xd->maxspeed = gdata.transfermaxspeed;                        hdr->length -= sizeof(*hdr);            ihdr = &hdr[1];                        while (hdr->length >= sizeof(*hdr))              {                ihdr->tag = ntohl(ihdr->tag);                ihdr->length = ntohl(ihdr->length);                switch (ihdr->tag)                  {                  case STATEFILE_TAG_XDCCS_FILE:                    if (ihdr->length > sizeof(statefile_hdr_t))                      {                        char *file = (char*)(&ihdr[1]);                        file[ihdr->length-sizeof(statefile_hdr_t)-1] = '\0';                        xd->file = mycalloc(strlen(file)+1);                        strcpy(xd->file,file);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad XDCC File Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_XDCCS_DESC:                    if (ihdr->length > sizeof(statefile_hdr_t))                      {                        char *desc = (char*)(&ihdr[1]);                        desc[ihdr->length-sizeof(statefile_hdr_t)-1] = '\0';                        xd->desc = mycalloc(strlen(desc)+1);                        strcpy(xd->desc,desc);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad XDCC Desc Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_XDCCS_NOTE:                    if (ihdr->length > sizeof(statefile_hdr_t))                      {                        char *note = (char*)(&ihdr[1]);                        note[ihdr->length-sizeof(statefile_hdr_t)-1] = '\0';                        xd->note = mycalloc(strlen(note)+1);                        strcpy(xd->note,note);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad XDCC Note Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_XDCCS_GETS:                    if (ihdr->length == sizeof(statefile_item_generic_int_t))                      {                        statefile_item_generic_int_t *g_int = (statefile_item_generic_int_t*)ihdr;                        xd->gets = ntohl(g_int->g_int);                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad XDCC Gets Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_XDCCS_MINSPEED:                    if (ihdr->length == sizeof(statefile_item_generic_float_t))                      {                        statefile_item_generic_float_t *g_float = (statefile_item_generic_float_t*)ihdr;                        if (g_float->g_float)                          {                            xd->minspeed = g_float->g_float;                          }                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad XDCC Minspeed Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_XDCCS_MAXSPEED:                    if (ihdr->length == sizeof(statefile_item_generic_float_t))                      {                        statefile_item_generic_float_t *g_float = (statefile_item_generic_float_t*)ihdr;                        if (g_float->g_float)                          {                            xd->maxspeed = g_float->g_float;                          }                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad XDCC Maxspeed Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      case STATEFILE_TAG_XDCCS_MD5SUM_INFO:                    if (ihdr->length == sizeof(statefile_item_md5sum_info_t))                      {                        statefile_item_md5sum_info_t *md5sum_info = (statefile_item_md5sum_info_t*)ihdr;                        xd->has_md5sum = 1;                        xd->st_size = (off_t)((((ir_uint64)ntohl(md5sum_info->st_size.upper)) << 32) | ((ir_uint64)ntohl(md5sum_info->st_size.lower)));                        xd->st_dev  = (dev_t)((((ir_uint64)ntohl(md5sum_info->st_dev.upper)) << 32) | ((ir_uint64)ntohl(md5sum_info->st_dev.lower)));                        xd->st_ino  = (ino_t)((((ir_uint64)ntohl(md5sum_info->st_ino.upper)) << 32) | ((ir_uint64)ntohl(md5sum_info->st_ino.lower)));                        xd->mtime   = ntohl(md5sum_info->mtime);                        memcpy(xd->md5sum, md5sum_info->md5sum, sizeof(MD5Digest));                      }                    else                      {                        outerror(OUTERROR_TYPE_WARN, "Ignoring Bad XDCC md5sum Tag (len = %d)",                                 ihdr->length);                      }                    break;                                      default:                    outerror(OUTERROR_TYPE_WARN, "Ignoring Unknown XDCC Tag 0x%X (len=%d)",                             ihdr->tag, ihdr->length);                  }                hdr->length -= ceiling(ihdr->length, 4);                ihdr = (statefile_hdr_t*)(((char*)ihdr) + ceiling(ihdr->length, 4));              }                        if ((!xd->file) || (!xd->desc) || (!xd->note))              {                outerror(OUTERROR_TYPE_WARN, "Ignoring Incomplete XDCC Tag");                                mydelete(xd->file);                mydelete(xd->desc);                mydelete(xd->note);                irlist_delete(&gdata.xdccs, xd);              }            else              {                int xfd;                xfd = open(xd->file, O_RDONLY | ADDED_OPEN_FLAGS);                if (xfd < 0)                  {                    outerror(OUTERROR_TYPE_WARN,"Cant Access Offered File '%s': %s",                             xd->file, strerror(errno));                    memset(&st,0,sizeof(st));                  }                else if (fstat(xfd, &st) < 0)                  {                    outerror(OUTERROR_TYPE_WARN,"Cant Access Offered File Details '%s': %s",                             xd->file, strerror(errno));                    memset(&st, 0, sizeof(st));                  }                                if (!xd->has_md5sum ||                    (xd->st_dev   != st.st_dev) ||                    (xd->st_ino   != st.st_ino) ||                    (xd->mtime    != st.st_mtime) ||                    (xd->st_size  != st.st_size))                  {                    xd->st_size     = st.st_size;                    xd->st_dev      = st.st_dev;                    xd->st_ino      = st.st_ino;                    xd->mtime       = st.st_mtime;                    xd->has_md5sum  = 0;                    memset(xd->md5sum, 0, sizeof(MD5Digest));                  }                                if (xd->st_size == 0)                  {                    outerror(OUTERROR_TYPE_WARN,"The file \"%s\" has size of 0 bytes!",                             xd->file);                  }                                if (xd->st_size > gdata.max_file_size)                  {                    outerror(OUTERROR_TYPE_CRASH,"The file \"%s\" is too large!",                             xd->file);                  }                                if (xfd >= 0)                  {                    close(xfd);                  }              }          }                    break;                  default:          outerror(OUTERROR_TYPE_WARN, "Ignoring Unknown Tag 0x%X (len=%d)",                 hdr->tag, hdr->length);          break;        }    }    if (buffer_len)    {      outerror(OUTERROR_TYPE_WARN, "Extra data at end of state file!? %d left",               buffer_len);    }    /* end read */    if ((gdata.debug > 0) || irlist_size(&gdata.ignorelist))    {      ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,              COLOR_NO_COLOR, "  [Found %d Ignore%s]",              irlist_size(&gdata.ignorelist),              (irlist_size(&gdata.ignorelist) == 1) ? "" : "s");    }    if ((gdata.debug > 0) || irlist_size(&gdata.msglog))    {      ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,              COLOR_NO_COLOR, "  [Found %d Message%s]",              irlist_size(&gdata.msglog),              (irlist_size(&gdata.msglog) == 1) ? "" : "s");    }    if ((gdata.debug > 0) || irlist_size(&gdata.xdccs))    {      ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,              COLOR_NO_COLOR, "  [Found %d Pack%s]",              irlist_size(&gdata.xdccs),              (irlist_size(&gdata.xdccs) == 1) ? "" : "s");    }    ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,          COLOR_NO_COLOR, "  [Done]");   error_out:    mydelete(buffer_begin);    return;}/* End of File */