From 12315f4d0e0ae993805f141f64cb8c73c5297311 Mon Sep 17 00:00:00 2001 From: Hans Lambermont Date: Sat, 12 Oct 2002 11:37:38 +0000 Subject: Initial revision --- .../blender/readblenfile/intern/BLO_readblenfile.c | 647 +++++++++++++++++++++ source/blender/readblenfile/intern/Makefile | 54 ++ 2 files changed, 701 insertions(+) create mode 100644 source/blender/readblenfile/intern/BLO_readblenfile.c create mode 100644 source/blender/readblenfile/intern/Makefile (limited to 'source/blender/readblenfile/intern') diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c new file mode 100644 index 00000000000..9b9bf7d27a3 --- /dev/null +++ b/source/blender/readblenfile/intern/BLO_readblenfile.c @@ -0,0 +1,647 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +#include +#include +#include +#include + +#ifdef WIN32 +#include // read, open +#else // ! WIN32 +#include // read +#endif + +#include "BLO_readStreamGlue.h" + +#include "BLO_readfile.h" +#include "BLO_readblenfile.h" + +#include "BKE_blender.h" + +#define CACHESIZE 100000 + +char *headerMagic = "BLENDFI"; + +void BLO_setversionnumber(char array[4], int version) +{ + memset(array, 0, sizeof(array)); + + array[1] = version / 100; + array[2] = version % 100; +} + +void BLO_setcurrentversionnumber(char array[4]) +{ + BLO_setversionnumber(array, BLENDER_VERSION); +} + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +struct BLO_readblenfileStruct { + struct readStreamGlueStruct *streamGlue; + int fileDes; + unsigned int cacheSize; + unsigned int inCache; + unsigned int leftToRead; + unsigned int Seek; + + int (*read)(struct BLO_readblenfileStruct *readblenfileStruct, void *buffer, int size); + + char *readCache; + char *fromBuffer; + int fromBufferSize; + char crInBuffer; + char removeCR; +}; + +// declare static functions + +static int readfromfilehandle( + struct BLO_readblenfileStruct *readblenfileStruct, + void *buffer, + int size); + +static int readfrommemory( + struct BLO_readblenfileStruct *readblenfileStruct, + void *buffer, + int size); + +static int fillcache( + struct BLO_readblenfileStruct *readblenfileStruct); + +static unsigned int readfromcache( + struct BLO_readblenfileStruct *readblenfileStruct, + void * buffer, + unsigned int size); + +static BlendFileData *readblenfilegeneric( + struct BLO_readblenfileStruct *readblenfileStruct, + BlendReadError *error_r); + +// implementation of static functions + +static int readfromfilehandle( + struct BLO_readblenfileStruct *readblenfileStruct, + void *buffer, + int size) +{ + int readsize = -1; + + if (readblenfileStruct->fileDes != -1) { + readsize = read(readblenfileStruct->fileDes, buffer, size); + } + + return(readsize); +} + +static int readfrommemory( + struct BLO_readblenfileStruct *readblenfileStruct, + void *buffer, + int size) +{ + int readsize = -1; + + if (readblenfileStruct->fromBuffer) { + if (size > readblenfileStruct->fromBufferSize) { + size = readblenfileStruct->fromBufferSize; + } + + memcpy(buffer, readblenfileStruct->fromBuffer, size); + readblenfileStruct->fromBufferSize -= size; + readblenfileStruct->fromBuffer += size; + + readsize = size; + } + + return(readsize); +} + +static int fillcache( + struct BLO_readblenfileStruct *readblenfileStruct) +{ + int readsize; + int toread; + + // how many bytes can we read ? + + toread = readblenfileStruct->leftToRead; + + if (toread > readblenfileStruct->cacheSize) { + toread = readblenfileStruct->cacheSize; + } + + readsize = readblenfileStruct->read(readblenfileStruct, readblenfileStruct->readCache, toread); + if (readsize > 0) { + if (readblenfileStruct->removeCR) { + // do some stuff here + } + readblenfileStruct->inCache = readsize; + readblenfileStruct->leftToRead -= readsize; + } + + return (readsize); +} + + +static unsigned int readfromcache( + struct BLO_readblenfileStruct *readblenfileStruct, + void * buffer, + unsigned int size) +{ + unsigned int readsize = 0; + + if (readblenfileStruct->inCache - readblenfileStruct->Seek > size) { + memcpy(buffer, readblenfileStruct->readCache + readblenfileStruct->Seek, size); + readblenfileStruct->Seek += size; + readsize = size; + } else { + // handle me + } + + return(readsize); +} + +static BlendReadError brs_to_bre(int err) +{ + int errFunction = BRS_GETFUNCTION(err); + int errGeneric = BRS_GETGENERR(err); + int errSpecific = BRS_GETSPECERR(err); + + if (errGeneric) { + switch (errGeneric) { + case BRS_MALLOC: + return BRE_OUT_OF_MEMORY; + case BRS_NULL: + return BRE_INTERNAL_ERROR; + case BRS_MAGIC: + return BRE_NOT_A_BLEND; + case BRS_CRCHEADER: + case BRS_CRCDATA: + return BRE_CORRUPT; + case BRS_DATALEN: + return BRE_INCOMPLETE; + case BRS_STUB: + return BRE_NOT_A_BLEND; + } + } else if (errSpecific) { + switch (errFunction) { + case BRS_READSTREAMGLUE: + switch (errSpecific) { + case BRS_UNKNOWN: + return BRE_INTERNAL_ERROR; + } + break; + case BRS_READSTREAMFILE: + switch (errSpecific) { + case BRS_NOTABLEND: + return BRE_NOT_A_BLEND; + case BRS_READERROR: + return BRE_UNABLE_TO_READ; + } + break; + case BRS_INFLATE: + switch (errSpecific) { + case BRS_INFLATEERROR: + return BRE_CORRUPT; + } + break; + case BRS_DECRYPT: + switch (errSpecific) { + case BRS_RSANEWERROR: + return BRE_INTERNAL_ERROR; + case BRS_DECRYPTERROR: + return BRE_INTERNAL_ERROR; + case BRS_NOTOURPUBKEY: + return BRE_NOT_ALLOWED; + } + break; + case BRS_VERIFY: + switch (errSpecific) { + case BRS_RSANEWERROR: + return BRE_INTERNAL_ERROR; + case BRS_SIGFAILED: + return BRE_INTERNAL_ERROR; + } + break; + } + } + + return BRE_INVALID; +} + +static BlendFileData *readblenfilegeneric( + struct BLO_readblenfileStruct *readblenfileStruct, + BlendReadError *error_r) +{ + BlendFileData *bfd= NULL; + unsigned char reserved[BLO_RESERVEDSIZE]; + uint8_t minversion[4]; + uint8_t myversion[4]; + uint8_t version[4]; + uint8_t flags[4]; + void *parms[2]; + int filesize; + + parms[0]= &bfd; + parms[1]= error_r; + + BLO_setcurrentversionnumber(myversion); + + readblenfileStruct->cacheSize = CACHESIZE; + readblenfileStruct->readCache = malloc(readblenfileStruct->cacheSize); + + if (fillcache(readblenfileStruct) <= 0) { + *error_r = BRE_UNABLE_TO_READ; + } else if (readfromcache(readblenfileStruct, minversion, sizeof(minversion)) != sizeof(minversion)) { + *error_r = BRE_UNABLE_TO_READ; + } else if (memcmp(minversion, myversion, sizeof(minversion)) > 0) { + *error_r = BRE_TOO_NEW; + } else if (readfromcache(readblenfileStruct, version, sizeof(version)) != sizeof(version)) { + *error_r = BRE_UNABLE_TO_READ; + } else if (readfromcache(readblenfileStruct, flags, sizeof(flags)) != sizeof(flags)) { + *error_r = BRE_UNABLE_TO_READ; + } else if (readfromcache(readblenfileStruct, &filesize, sizeof(filesize)) != sizeof(filesize)) { + *error_r = BRE_UNABLE_TO_READ; + } else if (readfromcache(readblenfileStruct, reserved, sizeof(reserved)) != sizeof(reserved)) { + *error_r = BRE_UNABLE_TO_READ; + } else { + filesize = ntohl(filesize); + + // substract number of bytes we've + // been handling outside readfromcache() + filesize -= strlen(headerMagic); + filesize--; + + if (filesize < readblenfileStruct->inCache) { + // we've allready read more than we're supposed to + readblenfileStruct->inCache = filesize; + readblenfileStruct->leftToRead = 0; + } else { + // + readblenfileStruct->leftToRead = filesize - readblenfileStruct->inCache; + } + + do { + int err; + + *error_r = BRE_NONE; + err = readStreamGlue( + parms, + &(readblenfileStruct->streamGlue), + readblenfileStruct->readCache + readblenfileStruct->Seek, + readblenfileStruct->inCache - readblenfileStruct->Seek); + + readblenfileStruct->inCache = 0; + readblenfileStruct->Seek = 0; + + if (err) { + bfd = NULL; + + /* If *error_r != BRE_NONE then it is + * blo_readstreamfile_end signaling an error + * in the loading code. Otherwise it is some + * other part of the streamglue system signalling + * and error so we convert the BRS error into + * a BRE error. + * + * Does this have to be so convoluted? No. + */ + if (*error_r == BRE_NONE) { + *error_r = brs_to_bre(err); + } + + break; + } + } while (fillcache(readblenfileStruct) > 0); + } + + free(readblenfileStruct->readCache); + readblenfileStruct->readCache = 0; + + return bfd; +} + +// implementation of exported functions + +BlendFileData * +BLO_readblenfilememory( + char *fromBuffer, + int fromBufferSize, + BlendReadError *error_r) +{ + static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_readblenfilememory\n"; + int magiclen = strlen(headerMagic); + BlendFileData *bfd = NULL; + + if (!fromBuffer) { + *error_r = BRE_UNABLE_TO_OPEN; + } else if (fromBufferSize < magiclen) { + *error_r = BRE_UNABLE_TO_READ; + } else if (strncmp(fromBuffer, headerMagic, magiclen) != 0) { + *error_r = BRE_NOT_A_BLEND; + } else if (fromBufferSize < magiclen+1) { + *error_r = BRE_UNABLE_TO_READ; + } else if (fromBuffer[magiclen] != '\r' && fromBuffer[magiclen] != '\n') { + *error_r = BRE_NOT_A_BLEND; + } else { + int crnl; + + fromBuffer+= magiclen; + fromBufferSize-= magiclen; + crnl = (fromBuffer[0] == '\r'); + fromBuffer++; + fromBufferSize--; + + if (crnl && fromBufferSize<1) { + *error_r = BRE_UNABLE_TO_READ; + } else { + struct BLO_readblenfileStruct *readblenfileStruct = NULL; + + /* skip carriage return if necessary */ + if (crnl) { + fromBuffer++; + fromBufferSize--; + } + + // Allocate all the stuff we need + readblenfileStruct = calloc(sizeof(struct BLO_readblenfileStruct), 1); + readblenfileStruct->fileDes = -1; + readblenfileStruct->fromBuffer = fromBuffer; + readblenfileStruct->fromBufferSize = fromBufferSize; + readblenfileStruct->read = readfrommemory; + + readblenfileStruct->removeCR = crnl; + // fake filesize for now until we've + // actually read in the filesize from the header + // make sure we don't read more bytes than there + // are left to handle accoding to fromBufferSize + readblenfileStruct->leftToRead = readblenfileStruct->fromBufferSize; + + bfd = readblenfilegeneric(readblenfileStruct, error_r); + + free(readblenfileStruct); + readblenfileStruct = 0; + } + } + + return bfd; +} + + +BlendFileData * +BLO_readblenfilehandle( + int fd, + BlendReadError *error_r) +{ + static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_readblenfilehandle\n"; + int magiclen = strlen(headerMagic); + BlendFileData *bfd = NULL; + char tempbuffer[256]; + + if (fd==-1) { + *error_r = BRE_UNABLE_TO_OPEN; + } else if (read(fd, tempbuffer, magiclen) != magiclen) { + *error_r = BRE_UNABLE_TO_READ; + } else if (strncmp(tempbuffer, headerMagic, magiclen) != 0 ) { + *error_r = BRE_NOT_A_BLEND; + } else if (read(fd, tempbuffer, 1) != 1) { + *error_r = BRE_UNABLE_TO_READ; + } else if (tempbuffer[0] != '\r' && tempbuffer[0] != '\n') { + *error_r = BRE_NOT_A_BLEND; + } else { + int crnl = (tempbuffer[0] == '\r'); + + if (crnl && read(fd, tempbuffer, 1)!=1) { + *error_r = BRE_UNABLE_TO_READ; + } else { + struct BLO_readblenfileStruct *readblenfileStruct; + + // Allocate all the stuff we need + readblenfileStruct = calloc(sizeof(struct BLO_readblenfileStruct), 1); + readblenfileStruct->fileDes = fd; + readblenfileStruct->read = readfromfilehandle; + + readblenfileStruct->removeCR = crnl; + // fake filesize for now until we've + // actually read in the filesize from the header + readblenfileStruct->leftToRead = CACHESIZE; + + bfd = readblenfilegeneric(readblenfileStruct, error_r); + + free(readblenfileStruct); + readblenfileStruct = 0; + } + } + + return bfd; +} + +BlendFileData * +BLO_readblenfilename( + char *fileName, + BlendReadError *error_r) +{ + static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_readblenfilename\n"; + BlendFileData *bfd = NULL; + int fd; + + fd = open(fileName, O_RDONLY | O_BINARY); + if (fd==-1) { + *error_r= BRE_UNABLE_TO_OPEN; + } else { + bfd = BLO_readblenfilehandle(fd, error_r); + } + + if (fd!=-1) + close(fd); + + return bfd; +} + + /* Runtime reading */ + +static int handle_read_msb_int(int handle) { + unsigned char buf[4]; + + if (read(handle, buf, 4)!=4) + return -1; + else + return (buf[0]<<24) + (buf[1]<<16) + (buf[2]<<8) + (buf[3]<<0); +} + +int blo_is_a_runtime(char *path) { + int res= 0, fd= open(path, O_BINARY|O_RDONLY, 0); + int datastart; + char buf[8]; + + if (fd==-1) + goto cleanup; + + lseek(fd, -12, SEEK_END); + + datastart= handle_read_msb_int(fd); + if (datastart==-1) + goto cleanup; + else if (read(fd, buf, 8)!=8) + goto cleanup; + else if (memcmp(buf, "BRUNTIME", 8)!=0) + goto cleanup; + else + res= 1; + +cleanup: + if (fd!=-1) + close(fd); + + return res; +} + +BlendFileData * +blo_read_runtime( + char *path, + BlendReadError *error_r) +{ + static char *functionality_check= "\0FUNCTIONALITY_CHECK += BLO_read_runtime\n"; + BlendFileData *bfd= NULL; + int fd, datastart; + char buf[8]; + + fd= open(path, O_BINARY|O_RDONLY, 0); + if (fd==-1) { + *error_r= BRE_UNABLE_TO_OPEN; + goto cleanup; + } + + lseek(fd, -12, SEEK_END); + + datastart= handle_read_msb_int(fd); + if (datastart==-1) { + *error_r= BRE_UNABLE_TO_READ; + goto cleanup; + } else if (read(fd, buf, 8)!=8) { + *error_r= BRE_UNABLE_TO_READ; + goto cleanup; + } else if (memcmp(buf, "BRUNTIME", 8)!=0) { + *error_r= BRE_NOT_A_BLEND; + goto cleanup; + } else { + lseek(fd, datastart, SEEK_SET); + bfd= BLO_readblenfilehandle(fd, error_r); + } + +cleanup: + if (fd!=-1) + close(fd); + + return bfd; +} + +#if 0 +static char *brs_error_to_string(int err) { + int errFunction = BRS_GETFUNCTION(err); + int errGeneric = BRS_GETGENERR(err); + int errSpecific = BRS_GETSPECERR(err); + char *errFunctionStrings[] = { + "", + "The read stream", + "The read stream loopback", + "The key store", + "The file reading", + "Decompressing the file", + "Decrypting the file", + "Verifying the signature"}; + char *errGenericStrings[] = { + "", + "generated an out of memory error", + "bumped on an internal programming error", + "did not recognize this as a blend file", + "failed a blend file check", + "bumped on corrupted data", + "needed the rest of the blend file", + "is not allowed in this version"}; + char *errReadStreamGlueStrings[] = { + "", + "does not know how to proceed"}; + char *errReadStreamFileStrings[] = { + "", + "did not recognize this as a blend file", + "was busted on a read error"}; + char *errInflateStrings[] = { + "", + "bumped on a decompress error"}; + char *errDecryptStrings[] = { + "", + "could not make a new key", + "bumped on a decrypt error", + "was not allowed. This blend file is not made by you."}; + char *errVerifyStrings[] = { + "", + "could not make a new key", + "failed"}; + char *errFunctionString= errFunctionStrings[errFunction]; + char *errExtraString= ""; + char *errString; + + if (errGeneric) { + errExtraString= errGenericStrings[errGeneric]; + } else if (errSpecific) { + switch (errFunction) { + case BRS_READSTREAMGLUE: + errExtraString= errReadStreamGlueStrings[errSpecific]; + break; + case BRS_READSTREAMFILE: + errExtraString= errReadStreamFileStrings[errSpecific]; + break; + case BRS_INFLATE: + errExtraString= errInflateStrings[errSpecific]; + break; + case BRS_DECRYPT: + errExtraString= errDecryptStrings[errSpecific]; + break; + case BRS_VERIFY: + errExtraString= errVerifyStrings[errSpecific]; + break; + default: + break; + } + } + + errString= MEM_mallocN(strlen(errFunctionString) + 1 + strlen(errExtraString) + 1); + sprintf(errString, "%s %s", errFunctionString, errExtraString); + + return errString; +} +#endif diff --git a/source/blender/readblenfile/intern/Makefile b/source/blender/readblenfile/intern/Makefile new file mode 100644 index 00000000000..6c6683eb07d --- /dev/null +++ b/source/blender/readblenfile/intern/Makefile @@ -0,0 +1,54 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +# +# 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. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# 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. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = readblenfile +DIR = $(OCGDIR)/blender/$(LIBNAME) + +include nan_compile.mk + +ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows")) + CFLAGS += -funsigned-char +endif + +CFLAGS += $(LEVEL_2_C_WARNINGS) + +# path to our own external headerfiles +CPPFLAGS += -I.. + +# external modules +CPPFLAGS += -I../../../kernel/gen_messaging +CPPFLAGS += -I../../readstreamglue +CPPFLAGS += -I../../blenlib +CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../blenkernel +CPPFLAGS += -I../../blenloader -- cgit v1.2.3