From 18844f94a983092a3482ac30dae7b720d5c597a7 Mon Sep 17 00:00:00 2001 From: TCA Date: Sat, 20 Apr 2024 15:17:39 +0200 Subject: [PATCH] Reworked error checking Also fixed compile time error for tests --- .vscode/settings.json | 3 +- Makefile | 35 ++++---- src/blockPrint.c | 11 ++- src/chunkExtractor.c | 6 +- src/lib/chunkParser.c | 10 ++- src/lib/errorDefs.h | 188 +++++++++++++++++++++++++---------------- src/lib/generator.c | 4 +- src/lib/mcErrno.c | 16 ++++ src/lib/model.c | 18 ++++ src/lib/regionParser.c | 8 ++ src/modelGenerator.c | 26 ++++-- src/radiusGenerator.c | 21 +++++ tests/hTable.check | 8 +- 13 files changed, 245 insertions(+), 109 deletions(-) create mode 100644 src/lib/mcErrno.c diff --git a/.vscode/settings.json b/.vscode/settings.json index 4da50ff..ee64db7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -22,7 +22,8 @@ "generator.h": "c", "stdbool.h": "c", "htable.h": "c", - "stdlib.h": "c" + "stdlib.h": "c", + "functional": "c" }, "cSpell.words": [ "blockstates", diff --git a/Makefile b/Makefile index ea0bdf6..d234aee 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,9 @@ all: radiusGenerator modelGenerator chunkExtractor regionFileReader blockPrint debug: CFLAGS := -Wall -Werror -Wpedantic -g debug: radiusGenerator modelGenerator chunkExtractor regionFileReader blockPrint +mcErrno.o: src/lib/mcErrno.c + gcc src/lib/mcErrno.c -o mcErrno.o -c $(CFLAGS) + cNBT.o: gcc cNBT/buffer.c -o cNBT/buffer.o -c $(CFLAGS) gcc cNBT/nbt_parsing.c -o cNBT/nbt_parsing.o -c $(CFLAGS) @@ -38,23 +41,23 @@ hTable.o: src/lib/hTable.c model.o: src/lib/model.c gcc src/lib/model.c -o model.o -c $(CFLAGS) -regionFileReader: regionParser.o src/regionFileReader.c - gcc src/regionFileReader.c regionParser.o -o regionFileReader $(ZLIB) -lm $(CFLAGS) +regionFileReader: regionParser.o mcErrno.o src/regionFileReader.c + gcc src/regionFileReader.c regionParser.o mcErrno.o -o regionFileReader $(ZLIB) -lm $(CFLAGS) -chunkExtractor: regionParser.o src/chunkExtractor.c - gcc src/chunkExtractor.c regionParser.o -o chunkExtractor $(ZLIB) -lm $(CFLAGS) +chunkExtractor: regionParser.o mcErrno.o src/chunkExtractor.c + gcc src/chunkExtractor.c regionParser.o mcErrno.o -o chunkExtractor $(ZLIB) -lm $(CFLAGS) generator.o: src/lib/generator.c gcc src/lib/generator.c -o generator.o -c $(CFLAGS) -modelGenerator: model.o generator.o hTable.o chunkParser.o cNBT.o src/modelGenerator.c - gcc src/modelGenerator.c generator.o model.o hTable.o chunkParser.o cNBT.o -o modelGenerator -lm $(CFLAGS) +modelGenerator: model.o generator.o hTable.o mcErrno.o chunkParser.o cNBT.o src/modelGenerator.c + gcc src/modelGenerator.c generator.o model.o mcErrno.o hTable.o chunkParser.o cNBT.o -o modelGenerator -lm $(CFLAGS) -radiusGenerator: model.o generator.o hTable.o chunkParser.o regionParser.o cNBT.o src/radiusGenerator.c - gcc src/radiusGenerator.c generator.o model.o regionParser.o hTable.o chunkParser.o cNBT.o $(ZLIB) -lm -o radiusGenerator $(CFLAGS) +radiusGenerator: model.o generator.o hTable.o mcErrno.o chunkParser.o regionParser.o cNBT.o src/radiusGenerator.c + gcc src/radiusGenerator.c generator.o model.o mcErrno.o regionParser.o hTable.o chunkParser.o cNBT.o $(ZLIB) -lm -o radiusGenerator $(CFLAGS) -blockPrint: src/blockPrint.c chunkParser.o cNBT.o hTable.o - gcc src/blockPrint.c chunkParser.o cNBT.o hTable.o -o blockPrint -lm $(CFLAGS) +blockPrint: src/blockPrint.c chunkParser.o mcErrno.o cNBT.o hTable.o + gcc src/blockPrint.c chunkParser.o cNBT.o mcErrno.o hTable.o -o blockPrint -lm $(CFLAGS) cNBT.ow: x86_64-w64-mingw32-gcc-win32 cNBT/buffer.c -o cNBT/buffer.ow -c $(CFLAGS) @@ -109,26 +112,26 @@ clean: rm -f blockPrint rm -f blockPrint.exe -check: hTable.o regionParser.o chunkParser.o cNBT.o model.o +check: hTable.o regionParser.o chunkParser.o cNBT.o model.o mcErrno.o #hTable tests checkmk tests/hTable.check > tests/hTableCheck.c - gcc tests/hTableCheck.c hTable.o -lcheck -g -lm $(SUBUNIT) -Wall -o tests/hTableCheck + gcc tests/hTableCheck.c hTable.o mcErrno.o -lcheck -g -lm $(SUBUNIT) -Wall -o tests/hTableCheck ./tests/hTableCheck #regionParser tests checkmk tests/regionParser.check > tests/regionParserCheck.c - gcc tests/regionParserCheck.c regionParser.o -lcheck -g -lm $(ZLIB) $(SUBUNIT) -o tests/regionParserCheck + gcc tests/regionParserCheck.c regionParser.o mcErrno.o -lcheck -g -lm $(ZLIB) $(SUBUNIT) -o tests/regionParserCheck ./tests/regionParserCheck #chunkParser tests checkmk tests/chunkParser.check > tests/chunkParserCheck.c - gcc tests/chunkParserCheck.c chunkParser.o cNBT.o -lcheck -g -lm $(SUBUNIT) -o tests/chunkParserCheck + gcc tests/chunkParserCheck.c chunkParser.o cNBT.o mcErrno.o -lcheck -g -lm $(SUBUNIT) -o tests/chunkParserCheck ./tests/chunkParserCheck #model tests checkmk tests/model.check > tests/modelCheck.c - gcc tests/modelCheck.c model.o hTable.o -lcheck -g -lm $(SUBUNIT) -o tests/modelCheck + gcc tests/modelCheck.c model.o hTable.o mcErrno.o -lcheck -g -lm $(SUBUNIT) -o tests/modelCheck ./tests/modelCheck #wavefront tests - doesn't work on windows because os bs #checkmk tests/wavefront.check > tests/wavefrontCheck.c - #gcc tests/wavefrontCheck.c model.o hTable.o -lcheck -g -lm $(SUBUNIT) -o tests/wavefrontCheck + #gcc tests/wavefrontCheck.c model.o hTable.o mcErrno.o -lcheck -g -lm $(SUBUNIT) -o tests/wavefrontCheck #./tests/wavefrontCheck doc: doc/build/html diff --git a/src/blockPrint.c b/src/blockPrint.c index 3629c0d..e4a07fe 100644 --- a/src/blockPrint.c +++ b/src/blockPrint.c @@ -19,34 +19,37 @@ int main(int argc, char** argv){ if(argc < 2){ argCountError("blockPrint "); + errorCheck("argCountError"); } unsigned char* data; long sz; { FILE* file = fopen(argv[1], "rb"); if(file == NULL){ - fileError(argv[1], "opened"); + errorCheck("fopen"); } if(fseek(file, 0, SEEK_END) != 0){ - fileError(argv[1], "seeked"); + errorCheck("fseek"); } sz = ftell(file); if(fseek(file, 0, SEEK_SET) != 0){ - fileError(argv[1], "seeked"); + errorCheck("fseek"); } data = malloc(sz); if(fread(data, sz, 1, file) != 1){ - fileError(argv[1], "read"); + errorCheck("fread"); } fclose(file); } section sections[maxSections]; int sectionN = getSections(data, sz, sections); + errorCheck("getSections"); free(data); hashTable* blockCount = initHashTable(49152); //max blocks in chunk divided by 2 for(int i = 0; i < sectionN; i++){ int outLen; unsigned int* blockStates = getBlockStates(sections[i], &outLen); + errorCheck("getBlockStates"); if(blockStates == NULL){ char* key = sections[i].blockPalette[0]; if(getVal(blockCount, key) == NULL){ diff --git a/src/chunkExtractor.c b/src/chunkExtractor.c index 0e04b0f..d1ffd73 100644 --- a/src/chunkExtractor.c +++ b/src/chunkExtractor.c @@ -23,19 +23,21 @@ int main(int argc, char** argv){ if(argc < 3){ argCountError("chunkExtractor "); + errorCheck("argCountError"); } for(int i = 3; i < argc; i+=3){ int x = atoi(argv[i - 1]); int z = atoi(argv[i]); chunk ourChunk = extractChunk(argv[i - 2], x, z); + errorCheck("extractChunk"); char* filename = malloc(8 + 10 + 10); sprintf(filename, "./%d.%d.nbt", x, z); FILE* outFile = fopen(filename, "wb"); if(outFile == NULL){ - fileError(filename, "opened"); + errorCheck("fopen"); } if(fwrite(ourChunk.data, ourChunk.byteLength, 1, outFile) != 1){ - fileError(filename, "written to"); + errorCheck("fwrite"); } free(filename); fclose(outFile); diff --git a/src/lib/chunkParser.c b/src/lib/chunkParser.c index d51fdf9..a1922e5 100644 --- a/src/lib/chunkParser.c +++ b/src/lib/chunkParser.c @@ -68,9 +68,11 @@ unsigned int getSections(unsigned char* nbtFileData, long sz, section* sections) nbt_node* node = nbt_parse(nbtFileData, sz); if(errno != 0){ cNBTError("the nbt file") + return 0; } if(node->type != TAG_COMPOUND){ nbtTypeError(node->type, 10); + return 0; } //Debug message //const struct list_head* head = &node->payload.tag_compound->entry; @@ -79,6 +81,7 @@ unsigned int getSections(unsigned char* nbtFileData, long sz, section* sections) nbt_node* sectionsNode = nbt_find_by_name(node, "sections"); if(sectionsNode == NULL){ nbtTagError("sections"); + return 0; } struct nbt_list* sectionsList = sectionsNode->payload.tag_list; struct list_head* pos; @@ -93,12 +96,14 @@ unsigned int getSections(unsigned char* nbtFileData, long sz, section* sections) nbt_node* yNode = nbt_find_by_name(compound, "Y"); if(yNode == NULL){ nbtTagError("Y"); + return 0; } newSection.y = yNode->payload.tag_byte; //get the block data nbt_node* blockNode = nbt_find_by_name(compound, "block_states"); if(blockNode == NULL){ nbtTagError("block_states"); + return 0; } //get the individual block data nbt_node* blockData = nbt_find_by_name(blockNode, "data"); @@ -115,6 +120,7 @@ unsigned int getSections(unsigned char* nbtFileData, long sz, section* sections) nbt_node* palette = nbt_find_by_name(blockNode, "palette"); if(palette == NULL){ nbtTagError("palette"); + return 0; } //const struct list_head* paletteHead = &palette->payload.tag_list->entry; char** blockPalette = malloc(sizeof(char*)); @@ -127,6 +133,7 @@ unsigned int getSections(unsigned char* nbtFileData, long sz, section* sections) nbt_node* string = nbt_find_by_name(pal->data, "Name"); if(string == NULL){ nbtTagError("Name"); + return 0; } //Instead of appending all properties in block using a for loop we extract a few specific ones char* direction = NULL; @@ -202,6 +209,7 @@ unsigned int getSections(unsigned char* nbtFileData, long sz, section* sections) newSection.blockPalette = blockPalette; if(i == UINT32_MAX){ overflowError("UINT32"); + return 0; } newSection.paletteLen = i; sections[n] = newSection; @@ -260,7 +268,7 @@ block createBlock(int x, int y, int z, unsigned int* blockStates, section parent int state = blockStates[blockPos]; //paletteLen and I are fine it must be something with the data extraction process if(state >= parentSection.paletteLen){ - statesError(state, parentSection.paletteLen, newBlock); + statesWarning(state, parentSection.paletteLen, newBlock); newBlock.type = mcAir; } else{ diff --git a/src/lib/errorDefs.h b/src/lib/errorDefs.h index f7e5fd8..9c06b8e 100644 --- a/src/lib/errorDefs.h +++ b/src/lib/errorDefs.h @@ -3,23 +3,86 @@ * @brief Contains error definitions for the project * * @details Within this project errors are handled by calling one of these macros. They print an error message to stderr, set errno to a specific value and exit the program with EXIT_FAILURE. - */ - -//Since the ERRNO macros are very unspecific and as far as I can see usually associated with errors a kernel may encounter, I have only loosely associated them with my own error convention +*/ #include #include -#include + +/*! + @defgroup mcErrno Error Reporting + @brief A shared error reporting system + @details This shared error reporting system is used to report errors in the project using a global variable mcErrno of type mcError_t +*/ /*! @defgroup errorDefs Error Definitions @brief Contains error definitions for the project + @details These macros are used to report errors in the project + @ingroup mcErrno */ /*! @defgroup warningDefs Warning Definitions @brief Contains warning definitions for the project + @details These macros are used to report warnings in the project + @ingroup mcErrno +*/ + +/*! + @enum mcError_t + @brief Contains error types for the project + @see mcErrno + @see errorDefs, warningDefs on how to set these + @ingroup mcErrno +*/ +typedef enum{ + none, /*!< No error, the default value */ + cNBTError, /*!< Error encountered while parsing an NBT file */ + nbtTypeError, /*!< Error when the tag has a different type */ + nbtTagError, /*!< Error when the needed tag is missing */ + fileError, /*!< Error related to C syscalls regarding files */ + parsingError, /*!< Error encountered during the parsing of a file */ + statesWarning, /*!< Warning when a minecraft block state is larger than the palette */ + argError, /*!< Error when an invalid amount of sub-arguments is provided */ + argCountError, /*!< Error when an invalid amount of arguments is provided */ + dirError, /*!< Error when a directory cannot be opened */ + materialWarning, /*!< Warning when the material for a type couldn't be found in the mtl file */ + vertexWarning, /*!< Warning when there is a possible vertex-face mismatch in an object */ + argValError, /*!< Error when an invalid value of an argument is provided */ + pipeError, /*!< Error when something goes wrong with a pipe */ + forkError, /*!< Error when fork fails */ + shmError, /*!< Error when something goes wrong with shared memory */ + localizedFileError, /*!< Error with a specific position in a file */ + semaphoreError, /*!< Error when something goes wrong with a semaphore */ + mallocError, /*!< Error when detecting NULL return value of malloc */ + overflowError, /*!< Error when an overflow condition has been detected */ + stringError /*!< Error when there is an issue with string operations */ +} mcError_t; + +/*! + @var mcErrno + @brief Contains the error type for the project + @see mcError_t + @see errorCheck on how to check this + @see errorDefs, warningDefs on how to set this + @ingroup mcErrno +*/ +extern mcError_t mcErrno; + +/*! + @brief Checks if an error has been set and exits the program if it has + @details Mainly a convenience function, call this after performing an operation that might set an error + @param func The name of the function that is being checked + @ingroup mcErrno +*/ +void errorCheck(const char* func); + +/*! + @brief Clears the error + @details Sets mcErrno to none and errno to 0 + @ingroup mcErrno */ +void clearError(); /*! * @def cNBTError @@ -28,9 +91,8 @@ * @ingroup errorDefs */ #define cNBTError(filename) \ - fprintf(stderr, "cNBT encountered an error while parsing %s", filename); \ - perror("cNBT error"); \ - exit(EXIT_FAILURE); \ + mcErrno = cNBTError; \ + fprintf(stderr, "cNBT encountered an error while parsing %s", filename); \ /*! * @def nbtTypeError @@ -40,10 +102,8 @@ * @ingroup errorDefs */ #define nbtTypeError(type, expected) \ - fprintf(stderr, "Expected type:%d, current type:%d.", expected, type);\ - errno = EIO; \ - perror("Nbt type error"); \ - exit(EXIT_FAILURE); + mcErrno = nbtTypeError; \ + fprintf(stderr, "Expected type:%d, current type:%d.", expected, type);\ /*! * @def nbtTagError @@ -52,10 +112,8 @@ * @ingroup errorDefs */ #define nbtTagError(tag) \ - fprintf(stderr, "Tag %s was not found.", tag);\ - errno = EIO; \ - perror("Nbt type error"); \ - exit(EXIT_FAILURE); + mcErrno = nbtTagError; \ + fprintf(stderr, "Tag %s was not found.", tag);\ /*! * @def fileError @@ -65,10 +123,8 @@ * @ingroup errorDefs */ #define fileError(filename, action) \ - fprintf(stderr, "File %s couldn't be " action ".", filename); \ - errno = EIO; \ - perror("File error.");\ - exit(EXIT_FAILURE); + mcErrno = fileError; \ + fprintf(stderr, "File %s couldn't be " action ".", filename); \ /*! * @def parsingError @@ -78,21 +134,20 @@ * @ingroup errorDefs */ #define parsingError(filename, action) \ - fprintf(stderr, "Error encountered during " action " of %s.", filename); \ - errno = EIO; \ - perror("Parsing error.");\ - exit(EXIT_FAILURE); + mcErrno = parsingError; \ + fprintf(stderr, "Error encountered during " action " of %s.", filename); \ /*! - * @def statesError + * @def statesWarning * @brief Reports a warning when a minecraft block state is larger than the palette * @param state The current state value * @param paletteLen The length of the palette * @param block The name of the block * @ingroup errorDefs */ -#define statesError(state, paletteLen, block) \ - fprintf(stderr, "%d >= %ld:states error\n", state, paletteLen); \ +#define statesWarning(state, paletteLen, block) \ + mcErrno = statesWarning; \ + fprintf(stderr, "%d >= %ld:states warning\n", state, paletteLen); \ /*! * @def argError @@ -102,10 +157,8 @@ * @ingroup errorDefs */ #define argError(argName, argCount) \ - fprintf(stderr, "Incorrect number of arguments." argName " requires " argCount " arguments to follow."); \ - errno = EINVAL; \ - perror("Arg error"); \ - break; + mcErrno = argError; \ + fprintf(stderr, "Incorrect number of arguments." argName " requires " argCount " arguments to follow."); \ /*! * @def argCountError @@ -114,10 +167,8 @@ * @ingroup errorDefs */ #define argCountError(usage) \ - fprintf(stderr, "Invalid number of arguments was provided\n" usage "\n"); \ - errno = EINVAL; \ - perror("Arg count error."); \ - exit(EXIT_FAILURE); + mcErrno = argCountError; \ + fprintf(stderr, "Invalid number of arguments was provided\n" usage "\n"); \ /*! * @def dirError @@ -126,10 +177,8 @@ * @ingroup errorDefs */ #define dirError(dirname) \ - fprintf(stderr, "Directory %s couldn't be opened.\n", dirname); \ - errno = ENOENT; \ - perror("Dir error."); \ - exit(EXIT_FAILURE); + mcErrno = dirError; \ + fprintf(stderr, "Directory %s couldn't be opened.\n", dirname); \ /*! * @def materialWarning @@ -138,7 +187,8 @@ * @ingroup warningDefs */ #define materialWarning(type) \ - fprintf(stdout, "Material for %s couldn't be found in the mtl file.\n", type); + mcErrno = materialWarning; \ + fprintf(stdout, "Material for %s couldn't be found in the mtl file.\n", type); /*! * @def vertexWarning @@ -147,7 +197,8 @@ * @ingroup warningDefs */ #define vertexWarning(objName) \ - fprintf(stderr, "A possible vertex-face mismatch in object %s\n", objName); + mcErrno = vertexWarning; \ + fprintf(stderr, "A possible vertex-face mismatch in object %s\n", objName); /*! * @def argValError @@ -156,10 +207,8 @@ * @ingroup errorDefs */ #define argValError(arg) \ - fprintf(stderr, "Invalid " arg " argument value.\n"); \ - errno = EINVAL; \ - perror("Arg val error"); \ - exit(EXIT_FAILURE); + mcErrno = argValError; \ + fprintf(stderr, "Invalid " arg " argument value.\n"); \ /*! * @def pipeError @@ -169,10 +218,8 @@ * @ingroup errorDefs */ #define pipeError(pipe, operation) \ - fprintf(stderr, "Pipe " pipe " " operation " failed.\n"); \ - errno = EPIPE; \ - perror("Pipe error"); \ - exit(EXIT_FAILURE); + mcErrno = pipeError; \ + fprintf(stderr, "Pipe " pipe " " operation " failed.\n"); \ /*! * @def forkError @@ -181,10 +228,8 @@ * @ingroup errorDefs */ #define forkError(fork) \ - fprintf(stderr, "Fork " fork " failed.\n"); \ - errno = ECHILD; \ - perror("Pipe error"); \ - exit(EXIT_FAILURE); + mcErrno = forkError; \ + fprintf(stderr, "Fork " fork " failed.\n"); \ /*! * @def shmError @@ -193,9 +238,8 @@ * @ingroup errorDefs */ #define shmError(shm) \ - fprintf(stderr, shm " failed.\n"); \ - perror("Shared memory error"); \ - exit(EXIT_FAILURE); + mcErrno = shmError; \ + fprintf(stderr, shm " failed.\n"); \ /*! * @def localizedFileError @@ -203,11 +247,13 @@ * @param pos The position in the file * @param fileName The name of the file * @param action The action being performed on the file + * @extends fileError * @ingroup errorDefs */ #define localizedFileError(pos, fileName, action) \ - fprintf(stderr, "At %lu ", pos); \ - fileError(fileName, action); + fprintf(stderr, "At %lu ", pos); \ + fileError(fileName, action); \ + mcErrno = localizedFileError; /*! * @def semaphoreError @@ -217,34 +263,34 @@ * @ingroup errorDefs */ #define semaphoreError(sem, action) \ - fprintf(stderr, "Semaphore " sem " couldn't " action "\n"); \ - perror("Semaphore error"); \ - exit(EXIT_FAILURE); + mcErrno = semaphoreError; \ + fprintf(stderr, "Semaphore " sem " couldn't " action "\n"); \ /*! * @def mallocError * @brief Reports an error when detecting NULL return value of malloc * @param malloc The name of the malloc * @param size The size of the memory being allocated + * @extends perror * @ingroup errorDefs */ #define mallocError(malloc, size) \ - fprintf(stderr, "Malloc " malloc " of size %zu couldn't be performed. Check for uninitialized values.\n", size); \ - if(errno == 0){errno = ENOMEM;} \ - perror("Malloc error"); \ - exit(EXIT_FAILURE); + mcErrno = mallocError; \ + fprintf(stderr, "Malloc " malloc " of size %zu couldn't be performed. Check for uninitialized values.\n", size); \ + if(errno == 0){errno = ENOMEM;} \ + perror("Malloc error"); \ /*! * @def overflowError * @brief Reports an error when an overflow condition has been detected * @param type The type of the overflow + * @extends EOVERFLOW * @ingroup errorDefs */ #define overflowError(type) \ - fprintf(stderr, "An overflow condition has been detected of " type ". To prevent a crash further down the line program will be shut down."); \ - errno = EOVERFLOW; \ - perror("Overflow error"); \ - exit(EXIT_FAILURE); + mcErrno = overflowError; \ + fprintf(stderr, "An overflow condition has been detected of " type "."); \ + errno = EOVERFLOW; \ /*! * @def stringError @@ -252,6 +298,6 @@ * @ingroup errorDefs */ #define stringError(function) \ - fprintf(stderr, "Function " function " encountered a problem.\n"); \ - perror("String function error"); \ - exit(EXIT_FAILURE); + mcErrno = stringError; \ + fprintf(stderr, "Function " function " encountered a problem.\n"); \ + diff --git a/src/lib/generator.c b/src/lib/generator.c index 1328955..71154bf 100644 --- a/src/lib/generator.c +++ b/src/lib/generator.c @@ -36,7 +36,7 @@ model generateFromNbt(unsigned char* data, int dataSize, hashTable* materials, h }*/ materialsArr = (material**)hashTableToArray(materials); materialsLen = materials->count; - freeHashTable(materials); + freeHashTable(materials, NULL); } if(!f){ cullFaces(&cubeModel, !b, objects); @@ -123,5 +123,5 @@ void freeObjectsHashTable(hashTable* objects){ free(obj->faces); free(obj); } - freeHashTable(objects); + freeHashTable(objects, NULL); } \ No newline at end of file diff --git a/src/lib/mcErrno.c b/src/lib/mcErrno.c new file mode 100644 index 0000000..829c933 --- /dev/null +++ b/src/lib/mcErrno.c @@ -0,0 +1,16 @@ +#include "errorDefs.h" +#include + +mcError_t mcErrno; + +void errorCheck(const char* func){ + if(mcErrno != none || errno != 0){ + perror(func); + exit(EXIT_FAILURE); + } +} + +void clearError(){ + mcErrno = none; + errno = 0; +} diff --git a/src/lib/model.c b/src/lib/model.c index fd07154..de8e686 100644 --- a/src/lib/model.c +++ b/src/lib/model.c @@ -375,6 +375,7 @@ static char* appendMtlLine(const char* mtlName, char* appendTo, size_t* outSize, char* mtlLine = malloc(mtlLineSize); if(snprintf(mtlLine, mtlLineSize, "usemtl %s\n", mtlName) < 0){ stringError("snprintf") + return NULL; } *outSize += mtlLineSize - 1; appendTo = reallocBy(appendTo, alloc, outSize, reallocMult); @@ -430,9 +431,11 @@ char* generateModel(const model* thisModel, size_t* outSize, const char* materia objectLine = malloc(objectLineSize); if(objectLine == NULL){ mallocError("object line", objectLineSize); + return NULL; } if(snprintf(objectLine, objectLineSize, "o cube%d-%d-%d:%s:%lu\n", x, y, z, type, *offset) < 0){ stringError("snprintf"); + return NULL; } *outSize += objectLineSize - 1; fileContents = reallocBy(fileContents, &alloc, outSize, reallocMult); @@ -450,9 +453,11 @@ char* generateModel(const model* thisModel, size_t* outSize, const char* materia vertexLine = malloc(size); if(vertexLine == NULL){ mallocError("vertexLine", size); + return NULL; } if(snprintf(vertexLine, size, "v %.6f %.6f %.6f\n", v.coordinates.x, v.coordinates.y , v.coordinates.z) < 0){ stringError("snprintf") + return NULL; } *outSize += size - 1; fileContents = reallocBy(fileContents, &alloc, outSize, reallocMult); @@ -473,6 +478,7 @@ char* generateModel(const model* thisModel, size_t* outSize, const char* materia char* line = malloc(size); if(line == NULL){ mallocError("line", size); + return NULL; } line[0] = '\0'; strcat(line, "f "); @@ -481,6 +487,7 @@ char* generateModel(const model* thisModel, size_t* outSize, const char* materia size_t len = digits(face.vertices[m]) + 1; if(snprintf(line + lineOff, len + 1, "%d ", face.vertices[m]) < 0){ stringError("snprintf") + return NULL; } lineOff += len; } @@ -492,6 +499,7 @@ char* generateModel(const model* thisModel, size_t* outSize, const char* materia } if(*offset + thisObject->vertexCount > __LONG_MAX__){ overflowError("ULONG") + return NULL; } *offset += thisObject->vertexCount; } @@ -540,17 +548,21 @@ hashTable* getMaterials(char* filename){ FILE* mtlFile = fopen(filename, "r"); if(mtlFile == NULL){ fileError(filename, "opened"); + return NULL; } if(fseek(mtlFile, 0, SEEK_END) != 0){ fileError(filename, "seek"); + return NULL; } long sz = ftell(mtlFile); if(fseek(mtlFile, 0, SEEK_SET) != 0){ fileError(filename, "seek"); + return NULL; } char* bytes = malloc(sz + 1); if(fread(bytes, sz, 1, mtlFile) != 1){ fileError(filename, "read"); + return NULL; } bytes[sz] = '\0'; hashTable* result = initHashTable(objCount); @@ -609,18 +621,22 @@ hashTable* readWavefront(char* filename, hashTable* materials, unsigned int side } if(fseek(fp, 0, SEEK_END) != 0){ fileError(filename, "seek"); + return NULL; } long sz = ftell(fp); if(fseek(fp, 0, SEEK_SET) != 0){ fileError(filename, "seek"); + return NULL; } char* bytes = malloc(sz + 1); if(fread(bytes, sz, 1, fp) != 1){ fileError(filename, "read"); + return NULL; } bytes[sz] = '\0'; //done to fix an invalid read if(fclose(fp) == EOF){ fileError(filename, "closed"); + return NULL; } hashTable* result = initHashTable(objCount); char* token = strtok(bytes, "\n"); @@ -670,6 +686,7 @@ hashTable* readWavefront(char* filename, hashTable* materials, unsigned int side char* name = strchr(token, ' '); if(name == NULL){ parsingError(filename, "object definition parsing; no space found") + return NULL; } name++; //these two lines cause a very weird memory error @@ -682,6 +699,7 @@ hashTable* readWavefront(char* filename, hashTable* materials, unsigned int side float z; if(sscanf(token, "v %f %f %f", &x, &y, &z) != 3){ parsingError(filename, "vertex definition parsing") + return NULL; } if(newObject.vertices == NULL){ newObject.vertices = malloc(sizeof(vertex)); diff --git a/src/lib/regionParser.c b/src/lib/regionParser.c index 8e02b41..7f09f4d 100644 --- a/src/lib/regionParser.c +++ b/src/lib/regionParser.c @@ -149,6 +149,7 @@ chunk* getChunks(FILE* regionFile){ } else{ parsingError("region file", "first segment"); + return NULL; } } chunks[i] = newChunk; @@ -157,6 +158,7 @@ chunk* getChunks(FILE* regionFile){ for(int i = 0; i < chunkN; i++){ if(handleSecondSegment(&chunks[i], regionFile) != 0 && !chunkIsNull(chunks[i])){ parsingError("region file", "second segment"); + return NULL; } } //Then there's encoded chunk data in n*4096 byte long chunks @@ -188,12 +190,14 @@ chunk getChunk(int x, int z, FILE* regionFile, char* regionFileName){ result.z = z; if(fseek(regionFile, offset, SEEK_SET) != 0){ fileError("region file", "seek"); + return result; } if(handleFirstSegment(&result, regionFile, regionFileName) != 0){ return result; } if(fseek(regionFile, offset + segmentLength, SEEK_SET) != 0){ fileError("region file", "seek"); + return result; } if(handleSecondSegment(&result, regionFile) != 0){ return result; @@ -215,17 +219,21 @@ chunk extractChunk(char* regionDirPath, int x, int z){ FILE* regionFile = fopen(filename, "rb"); if(regionFile == NULL){ fileError(filename, "located"); + return (chunk){0}; } chunk ourChunk = getChunk(x, z, regionFile, filename); //I could use errno here, or rework getChunk so that it returns an errno value, but I like it this way better if(chunkIsNull(ourChunk)){ parsingError(filename, "parsing of the first segment; chunk isn't saved") + return ourChunk; } else if(ourChunk.offset == -1){ parsingError(filename, "parsing of the first segment; chunk offset is corrupted and larger than filesize") + return ourChunk; } else if(ourChunk.timestamp < 0){ parsingError(filename, "parsing of the second segment") + return ourChunk; } free(filename); fclose(regionFile); diff --git a/src/modelGenerator.c b/src/modelGenerator.c index 11af7d5..e6e9702 100644 --- a/src/modelGenerator.c +++ b/src/modelGenerator.c @@ -27,6 +27,7 @@ int main(int argc, char** argv){ if(argc < 2){ argCountError("modelGenerator ..."); + errorCheck("argCountError"); } bool yLim = false; //if we wan't to remove some verticality int upLim = 0; //y+ cutoff @@ -42,6 +43,7 @@ int main(int argc, char** argv){ if(strcmp(argv[i], "-l") == 0){ if(argc <= i + 2){ argError("-l", "2"); + errorCheck("argError"); } yLim = true; upLim = atoi(argv[i + 1]); @@ -62,6 +64,7 @@ int main(int argc, char** argv){ else if(strcmp(argv[i], "-s") == 0){ if(argc <= i + 1){ argError("-s", "1"); + errorCheck("argError"); } side = atoi(argv[i + 1]); i+=1; @@ -69,6 +72,7 @@ int main(int argc, char** argv){ else if(strcmp(argv[i], "-m") == 0){ if(argc <= i + 1){ argError("-m", "1"); + errorCheck("argError"); } materialFilename = argv[i + 1]; i += 1; @@ -76,6 +80,7 @@ int main(int argc, char** argv){ else if(strcmp(argv[i], "-o") == 0){ if(argc <= i + 1){ argError("-o", "1"); + errorCheck("argError"); } objFilename = argv[i + 1]; i += 1; @@ -83,6 +88,7 @@ int main(int argc, char** argv){ else if(strcmp(argv[i], "-out") == 0){ if(argc <= i + 1){ argError("-out", "1"); + errorCheck("argError"); } outFilename = argv[i + 1]; i += 1; @@ -93,6 +99,7 @@ int main(int argc, char** argv){ if(materialFilename != NULL){ //parse the material file, after-all we have to account for transparent textures materials = getMaterials(materialFilename); + errorCheck("getMaterials"); } /*Note on the objects So generally the workflow looks thusly: file->sections->blocks->cubes->objects->model @@ -105,41 +112,44 @@ int main(int argc, char** argv){ hashTable* objects = NULL; //special objects if(objFilename != NULL){ objects = readWavefront(objFilename, materials, side); + errorCheck("getMaterials"); } //Get the nbt data FILE* nbtFile = fopen(argv[1], "rb"); if(nbtFile == NULL){ - fileError(argv[1], "located"); + errorCheck("fopen"); } if(fseek(nbtFile, 0L, SEEK_END) != 0){ - fileError(argv[1], "seek"); + errorCheck("fseek"); } long sz = ftell(nbtFile); if(fseek(nbtFile, 0, SEEK_SET) != 0){ - fileError(argv[1], "seek"); + errorCheck("fseek"); } unsigned char* data = malloc(sz); //raw NBT file bytes if(fread(data, sz, 1, nbtFile) != 1){ - fileError(argv[1], "read"); + errorCheck("fread"); } if(fclose(nbtFile) == EOF){ - fileError(argv[1], "closed"); + errorCheck("fclose"); } model newModel = generateFromNbt(data, sz, materials, objects, yLim, upLim, downLim, b, f, side, 0, 0); + errorCheck("generateFromNbt"); size_t size = 0; //chunk can hold a maximum of 98304 objects char* content = generateModel(&newModel, &size, materialFilename, NULL); + errorCheck("generateModel"); freeModel(&newModel); printf("Model string generated\n"); FILE* outFile = fopen(outFilename, "w"); if(outFile == NULL){ - fileError(outFilename, "opened"); + errorCheck("fileError"); } if(fwrite(content, size, 1, outFile) != 1){ - fileError(outFilename, "written"); + errorCheck("fwrite"); } if(fclose(outFile) == EOF){ - fileError(outFilename, "closed"); + errorCheck("fclose"); } free(content); return EXIT_SUCCESS; diff --git a/src/radiusGenerator.c b/src/radiusGenerator.c index 066d9d9..938225e 100644 --- a/src/radiusGenerator.c +++ b/src/radiusGenerator.c @@ -123,6 +123,7 @@ int main(int argc, char** argv){ //very similar to modelGenerator if(argc < 5){ argCountError("radiusGenerator "); + errorCheck("argCountError"); } bool yLim = false; //if we want to int upLim = 0; @@ -137,11 +138,13 @@ int main(int argc, char** argv){ int radius = atoi(argv[4]); if(radius < 0){ argValError("radius"); + errorCheck("argValError"); } for(int i = 5; i < argc; i++){ if(strcmp(argv[i], "-l") == 0){ if(argc <= i + 2){ argError("-l", "2"); + errorCheck("argError"); } yLim = true; upLim = atoi(argv[i + 1]); @@ -156,6 +159,7 @@ int main(int argc, char** argv){ else if(strcmp(argv[i], "-s") == 0){ if(argc <= i + 1){ argError("-s", "1"); + errorCheck("argError"); } side = atoi(argv[i + 1]); i+=1; @@ -163,6 +167,7 @@ int main(int argc, char** argv){ else if(strcmp(argv[i], "-m") == 0){ if(argc <= i + 1){ argError("-m", "1"); + errorCheck("argError"); } materialFilename = argv[i + 1]; i += 1; @@ -170,6 +175,7 @@ int main(int argc, char** argv){ else if(strcmp(argv[i], "-o") == 0){ if(argc <= i + 1){ argError("-o", "1"); + errorCheck("argError"); } objFilename = argv[i + 1]; i += 1; @@ -177,6 +183,7 @@ int main(int argc, char** argv){ else if(strcmp(argv[i], "-out") == 0){ if(argc <= i + 1){ argError("-out", "1"); + errorCheck("argError"); } outFilename = argv[i + 1]; i += 1; @@ -186,10 +193,12 @@ int main(int argc, char** argv){ hashTable* materials = NULL; if(materialFilename != NULL){ materials = getMaterials(materialFilename); + errorCheck("getMaterials"); } hashTable* objects = NULL; //special objects if(objFilename != NULL){ objects = readWavefront(objFilename, materials, side); + errorCheck("readWavefront"); } //matches the counter after the double for loop has run it's course @@ -213,14 +222,17 @@ int main(int argc, char** argv){ } else{ shmError("offset mmap"); + errorCheck("shmError"); } //Unnamed shared semaphore sem_t *sem = sharedMalloc(sizeof(sem_t)); if(sem == MAP_FAILED){ shmError("semaphore map"); + errorCheck("shmError"); } if(sem_init(sem, 1, 1) < 0){ semaphoreError("main", "be initialized"); + errorCheck("semaphoreError"); } //and now the big thing pid_t parentId = getpid(); @@ -234,6 +246,7 @@ int main(int argc, char** argv){ fd[i] = calloc(2, sizeof(int)); if(pipe(fd[i]) < 0){ pipeError("", "creation"); + errorCheck("pipeError"); } } int counter = 0; @@ -272,16 +285,19 @@ int main(int argc, char** argv){ int shmid = shmget(parentId + counter, size, 0644 | IPC_CREAT | IPC_EXCL); if(shmid < 0){ shmError("shmget"); + errorCheck("shmError"); } char* shmBuffer = (char*)shmat(shmid, NULL, 0); if(shmBuffer == NULL){ shmError("shmat"); + errorCheck("shmError"); } //Ok so we created the shared buffer now we can write to it strcpy(shmBuffer, modelStr); //And then we pipe over the size so that the other side can prepare itself for reading if(write(fd[counter][WRITE_END], &size, sizeof(size_t)) != sizeof(size_t)){ pipeError("child", "writing size"); + errorCheck("pipeError"); } close(fd[counter][WRITE_END]); free(modelStr); @@ -289,6 +305,7 @@ int main(int argc, char** argv){ } else{ forkError("chunk"); + errorCheck("forkError"); } } } @@ -324,19 +341,23 @@ int main(int argc, char** argv){ ssize_t res = read(fd[childNum][READ_END], &size, sizeof(size_t)); if(res < 0){ pipeError("parent", "reading 1"); + errorCheck("pipeError"); } if(size < 1){ pipeError("parent", "reading-size value invalid"); + errorCheck("pipeError"); } parts[childNum] = malloc(size); close(fd[childNum][READ_END]); int shmid = shmget(parentId + childNum, size, 0644); if(shmid < 0){ shmError("parent shmget"); + errorCheck("shmError"); } char* shmBuffer = (char*)shmat(shmid, NULL, 0); if(shmBuffer == NULL){ shmError("parent shmat"); + errorCheck("shmError"); } strcpy(parts[childNum], shmBuffer); shmdt(shmBuffer); diff --git a/tests/hTable.check b/tests/hTable.check index 67594c1..80797a7 100644 --- a/tests/hTable.check +++ b/tests/hTable.check @@ -21,7 +21,7 @@ int* val = (int*)getVal(testTable, key); ck_assert_msg(*val == 127, "Got the wrong value back"); } - freeHashTable(testTable); + freeHashTable(testTable, NULL); #test updateTest hashTable* testTable = initHashTable(2000); @@ -34,7 +34,7 @@ //If the returned values don't match something was inserted ck_assert_msg(oldSize == newSize, "Sizes differ"); } - freeHashTable(testTable); + freeHashTable(testTable, NULL); #test readingTest hashTable* testTable = initHashTable(2000); @@ -53,7 +53,7 @@ int* val = (int*)getVal(testTable, key); ck_assert_msg(*val == i, "Got the wrong value back"); } - freeHashTable(testTable); + freeHashTable(testTable, NULL); #test arrayTest hashTable* testTable = initHashTable(2000); @@ -75,4 +75,4 @@ int* oldI = getVal(testTable, key); ck_assert_msg(*oldI == val, "Val != i"); } - freeHashTable(testTable); \ No newline at end of file + freeHashTable(testTable, NULL); \ No newline at end of file