Codebase list dopewars / scrub-obsolete/main win32 / makeinstall.c
scrub-obsolete/main

Tree @scrub-obsolete/main (Download .tar.gz)

makeinstall.c @scrub-obsolete/mainraw · history · blame

/************************************************************************
 * makeinstall.c  Program to create install data for setup.c            *
 * Copyright (C)  2001-2004  Ben Webb                                   *
 *                Email: benwebb@users.sf.net                           *
 *                WWW: http://dopewars.sourceforge.net/                 *
 *                                                                      *
 * 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; either version 2       *
 * of the License, or (at your option) any later version.               *
 *                                                                      *
 * 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 <windows.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef LIBBZ2
# include "bzlib/bzlib.h"
#else
# include "zlib/zlib.h"
#endif
#include "util.h"

char *read_line(HANDLE hin)
{
  char *buf;
  int bufsize = 32, strind = 0;
  DWORD bytes_read;

  buf = bmalloc(bufsize);

  while (1) {
    if (!ReadFile(hin, &buf[strind], 1, &bytes_read, NULL)) {
      printf("Read error\n");
      break;
    }
    if (bytes_read == 0) {
      buf[strind] = '\0';
      break;
    } else if (buf[strind] == '\r')
      continue;
    else if (buf[strind] == '\n') {
      buf[strind++] = '\0';
      break;
    } else {
      strind++;
      if (strind >= bufsize) {
        bufsize *= 2;
        buf = brealloc(buf, bufsize);
      }
    }
  }
  if (strind == 0) {
    bfree(buf);
    return NULL;
  } else
    return buf;
}

InstData *ReadInstallData()
{
  HANDLE fin;
  char *line, *line2, *line3, *line4;
  InstFiles *lastinst = NULL, *lastextra = NULL, *lastkeep = NULL;
  InstLink *lastmenu = NULL, *lastdesktop = NULL;
  InstData *idata;
  int i;
  enum {
    S_PRODUCT = 0, S_INSTDIR, S_INSTALL, S_EXTRA, S_KEEP, S_STARTMENUDIR,
    S_STARTMENU, S_DESKTOP, S_NTSERVICE, S_NONE
  } section = S_NONE;
  char *titles[S_NONE] = {
    "[product]", "[instdir]", "[install]", "[extrafiles]", "[keepfiles]",
    "[startmenudir]", "[startmenu]", "[desktop]", "[NT Service]"
  };

  idata = bmalloc(sizeof(InstData));
  idata->installdir = idata->startmenudir = NULL;
  idata->instfiles = idata->extrafiles = idata->keepfiles = NULL;
  idata->startmenu = idata->desktop = NULL;
  idata->service = NULL;

  fin = CreateFile("filelist", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

  if (fin != INVALID_HANDLE_VALUE) {
    while (1) {
      line = read_line(fin);
      if (!line)
        break;
      if (line[0] == '\0') {
        bfree(line);
        continue;
      }

      for (i = S_PRODUCT; i < S_NONE; i++) {
        if (strcmp(line, titles[i]) == 0) {
          section = i;
          break;
        }
      }
      if (i < S_NONE) {
        bfree(line);
        continue;
      }

      switch (section) {
      case S_NONE:
        printf("Bad line %s\n", line);
        exit(EXIT_FAILURE);
      case S_PRODUCT:
        printf("product ID = %s\n", line);
        idata->product = line;
        break;
      case S_INSTDIR:
        printf("install dir = %s\n", line);
        idata->installdir = line;
        break;
      case S_STARTMENUDIR:
        printf("start menu dir = %s\n", line);
        idata->startmenudir = line;
        break;
      case S_INSTALL:
        AddInstFiles(line, 0, &lastinst, &idata->instfiles);
        break;
      case S_EXTRA:
        AddInstFiles(line, 0, &lastextra, &idata->extrafiles);
        break;
      case S_KEEP:
        AddInstFiles(line, 0, &lastkeep, &idata->keepfiles);
        break;
      case S_STARTMENU:
        line2 = read_line(fin);
        line3 = read_line(fin);
        printf("start menu entry = %s/%s/%s\n", line, line2, line3);
        AddInstLink(line, line2, line3, &lastmenu, &idata->startmenu);
        break;
      case S_NTSERVICE:
        line2 = read_line(fin);
        line3 = read_line(fin);
        line4 = read_line(fin);
        printf("NT Service = %s/%s/%s/%s\n", line, line2, line3, line4);
        AddServiceDetails(line, line2, line3, line4, &idata->service);
        break;
      case S_DESKTOP:
        line2 = read_line(fin);
        line3 = read_line(fin);
        printf("desktop entry = %s/%s/%s\n", line, line2, line3);
        AddInstLink(line, line2, line3, &lastdesktop, &idata->desktop);
        break;
      }
    }
    CloseHandle(fin);
  }

  if (idata->installdir && idata->startmenudir && idata->product) {
    return idata;
  } else {
    printf("No directories specified\n");
    exit(EXIT_FAILURE);
  }
}

#define BUFFER_SIZE (32*1024)
#define COMPRESSION 9

void OpenNextFile(InstFiles *filelist, InstFiles **listpt, HANDLE *fin)
{
  char *filename, *sep;

  if (*fin)
    CloseHandle(*fin);
  *fin = NULL;

  if (!*listpt)
    *listpt = filelist;
  else
    *listpt = (*listpt)->next;

  if (*listpt) {
    filename = (*listpt)->filename;
    sep = strstr(filename, " -> ");
    if (sep)
      *sep = '\0';
    *fin = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (sep)
      strcpy(filename, sep + 4);
    if (*fin == INVALID_HANDLE_VALUE)
      printf("Cannot open file: %s\n", filename);
  }
}

int main()
{
  HANDLE fout, fin;
  DWORD bytes_read, bytes_written;
  InstData *idata;
  InstFiles *filept;
  char *inbuf, *outbuf;
  int status, count;
  bstr *str;
#ifdef LIBBZ2
  bz_stream z;
#else
  z_stream z;
#endif

  idata = ReadInstallData();

  fout = CreateFile("installfiles.z", GENERIC_WRITE, 0, NULL,
                    CREATE_ALWAYS, 0, NULL);

  outbuf = bmalloc(BUFFER_SIZE);
  inbuf = bmalloc(BUFFER_SIZE);

#ifdef LIBBZ2
  z.bzalloc = NULL;
  z.bzfree = NULL;
  z.opaque = NULL;
  BZ2_bzCompressInit(&z, COMPRESSION, 0, 30);
#else
  z.zalloc = Z_NULL;
  z.zfree  = Z_NULL;
  z.opaque = Z_NULL;
  deflateInit(&z, COMPRESSION);
#endif
  z.avail_in = 0;
  z.next_out = outbuf;
  z.avail_out = BUFFER_SIZE;

  filept = NULL;
  fin = NULL;
  OpenNextFile(idata->instfiles, &filept, &fin);
  if (fin == INVALID_HANDLE_VALUE) {
    return 1;
  }

  while (fin != INVALID_HANDLE_VALUE) {
    if (z.avail_in == 0) {
      z.next_in = inbuf;
      bytes_read = 0;
      while (!bytes_read && fin) {
        if (!ReadFile(fin, inbuf, BUFFER_SIZE, &bytes_read, NULL)) {
          printf("Read error\n");
          break;
        }
        filept->filesize += bytes_read;
        if (!bytes_read)
          OpenNextFile(idata->instfiles, &filept, &fin);
      }
      z.avail_in = bytes_read;
    }
#ifdef LIBBZ2
    status = BZ2_bzCompress(&z, z.avail_in == 0 ? BZ_FINISH : BZ_RUN);
#else
    status = deflate(&z, z.avail_in == 0 ? Z_FINISH : Z_NO_FLUSH);
#endif
    count = BUFFER_SIZE - z.avail_out;
    if (!WriteFile(fout, outbuf, count, &bytes_written, NULL)) {
      printf("Write error\n");
    }
    z.next_out = outbuf;
    z.avail_out = BUFFER_SIZE;

#ifdef LIBBZ2
    if (status == BZ_STREAM_END) {
      break;
    } else if (status != BZ_RUN_OK && status != BZ_FINISH_OK) {
      printf("Unexpected bzlib status: %d\n", status);
      break;
    }
#else
    if (status == Z_STREAM_END) {
      break;
    } else if (status != Z_OK) {
      printf("Unexpected libz status: %d\n", status);
      break;
    }
#endif
  }

#ifdef LIBBZ2
  printf("Written compressed data: raw %d, compressed %d\n",
         z.total_in_lo32, z.total_out_lo32);
  bytes_written = z.total_out_lo32;
  BZ2_bzCompressEnd(&z);
#else
  printf("Written compressed data: raw %ld, compressed %ld\n",
         z.total_in, z.total_out);
  bytes_written = z.total_out;
  deflateEnd(&z);
#endif

  CloseHandle(fout);

  fout = CreateFile("manifest", GENERIC_WRITE, 0, NULL,
                    CREATE_ALWAYS, 0, NULL);
  if (fout == INVALID_HANDLE_VALUE)
    printf("Cannot create file list\n");

  str = bstr_new();
  bstr_setlength(str, 0);
  bstr_append_long(str, bytes_written);
  if (!WriteFile(fout, str->text, str->length + 1, &bytes_written, NULL)) {
    printf("Write error\n");
  }

  if (!WriteFile(fout, idata->product, strlen(idata->product) + 1,
                 &bytes_written, NULL)) {
    printf("Write error\n");
  }
  if (!WriteFile(fout, idata->installdir, strlen(idata->installdir) + 1,
                 &bytes_written, NULL)) {
    printf("Write error\n");
  }
  if (!WriteFile
      (fout, idata->startmenudir, strlen(idata->startmenudir) + 1,
       &bytes_written, NULL)) {
    printf("Write error\n");
  }

  WriteFileList(fout, idata->instfiles);
  WriteFileList(fout, idata->extrafiles);

  WriteLinkList(fout, idata->startmenu);
  WriteLinkList(fout, idata->desktop);

  WriteServiceDetails(fout, idata->service);
  WriteFileList(fout, idata->keepfiles);

  CloseHandle(fout);
  bfree(inbuf);
  bfree(outbuf);

  FreeInstData(idata, TRUE);

  return 0;
}

#ifdef LIBBZ2
void bz_internal_error(int errcode)
{
  printf("bzip error %d\n", errcode);
}
#endif