/*
* 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.23@(#)
* pmg@wellington.i202.centerclick.org|src/iroffer_statefile.c|20050313183435|62320
*
*/
/* 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_TLIMIT_DAILY_USED = 13 << 8,
STATEFILE_TAG_TLIMIT_DAILY_ENDS,
STATEFILE_TAG_TLIMIT_WEEKLY_USED,
STATEFILE_TAG_TLIMIT_WEEKLY_ENDS,
STATEFILE_TAG_TLIMIT_MONTHLY_USED,
STATEFILE_TAG_TLIMIT_MONTHLY_ENDS,
} 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 1
typedef 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 = mymalloc(strlen(gdata.statefile)+5);
statefile_bkup = mymalloc(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);
}
}
{
statefile_item_generic_ullint_t item_daily_used;
item_daily_used.hdr.tag = STATEFILE_TAG_TLIMIT_DAILY_USED;
item_daily_used.hdr.length = sizeof(statefile_item_generic_ullint_t);
item_daily_used.g_ullint.upper = htonl(gdata.transferlimits[TRANSFERLIMIT_DAILY].used >> 32);
item_daily_used.g_ullint.lower = htonl(gdata.transferlimits[TRANSFERLIMIT_DAILY].used & 0xFFFFFFFF);
write_statefile_item(&bout, &item_daily_used);
}
{
statefile_item_generic_time_t item_daily_ends;
item_daily_ends.hdr.tag = STATEFILE_TAG_TLIMIT_DAILY_ENDS;
item_daily_ends.hdr.length = sizeof(statefile_item_generic_time_t);
item_daily_ends.g_time = htonl(gdata.transferlimits[TRANSFERLIMIT_DAILY].ends);
write_statefile_item(&bout, &item_daily_ends);
}
{
statefile_item_generic_ullint_t item_weekly_used;
item_weekly_used.hdr.tag = STATEFILE_TAG_TLIMIT_WEEKLY_USED;
item_weekly_used.hdr.length = sizeof(statefile_item_generic_ullint_t);
item_weekly_used.g_ullint.upper = htonl(gdata.transferlimits[TRANSFERLIMIT_WEEKLY].used >> 32);
item_weekly_used.g_ullint.lower = htonl(gdata.transferlimits[TRANSFERLIMIT_WEEKLY].used & 0xFFFFFFFF);
write_statefile_item(&bout, &item_weekly_used);
}
{
statefile_item_generic_time_t item_weekly_ends;
item_weekly_ends.hdr.tag = STATEFILE_TAG_TLIMIT_WEEKLY_ENDS;
item_weekly_ends.hdr.length = sizeof(statefile_item_generic_time_t);
item_weekly_ends.g_time = htonl(gdata.transferlimits[TRANSFERLIMIT_WEEKLY].ends);
write_statefile_item(&bout, &item_weekly_ends);
}
{
statefile_item_generic_ullint_t item_monthly_used;
item_monthly_used.hdr.tag = STATEFILE_TAG_TLIMIT_MONTHLY_USED;
item_monthly_used.hdr.length = sizeof(statefile_item_generic_ullint_t);
item_monthly_used.g_ullint.upper = htonl(gdata.transferlimits[TRANSFERLIMIT_MONTHLY].used >> 32);
item_monthly_used.g_ullint.lower = htonl(gdata.transferlimits[TRANSFERLIMIT_MONTHLY].used & 0xFFFFFFFF);
write_statefile_item(&bout, &item_monthly_used);
}
{
statefile_item_generic_time_t item_monthly_ends;
item_monthly_ends.hdr.tag = STATEFILE_TAG_TLIMIT_MONTHLY_ENDS;
item_monthly_ends.hdr.length = sizeof(statefile_item_generic_time_t);
item_monthly_ends.g_time = htonl(gdata.transferlimits[TRANSFERLIMIT_MONTHLY].ends);
write_statefile_item(&bout, &item_monthly_ends);
}
{
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, " [Record %1.1fKB/s]", 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, " [Bandwidth Record %1.1fKB/s]", 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, " [Total Transferred %1.2f %cB]",
(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 = mymalloc(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)/gdata.autoignore_threshold;
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 = mymalloc(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 = mymalloc(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 = mymalloc(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 = mymalloc(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 = mymalloc(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;
case STATEFILE_TAG_TLIMIT_DAILY_USED:
if (hdr->length == sizeof(statefile_item_generic_ullint_t))
{
statefile_item_generic_ullint_t *g_ullint = (statefile_item_generic_ullint_t*)hdr;
gdata.transferlimits[TRANSFERLIMIT_DAILY].used = (((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, " [Daily Transfer Limit Used %" LLPRINTFMT "uMB]",
gdata.transferlimits[TRANSFERLIMIT_DAILY].used / 1024 / 1024);
}
}
else
{
outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Daily Transfer Limit Used Tag (len = %d)",
hdr->length);
}
break;
case STATEFILE_TAG_TLIMIT_DAILY_ENDS:
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.transferlimits[TRANSFERLIMIT_DAILY].ends = ntohl(g_time->g_time);
if (gdata.debug > 0)
{
tempstr = mycalloc(maxtextlength);
getdatestr(tempstr, gdata.transferlimits[TRANSFERLIMIT_DAILY].ends, maxtextlength);
ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,
COLOR_NO_COLOR, " [Daily Transfer Limit Ends %s]", tempstr);
mydelete(tempstr);
}
}
else
{
outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Daily Transfer Limit Ends Tag (len = %d)",
hdr->length);
}
break;
case STATEFILE_TAG_TLIMIT_WEEKLY_USED:
if (hdr->length == sizeof(statefile_item_generic_ullint_t))
{
statefile_item_generic_ullint_t *g_ullint = (statefile_item_generic_ullint_t*)hdr;
gdata.transferlimits[TRANSFERLIMIT_WEEKLY].used = (((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, " [Weekly Transfer Limit Used %" LLPRINTFMT "uMB]",
gdata.transferlimits[TRANSFERLIMIT_WEEKLY].used / 1024 / 1024);
}
}
else
{
outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Weekly Transfer Limit Used Tag (len = %d)",
hdr->length);
}
break;
case STATEFILE_TAG_TLIMIT_WEEKLY_ENDS:
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.transferlimits[TRANSFERLIMIT_WEEKLY].ends = ntohl(g_time->g_time);
if (gdata.debug > 0)
{
tempstr = mycalloc(maxtextlength);
getdatestr(tempstr, gdata.transferlimits[TRANSFERLIMIT_WEEKLY].ends, maxtextlength);
ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,
COLOR_NO_COLOR, " [Weekly Transfer Limit Ends %s]", tempstr);
mydelete(tempstr);
}
}
else
{
outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Weekly Transfer Limit Ends Tag (len = %d)",
hdr->length);
}
break;
case STATEFILE_TAG_TLIMIT_MONTHLY_USED:
if (hdr->length == sizeof(statefile_item_generic_ullint_t))
{
statefile_item_generic_ullint_t *g_ullint = (statefile_item_generic_ullint_t*)hdr;
gdata.transferlimits[TRANSFERLIMIT_MONTHLY].used = (((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, " [Monthly Transfer Limit Used %" LLPRINTFMT "uMB]",
gdata.transferlimits[TRANSFERLIMIT_MONTHLY].used / 1024 / 1024);
}
}
else
{
outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Monthly Transfer Limit Used Tag (len = %d)",
hdr->length);
}
break;
case STATEFILE_TAG_TLIMIT_MONTHLY_ENDS:
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.transferlimits[TRANSFERLIMIT_MONTHLY].ends = ntohl(g_time->g_time);
if (gdata.debug > 0)
{
tempstr = mycalloc(maxtextlength);
getdatestr(tempstr, gdata.transferlimits[TRANSFERLIMIT_MONTHLY].ends, maxtextlength);
ioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D,
COLOR_NO_COLOR, " [Monthly Transfer Limit Ends %s]", tempstr);
mydelete(tempstr);
}
}
else
{
outerror(OUTERROR_TYPE_WARN, "Ignoring Bad Monthly Transfer Limit Ends Tag (len = %d)",
hdr->length);
}
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 */
syntax highlighted by Code2HTML, v. 0.9.1