diff --git a/source/src/main.cpp b/source/src/main.cpp index 696e0432..b1715e5a 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -943,38 +943,31 @@ void autostartscripts(const char *prefix) void createconfigtemplates(const char *templatezip) // create customisable config files in homedir - only if missing { -#if 0 - if(addzip(templatezip)) + vector files; + void *mz = zipmanualopen(openfile(templatezip, "rb"), files); + if(mz) { - vector files; - listzipfiles("", "cfg", files); // only look for config files in the root dir of the zip file loopv(files) { - defformatstring(fname)("config%c%s.cfg", PATHDIV, behindpath(files[i])); // (the "behindpath()" should not be necessary, but we want to be careful: the zip may be weird) - stream *f = openrawfile(fname, "rb"); - if(f) delete f; // config already exists - else + const char *filename = behindpath(files[i]); // only look for config files in the zip file, ignore all paths in the zip + if(strlen(filename) > 4 && !strcmp(filename + strlen(filename) - 4, ".cfg")) { - int flen; - char *buf = loadfile(behindpath(fname), &flen); // fetch file content from zip - if(buf) + defformatstring(fname)("config%c%s.cfg", PATHDIV, files[i]); + if(getfilesize(fname) <= 0) // config does not exist or is empty { - f = openfile(fname, "wb"); - if(f) + stream *zf = openfile(fname, "wb"); + if(zf) { - f->write(buf, flen); - delete f; + zipmanualread(mz, i, zf, MAXCFGFILESIZE); // fetch file content from zip, write to new config file + delete zf; conoutf("created %s from template %s", fname, templatezip); } - delete[] buf; } } - delete[] files[i]; } - removezip(templatezip); + zipmanualclose(mz); } findfile(AUTOSTARTPATH "dummy", "w"); // create empty autostart directory, if it doesn't exist yet -#endif } extern void connectserv(char *, int *, char *); @@ -1180,7 +1173,7 @@ int main(int argc, char **argv) initclientlog(); if(quitdirectly) return EXIT_SUCCESS; - createconfigtemplates("config/configtemplates.zip"); + createconfigtemplates("config" PATHDIVS "configtemplates.zip"); initing = NOT_INITING; diff --git a/source/src/stream.cpp b/source/src/stream.cpp index 9ffd3819..5e066ef9 100644 --- a/source/src/stream.cpp +++ b/source/src/stream.cpp @@ -958,6 +958,14 @@ char *loadfile(const char *fn, int *size, const char *mode) return buf; } +int streamcopy(stream *dest, stream *source, int maxlen) +{ + int got = 0, len; + uchar copybuf[1024]; + while(got < maxlen && (len = source->read(copybuf, 1024))) got += dest->write(copybuf, len); + return got; +} + #ifndef STANDALONE void filerotate(const char *basename, const char *ext, int keepold, const char *oldformat) // rotate old logfiles { diff --git a/source/src/tools.h b/source/src/tools.h index 489eec3d..ba8e8bff 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -955,6 +955,7 @@ extern stream *openfile(const char *filename, const char *mode); extern stream *opentempfile(const char *filename, const char *mode); extern stream *opengzfile(const char *filename, const char *mode, stream *file = NULL, int level = Z_BEST_COMPRESSION); extern char *loadfile(const char *fn, int *size, const char *mode = NULL); +extern int streamcopy(stream *dest, stream *source, int maxlen = INT_MAX); extern void filerotate(const char *basename, const char *ext, int keepold, const char *oldformat = NULL); extern bool listdir(const char *dir, const char *ext, vector &files); extern void listfiles(const char *dir, const char *ext, vector &files); @@ -962,6 +963,10 @@ extern void listfilesrecursive(const char *dir, vector &files, int level extern void listzipfiles(const char *dir, const char *ext, vector &files); extern bool delfile(const char *path); extern void backup(char *name, char *backupname); +extern void *zipmanualopen(stream *f, vector &files); +extern stream *zipmanualstream(void *a, int n); +extern int zipmanualread(void *a, int n, stream *f, int maxlen = INT_MAX); +extern void zipmanualclose(void *a); extern struct mapstats *loadmapstats(const char *filename, bool getlayout); extern bool cmpb(void *b, int n, enet_uint32 c); extern bool cmpf(char *fn, enet_uint32 c); diff --git a/source/src/zip.cpp b/source/src/zip.cpp index 5a288a38..b1b6e125 100644 --- a/source/src/zip.cpp +++ b/source/src/zip.cpp @@ -679,6 +679,54 @@ void writezipmodconfig(stream *f) #endif +// simple interface to read zip contents without mounting them first + +void *zipmanualopen(stream *f, vector &files) +{ + if(!f) return NULL; + zipdirectoryheader h; + ziparchive *arch = new ziparchive; + if(!findzipdirectory(f, h) || !readzipdirectory(f, h.entries, h.offset, h.size, arch->files)) + { + delete arch; + delete f; + return NULL; + } + arch->data = f; + loopv(arch->files) files.add(arch->files[i].name); + return (void *)arch; +} + +stream *zipmanualstream(void *a, int n) +{ + ziparchive *arch = (ziparchive *)a; + if(arch->files.inrange(n)) + { + zipstream *s = new zipstream; + if(s->open(arch, &arch->files[n])) return s; + delete s; + } + return NULL; +} + +int zipmanualread(void *a, int n, stream *f, int maxlen) +{ + int got = -1; + stream *s = zipmanualstream(a, n); + if(s) + { + got = streamcopy(f, s, maxlen); + delete s; + } + return got; +} + +void zipmanualclose(void *a) +{ + ziparchive *arch = (ziparchive *)a; + delete arch; // also closes arch->data, the associated file stream! +} + // AC virtual filesystem bool findzipfile(const char *name)