/************************************************************************ * 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 #include #include #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