Initial revision
This commit is contained in:
647
source/blender/readblenfile/intern/BLO_readblenfile.c
Normal file
647
source/blender/readblenfile/intern/BLO_readblenfile.c
Normal file
@@ -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
|
Reference in New Issue
Block a user