/********************************************************
 * File: crashconvdupebase.c
 * Created at Sun Jan 28 22:10:29 MSK 2001 by raorn // raorn@binec.ru
 * Dumb dupebase converter to new format
 * $Id: crashconvdupebase.c,v 1.1 2002/08/12 17:49:47 raorn Exp $
 *******************************************************/

#include "crashecho.h"

#define DUPE_IDENTIFIER "CDU2"

#define GETULONG(ptr) ((((uchar*)(ptr))[0] & 0xFF)+((((uchar*)(ptr))[1] & 0xFF) << 8)+((((uchar*)(ptr))[2] & 0xFF) << 16)+((((uchar*)(ptr))[3] & 0xFF) << 24))
#define PUTULONG(ptr, num) do{ ((uchar*)(ptr))[0] = ((uchar)(num)) & 0xFF; ((uchar*)(ptr))[1] = ((uchar)((num) >> 8)) & 0xFF; ((uchar*)(ptr))[2] = ((uchar)((num) >> 16)) & 0xFF; ((uchar*)(ptr))[3] = ((uchar)((num) >> 24)) & 0xFF; }while(0)

ulong dupe_firstentry;
ulong dupe_lastentry;
ulong dupe_nextpos;
ulong dupe_emptyend;
ulong dupe_lastinbuf;

uchar dupeinfo[400];
ulong dupelen;

uchar *dupebuf;

ulong DupeSize;

void AddDupeBuf(uchar * dat, ulong len)
{
  ulong size;

  while (dupe_emptyend - dupe_nextpos < len + sizeof(ulong)) {
    if (dupe_nextpos + len + sizeof(ulong) + sizeof(ulong) >= DupeSize) {
      dupe_lastinbuf = dupe_nextpos;
      dupe_firstentry = 0;
      dupe_emptyend = 0;
      dupe_nextpos = 0;
    } else if (dupe_firstentry >= dupe_lastinbuf) {
      dupe_emptyend = DupeSize;

      if (dupe_emptyend - dupe_nextpos < len + sizeof(ulong)) {
        dupe_firstentry = 0;
        dupe_emptyend = 0;
        dupe_nextpos = 0;
        dupe_lastinbuf += len;
      }
    } else {
      size = GETULONG(dupebuf + dupe_firstentry);
      dupe_firstentry += size;
      dupe_emptyend += size;
    }
  }

  dupe_lastentry = dupe_nextpos;
  PUTULONG(dupebuf + dupe_nextpos, len + sizeof(ulong));
  dupe_nextpos += sizeof(ulong);
  memcpy(dupebuf + dupe_nextpos, dat, len);
  dupe_nextpos += len;
}

bool ReadDupes(uchar * file)
{
  FILE *fh;
  uchar buf[300];
  ushort size;

  if (!(fh = fopen(file, "rb")))
    return (TRUE);

  while (fread(&size, 1, sizeof(ushort), fh) == sizeof(ushort)) {
    if (size > 300) {
      fclose(fh);
      fprintf(stderr, "Error in dupefile %s", file);
      return (FALSE);
    }

    fread(buf, (ulong) size - sizeof(ushort), 1, fh);
    AddDupeBuf(buf, (ulong) size - sizeof(ushort));
  }

  fclose(fh);

  return (TRUE);
}

bool WriteDupes(uchar * file)
{
  FILE *fh;
  ulong size;
  ulong pos;

  if (!(fh = fopen(file, "wb"))) {
    fprintf(stderr, "Couldn't save dupe table to %s", file);
    fprintf(stderr, "Error: %s", strerror(errno));
    return (FALSE);
  }

  fwrite(DUPE_IDENTIFIER, 4, sizeof(uchar), fh);

  pos = dupe_firstentry;

  while (1) {
    size = GETULONG(dupebuf + pos);
    fwrite(dupebuf + pos, size, sizeof(uchar), fh);

    if (pos == dupe_lastentry)
      break;

    pos += size;

    if (pos >= dupe_lastinbuf && dupe_lastinbuf != 0)
      pos = 0;
  }

  fclose(fh);

  return (TRUE);
}

bool AllocDupebuf(void)
{
  if (!(dupebuf = malloc(DupeSize)))
    return (FALSE);

  dupe_firstentry = 0;
  dupe_lastentry = 0;
  dupe_nextpos = 0;
  dupe_emptyend = DupeSize;
  dupe_lastinbuf = 0;

  return (TRUE);
}

void FreeDupebuf(void)
{
  free(dupebuf);
}

int main(int argc, char *argv[])
{
  struct stat st;
  uchar *buf;

  if (argc != 2) {
    fprintf(stderr,"convertdupes - converts CrashEcho dupefile from old format to new.\n\n"
                   "Usage:\n"
                   "\tconvertdupes /path/to/dupebase\n");
    exit(1);
  }

  if(stat(argv[1], &st) != 0) {
    fprintf(stderr, "Can't stat %s\n", argv[1]);
    exit(1);
  }

  if ((buf = malloc(strlen(argv[1]+5))) == NULL) {
    fprintf(stderr, "Memory allocation failed\n");
    exit(1);
  }

  sprintf(buf, "%s.old", argv[1]);

  DupeSize = st.st_size;

  AllocDupebuf();
  ReadDupes(argv[1]);
  if (rename(argv[1], buf) != 0) {
    fprintf(stderr, "Can't rename %s to %s\n", argv[1], buf);
    FreeDupebuf();
    exit(1);
  }
  WriteDupes(argv[1]);
#ifndef __MINGW32__
  if (getuid() == 0) {
    chmod(argv[1], st.st_mode);
    chown(argv[1], st.st_uid, st.st_gid);
  }
#endif
  FreeDupebuf();
}


syntax highlighted by Code2HTML, v. 0.9.1