Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: client.cpp
- ===================================================================
- --- client.cpp (revision 6612)
- +++ client.cpp (working copy)
- @@ -813,3 +813,215 @@
- COMMAND(listdemos, ARG_NONE);
- COMMANDN(setmr, setminutesremaining, ARG_1INT);
- COMMANDN(rewind, rewinddemo, ARG_1INT);
- +
- +// packages auto - downloader
- +
- +// arrays
- +vector<pckserver *> pckservers;
- +vector<package *> packages;
- +//vector<package *> pendingpackages;
- +
- +// thread
- +SDL_Thread *pckthread;
- +int process_packages(void *ptr);
- +
- +// cubescript
- +
- +void addpckserver(char *addr)
- +{
- +
- +}
- +
- +void addpackage(char *type, char *name)
- +{
- + int t = atoi(type);
- + if(t < 0 || t >= PCK_NUM) return;
- + if(!name || name[0] == '\0') return;
- + package *pck = new package();
- + pck->name = newstring(name);
- + pck->type = t;
- + pck->source = pckservers[0]; // FIXME
- + packages.add(pck);
- +}
- +
- +void requirepackage(int type, char *name)
- +{
- + loopv(packages) if(packages[i]->type == type
- + && !strcmp(packages[i]->name, name))
- + {
- + packages[i]->pending = true;
- + }
- +}
- +
- +// reset current packages list
- +void resetpackages()
- +{
- + loopv(packages)
- + {
- + DELETEP(packages[i]);
- + packages.remove(i);
- + }
- + packages.shrink(0); // pointless?
- +}
- +
- +// update list of packages
- +void retrievepackages()
- +{
- + resetpackages();
- +
- + // TMP:
- + if(!pckservers.length())
- + {
- + pckserver *srcserver = new pckserver();
- + srcserver->addr = "http://de582.ispfr.net/cube";
- + srcserver->pending = true;
- + pckservers.add(srcserver);
- + }
- + // :TMP
- + loopv(pckservers) pckservers[i]->pending = true;
- + pckthread = SDL_CreateThread(process_packages, (void *)NULL);
- +}
- +
- +void downloadpackages()
- +{
- + pckthread = SDL_CreateThread(process_packages, (void *)NULL);
- +}
- +
- +void test()
- +{
- + loopi(10)
- + {
- + packages[260+i]->pending = true;
- + }
- + pckthread = SDL_CreateThread(process_packages, (void *)NULL);
- +}
- +
- +COMMAND(test, ARG_NONE);
- +COMMAND(addpckserver, ARG_1STR);
- +COMMAND(addpackage, ARG_2STR);
- +COMMAND(retrievepackages, ARG_NONE);
- +COMMAND(resetpackages, ARG_NONE);
- +
- +// cURL / Network
- +
- +static size_t write_callback(void *ptr, size_t size, size_t nmemb, FILE *stream)
- +{
- + return fwrite(ptr, size, nmemb, stream);
- +}
- +
- +// update packages list from a source
- +void retrievepackages(pckserver *srcserver, FILE *outfile)
- +{
- + srcserver->pending = false;
- + string req;
- + sprintf(req, "%s/get.php", srcserver->addr);
- + conoutf("retrieving list of packages from %s...", srcserver->addr);
- +
- + fprintf(outfile, "// setserver \"%s\";\n", srcserver->addr);
- +
- + CURL *curl = curl_easy_init();
- + curl_easy_setopt(curl, CURLOPT_URL, req);
- + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
- + curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
- + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "do=list");
- + curl_easy_perform(curl);
- + curl_easy_cleanup(curl);
- +}
- +
- +// download a package
- +bool dlpackage(package *pck)
- +{
- + if(!pck || !pck->source) return false;
- + FILE *outfile = fopen(path("config/tmp", true), "wb");
- + string req;
- + sprintf(req, "%s/get.php", pck->source->addr);
- + string post;
- + sprintf(post, "do=dl&name=%s&type=%d", pck->name, pck->type);
- + conoutf("downloading %s...", pck->name);
- +
- + CURL *curl = curl_easy_init();
- + curl_easy_setopt(curl, CURLOPT_URL, req);
- + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
- + curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
- + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
- + curl_easy_perform(curl);
- + curl_easy_cleanup(curl);
- + fclose(outfile);
- + return true;
- +}
- +
- +/*void retrievepackages()
- +{
- + resetpackages();
- + if(!pckservers.length())
- + {
- + pckserver *srcserver = new pckserver();
- + srcserver->addr = "http://de582.ispfr.net/cube";
- + pckservers.add(srcserver);
- + }
- + FILE *fp = fopen(path("config/packages.cfg", true), "w");
- + loopv(pckservers)
- + {
- + retrievepackages(pckservers[i], fp);
- + }
- + fclose(fp);
- + execfile("config/packages.cfg");
- +}*/
- +
- +// threading
- +
- +// threaded loop to process requests
- +int process_packages(void *ptr)
- +{
- + FILE *fp = NULL;
- + loopv(pckservers)
- + {
- + if(pckservers[i]->pending)
- + {
- + if(!fp) fp = fopen(path("config/packages.cfg", true), "w");
- + retrievepackages(pckservers[i], fp);
- + }
- + }
- + if(fp)
- + {
- + execfile("config/packages.cfg");
- + conoutf("%d packages loaded !", packages.length());
- + fclose(fp);
- + }
- +
- + bool dled = false;
- + loopv(packages)
- + {
- + if(packages[i]->pending)
- + {
- + dled = true;
- + packages[i]->pending = false; // even if an error occurs, do not dl again.
- + if(!dlpackage(packages[i]))
- + {
- + conoutf("\f3failed!");
- + continue;
- + }
- +
- + switch(packages[i]->type)
- + {
- + case PCK_TEXTURE:
- + {
- + string tmp;
- + sprintf(tmp, "packages/textures/%s", packages[i]->name);
- + preparedir(tmp);
- + // with textures, the image itself is sent. Just need to copy it from the temporary file
- + if(!copyfile(path("config/tmp", true), tmp)) conoutf("\f3failed to install %s", packages[i]->name);
- + }
- + break;
- +
- + default:
- + {
- + conoutf("could not install package %s", packages[i]->name);
- + }
- + break;
- + }
- + }
- + }
- + if(dled) conoutf("packages installed.");
- + return 0;
- +}
- \ No newline at end of file
- Index: entity.h
- ===================================================================
- --- entity.h (revision 6612)
- +++ entity.h (working copy)
- @@ -622,3 +622,23 @@
- return killmessages[gib?1:0][gun];
- }
- +
- +struct pckserver
- +{
- + char *addr;
- + bool pending;
- +
- + pckserver() : addr(NULL), pending(false) {}
- +};
- +
- +enum { PCK_TEXTURE, PCK_SKYBOX, PCK_MAPMODEL, PCK_AUDIO, PCK_MAP, PCK_NUM };
- +
- +struct package
- +{
- + char *name;
- + int type;
- + bool pending;
- + pckserver *source;
- +
- + package() : name(NULL), type(-1), pending(false) {}
- +};
- \ No newline at end of file
- Index: platform.h
- ===================================================================
- --- platform.h (revision 6612)
- +++ platform.h (working copy)
- @@ -71,3 +71,8 @@
- #include <setjmp.h>
- #endif
- +
- +#ifndef CURL_STATICLIB
- +#define CURL_STATICLIB
- +#endif
- +#include "curl/curl.h"
- \ No newline at end of file
- Index: protos.h
- ===================================================================
- --- protos.h (revision 6612)
- +++ protos.h (working copy)
- @@ -305,6 +305,9 @@
- extern float skyfloor;
- extern void draw_envbox(int fogdist);
- +extern void requirepackage(int type, char *name);
- +extern void downloadpackages();
- +
- extern int maxtmus;
- extern void inittmus();
- extern void resettmu(int n);
- Index: stream.cpp
- ===================================================================
- --- stream.cpp (revision 6612)
- +++ stream.cpp (working copy)
- @@ -1,785 +1,817 @@
- -#include "cube.h"
- -
- -///////////////////////// file system ///////////////////////
- -
- -#ifndef WIN32
- -#include <unistd.h>
- -#include <sys/stat.h>
- -#include <sys/types.h>
- -#include <dirent.h>
- -#endif
- -
- -string homedir = "";
- -vector<char *> packagedirs;
- -
- -char *makerelpath(const char *dir, const char *file, const char *prefix, const char *cmd)
- -{
- - static string tmp;
- - if(prefix) copystring(tmp, prefix);
- - else tmp[0] = '\0';
- - if(file[0]=='<')
- - {
- - const char *end = strrchr(file, '>');
- - if(end)
- - {
- - size_t len = strlen(tmp);
- - copystring(&tmp[len], file, min(sizeof(tmp)-len, size_t(end+2-file)));
- - file = end+1;
- - }
- - }
- - if(cmd) concatstring(tmp, cmd);
- - defformatstring(pname)("%s/%s", dir, file);
- - concatstring(tmp, pname);
- - return tmp;
- -}
- -
- -
- -char *path(char *s)
- -{
- - for(char *curpart = s;;)
- - {
- - char *endpart = strchr(curpart, '&');
- - if(endpart) *endpart = '\0';
- - if(curpart[0]=='<')
- - {
- - char *file = strrchr(curpart, '>');
- - if(!file) return s;
- - curpart = file+1;
- - }
- - for(char *t = curpart; (t = strpbrk(t, "/\\")); *t++ = PATHDIV);
- - for(char *prevdir = NULL, *curdir = s;;)
- - {
- - prevdir = curdir[0]==PATHDIV ? curdir+1 : curdir;
- - curdir = strchr(prevdir, PATHDIV);
- - if(!curdir) break;
- - if(prevdir+1==curdir && prevdir[0]=='.')
- - {
- - memmove(prevdir, curdir+1, strlen(curdir+1)+1);
- - curdir = prevdir;
- - }
- - else if(curdir[1]=='.' && curdir[2]=='.' && curdir[3]==PATHDIV)
- - {
- - if(prevdir+2==curdir && prevdir[0]=='.' && prevdir[1]=='.') continue;
- - memmove(prevdir, curdir+4, strlen(curdir+4)+1);
- - curdir = prevdir;
- - }
- - }
- - if(endpart)
- - {
- - *endpart = '&';
- - curpart = endpart+1;
- - }
- - else break;
- - }
- - return s;
- -}
- -
- -char *path(const char *s, bool copy)
- -{
- - static string tmp;
- - copystring(tmp, s);
- - path(tmp);
- - return tmp;
- -}
- -
- -const char *parentdir(const char *directory)
- -{
- - const char *p = directory + strlen(directory);
- - while(p > directory && *p != '/' && *p != '\\') p--;
- - static string parent;
- - size_t len = p-directory+1;
- - copystring(parent, directory, len);
- - return parent;
- -}
- -
- -const char *behindpath(const char *s)
- -{
- - const char *t = s;
- - for( ; (s = strpbrk(s, "/\\")); t = ++s);
- - return t;
- -}
- -
- -bool fileexists(const char *path, const char *mode)
- -{
- - bool exists = true;
- - if(mode[0]=='w' || mode[0]=='a') path = parentdir(path);
- -#ifdef WIN32
- - if(GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES) exists = false;
- -#else
- - if(access(path, R_OK | (mode[0]=='w' || mode[0]=='a' ? W_OK : 0)) == -1) exists = false;
- -#endif
- - return exists;
- -}
- -
- -bool createdir(const char *path)
- -{
- - size_t len = strlen(path);
- - if(path[len-1]==PATHDIV)
- - {
- - static string strip;
- - path = copystring(strip, path, len);
- - }
- -#ifdef WIN32
- - return CreateDirectory(path, NULL)!=0;
- -#else
- - return mkdir(path, 0777)==0;
- -#endif
- -}
- -
- -size_t fixpackagedir(char *dir)
- -{
- - path(dir);
- - size_t len = strlen(dir);
- - if(len > 0 && dir[len-1] != PATHDIV)
- - {
- - dir[len] = PATHDIV;
- - dir[len+1] = '\0';
- - }
- - return len;
- -}
- -
- -#ifdef WIN32
- -char *getregszvalue(HKEY root, const char *keystr, const char *query)
- -{
- - HKEY key;
- - if(RegOpenKeyEx(HKEY_CURRENT_USER, keystr, 0, KEY_READ, &key)==ERROR_SUCCESS)
- - {
- - DWORD type = 0, len = 0;
- - if(RegQueryValueEx(key, query, 0, &type, 0, &len)==ERROR_SUCCESS && type==REG_SZ)
- - {
- - char *val = new char[len];
- - long result = RegQueryValueEx(key, query, 0, &type, (uchar *)val, &len);
- - if(result==ERROR_SUCCESS)
- - {
- - RegCloseKey(key);
- - val[len-1] = '\0';
- - return val;
- - }
- - delete[] val;
- - }
- - RegCloseKey(key);
- - }
- - return NULL;
- -}
- -#endif
- -
- -void sethomedir(const char *dir)
- -{
- - string tmpdir;
- - copystring(tmpdir, dir);
- -
- -#ifdef WIN32
- - const char substitute[] = "?MYDOCUMENTS?";
- - if(!strncmp(dir, substitute, strlen(substitute)))
- - {
- - const char *regpath = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
- - char *mydocuments = getregszvalue(HKEY_CURRENT_USER, regpath, "Personal");
- - if(mydocuments)
- - {
- - formatstring(tmpdir)("%s%s", mydocuments, dir+strlen(substitute));
- - delete[] mydocuments;
- - }
- - else
- - {
- - printf("failed to retrieve 'Personal' path from '%s'\n", regpath);
- - }
- - }
- -#endif
- -
- -#ifndef STANDALONE
- - clientlogf("Using home directory: %s", tmpdir);
- -#endif
- -
- - if(fixpackagedir(tmpdir) > 0)
- - {
- - copystring(homedir, tmpdir);
- - createdir(homedir);
- - }
- -}
- -
- -void addpackagedir(const char *dir)
- -{
- -#ifndef STANDALONE
- - clientlogf("Adding package directory: %s", dir);
- -#endif
- -
- - string pdir;
- - copystring(pdir, dir);
- - if(fixpackagedir(pdir) > 0) packagedirs.add(newstring(pdir));
- -}
- -
- -const char *findfile(const char *filename, const char *mode)
- -{
- - static string s;
- - if(homedir[0])
- - {
- - formatstring(s)("%s%s", homedir, filename);
- - if(fileexists(s, mode)) return s;
- - if(mode[0]=='w' || mode[0]=='a')
- - {
- - string dirs;
- - copystring(dirs, s);
- - char *dir = strchr(dirs[0]==PATHDIV ? dirs+1 : dirs, PATHDIV);
- - while(dir)
- - {
- - *dir = '\0';
- - if(!fileexists(dirs, "r") && !createdir(dirs)) return s;
- - *dir = PATHDIV;
- - dir = strchr(dir+1, PATHDIV);
- - }
- - return s;
- - }
- - }
- - if(mode[0]=='w' || mode[0]=='a') return filename;
- - loopv(packagedirs)
- - {
- - formatstring(s)("%s%s", packagedirs[i], filename);
- - if(fileexists(s, mode)) return s;
- - }
- - return filename;
- -}
- -
- -bool listdir(const char *dir, const char *ext, vector<char *> &files)
- -{
- - int extsize = ext ? (int)strlen(ext)+1 : 0;
- - #if defined(WIN32)
- - defformatstring(pathname)("%s\\*.%s", dir, ext ? ext : "*");
- - WIN32_FIND_DATA FindFileData;
- - HANDLE Find = FindFirstFile(path(pathname), &FindFileData);
- - if(Find != INVALID_HANDLE_VALUE)
- - {
- - do {
- - files.add(newstring(FindFileData.cFileName, (int)strlen(FindFileData.cFileName) - extsize));
- - } while(FindNextFile(Find, &FindFileData));
- - FindClose(Find);
- - return true;
- - }
- - #else
- - string pathname;
- - copystring(pathname, dir);
- - DIR *d = opendir(path(pathname));
- - if(d)
- - {
- - struct dirent *de;
- - while((de = readdir(d)) != NULL)
- - {
- - if(!ext) files.add(newstring(de->d_name));
- - else
- - {
- - int namelength = (int)strlen(de->d_name) - extsize;
- - if(namelength > 0 && de->d_name[namelength] == '.' && strncmp(de->d_name+namelength+1, ext, extsize-1)==0)
- - files.add(newstring(de->d_name, namelength));
- - }
- - }
- - closedir(d);
- - return true;
- - }
- - #endif
- - else return false;
- -}
- -
- -int listfiles(const char *dir, const char *ext, vector<char *> &files)
- -{
- - int dirs = 0;
- - if(listdir(dir, ext, files)) dirs++;
- - string s;
- - if(homedir[0])
- - {
- - formatstring(s)("%s%s", homedir, dir);
- - if(listdir(s, ext, files)) dirs++;
- - }
- - loopv(packagedirs)
- - {
- - formatstring(s)("%s%s", packagedirs[i], dir);
- - if(listdir(s, ext, files)) dirs++;
- - }
- -#ifndef STANDALONE
- - dirs += listzipfiles(dir, ext, files);
- -#endif
- - return dirs;
- -}
- -
- -bool delfile(const char *path)
- -{
- - return !remove(path);
- -}
- -
- -#ifndef STANDALONE
- -static int rwopsseek(SDL_RWops *rw, int offset, int whence)
- -{
- - stream *f = (stream *)rw->hidden.unknown.data1;
- - if((!offset && whence==SEEK_CUR) || f->seek(offset, whence)) return f->tell();
- - return -1;
- -}
- -
- -static int rwopsread(SDL_RWops *rw, void *buf, int size, int nmemb)
- -{
- - stream *f = (stream *)rw->hidden.unknown.data1;
- - return f->read(buf, size*nmemb)/size;
- -}
- -
- -static int rwopswrite(SDL_RWops *rw, const void *buf, int size, int nmemb)
- -{
- - stream *f = (stream *)rw->hidden.unknown.data1;
- - return f->write(buf, size*nmemb)/size;
- -}
- -
- -static int rwopsclose(SDL_RWops *rw)
- -{
- - return 0;
- -}
- -
- -SDL_RWops *stream::rwops()
- -{
- - SDL_RWops *rw = SDL_AllocRW();
- - if(!rw) return NULL;
- - rw->hidden.unknown.data1 = this;
- - rw->seek = rwopsseek;
- - rw->read = rwopsread;
- - rw->write = rwopswrite;
- - rw->close = rwopsclose;
- - return rw;
- -}
- -#endif
- -
- -long stream::size()
- -{
- - long pos = tell(), endpos;
- - if(pos < 0 || !seek(0, SEEK_END)) return -1;
- - endpos = tell();
- - return pos == endpos || seek(pos, SEEK_SET) ? endpos : -1;
- -}
- -
- -bool stream::getline(char *str, int len)
- -{
- - loopi(len-1)
- - {
- - if(read(&str[i], 1) != 1) { str[i] = '\0'; return i > 0; }
- - else if(str[i] == '\n') { str[i+1] = '\0'; return true; }
- - }
- - if(len > 0) str[len-1] = '\0';
- - return true;
- -}
- -
- -#ifdef __linux__
- -#include <sys/statvfs.h>
- -#define MINFSSIZE 50000000ull // 50MB
- -#endif
- -
- -struct filestream : stream
- -{
- - FILE *file;
- -
- - filestream() : file(NULL) {}
- - ~filestream() { close(); }
- -
- - bool open(const char *name, const char *mode)
- - {
- - if(file) return false;
- - file = fopen(name, mode);
- -#ifdef __linux__
- - struct statvfs buf;
- - if(file && strchr(mode,'w'))
- - {
- - int fail = fstatvfs(fileno(file), &buf);
- - if (fail || (unsigned long long)buf.f_frsize * (unsigned long long)buf.f_bavail < MINFSSIZE)
- - {
- - close();
- - return false;
- - }
- - }
- -#endif
- - return file!=NULL;
- - }
- -
- - bool opentemp(const char *name, const char *mode)
- - {
- - if(file) return false;
- -#ifdef WIN32
- - file = fopen(name, mode);
- -#else
- - file = tmpfile();
- -#endif
- - return file!=NULL;
- - }
- -
- - void close()
- - {
- - if(file) { fclose(file); file = NULL; }
- - }
- -
- - bool end() { return feof(file)!=0; }
- - long tell() { return ftell(file); }
- - bool seek(long offset, int whence) { return fseek(file, offset, whence) >= 0; }
- - int read(void *buf, int len) { return (int)fread(buf, 1, len, file); }
- - int write(const void *buf, int len) { return (int)fwrite(buf, 1, len, file); }
- - int getchar() { return fgetc(file); }
- - bool putchar(int c) { return fputc(c, file)!=EOF; }
- - bool getline(char *str, int len) { return fgets(str, len, file)!=NULL; }
- - bool putstring(const char *str) { return fputs(str, file)!=EOF; }
- -
- - int printf(const char *fmt, ...)
- - {
- - va_list v;
- - va_start(v, fmt);
- - int result = vfprintf(file, fmt, v);
- - va_end(v);
- - return result;
- - }
- -};
- -
- -#ifndef STANDALONE
- -VAR(dbggz, 0, 0, 1);
- -#endif
- -
- -struct gzstream : stream
- -{
- - enum
- - {
- - MAGIC1 = 0x1F,
- - MAGIC2 = 0x8B,
- - BUFSIZE = 16384,
- - OS_UNIX = 0x03
- - };
- -
- - enum
- - {
- - F_ASCII = 0x01,
- - F_CRC = 0x02,
- - F_EXTRA = 0x04,
- - F_NAME = 0x08,
- - F_COMMENT = 0x10,
- - F_RESERVED = 0xE0
- - };
- -
- - stream *file;
- - z_stream zfile;
- - uchar *buf;
- - bool reading, writing, autoclose;
- - uint crc;
- - int headersize;
- -
- - gzstream() : file(NULL), buf(NULL), reading(false), writing(false), autoclose(false), crc(0), headersize(0)
- - {
- - zfile.zalloc = NULL;
- - zfile.zfree = NULL;
- - zfile.opaque = NULL;
- - zfile.next_in = zfile.next_out = NULL;
- - zfile.avail_in = zfile.avail_out = 0;
- - }
- -
- - ~gzstream()
- - {
- - close();
- - }
- -
- - void writeheader()
- - {
- - uchar header[] = { MAGIC1, MAGIC2, Z_DEFLATED, 0, 0, 0, 0, 0, 0, OS_UNIX };
- - file->write(header, sizeof(header));
- - }
- -
- - void readbuf(int size = BUFSIZE)
- - {
- - if(!zfile.avail_in) zfile.next_in = (Bytef *)buf;
- - size = min(size, int(&buf[BUFSIZE] - &zfile.next_in[zfile.avail_in]));
- - int n = file->read(zfile.next_in + zfile.avail_in, size);
- - if(n > 0) zfile.avail_in += n;
- - }
- -
- - int readbyte(int size = BUFSIZE)
- - {
- - if(!zfile.avail_in) readbuf(size);
- - if(!zfile.avail_in) return 0;
- - zfile.avail_in--;
- - return *(uchar *)zfile.next_in++;
- - }
- -
- - void skipbytes(int n)
- - {
- - while(n > 0 && zfile.avail_in > 0)
- - {
- - int skipped = min(n, (int)zfile.avail_in);
- - zfile.avail_in -= skipped;
- - zfile.next_in += skipped;
- - n -= skipped;
- - }
- - if(n <= 0) return;
- - file->seek(n, SEEK_CUR);
- - }
- -
- - bool checkheader()
- - {
- - readbuf(10);
- - if(readbyte() != MAGIC1 || readbyte() != MAGIC2 || readbyte() != Z_DEFLATED) return false;
- - int flags = readbyte();
- - if(flags & F_RESERVED) return false;
- - skipbytes(6);
- - if(flags & F_EXTRA)
- - {
- - int len = readbyte(512);
- - len |= readbyte(512)<<8;
- - skipbytes(len);
- - }
- - if(flags & F_NAME) while(readbyte(512));
- - if(flags & F_COMMENT) while(readbyte(512));
- - if(flags & F_CRC) skipbytes(2);
- - headersize = file->tell() - zfile.avail_in;
- - return zfile.avail_in > 0 || !file->end();
- - }
- -
- - bool open(stream *f, const char *mode, bool needclose, int level)
- - {
- - if(file) return false;
- - for(; *mode; mode++)
- - {
- - if(*mode=='r') { reading = true; break; }
- - else if(*mode=='w') { writing = true; break; }
- - }
- - if(reading)
- - {
- - if(inflateInit2(&zfile, -MAX_WBITS) != Z_OK) reading = false;
- - }
- - else if(writing && deflateInit2(&zfile, level, Z_DEFLATED, -MAX_WBITS, min(MAX_MEM_LEVEL, 8), Z_DEFAULT_STRATEGY) != Z_OK) writing = false;
- - if(!reading && !writing) return false;
- -
- - autoclose = needclose;
- - file = f;
- - crc = crc32(0, NULL, 0);
- - buf = new uchar[BUFSIZE];
- -
- - if(reading)
- - {
- - if(!checkheader()) { stopreading(); return false; }
- - }
- - else if(writing) writeheader();
- - return true;
- - }
- -
- - uint getcrc() { return crc; }
- -
- - void finishreading()
- - {
- - if(!reading) return;
- -#ifndef STANDALONE
- - if(dbggz)
- - {
- - uint checkcrc = 0, checksize = 0;
- - loopi(4) checkcrc |= uint(readbyte()) << (i*8);
- - loopi(4) checksize |= uint(readbyte()) << (i*8);
- - if(checkcrc != crc)
- - conoutf("gzip crc check failed: read %X, calculated %X", checkcrc, crc);
- - if(checksize != zfile.total_out)
- - conoutf("gzip size check failed: read %d, calculated %d", checksize, zfile.total_out);
- - }
- -#endif
- - }
- -
- - void stopreading()
- - {
- - if(!reading) return;
- - inflateEnd(&zfile);
- - reading = false;
- - }
- -
- - void finishwriting()
- - {
- - if(!writing) return;
- - for(;;)
- - {
- - int err = zfile.avail_out > 0 ? deflate(&zfile, Z_FINISH) : Z_OK;
- - if(err != Z_OK && err != Z_STREAM_END) break;
- - flush();
- - if(err == Z_STREAM_END) break;
- - }
- - uchar trailer[8] =
- - {
- - crc&0xFF, (crc>>8)&0xFF, (crc>>16)&0xFF, (crc>>24)&0xFF,
- - zfile.total_in&0xFF, (zfile.total_in>>8)&0xFF, (zfile.total_in>>16)&0xFF, (zfile.total_in>>24)&0xFF
- - };
- - file->write(trailer, sizeof(trailer));
- - }
- -
- - void stopwriting()
- - {
- - if(!writing) return;
- - deflateEnd(&zfile);
- - writing = false;
- - }
- -
- - void close()
- - {
- - if(reading) finishreading();
- - stopreading();
- - if(writing) finishwriting();
- - stopwriting();
- - DELETEA(buf);
- - if(autoclose) DELETEP(file);
- - }
- -
- - bool end() { return !reading && !writing; }
- - long tell() { return reading ? zfile.total_out : (writing ? zfile.total_in : -1); }
- -
- - bool seek(long offset, int whence)
- - {
- - if(writing || !reading) return false;
- -
- - if(whence == SEEK_END)
- - {
- - uchar skip[512];
- - while(read(skip, sizeof(skip)) == sizeof(skip));
- - return !offset;
- - }
- - else if(whence == SEEK_CUR) offset += zfile.total_out;
- -
- - if(offset >= (int)zfile.total_out) offset -= zfile.total_out;
- - else if(offset < 0 || !file->seek(headersize, SEEK_SET)) return false;
- - else
- - {
- - if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf))
- - {
- - zfile.avail_in += zfile.total_in;
- - zfile.next_in -= zfile.total_in;
- - }
- - else
- - {
- - zfile.avail_in = 0;
- - zfile.next_in = NULL;
- - }
- - inflateReset(&zfile);
- - crc = crc32(0, NULL, 0);
- - }
- -
- - uchar skip[512];
- - while(offset > 0)
- - {
- - int skipped = min(offset, (long)sizeof(skip));
- - if(read(skip, skipped) != skipped) { stopreading(); return false; }
- - offset -= skipped;
- - }
- -
- - return true;
- - }
- -
- - int read(void *buf, int len)
- - {
- - if(!reading || !buf || !len) return 0;
- - zfile.next_out = (Bytef *)buf;
- - zfile.avail_out = len;
- - while(zfile.avail_out > 0)
- - {
- - if(!zfile.avail_in)
- - {
- - readbuf(BUFSIZE);
- - if(!zfile.avail_in) { stopreading(); break; }
- - }
- - int err = inflate(&zfile, Z_NO_FLUSH);
- - if(err == Z_STREAM_END) { crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out); finishreading(); stopreading(); return len - zfile.avail_out; }
- - else if(err != Z_OK) { stopreading(); break; }
- - }
- - crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out);
- - return len - zfile.avail_out;
- - }
- -
- - bool flush()
- - {
- - if(zfile.next_out && zfile.avail_out < BUFSIZE)
- - {
- - if(file->write(buf, BUFSIZE - zfile.avail_out) != int(BUFSIZE - zfile.avail_out))
- - return false;
- - }
- - zfile.next_out = buf;
- - zfile.avail_out = BUFSIZE;
- - return true;
- - }
- -
- - int write(const void *buf, int len)
- - {
- - if(!writing || !buf || !len) return 0;
- - zfile.next_in = (Bytef *)buf;
- - zfile.avail_in = len;
- - while(zfile.avail_in > 0)
- - {
- - if(!zfile.avail_out && !flush()) { stopwriting(); break; }
- - int err = deflate(&zfile, Z_NO_FLUSH);
- - if(err != Z_OK) { stopwriting(); break; }
- - }
- - crc = crc32(crc, (Bytef *)buf, len - zfile.avail_in);
- - return len - zfile.avail_in;
- - }
- -};
- -
- -
- -stream *openrawfile(const char *filename, const char *mode)
- -{
- - const char *found = findfile(filename, mode);
- -#ifndef STANDALONE
- - if(mode && (mode[0]=='w' || mode[0]=='a')) conoutf("writing to file: %s", found);
- -#endif
- - if(!found) return NULL;
- - filestream *file = new filestream;
- - if(!file->open(found, mode))
- - {
- -#ifndef STANDALONE
- -// conoutf("file failure! %s",filename);
- -#endif
- - delete file; return NULL;
- - }
- - return file;
- -}
- -
- -stream *openfile(const char *filename, const char *mode)
- -{
- -#ifndef STANDALONE
- - stream *s = openzipfile(filename, mode);
- - if(s) return s;
- -#endif
- - return openrawfile(filename, mode);
- -}
- -
- -int getfilesize(const char *filename)
- -{
- - stream *f = openfile(filename, "rb");
- - if(!f) return -1;
- - int len = f->size();
- - delete f;
- - return len;
- -}
- -
- -stream *opentempfile(const char *name, const char *mode)
- -{
- - const char *found = findfile(name, mode);
- - filestream *file = new filestream;
- - if(!file->opentemp(found ? found : name, mode)) { delete file; return NULL; }
- - return file;
- -}
- -
- -stream *opengzfile(const char *filename, const char *mode, stream *file, int level)
- -{
- - stream *source = file ? file : openfile(filename, mode);
- - if(!source) return NULL;
- - gzstream *gz = new gzstream;
- - if(!gz->open(source, mode, !file, level)) { if(!file) delete source; return NULL; }
- - return gz;
- -}
- -
- -char *loadfile(const char *fn, int *size, const char *mode)
- -{
- - stream *f = openfile(fn, mode ? mode : "rb");
- - if(!f) return NULL;
- - int len = f->size();
- - if(len<=0) { delete f; return NULL; }
- - char *buf = new char[len+1];
- - if(!buf) { delete f; return NULL; }
- - buf[len] = 0;
- - int rlen = f->read(buf, len);
- - delete f;
- - if(len!=rlen && (!mode || strchr(mode, 'b')))
- - {
- - delete[] buf;
- - return NULL;
- - }
- - if(size!=NULL) *size = len;
- - return buf;
- -}
- -
- +#include "cube.h"
- +
- +///////////////////////// file system ///////////////////////
- +
- +#ifndef WIN32
- +#include <unistd.h>
- +#include <sys/stat.h>
- +#include <sys/types.h>
- +#include <dirent.h>
- +#endif
- +
- +string homedir = "";
- +vector<char *> packagedirs;
- +
- +char *makerelpath(const char *dir, const char *file, const char *prefix, const char *cmd)
- +{
- + static string tmp;
- + if(prefix) copystring(tmp, prefix);
- + else tmp[0] = '\0';
- + if(file[0]=='<')
- + {
- + const char *end = strrchr(file, '>');
- + if(end)
- + {
- + size_t len = strlen(tmp);
- + copystring(&tmp[len], file, min(sizeof(tmp)-len, size_t(end+2-file)));
- + file = end+1;
- + }
- + }
- + if(cmd) concatstring(tmp, cmd);
- + defformatstring(pname)("%s/%s", dir, file);
- + concatstring(tmp, pname);
- + return tmp;
- +}
- +
- +
- +char *path(char *s)
- +{
- + for(char *curpart = s;;)
- + {
- + char *endpart = strchr(curpart, '&');
- + if(endpart) *endpart = '\0';
- + if(curpart[0]=='<')
- + {
- + char *file = strrchr(curpart, '>');
- + if(!file) return s;
- + curpart = file+1;
- + }
- + for(char *t = curpart; (t = strpbrk(t, "/\\")); *t++ = PATHDIV);
- + for(char *prevdir = NULL, *curdir = s;;)
- + {
- + prevdir = curdir[0]==PATHDIV ? curdir+1 : curdir;
- + curdir = strchr(prevdir, PATHDIV);
- + if(!curdir) break;
- + if(prevdir+1==curdir && prevdir[0]=='.')
- + {
- + memmove(prevdir, curdir+1, strlen(curdir+1)+1);
- + curdir = prevdir;
- + }
- + else if(curdir[1]=='.' && curdir[2]=='.' && curdir[3]==PATHDIV)
- + {
- + if(prevdir+2==curdir && prevdir[0]=='.' && prevdir[1]=='.') continue;
- + memmove(prevdir, curdir+4, strlen(curdir+4)+1);
- + curdir = prevdir;
- + }
- + }
- + if(endpart)
- + {
- + *endpart = '&';
- + curpart = endpart+1;
- + }
- + else break;
- + }
- + return s;
- +}
- +
- +char *path(const char *s, bool copy)
- +{
- + static string tmp;
- + copystring(tmp, s);
- + path(tmp);
- + return tmp;
- +}
- +
- +const char *parentdir(const char *directory)
- +{
- + const char *p = directory + strlen(directory);
- + while(p > directory && *p != '/' && *p != '\\') p--;
- + static string parent;
- + size_t len = p-directory+1;
- + copystring(parent, directory, len);
- + return parent;
- +}
- +
- +const char *behindpath(const char *s)
- +{
- + const char *t = s;
- + for( ; (s = strpbrk(s, "/\\")); t = ++s);
- + return t;
- +}
- +
- +bool fileexists(const char *path, const char *mode)
- +{
- + bool exists = true;
- + if(mode[0]=='w' || mode[0]=='a') path = parentdir(path);
- +#ifdef WIN32
- + if(GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES) exists = false;
- +#else
- + if(access(path, R_OK | (mode[0]=='w' || mode[0]=='a' ? W_OK : 0)) == -1) exists = false;
- +#endif
- + return exists;
- +}
- +
- +bool createdir(const char *path)
- +{
- + size_t len = strlen(path);
- + if(path[len-1]==PATHDIV)
- + {
- + static string strip;
- + path = copystring(strip, path, len);
- + }
- +#ifdef WIN32
- + return CreateDirectory(path, NULL)!=0;
- +#else
- + return mkdir(path, 0777)==0;
- +#endif
- +}
- +
- +size_t fixpackagedir(char *dir)
- +{
- + path(dir);
- + size_t len = strlen(dir);
- + if(len > 0 && dir[len-1] != PATHDIV)
- + {
- + dir[len] = PATHDIV;
- + dir[len+1] = '\0';
- + }
- + return len;
- +}
- +
- +#ifdef WIN32
- +char *getregszvalue(HKEY root, const char *keystr, const char *query)
- +{
- + HKEY key;
- + if(RegOpenKeyEx(HKEY_CURRENT_USER, keystr, 0, KEY_READ, &key)==ERROR_SUCCESS)
- + {
- + DWORD type = 0, len = 0;
- + if(RegQueryValueEx(key, query, 0, &type, 0, &len)==ERROR_SUCCESS && type==REG_SZ)
- + {
- + char *val = new char[len];
- + long result = RegQueryValueEx(key, query, 0, &type, (uchar *)val, &len);
- + if(result==ERROR_SUCCESS)
- + {
- + RegCloseKey(key);
- + val[len-1] = '\0';
- + return val;
- + }
- + delete[] val;
- + }
- + RegCloseKey(key);
- + }
- + return NULL;
- +}
- +#endif
- +
- +void sethomedir(const char *dir)
- +{
- + string tmpdir;
- + copystring(tmpdir, dir);
- +
- +#ifdef WIN32
- + const char substitute[] = "?MYDOCUMENTS?";
- + if(!strncmp(dir, substitute, strlen(substitute)))
- + {
- + const char *regpath = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
- + char *mydocuments = getregszvalue(HKEY_CURRENT_USER, regpath, "Personal");
- + if(mydocuments)
- + {
- + formatstring(tmpdir)("%s%s", mydocuments, dir+strlen(substitute));
- + delete[] mydocuments;
- + }
- + else
- + {
- + printf("failed to retrieve 'Personal' path from '%s'\n", regpath);
- + }
- + }
- +#endif
- +
- +#ifndef STANDALONE
- + clientlogf("Using home directory: %s", tmpdir);
- +#endif
- +
- + if(fixpackagedir(tmpdir) > 0)
- + {
- + copystring(homedir, tmpdir);
- + createdir(homedir);
- + }
- +}
- +
- +void addpackagedir(const char *dir)
- +{
- +#ifndef STANDALONE
- + clientlogf("Adding package directory: %s", dir);
- +#endif
- +
- + string pdir;
- + copystring(pdir, dir);
- + if(fixpackagedir(pdir) > 0) packagedirs.add(newstring(pdir));
- +}
- +
- +const char *findfile(const char *filename, const char *mode)
- +{
- + static string s;
- + if(homedir[0])
- + {
- + formatstring(s)("%s%s", homedir, filename);
- + if(fileexists(s, mode)) return s;
- + if(mode[0]=='w' || mode[0]=='a')
- + {
- + string dirs;
- + copystring(dirs, s);
- + char *dir = strchr(dirs[0]==PATHDIV ? dirs+1 : dirs, PATHDIV);
- + while(dir)
- + {
- + *dir = '\0';
- + if(!fileexists(dirs, "r") && !createdir(dirs)) return s;
- + *dir = PATHDIV;
- + dir = strchr(dir+1, PATHDIV);
- + }
- + return s;
- + }
- + }
- + if(mode[0]=='w' || mode[0]=='a') return filename;
- + loopv(packagedirs)
- + {
- + formatstring(s)("%s%s", packagedirs[i], filename);
- + if(fileexists(s, mode)) return s;
- + }
- + return filename;
- +}
- +
- +bool listdir(const char *dir, const char *ext, vector<char *> &files)
- +{
- + int extsize = ext ? (int)strlen(ext)+1 : 0;
- + #if defined(WIN32)
- + defformatstring(pathname)("%s\\*.%s", dir, ext ? ext : "*");
- + WIN32_FIND_DATA FindFileData;
- + HANDLE Find = FindFirstFile(path(pathname), &FindFileData);
- + if(Find != INVALID_HANDLE_VALUE)
- + {
- + do {
- + files.add(newstring(FindFileData.cFileName, (int)strlen(FindFileData.cFileName) - extsize));
- + } while(FindNextFile(Find, &FindFileData));
- + FindClose(Find);
- + return true;
- + }
- + #else
- + string pathname;
- + copystring(pathname, dir);
- + DIR *d = opendir(path(pathname));
- + if(d)
- + {
- + struct dirent *de;
- + while((de = readdir(d)) != NULL)
- + {
- + if(!ext) files.add(newstring(de->d_name));
- + else
- + {
- + int namelength = (int)strlen(de->d_name) - extsize;
- + if(namelength > 0 && de->d_name[namelength] == '.' && strncmp(de->d_name+namelength+1, ext, extsize-1)==0)
- + files.add(newstring(de->d_name, namelength));
- + }
- + }
- + closedir(d);
- + return true;
- + }
- + #endif
- + else return false;
- +}
- +
- +int listfiles(const char *dir, const char *ext, vector<char *> &files)
- +{
- + int dirs = 0;
- + if(listdir(dir, ext, files)) dirs++;
- + string s;
- + if(homedir[0])
- + {
- + formatstring(s)("%s%s", homedir, dir);
- + if(listdir(s, ext, files)) dirs++;
- + }
- + loopv(packagedirs)
- + {
- + formatstring(s)("%s%s", packagedirs[i], dir);
- + if(listdir(s, ext, files)) dirs++;
- + }
- +#ifndef STANDALONE
- + dirs += listzipfiles(dir, ext, files);
- +#endif
- + return dirs;
- +}
- +
- +bool delfile(const char *path)
- +{
- + return !remove(path);
- +}
- +
- +bool copyfile(const char *source, const char *destination)
- +{
- + FILE *from = fopen(source, "rb");
- + FILE *dest = fopen(destination, "wb");
- +
- + if(!from) { return false; }
- + if(!dest) { return false; }
- + size_t len;
- + uchar buf[1024];
- + while(len = fread(&buf, sizeof(uchar), 1024, from))
- + {
- + fwrite(&buf, sizeof(uchar), len, dest);
- + }
- + fclose(from);
- + fclose(dest);
- + return true;
- +}
- +
- +bool preparedir(const char *destination)
- +{
- + string dir;
- + copystring(dir, parentdir(destination));
- + vector<char *> dirs;
- + while(!fileexists(dir, "r"))
- + {
- + dirs.add(newstring(dir));
- + copystring(dir, parentdir(dir));
- + }
- + for(int i = dirs.length() - 1; i >= 0; --i) if(!createdir(dirs[i])) return false;
- + return true;
- +}
- +
- +#ifndef STANDALONE
- +static int rwopsseek(SDL_RWops *rw, int offset, int whence)
- +{
- + stream *f = (stream *)rw->hidden.unknown.data1;
- + if((!offset && whence==SEEK_CUR) || f->seek(offset, whence)) return f->tell();
- + return -1;
- +}
- +
- +static int rwopsread(SDL_RWops *rw, void *buf, int size, int nmemb)
- +{
- + stream *f = (stream *)rw->hidden.unknown.data1;
- + return f->read(buf, size*nmemb)/size;
- +}
- +
- +static int rwopswrite(SDL_RWops *rw, const void *buf, int size, int nmemb)
- +{
- + stream *f = (stream *)rw->hidden.unknown.data1;
- + return f->write(buf, size*nmemb)/size;
- +}
- +
- +static int rwopsclose(SDL_RWops *rw)
- +{
- + return 0;
- +}
- +
- +SDL_RWops *stream::rwops()
- +{
- + SDL_RWops *rw = SDL_AllocRW();
- + if(!rw) return NULL;
- + rw->hidden.unknown.data1 = this;
- + rw->seek = rwopsseek;
- + rw->read = rwopsread;
- + rw->write = rwopswrite;
- + rw->close = rwopsclose;
- + return rw;
- +}
- +#endif
- +
- +long stream::size()
- +{
- + long pos = tell(), endpos;
- + if(pos < 0 || !seek(0, SEEK_END)) return -1;
- + endpos = tell();
- + return pos == endpos || seek(pos, SEEK_SET) ? endpos : -1;
- +}
- +
- +bool stream::getline(char *str, int len)
- +{
- + loopi(len-1)
- + {
- + if(read(&str[i], 1) != 1) { str[i] = '\0'; return i > 0; }
- + else if(str[i] == '\n') { str[i+1] = '\0'; return true; }
- + }
- + if(len > 0) str[len-1] = '\0';
- + return true;
- +}
- +
- +#ifdef __linux__
- +#include <sys/statvfs.h>
- +#define MINFSSIZE 50000000ull // 50MB
- +#endif
- +
- +struct filestream : stream
- +{
- + FILE *file;
- +
- + filestream() : file(NULL) {}
- + ~filestream() { close(); }
- +
- + bool open(const char *name, const char *mode)
- + {
- + if(file) return false;
- + file = fopen(name, mode);
- +#ifdef __linux__
- + struct statvfs buf;
- + if(file && strchr(mode,'w'))
- + {
- + int fail = fstatvfs(fileno(file), &buf);
- + if (fail || (unsigned long long)buf.f_frsize * (unsigned long long)buf.f_bavail < MINFSSIZE)
- + {
- + close();
- + return false;
- + }
- + }
- +#endif
- + return file!=NULL;
- + }
- +
- + bool opentemp(const char *name, const char *mode)
- + {
- + if(file) return false;
- +#ifdef WIN32
- + file = fopen(name, mode);
- +#else
- + file = tmpfile();
- +#endif
- + return file!=NULL;
- + }
- +
- + void close()
- + {
- + if(file) { fclose(file); file = NULL; }
- + }
- +
- + bool end() { return feof(file)!=0; }
- + long tell() { return ftell(file); }
- + bool seek(long offset, int whence) { return fseek(file, offset, whence) >= 0; }
- + int read(void *buf, int len) { return (int)fread(buf, 1, len, file); }
- + int write(const void *buf, int len) { return (int)fwrite(buf, 1, len, file); }
- + int getchar() { return fgetc(file); }
- + bool putchar(int c) { return fputc(c, file)!=EOF; }
- + bool getline(char *str, int len) { return fgets(str, len, file)!=NULL; }
- + bool putstring(const char *str) { return fputs(str, file)!=EOF; }
- +
- + int printf(const char *fmt, ...)
- + {
- + va_list v;
- + va_start(v, fmt);
- + int result = vfprintf(file, fmt, v);
- + va_end(v);
- + return result;
- + }
- +};
- +
- +#ifndef STANDALONE
- +VAR(dbggz, 0, 0, 1);
- +#endif
- +
- +struct gzstream : stream
- +{
- + enum
- + {
- + MAGIC1 = 0x1F,
- + MAGIC2 = 0x8B,
- + BUFSIZE = 16384,
- + OS_UNIX = 0x03
- + };
- +
- + enum
- + {
- + F_ASCII = 0x01,
- + F_CRC = 0x02,
- + F_EXTRA = 0x04,
- + F_NAME = 0x08,
- + F_COMMENT = 0x10,
- + F_RESERVED = 0xE0
- + };
- +
- + stream *file;
- + z_stream zfile;
- + uchar *buf;
- + bool reading, writing, autoclose;
- + uint crc;
- + int headersize;
- +
- + gzstream() : file(NULL), buf(NULL), reading(false), writing(false), autoclose(false), crc(0), headersize(0)
- + {
- + zfile.zalloc = NULL;
- + zfile.zfree = NULL;
- + zfile.opaque = NULL;
- + zfile.next_in = zfile.next_out = NULL;
- + zfile.avail_in = zfile.avail_out = 0;
- + }
- +
- + ~gzstream()
- + {
- + close();
- + }
- +
- + void writeheader()
- + {
- + uchar header[] = { MAGIC1, MAGIC2, Z_DEFLATED, 0, 0, 0, 0, 0, 0, OS_UNIX };
- + file->write(header, sizeof(header));
- + }
- +
- + void readbuf(int size = BUFSIZE)
- + {
- + if(!zfile.avail_in) zfile.next_in = (Bytef *)buf;
- + size = min(size, int(&buf[BUFSIZE] - &zfile.next_in[zfile.avail_in]));
- + int n = file->read(zfile.next_in + zfile.avail_in, size);
- + if(n > 0) zfile.avail_in += n;
- + }
- +
- + int readbyte(int size = BUFSIZE)
- + {
- + if(!zfile.avail_in) readbuf(size);
- + if(!zfile.avail_in) return 0;
- + zfile.avail_in--;
- + return *(uchar *)zfile.next_in++;
- + }
- +
- + void skipbytes(int n)
- + {
- + while(n > 0 && zfile.avail_in > 0)
- + {
- + int skipped = min(n, (int)zfile.avail_in);
- + zfile.avail_in -= skipped;
- + zfile.next_in += skipped;
- + n -= skipped;
- + }
- + if(n <= 0) return;
- + file->seek(n, SEEK_CUR);
- + }
- +
- + bool checkheader()
- + {
- + readbuf(10);
- + if(readbyte() != MAGIC1 || readbyte() != MAGIC2 || readbyte() != Z_DEFLATED) return false;
- + int flags = readbyte();
- + if(flags & F_RESERVED) return false;
- + skipbytes(6);
- + if(flags & F_EXTRA)
- + {
- + int len = readbyte(512);
- + len |= readbyte(512)<<8;
- + skipbytes(len);
- + }
- + if(flags & F_NAME) while(readbyte(512));
- + if(flags & F_COMMENT) while(readbyte(512));
- + if(flags & F_CRC) skipbytes(2);
- + headersize = file->tell() - zfile.avail_in;
- + return zfile.avail_in > 0 || !file->end();
- + }
- +
- + bool open(stream *f, const char *mode, bool needclose, int level)
- + {
- + if(file) return false;
- + for(; *mode; mode++)
- + {
- + if(*mode=='r') { reading = true; break; }
- + else if(*mode=='w') { writing = true; break; }
- + }
- + if(reading)
- + {
- + if(inflateInit2(&zfile, -MAX_WBITS) != Z_OK) reading = false;
- + }
- + else if(writing && deflateInit2(&zfile, level, Z_DEFLATED, -MAX_WBITS, min(MAX_MEM_LEVEL, 8), Z_DEFAULT_STRATEGY) != Z_OK) writing = false;
- + if(!reading && !writing) return false;
- +
- + autoclose = needclose;
- + file = f;
- + crc = crc32(0, NULL, 0);
- + buf = new uchar[BUFSIZE];
- +
- + if(reading)
- + {
- + if(!checkheader()) { stopreading(); return false; }
- + }
- + else if(writing) writeheader();
- + return true;
- + }
- +
- + uint getcrc() { return crc; }
- +
- + void finishreading()
- + {
- + if(!reading) return;
- +#ifndef STANDALONE
- + if(dbggz)
- + {
- + uint checkcrc = 0, checksize = 0;
- + loopi(4) checkcrc |= uint(readbyte()) << (i*8);
- + loopi(4) checksize |= uint(readbyte()) << (i*8);
- + if(checkcrc != crc)
- + conoutf("gzip crc check failed: read %X, calculated %X", checkcrc, crc);
- + if(checksize != zfile.total_out)
- + conoutf("gzip size check failed: read %d, calculated %d", checksize, zfile.total_out);
- + }
- +#endif
- + }
- +
- + void stopreading()
- + {
- + if(!reading) return;
- + inflateEnd(&zfile);
- + reading = false;
- + }
- +
- + void finishwriting()
- + {
- + if(!writing) return;
- + for(;;)
- + {
- + int err = zfile.avail_out > 0 ? deflate(&zfile, Z_FINISH) : Z_OK;
- + if(err != Z_OK && err != Z_STREAM_END) break;
- + flush();
- + if(err == Z_STREAM_END) break;
- + }
- + uchar trailer[8] =
- + {
- + crc&0xFF, (crc>>8)&0xFF, (crc>>16)&0xFF, (crc>>24)&0xFF,
- + zfile.total_in&0xFF, (zfile.total_in>>8)&0xFF, (zfile.total_in>>16)&0xFF, (zfile.total_in>>24)&0xFF
- + };
- + file->write(trailer, sizeof(trailer));
- + }
- +
- + void stopwriting()
- + {
- + if(!writing) return;
- + deflateEnd(&zfile);
- + writing = false;
- + }
- +
- + void close()
- + {
- + if(reading) finishreading();
- + stopreading();
- + if(writing) finishwriting();
- + stopwriting();
- + DELETEA(buf);
- + if(autoclose) DELETEP(file);
- + }
- +
- + bool end() { return !reading && !writing; }
- + long tell() { return reading ? zfile.total_out : (writing ? zfile.total_in : -1); }
- +
- + bool seek(long offset, int whence)
- + {
- + if(writing || !reading) return false;
- +
- + if(whence == SEEK_END)
- + {
- + uchar skip[512];
- + while(read(skip, sizeof(skip)) == sizeof(skip));
- + return !offset;
- + }
- + else if(whence == SEEK_CUR) offset += zfile.total_out;
- +
- + if(offset >= (int)zfile.total_out) offset -= zfile.total_out;
- + else if(offset < 0 || !file->seek(headersize, SEEK_SET)) return false;
- + else
- + {
- + if(zfile.next_in && zfile.total_in <= uint(zfile.next_in - buf))
- + {
- + zfile.avail_in += zfile.total_in;
- + zfile.next_in -= zfile.total_in;
- + }
- + else
- + {
- + zfile.avail_in = 0;
- + zfile.next_in = NULL;
- + }
- + inflateReset(&zfile);
- + crc = crc32(0, NULL, 0);
- + }
- +
- + uchar skip[512];
- + while(offset > 0)
- + {
- + int skipped = min(offset, (long)sizeof(skip));
- + if(read(skip, skipped) != skipped) { stopreading(); return false; }
- + offset -= skipped;
- + }
- +
- + return true;
- + }
- +
- + int read(void *buf, int len)
- + {
- + if(!reading || !buf || !len) return 0;
- + zfile.next_out = (Bytef *)buf;
- + zfile.avail_out = len;
- + while(zfile.avail_out > 0)
- + {
- + if(!zfile.avail_in)
- + {
- + readbuf(BUFSIZE);
- + if(!zfile.avail_in) { stopreading(); break; }
- + }
- + int err = inflate(&zfile, Z_NO_FLUSH);
- + if(err == Z_STREAM_END) { crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out); finishreading(); stopreading(); return len - zfile.avail_out; }
- + else if(err != Z_OK) { stopreading(); break; }
- + }
- + crc = crc32(crc, (Bytef *)buf, len - zfile.avail_out);
- + return len - zfile.avail_out;
- + }
- +
- + bool flush()
- + {
- + if(zfile.next_out && zfile.avail_out < BUFSIZE)
- + {
- + if(file->write(buf, BUFSIZE - zfile.avail_out) != int(BUFSIZE - zfile.avail_out))
- + return false;
- + }
- + zfile.next_out = buf;
- + zfile.avail_out = BUFSIZE;
- + return true;
- + }
- +
- + int write(const void *buf, int len)
- + {
- + if(!writing || !buf || !len) return 0;
- + zfile.next_in = (Bytef *)buf;
- + zfile.avail_in = len;
- + while(zfile.avail_in > 0)
- + {
- + if(!zfile.avail_out && !flush()) { stopwriting(); break; }
- + int err = deflate(&zfile, Z_NO_FLUSH);
- + if(err != Z_OK) { stopwriting(); break; }
- + }
- + crc = crc32(crc, (Bytef *)buf, len - zfile.avail_in);
- + return len - zfile.avail_in;
- + }
- +};
- +
- +
- +stream *openrawfile(const char *filename, const char *mode)
- +{
- + const char *found = findfile(filename, mode);
- +#ifndef STANDALONE
- + if(mode && (mode[0]=='w' || mode[0]=='a')) conoutf("writing to file: %s", found);
- +#endif
- + if(!found) return NULL;
- + filestream *file = new filestream;
- + if(!file->open(found, mode))
- + {
- +#ifndef STANDALONE
- +// conoutf("file failure! %s",filename);
- +#endif
- + delete file; return NULL;
- + }
- + return file;
- +}
- +
- +stream *openfile(const char *filename, const char *mode)
- +{
- +#ifndef STANDALONE
- + stream *s = openzipfile(filename, mode);
- + if(s) return s;
- +#endif
- + return openrawfile(filename, mode);
- +}
- +
- +int getfilesize(const char *filename)
- +{
- + stream *f = openfile(filename, "rb");
- + if(!f) return -1;
- + int len = f->size();
- + delete f;
- + return len;
- +}
- +
- +stream *opentempfile(const char *name, const char *mode)
- +{
- + const char *found = findfile(name, mode);
- + filestream *file = new filestream;
- + if(!file->opentemp(found ? found : name, mode)) { delete file; return NULL; }
- + return file;
- +}
- +
- +stream *opengzfile(const char *filename, const char *mode, stream *file, int level)
- +{
- + stream *source = file ? file : openfile(filename, mode);
- + if(!source) return NULL;
- + gzstream *gz = new gzstream;
- + if(!gz->open(source, mode, !file, level)) { if(!file) delete source; return NULL; }
- + return gz;
- +}
- +
- +char *loadfile(const char *fn, int *size, const char *mode)
- +{
- + stream *f = openfile(fn, mode ? mode : "rb");
- + if(!f) return NULL;
- + int len = f->size();
- + if(len<=0) { delete f; return NULL; }
- + char *buf = new char[len+1];
- + if(!buf) { delete f; return NULL; }
- + buf[len] = 0;
- + int rlen = f->read(buf, len);
- + delete f;
- + if(len!=rlen && (!mode || strchr(mode, 'b')))
- + {
- + delete[] buf;
- + return NULL;
- + }
- + if(size!=NULL) *size = len;
- + return buf;
- +}
- +
- Index: tools.h
- ===================================================================
- --- tools.h (revision 6612)
- +++ tools.h (working copy)
- @@ -901,6 +901,8 @@
- extern int listfiles(const char *dir, const char *ext, vector<char *> &files);
- extern int listzipfiles(const char *dir, const char *ext, vector<char *> &files);
- extern bool delfile(const char *path);
- +extern bool copyfile(const char *source, const char *destination);
- +extern bool preparedir(const char *destination);
- 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);
- Index: worldio.cpp
- ===================================================================
- --- worldio.cpp (revision 6612)
- +++ worldio.cpp (working copy)
- @@ -840,6 +840,12 @@
- delete f;
- }
- +// get all dependencies for the current map
- +void curmapdeps()
- +{
- +
- +}
- +
- COMMAND(listmapdependencies, ARG_1STR);
- void listmapdependencies_all(int sure)
Add Comment
Please, Sign In to add comment