diff --git a/chunk.c b/chunk.c index 975ebed..8971253 100644 --- a/chunk.c +++ b/chunk.c @@ -35,57 +35,55 @@ int overwriteChunk(const char* regionFolder, ChunkID chunk, void* chunkData, siz sprintf(regionFilename,"%s/r.%d.%d.mca",regionFolder,region.x,region.z); if(access(regionFilename,R_OK | W_OK) == -1) { - fprintf(stderr,"Can't access file %s: %s\n",regionFilename,strerror(errno)); - return -1; + return ACCESS_ERROR; } int fd = open(regionFilename,O_RDWR); if(fd == -1) { - fprintf(stderr,"Unable to open region file %s: %s\n",regionFilename,strerror(errno)); - return -2; + return OPEN_ERROR; } free(regionFilename); uint32_t chunkHeaderOffset; if(pread(fd,&chunkHeaderOffset,sizeof(uint32_t),(relativeChunk.x + relativeChunk.z * CHUNK_OFFSET_LENGTH) * sizeof(uint32_t)) == -1) { close(fd); - fprintf(stderr,"Unable to read chunk header offset: %s\n",strerror(errno)); - return -3; + return READ_ERROR; } uint32_t totalChunkLength = (chunkHeaderOffset >> 24) * 4096; chunkHeaderOffset = (__bswap_32(chunkHeaderOffset & 0x00FFFFFF) >> 8) * CHUNK_SECTOR_SIZE; int pos = lseek(fd,chunkHeaderOffset,SEEK_SET); if(pos == -1) { close(fd); - fprintf(stderr,"Unable to seek to header offset: %s\n",strerror(errno)); - return -4; + return SEEK_ERROR; } ChunkHeader header; if(pread(fd,&header,sizeof(ChunkHeader),pos) <= 0) { close(fd); - fprintf(stderr,"Unable to read chunk header: %s\n",strerror(errno)); - return -5; + return READ_ERROR; } header.length = __bswap_32(header.length); void* compressedChunk; ssize_t compressedChunkLength = deflateGzip(chunkData,chunkLength,&compressedChunk,(header.compressionType == COMPRESSION_TYPE_ZLIB)); + if(compressedChunkLength < 0) { + // Compression error + close(fd); + return compressedChunkLength; + } if(compressedChunkLength > totalChunkLength) { // Haven't determined if we can just allocate a new 4KiB sector for the chunk // To avoid corrupting the region, let's just make the function fail and retry on another chunk that has // free space at the end close(fd); free(compressedChunk); - fprintf(stderr,"Not enough free space to overwrite the chunk.\n\nOriginal chunk size (with padding): %d\nNew chunk size:%d\n",totalChunkLength,(unsigned int)compressedChunkLength); - return -6; + return INSUFFICIENT_SPACE_FOR_CHUNK; } header.length = __bswap_32((uint32_t)compressedChunkLength+1); if(write(fd,&header,sizeof(ChunkHeader)) <= 0) { close(fd); free(compressedChunk); - fprintf(stderr,"Unable to read chunk header: %s\n",strerror(errno)); - return -7; + return WRITE_ERROR; } ssize_t nWritten = 0; size_t totalWritten = 0; @@ -95,16 +93,15 @@ int overwriteChunk(const char* regionFolder, ChunkID chunk, void* chunkData, siz if(errno == EINTR) { continue; } - fprintf(stderr,"Unable to write chunk: %s\n",strerror(errno)); close(fd); free(compressedChunk); - return -8; + return WRITE_ERROR; } totalWritten += nWritten; } close(fd); free(compressedChunk); - return 0; + return SUCCESS; } ssize_t loadChunk(const char* regionFolder, ChunkID chunk, void** chunkData) { @@ -117,53 +114,42 @@ ssize_t loadChunk(const char* regionFolder, ChunkID chunk, void** chunkData) { sprintf(regionFilename,"%s/r.%d.%d.mca",regionFolder,region.x,region.z); if(access(regionFilename,R_OK) == -1) { - fprintf(stderr,"Can't access file %s: %s\n",regionFilename,strerror(errno)); - return -1; + return ACCESS_ERROR; } int fd = open(regionFilename,O_RDONLY); if(fd == -1) { - fprintf(stderr,"Unable to open region file %s: %s\n",regionFilename,strerror(errno)); - return -2; + return OPEN_ERROR; } free(regionFilename); uint32_t chunkHeaderOffset; if(pread(fd,&chunkHeaderOffset,sizeof(uint32_t),(relativeChunk.x + relativeChunk.z * CHUNK_OFFSET_LENGTH) * sizeof(uint32_t)) == -1) { close(fd); - fprintf(stderr,"Unable to read chunk header offset: %s\n",strerror(errno)); - return -3; + return READ_ERROR; } chunkHeaderOffset = (__bswap_32(chunkHeaderOffset & 0x00FFFFFF) >> 8) * CHUNK_SECTOR_SIZE; if(chunkHeaderOffset == 0) { // Chunk not present. Hasn't been generated - close(fd); - return 0; + close(fd); + return CHUNK_NOT_PRESENT; } if(lseek(fd,chunkHeaderOffset,SEEK_SET) == -1) { close(fd); - fprintf(stderr,"Unable to seek to header offset: %s\n",strerror(errno)); - return -4; + return SEEK_ERROR; } ChunkHeader header; if(read(fd,&header,sizeof(ChunkHeader)) <= 0) { close(fd); - fprintf(stderr,"Unable to read chunk header: %s\n",strerror(errno)); - return -5; + return READ_ERROR; } header.length = __bswap_32(header.length); ssize_t chunkLength = header.length; - if(header.compressionType != COMPRESSION_TYPE_ZLIB && header.compressionType != COMPRESSION_TYPE_GZIP) { - fprintf(stderr, "Invalid compression method. Proably reading the wrong data for the header\n"); + if((header.compressionType != COMPRESSION_TYPE_ZLIB && header.compressionType != COMPRESSION_TYPE_GZIP) || header.length == 0) { close(fd); - return -6; - } - if(header.length == 0) { - fprintf(stderr, "Header length is 0. Probably reading the wrong data for the header\n"); - close(fd); - return -7; + return INVALID_HEADER; } void* compressedChunk = calloc(chunkLength,sizeof(char)); @@ -175,10 +161,9 @@ ssize_t loadChunk(const char* regionFolder, ChunkID chunk, void** chunkData) { if(errno == EINTR) { continue; } - fprintf(stderr,"Unable to read chunk: %s\n",strerror(errno)); close(fd); free(compressedChunk); - return -8; + return READ_ERROR; } totalRead += nRead; } @@ -186,11 +171,10 @@ ssize_t loadChunk(const char* regionFolder, ChunkID chunk, void** chunkData) { void *decompressedChunk; chunkLength = inflateGzip(compressedChunk,chunkLength,&decompressedChunk,(header.compressionType == COMPRESSION_TYPE_ZLIB)); - - if(chunkLength <= 0) { - fprintf(stderr,"Error while decompressing chunk\n"); + if(chunkLength < 0) { + // Error while decompressing chunk free(compressedChunk); - return -9; + return chunkLength; } free(compressedChunk); diff --git a/chunk.h b/chunk.h index f45a4f3..543bcf2 100644 --- a/chunk.h +++ b/chunk.h @@ -12,6 +12,7 @@ #include #include "compression.h" +#include "errors.h" #define BLOCKS_PER_CHUNK 16 #define CHUNKS_PER_REGION 32 diff --git a/compression.c b/compression.c index 6edfd2e..b4a4b20 100644 --- a/compression.c +++ b/compression.c @@ -21,9 +21,8 @@ ssize_t inflateGzip(void* compData, size_t compDataLen, void** unCompData, int h } if(err != Z_OK) { - fprintf(stderr, "Unable to initialize zlib zstream for decompression\n"); free(uncomp); - return -1; + return ZLIB_STREAM_INIT_ERROR; } do { @@ -32,10 +31,9 @@ ssize_t inflateGzip(void* compData, size_t compDataLen, void** unCompData, int h // Increase size of output buffer void* newptr = realloc(uncomp,uncompLength + increase); if(newptr == NULL) { - fprintf(stderr,"Unable to request memory realloc\n"); inflateEnd(&strm); free(uncomp); - return -2; + return MEMORY_ERROR; } uncomp = newptr; uncompLength += increase; @@ -47,18 +45,16 @@ ssize_t inflateGzip(void* compData, size_t compDataLen, void** unCompData, int h // Inflate another chunk. err = inflate(&strm, Z_SYNC_FLUSH); if(err != Z_OK && err != Z_STREAM_END) { - fprintf(stderr, "Error while inflating buffer: %d - %s.\n", err,strm.msg); inflateEnd(&strm); free(uncomp); - return -3; + return ZLIB_INFLATE_ERROR; } } while(err != Z_STREAM_END); uncompLength = strm.total_out; if(inflateEnd(&strm) != Z_OK) { - fprintf(stderr,"Error while deallocating libz zstream\n"); free(uncomp); - return -4; + return ZLIB_STREAM_FREE_ERROR; } *unCompData = uncomp; @@ -85,9 +81,8 @@ ssize_t deflateGzip(void* unCompData, size_t unCompDataLen, void** compData, int } if(err != Z_OK) { - fprintf(stderr, "Unable to initialize zlib zstream for compression\n"); free(comp); - return -1; + return ZLIB_STREAM_INIT_ERROR; } do { @@ -96,10 +91,9 @@ ssize_t deflateGzip(void* unCompData, size_t unCompDataLen, void** compData, int // Increase size of output buffer void* newptr = realloc(comp, compLength + increase); if(newptr == NULL) { - fprintf(stderr,"Unable to request memory realloc\n"); deflateEnd(&strm); free(comp); - return -2; + return MEMORY_ERROR; } comp = newptr; compLength += increase; @@ -111,18 +105,16 @@ ssize_t deflateGzip(void* unCompData, size_t unCompDataLen, void** compData, int // deflate another chunk err = deflate(&strm, Z_FINISH); if(err != Z_OK && err != Z_STREAM_END) { - fprintf(stderr, "Error while deflating buffer: %d - %s\n",err,strm.msg); deflateEnd(&strm); free(comp); - return -3; + return ZLIB_DEFLATE_ERROR; } } while(err != Z_STREAM_END); compLength = strm.total_out; if(deflateEnd(&strm) != Z_OK) { - fprintf(stderr,"Error while deallocating libz zstream\n"); free(comp); - return -4; + return ZLIB_STREAM_FREE_ERROR; } if(!headerless) { diff --git a/compression.h b/compression.h index cacedcc..45123ed 100644 --- a/compression.h +++ b/compression.h @@ -5,6 +5,8 @@ #include #include +#include "errors.h" + #define OS_FLAG_OFFSET 0x9 ssize_t deflateGzip(void* unCompData, size_t unCompDataLen, void** compData, int headerless); diff --git a/nbt.c b/nbt.c index 7b89f3b..c3eeb37 100644 --- a/nbt.c +++ b/nbt.c @@ -8,18 +8,17 @@ void destroyTagList(TagList* l); void destroyTagCompound(TagCompound* tc); size_t getTypeSize(uint8_t type); unsigned int parseList(void* addr, TagList* tl, uint8_t type); -unsigned int parseCompound(void* addr, TagCompound* tc); -unsigned int parsePayload(void* addr,Tag* t); -unsigned int parseTag(void* addr, Tag* t); -size_t composeCompound(TagCompound* tc, void** data); -size_t composeList(uint8_t listType, TagList* tl, void** data); -size_t composePayload(Tag t, void** data); -size_t composeTag(Tag t, void** data); +ssize_t parseCompound(void* addr, TagCompound* tc); +ssize_t parsePayload(void* addr,Tag* t); +ssize_t parseTag(void* addr, Tag* t); +ssize_t composeCompound(TagCompound* tc, void** data); +ssize_t composeList(uint8_t listType, TagList* tl, void** data); +ssize_t composePayload(Tag t, void** data); +ssize_t composeTag(Tag t, void** data); ssize_t loadDB(const char* filename, void** data) { if(access(filename,R_OK) == -1) { - perror("Can't access file"); - return -1; + return ACCESS_ERROR; } struct stat sb; @@ -27,8 +26,7 @@ ssize_t loadDB(const char* filename, void** data) { int fd = open(filename,O_RDONLY); if(fd == -1) { - perror("Can't open file"); - return -2; + return OPEN_ERROR; } fstat(fd, &sb); @@ -44,8 +42,7 @@ ssize_t loadDB(const char* filename, void** data) { if(errno == EINTR) { continue; } - perror("Error reading file"); - return -7; + return READ_ERROR; } totalRead += nRead; } @@ -144,7 +141,7 @@ unsigned int parseList(void* addr, TagList* tl, uint8_t type) { return pos - addr; } -unsigned int parseCompound(void* addr, TagCompound* tc) { +ssize_t parseCompound(void* addr, TagCompound* tc) { void* pos = addr; unsigned int numTags = 0; Tag* list = calloc(REALLOC_SIZE,sizeof(Tag)); @@ -152,8 +149,8 @@ unsigned int parseCompound(void* addr, TagCompound* tc) { if(numTags && !(numTags % REALLOC_SIZE)) { void* newptr = reallocarray(list, numTags + REALLOC_SIZE, sizeof(Tag)); if(!newptr) { - fprintf(stderr,"Unable to request memory realloc\n"); - break; + free(list); + return MEMORY_ERROR; } list = newptr; } @@ -162,7 +159,8 @@ unsigned int parseCompound(void* addr, TagCompound* tc) { void* newptr = reallocarray(list, numTags, sizeof(Tag)); if(!newptr) { - fprintf(stderr,"Unable to request memory realloc\n"); + free(list); + return MEMORY_ERROR; } list = newptr; @@ -171,9 +169,10 @@ unsigned int parseCompound(void* addr, TagCompound* tc) { return pos - addr; } -unsigned int parsePayload(void* addr,Tag* t) { +ssize_t parsePayload(void* addr,Tag* t) { void* pos = addr; t->payloadLength = getTypeSize(t->type); // initially, then particularly for lists/compounds/strings + ssize_t compoundTagPos = 0; TagCompound* tc; TagList *tl; uint16_t u16 = 0; @@ -218,7 +217,12 @@ unsigned int parsePayload(void* addr,Tag* t) { tc = (TagCompound*)calloc(1,sizeof(TagCompound)); t->payloadLength = sizeof(sizeof(TagCompound)); t->payload = tc; - pos += parseCompound(pos,tc); + compoundTagPos = parseCompound(pos,tc); + if(compoundTagPos < 0) { + // Memory error while parsing TAG_COMPOUND + return compoundTagPos; + } + pos += compoundTagPos; break; case TAG_LIST: case TAG_BYTEARRAY: @@ -232,7 +236,7 @@ unsigned int parsePayload(void* addr,Tag* t) { return pos - addr; } -unsigned int parseTag(void* addr, Tag* t) { +ssize_t parseTag(void* addr, Tag* t) { void* pos = addr; t->type = *((uint8_t*)pos); t->nameLength = 0; @@ -247,12 +251,16 @@ unsigned int parseTag(void* addr, Tag* t) { } pos += sizeof(uint16_t) + t->nameLength; } - pos += parsePayload(pos,t); + ssize_t payloadPos = parsePayload(pos,t); + if(payloadPos < 0) { + return payloadPos; + } + pos += payloadPos; return pos-addr; } -size_t composeCompound(TagCompound* tc, void** data) { +ssize_t composeCompound(TagCompound* tc, void** data) { size_t totalPayloadLength = 0; void* totalPayload = calloc(1,sizeof(char)); unsigned int pos = 0; @@ -263,10 +271,9 @@ size_t composeCompound(TagCompound* tc, void** data) { totalPayloadLength += childTagPayloadLength; void* newptr = realloc(totalPayload,totalPayloadLength); if(newptr == NULL) { - fprintf(stderr, "Unable to realloc memory for child tag\n"); free(totalPayload); free(childTagPayload); - return 0; + return MEMORY_ERROR; } totalPayload = newptr; memcpy(totalPayload+pos,childTagPayload,childTagPayloadLength); @@ -275,9 +282,8 @@ size_t composeCompound(TagCompound* tc, void** data) { } void* newptr = realloc(totalPayload,++totalPayloadLength); if(newptr == NULL) { - fprintf(stderr, "Unable to realloc memory for end tag\n"); free(totalPayload); - return 0; + return MEMORY_ERROR; } totalPayload = newptr; ((uint8_t*)totalPayload)[pos] = 0x00; @@ -285,7 +291,7 @@ size_t composeCompound(TagCompound* tc, void** data) { return totalPayloadLength; } -size_t composeList(uint8_t listType, TagList* tl, void** data) { +ssize_t composeList(uint8_t listType, TagList* tl, void** data) { size_t totalPayloadLength = 0; if(listType == TAG_LIST) { totalPayloadLength += sizeof(uint8_t); @@ -306,10 +312,9 @@ size_t composeList(uint8_t listType, TagList* tl, void** data) { totalPayloadLength += childTagPayloadLength; void* newptr = realloc(totalPayload,totalPayloadLength); if(newptr == NULL) { - fprintf(stderr, "Unable to realloc memory for child tag\n"); free(totalPayload); free(childTagPayload); - return 0; + return MEMORY_ERROR; } totalPayload = newptr; memcpy(totalPayload+pos,childTagPayload,childTagPayloadLength); @@ -321,7 +326,7 @@ size_t composeList(uint8_t listType, TagList* tl, void** data) { return totalPayloadLength; } -size_t composePayload(Tag t, void** data) { +ssize_t composePayload(Tag t, void** data) { size_t payloadLength = getTypeSize(t.type); // initially, then particularly for lists/compounds/strings void* payload; @@ -371,7 +376,7 @@ size_t composePayload(Tag t, void** data) { return payloadLength; } -size_t composeTag(Tag t, void** data) { +ssize_t composeTag(Tag t, void** data) { size_t headerSize = sizeof(uint8_t) + sizeof(uint16_t) + t.nameLength; void* tagHeader = calloc(headerSize,sizeof(char)); ((uint8_t*)tagHeader)[0] = t.type; @@ -379,13 +384,16 @@ size_t composeTag(Tag t, void** data) { memcpy(tagHeader+sizeof(uint8_t),&u16,sizeof(uint16_t)); memcpy(tagHeader+sizeof(uint8_t) + sizeof(uint16_t), t.name, t.nameLength); void* tagPayload; - size_t payloadSize = composePayload(t,&tagPayload); + ssize_t payloadSize = composePayload(t,&tagPayload); + if(payloadSize < 0) { + // Some error while composing payload + return payloadSize; + } void* tagData = realloc(tagHeader,headerSize + payloadSize); if(tagData == NULL) { - fprintf(stderr, "Unable to realloc memory to merge header and payload\n"); free(tagHeader); free(tagPayload); - return 0; + return MEMORY_ERROR; } memcpy(tagData + headerSize,tagPayload, payloadSize); free(tagPayload); diff --git a/nbt.h b/nbt.h index ce49e14..8deda21 100644 --- a/nbt.h +++ b/nbt.h @@ -13,6 +13,8 @@ #include #include +#include "errors.h" + #ifndef REALLOC_SIZE #define REALLOC_SIZE 10 #endif @@ -59,7 +61,7 @@ enum TAG { ssize_t loadDB(const char* filename, void** data); void destroyTag(Tag* t); -unsigned int parseTag(void* addr, Tag* t); -size_t composeTag(Tag t, void** data); +ssize_t parseTag(void* addr, Tag* t); +ssize_t composeTag(Tag t, void** data); #endif \ No newline at end of file