Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/readblenfile/intern/BLO_readblenfile.c')
-rw-r--r--source/blender/readblenfile/intern/BLO_readblenfile.c647
1 files changed, 647 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+#ifdef WIN32
+#include <io.h> // read, open
+#else // ! WIN32
+#include <unistd.h> // 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