diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 8dfb15314..78155d5da 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -477,7 +477,7 @@ def build_struct(struct): if size != 1: row.append('%s, ' % size ) row.append('sizeof(%s), ' % ftype) - if field['is_c_array']: + if is_c_array: row.append('true') else: row[-1] = row[-1][:-2] else: row[-1] = row[-1][:-2] @@ -734,22 +734,22 @@ def get_function_signature(function): with open('autogen/lua_definitions/functions.lua') as f: lines = f.readlines() function_params = [] - function_return = None + function_returns = [] for line in lines: if line.startswith('--- @param'): function_params.append(line.split()[2:4]) elif line.startswith('--- @return'): - function_return = line.split()[2] + function_returns.append(line.split()[2]) elif line.startswith('function'): sig = 'fun(' sig += ', '.join(['%s: %s' % (param_name, param_type) for param_name, param_type in function_params]) sig += ')' - if function_return: - sig += ': %s' % (function_return) + if function_returns: + sig += ': %s' % (", ".join(function_returns)) function_name = line.replace('(', ' ').split()[1] function_signatures[function_name] = sig function_params.clear() - function_return = None + function_returns = [] return function_signatures.get(function, 'function') def def_struct(struct): diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index 1050eaab8..e1b0fba0c 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -4667,10 +4667,10 @@ MOD_FS_COMPRESSION_MAX = 9 MOD_FS_COMPRESSION_DEFAULT = 1 --- @type integer -MOD_FS_MAX_SIZE = 0x2000000 +MOD_FS_MAX_SIZE = 0x8000000 --- @type integer -MOD_FS_MAX_FILES = 0x200 +MOD_FS_MAX_FILES = 0x400 --- @type integer MOD_FS_MAX_PATH = 0x100 @@ -4681,6 +4681,55 @@ MOD_FS_URI_PREFIX = "modfs:/" --- @type string MOD_FS_URI_FORMAT = "modfs:/%s/%s" +MOD_FS_ERR_NONE = 0 --- @type ModFsErrorCode +MOD_FS_ERR_ALLOC_FAILED = 1 --- @type ModFsErrorCode +MOD_FS_ERR_ALREADY_EXISTS = 2 --- @type ModFsErrorCode +MOD_FS_ERR_NOT_FOUND = 3 --- @type ModFsErrorCode +MOD_FS_ERR_INVALID_POINTER = 4 --- @type ModFsErrorCode +MOD_FS_ERR_INVALID_PARAMETER = 5 --- @type ModFsErrorCode +MOD_FS_ERR_FILE_INVALID_INDEX = 6 --- @type ModFsErrorCode +MOD_FS_ERR_FILE_TYPE_NOT_ALLOWED = 7 --- @type ModFsErrorCode +MOD_FS_ERR_TOTAL_SIZE_EXCEEDED = 8 --- @type ModFsErrorCode +MOD_FS_ERR_NUM_FILES_EXCEEDED = 9 --- @type ModFsErrorCode +MOD_FS_ERR_FILEPATH_EMPTY = 10 --- @type ModFsErrorCode +MOD_FS_ERR_FILEPATH_LEN_EXCEEDED = 11 --- @type ModFsErrorCode +MOD_FS_ERR_FILEPATH_RESERVED = 12 --- @type ModFsErrorCode +MOD_FS_ERR_FILEPATH_INVALID_CHAR = 13 --- @type ModFsErrorCode +MOD_FS_ERR_FILEPATH_MALFORMED = 14 --- @type ModFsErrorCode +MOD_FS_ERR_FILEPATH_INVALID_EXTENSION = 15 --- @type ModFsErrorCode +MOD_FS_ERR_READ_INVALID_MODPATH = 16 --- @type ModFsErrorCode +MOD_FS_ERR_READ_ZIP = 17 --- @type ModFsErrorCode +MOD_FS_ERR_READ_PROPERTIES = 18 --- @type ModFsErrorCode +MOD_FS_ERR_READ_FILE_TRUNCATED = 19 --- @type ModFsErrorCode +MOD_FS_ERR_READ_EOF = 20 --- @type ModFsErrorCode +MOD_FS_ERR_WRITE_ZIP = 21 --- @type ModFsErrorCode +MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD = 22 --- @type ModFsErrorCode + +--- @alias ModFsErrorCode +--- | `MOD_FS_ERR_NONE` +--- | `MOD_FS_ERR_ALLOC_FAILED` +--- | `MOD_FS_ERR_ALREADY_EXISTS` +--- | `MOD_FS_ERR_NOT_FOUND` +--- | `MOD_FS_ERR_INVALID_POINTER` +--- | `MOD_FS_ERR_INVALID_PARAMETER` +--- | `MOD_FS_ERR_FILE_INVALID_INDEX` +--- | `MOD_FS_ERR_FILE_TYPE_NOT_ALLOWED` +--- | `MOD_FS_ERR_TOTAL_SIZE_EXCEEDED` +--- | `MOD_FS_ERR_NUM_FILES_EXCEEDED` +--- | `MOD_FS_ERR_FILEPATH_EMPTY` +--- | `MOD_FS_ERR_FILEPATH_LEN_EXCEEDED` +--- | `MOD_FS_ERR_FILEPATH_RESERVED` +--- | `MOD_FS_ERR_FILEPATH_INVALID_CHAR` +--- | `MOD_FS_ERR_FILEPATH_MALFORMED` +--- | `MOD_FS_ERR_FILEPATH_INVALID_EXTENSION` +--- | `MOD_FS_ERR_READ_INVALID_MODPATH` +--- | `MOD_FS_ERR_READ_ZIP` +--- | `MOD_FS_ERR_READ_PROPERTIES` +--- | `MOD_FS_ERR_READ_FILE_TRUNCATED` +--- | `MOD_FS_ERR_READ_EOF` +--- | `MOD_FS_ERR_WRITE_ZIP` +--- | `MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD` + INT_TYPE_U8 = 0 --- @type ModFsFileIntType INT_TYPE_U16 = 1 --- @type ModFsFileIntType INT_TYPE_U32 = 2 --- @type ModFsFileIntType diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index c3309bfd2..44290c2f6 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -7783,6 +7783,7 @@ end --- @param modPath? string --- @return boolean +--- @return ModFsErrorCode err --- Checks the existence of a modfs at path `modPath` or for the active mod if not provided. Checking for the existence of a private modfs will return false, even if it exists function mod_fs_exists(modPath) -- ... @@ -7790,6 +7791,7 @@ end --- @param modPath? string --- @return ModFs +--- @return ModFsErrorCode err --- Gets the modfs object at path `modPath` or the active mod one if not provided. This function will return nil for a private modfs, even if it exists function mod_fs_get(modPath) -- ... @@ -7797,12 +7799,14 @@ end --- @param modPath? string --- @return ModFs +--- @return ModFsErrorCode err --- Reloads the modfs object at path `modPath`. This function will return nil for a private modfs, even if it exists function mod_fs_reload(modPath) -- ... end --- @return ModFs +--- @return ModFsErrorCode err --- Creates a modfs object for the active mod if it doesn't exist. Returns the modfs object on success function mod_fs_create() -- ... @@ -7811,6 +7815,7 @@ end --- @param modFs ModFs --- @param index integer --- @return string +--- @return ModFsErrorCode err --- Gets the filename at position `index` of the provided `modFs` function mod_fs_get_filename(modFs, index) -- ... @@ -7819,6 +7824,7 @@ end --- @param modFs ModFs --- @param filepath string --- @return ModFsFile +--- @return ModFsErrorCode err --- Gets the file object at path `filepath` of the provided `modFs`. This function will return nil for a private modfs file, even if it exists function mod_fs_get_file(modFs, filepath) -- ... @@ -7828,6 +7834,7 @@ end --- @param filepath string --- @param text boolean --- @return ModFsFile +--- @return ModFsErrorCode err --- Creates a new file at path `filepath` for the provided `modFs`. Set `text` to true to treat the file as a pure text file, not a binary file. Returns the created file on success function mod_fs_create_file(modFs, filepath, text) -- ... @@ -7838,6 +7845,7 @@ end --- @param newpath string --- @param overwriteExisting boolean --- @return boolean +--- @return ModFsErrorCode err --- Moves the file at path `oldpath` to `newpath` of the provided `modFs`. Set `overwriteExisting` to true to overwrite the file at path `newpath` if it exists. Returns true on success function mod_fs_move_file(modFs, oldpath, newpath, overwriteExisting) -- ... @@ -7848,6 +7856,7 @@ end --- @param dstpath string --- @param overwriteExisting boolean --- @return boolean +--- @return ModFsErrorCode err --- Copies the file at path `srcpath` to `dstpath` of the provided `modFs`. Set `overwriteExisting` to true to overwrite the file at path `dstpath` if it exists. Returns true on success function mod_fs_copy_file(modFs, srcpath, dstpath, overwriteExisting) -- ... @@ -7856,6 +7865,7 @@ end --- @param modFs ModFs --- @param filepath string --- @return boolean +--- @return ModFsErrorCode err --- Deletes the file at path `filepath` of the provided `modFs`. Returns true on success function mod_fs_delete_file(modFs, filepath) -- ... @@ -7863,6 +7873,7 @@ end --- @param modFs ModFs --- @return boolean +--- @return ModFsErrorCode err --- Deletes all files of the provided `modFs`. Returns true on success function mod_fs_clear(modFs) -- ... @@ -7870,6 +7881,7 @@ end --- @param modFs ModFs --- @return boolean +--- @return ModFsErrorCode err --- Saves the provided `modFs` to persistent storage. Returns true on success function mod_fs_save(modFs) -- ... @@ -7877,6 +7889,7 @@ end --- @param modFs ModFs --- @return boolean +--- @return ModFsErrorCode err --- Removes the provided `modFs` from persistent storage and deletes its object. Returns true on success function mod_fs_delete(modFs) -- ... @@ -7885,6 +7898,7 @@ end --- @param modFs ModFs --- @param pub boolean --- @return boolean +--- @return ModFsErrorCode err --- Marks the provided `modFs` as public (i.e. readable by other mods). Returns true on success function mod_fs_set_public(modFs, pub) -- ... @@ -7892,6 +7906,7 @@ end --- @param file ModFsFile --- @return boolean +--- @return ModFsErrorCode err --- Reads a boolean from a binary modfs `file` function mod_fs_file_read_bool(file) -- ... @@ -7900,6 +7915,7 @@ end --- @param file ModFsFile --- @param intType ModFsFileIntType --- @return integer +--- @return ModFsErrorCode err --- Reads an integer from a binary modfs `file`. `intType` must be one of the `INT_TYPE_*` constants function mod_fs_file_read_integer(file, intType) -- ... @@ -7908,6 +7924,7 @@ end --- @param file ModFsFile --- @param floatType ModFsFileFloatType --- @return number +--- @return ModFsErrorCode err --- Reads an floating-point number from a binary modfs `file`. `floatType` must be one of the `FLOAT_TYPE_*` constants function mod_fs_file_read_number(file, floatType) -- ... @@ -7916,6 +7933,7 @@ end --- @param file ModFsFile --- @param length integer --- @return string +--- @return ModFsErrorCode err --- Reads a bytestring of `length` bytes from a binary modfs `file` function mod_fs_file_read_bytes(file, length) -- ... @@ -7923,6 +7941,7 @@ end --- @param file ModFsFile --- @return string +--- @return ModFsErrorCode err --- Reads a string from a binary modfs `file`, or read the whole content of a text modfs `file` function mod_fs_file_read_string(file) -- ... @@ -7930,6 +7949,7 @@ end --- @param file ModFsFile --- @return string +--- @return ModFsErrorCode err --- Reads a line from a text modfs `file` function mod_fs_file_read_line(file) -- ... @@ -7938,6 +7958,7 @@ end --- @param file ModFsFile --- @param value boolean --- @return boolean +--- @return ModFsErrorCode err --- Writes a boolean to a binary modfs `file`. Returns true on success function mod_fs_file_write_bool(file, value) -- ... @@ -7947,6 +7968,7 @@ end --- @param value integer --- @param intType ModFsFileIntType --- @return boolean +--- @return ModFsErrorCode err --- Writes an integer to a binary modfs `file`. `intType` must be one of the `INT_TYPE_*` constants. Returns true on success function mod_fs_file_write_integer(file, value, intType) -- ... @@ -7956,6 +7978,7 @@ end --- @param value number --- @param floatType ModFsFileFloatType --- @return boolean +--- @return ModFsErrorCode err --- Writes an floating-point number to a binary modfs `file`. `floatType` must be one of the `FLOAT_TYPE_*` constants. Returns true on success function mod_fs_file_write_number(file, value, floatType) -- ... @@ -7964,6 +7987,7 @@ end --- @param file ModFsFile --- @param bytestring string --- @return boolean +--- @return ModFsErrorCode err --- Writes a bytestring to a modfs `file`. Returns true on success function mod_fs_file_write_bytes(file, bytestring) -- ... @@ -7972,6 +7996,7 @@ end --- @param file ModFsFile --- @param str string --- @return boolean +--- @return ModFsErrorCode err --- Writes a string to a modfs `file`. Returns true on success function mod_fs_file_write_string(file, str) -- ... @@ -7980,6 +8005,7 @@ end --- @param file ModFsFile --- @param str string --- @return boolean +--- @return ModFsErrorCode err --- Writes a line to a text modfs `file`. Returns true on success function mod_fs_file_write_line(file, str) -- ... @@ -7989,6 +8015,7 @@ end --- @param offset integer --- @param origin ModFsFileSeek --- @return boolean +--- @return ModFsErrorCode err --- Sets the current position of a modfs `file`.
--- If `origin` is `FILE_SEEK_SET`, file position is set to `offset`.
--- If `origin` is `FILE_SEEK_CUR`, `offset` is added to file current position.
@@ -8000,6 +8027,7 @@ end --- @param file ModFsFile --- @return boolean +--- @return ModFsErrorCode err --- Sets the current position of a modfs `file` to its beginning.
--- Returns true on success function mod_fs_file_rewind(file) @@ -8008,6 +8036,7 @@ end --- @param file ModFsFile --- @return boolean +--- @return ModFsErrorCode err --- Returns true if the provided modfs `file` has reached its end of file function mod_fs_file_is_eof(file) -- ... @@ -8017,6 +8046,7 @@ end --- @param byte integer --- @param length integer --- @return boolean +--- @return ModFsErrorCode err --- Fills a modfs `file` with `byte` repeated `length` times. Returns true on success function mod_fs_file_fill(file, byte, length) -- ... @@ -8025,6 +8055,7 @@ end --- @param file ModFsFile --- @param length integer --- @return boolean +--- @return ModFsErrorCode err --- Erases `length` bytes or characters from a modfs `file`. Returns true on success function mod_fs_file_erase(file, length) -- ... @@ -8033,6 +8064,7 @@ end --- @param file ModFsFile --- @param text boolean --- @return boolean +--- @return ModFsErrorCode err --- Marks the provided modfs `file` as text. Returns true on success function mod_fs_file_set_text_mode(file, text) -- ... @@ -8041,6 +8073,7 @@ end --- @param file ModFsFile --- @param pub boolean --- @return boolean +--- @return ModFsErrorCode err --- Marks the provided modfs `file` as public (i.e. readable by other mods). Returns true on success function mod_fs_file_set_public(file, pub) -- ... @@ -8049,7 +8082,8 @@ end --- @param file ModFsFile --- @param level integer --- @return boolean ---- Sets the compression level of the provided modfs `file`. Must be between 0 (no compression) and 9 (most compression). Returns true on success. +--- @return ModFsErrorCode err +--- Sets the compression level of the provided modfs `file`. Must be between 0 (no compression) and 9 (most compression). Returns true on success function mod_fs_file_set_compression(file, level) -- ... end @@ -8060,6 +8094,12 @@ function mod_fs_hide_errors(hide) -- ... end +--- @return ModFsErrorCode +--- Returns the last error code raised by `mod_fs` functions +function mod_fs_get_last_error_code() + -- ... +end + --- @return string --- Returns the last error message generated by `mod_fs` functions or nil if no error occurred function mod_fs_get_last_error() diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 9489cfe05..320cb79c0 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -1208,16 +1208,16 @@ --- @field public numFiles integer --- @field public totalSize integer --- @field public isPublic boolean ---- @field public get_filename fun(modFs: ModFs, index: integer): string ---- @field public get_file fun(modFs: ModFs, filepath: string): ModFsFile ---- @field public create_file fun(modFs: ModFs, filepath: string, text: boolean): ModFsFile ---- @field public move_file fun(modFs: ModFs, oldpath: string, newpath: string, overwriteExisting: boolean): boolean ---- @field public copy_file fun(modFs: ModFs, srcpath: string, dstpath: string, overwriteExisting: boolean): boolean ---- @field public delete_file fun(modFs: ModFs, filepath: string): boolean ---- @field public clear fun(modFs: ModFs): boolean ---- @field public save fun(modFs: ModFs): boolean ---- @field public delete fun(modFs: ModFs): boolean ---- @field public set_public fun(modFs: ModFs, pub: boolean): boolean +--- @field public get_filename fun(modFs: ModFs, index: integer): string, ModFsErrorCode +--- @field public get_file fun(modFs: ModFs, filepath: string): ModFsFile, ModFsErrorCode +--- @field public create_file fun(modFs: ModFs, filepath: string, text: boolean): ModFsFile, ModFsErrorCode +--- @field public move_file fun(modFs: ModFs, oldpath: string, newpath: string, overwriteExisting: boolean): boolean, ModFsErrorCode +--- @field public copy_file fun(modFs: ModFs, srcpath: string, dstpath: string, overwriteExisting: boolean): boolean, ModFsErrorCode +--- @field public delete_file fun(modFs: ModFs, filepath: string): boolean, ModFsErrorCode +--- @field public clear fun(modFs: ModFs): boolean, ModFsErrorCode +--- @field public save fun(modFs: ModFs): boolean, ModFsErrorCode +--- @field public delete fun(modFs: ModFs): boolean, ModFsErrorCode +--- @field public set_public fun(modFs: ModFs, pub: boolean): boolean, ModFsErrorCode --- @class ModFsFile --- @field public modFs ModFs @@ -1227,26 +1227,26 @@ --- @field public compressionLevel integer --- @field public isText boolean --- @field public isPublic boolean ---- @field public read_bool fun(file: ModFsFile): boolean ---- @field public read_integer fun(file: ModFsFile, intType: ModFsFileIntType): integer ---- @field public read_number fun(file: ModFsFile, floatType: ModFsFileFloatType): number ---- @field public read_bytes fun(file: ModFsFile, length: integer): string ---- @field public read_string fun(file: ModFsFile): string ---- @field public read_line fun(file: ModFsFile): string ---- @field public write_bool fun(file: ModFsFile, value: boolean): boolean ---- @field public write_integer fun(file: ModFsFile, value: integer, intType: ModFsFileIntType): boolean ---- @field public write_number fun(file: ModFsFile, value: number, floatType: ModFsFileFloatType): boolean ---- @field public write_bytes fun(file: ModFsFile, bytestring: string): boolean ---- @field public write_string fun(file: ModFsFile, str: string): boolean ---- @field public write_line fun(file: ModFsFile, str: string): boolean ---- @field public seek fun(file: ModFsFile, offset: integer, origin: ModFsFileSeek): boolean ---- @field public rewind fun(file: ModFsFile): boolean ---- @field public is_eof fun(file: ModFsFile): boolean ---- @field public fill fun(file: ModFsFile, byte: integer, length: integer): boolean ---- @field public erase fun(file: ModFsFile, length: integer): boolean ---- @field public set_text_mode fun(file: ModFsFile, text: boolean): boolean ---- @field public set_public fun(file: ModFsFile, pub: boolean): boolean ---- @field public set_compression fun(file: ModFsFile, level: integer): boolean +--- @field public read_bool fun(file: ModFsFile): boolean, ModFsErrorCode +--- @field public read_integer fun(file: ModFsFile, intType: ModFsFileIntType): integer, ModFsErrorCode +--- @field public read_number fun(file: ModFsFile, floatType: ModFsFileFloatType): number, ModFsErrorCode +--- @field public read_bytes fun(file: ModFsFile, length: integer): string, ModFsErrorCode +--- @field public read_string fun(file: ModFsFile): string, ModFsErrorCode +--- @field public read_line fun(file: ModFsFile): string, ModFsErrorCode +--- @field public write_bool fun(file: ModFsFile, value: boolean): boolean, ModFsErrorCode +--- @field public write_integer fun(file: ModFsFile, value: integer, intType: ModFsFileIntType): boolean, ModFsErrorCode +--- @field public write_number fun(file: ModFsFile, value: number, floatType: ModFsFileFloatType): boolean, ModFsErrorCode +--- @field public write_bytes fun(file: ModFsFile, bytestring: string): boolean, ModFsErrorCode +--- @field public write_string fun(file: ModFsFile, str: string): boolean, ModFsErrorCode +--- @field public write_line fun(file: ModFsFile, str: string): boolean, ModFsErrorCode +--- @field public seek fun(file: ModFsFile, offset: integer, origin: ModFsFileSeek): boolean, ModFsErrorCode +--- @field public rewind fun(file: ModFsFile): boolean, ModFsErrorCode +--- @field public is_eof fun(file: ModFsFile): boolean, ModFsErrorCode +--- @field public fill fun(file: ModFsFile, byte: integer, length: integer): boolean, ModFsErrorCode +--- @field public erase fun(file: ModFsFile, length: integer): boolean, ModFsErrorCode +--- @field public set_text_mode fun(file: ModFsFile, text: boolean): boolean, ModFsErrorCode +--- @field public set_public fun(file: ModFsFile, pub: boolean): boolean, ModFsErrorCode +--- @field public set_compression fun(file: ModFsFile, level: integer): boolean, ModFsErrorCode --- @class NametagsSettings --- @field public showHealth boolean diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 9ca604dd7..27371be13 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -57,6 +57,7 @@ - [enum MarioCapGSCId](#enum-MarioCapGSCId) - [enum MarioGrabPosGSCId](#enum-MarioGrabPosGSCId) - [mod_fs.h](#mod_fsh) + - [enum ModFsErrorCode](#enum-ModFsErrorCode) - [enum ModFsFileIntType](#enum-ModFsFileIntType) - [enum ModFsFileFloatType](#enum-ModFsFileFloatType) - [enum ModFsFileSeek](#enum-ModFsFileSeek) @@ -2229,6 +2230,33 @@ - MOD_FS_URI_PREFIX - MOD_FS_URI_FORMAT +### [enum ModFsErrorCode](#ModFsErrorCode) +| Identifier | Value | +| :--------- | :---- | +| MOD_FS_ERR_NONE | 0 | +| MOD_FS_ERR_ALLOC_FAILED | 1 | +| MOD_FS_ERR_ALREADY_EXISTS | 2 | +| MOD_FS_ERR_NOT_FOUND | 3 | +| MOD_FS_ERR_INVALID_POINTER | 4 | +| MOD_FS_ERR_INVALID_PARAMETER | 5 | +| MOD_FS_ERR_FILE_INVALID_INDEX | 6 | +| MOD_FS_ERR_FILE_TYPE_NOT_ALLOWED | 7 | +| MOD_FS_ERR_TOTAL_SIZE_EXCEEDED | 8 | +| MOD_FS_ERR_NUM_FILES_EXCEEDED | 9 | +| MOD_FS_ERR_FILEPATH_EMPTY | 10 | +| MOD_FS_ERR_FILEPATH_LEN_EXCEEDED | 11 | +| MOD_FS_ERR_FILEPATH_RESERVED | 12 | +| MOD_FS_ERR_FILEPATH_INVALID_CHAR | 13 | +| MOD_FS_ERR_FILEPATH_MALFORMED | 14 | +| MOD_FS_ERR_FILEPATH_INVALID_EXTENSION | 15 | +| MOD_FS_ERR_READ_INVALID_MODPATH | 16 | +| MOD_FS_ERR_READ_ZIP | 17 | +| MOD_FS_ERR_READ_PROPERTIES | 18 | +| MOD_FS_ERR_READ_FILE_TRUNCATED | 19 | +| MOD_FS_ERR_READ_EOF | 20 | +| MOD_FS_ERR_WRITE_ZIP | 21 | +| MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD | 22 | + ### [enum ModFsFileIntType](#ModFsFileIntType) | Identifier | Value | | :--------- | :---- | diff --git a/docs/lua/functions-5.md b/docs/lua/functions-5.md index dd8e633d2..d3c9a85ff 100644 --- a/docs/lua/functions-5.md +++ b/docs/lua/functions-5.md @@ -1336,7 +1336,7 @@ Linearly interpolates `res` between `a` and `b` with `delta` Checks the existence of a modfs at path `modPath` or for the active mod if not provided. Checking for the existence of a private modfs will return false, even if it exists ### Lua Example -`local booleanValue = mod_fs_exists(modPath)` +`local booleanValue, err = mod_fs_exists(modPath)` ### Parameters | Field | Type | @@ -1345,9 +1345,10 @@ Checks the existence of a modfs at path `modPath` or for the active mod if not p ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_exists(OPTIONAL const char *modPath);` +`bool mod_fs_exists(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1359,7 +1360,7 @@ Checks the existence of a modfs at path `modPath` or for the active mod if not p Gets the modfs object at path `modPath` or the active mod one if not provided. This function will return nil for a private modfs, even if it exists ### Lua Example -`local modFsValue = mod_fs_get(modPath)` +`local modFsValue, err = mod_fs_get(modPath)` ### Parameters | Field | Type | @@ -1368,9 +1369,10 @@ Gets the modfs object at path `modPath` or the active mod one if not provided. T ### Returns - [ModFs](structs.md#ModFs) +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`struct ModFs *mod_fs_get(OPTIONAL const char *modPath);` +`struct ModFs *mod_fs_get(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1382,7 +1384,7 @@ Gets the modfs object at path `modPath` or the active mod one if not provided. T Reloads the modfs object at path `modPath`. This function will return nil for a private modfs, even if it exists ### Lua Example -`local modFsValue = mod_fs_reload(modPath)` +`local modFsValue, err = mod_fs_reload(modPath)` ### Parameters | Field | Type | @@ -1391,9 +1393,10 @@ Reloads the modfs object at path `modPath`. This function will return nil for a ### Returns - [ModFs](structs.md#ModFs) +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`struct ModFs *mod_fs_reload(OPTIONAL const char *modPath);` +`struct ModFs *mod_fs_reload(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1405,16 +1408,17 @@ Reloads the modfs object at path `modPath`. This function will return nil for a Creates a modfs object for the active mod if it doesn't exist. Returns the modfs object on success ### Lua Example -`local modFsValue = mod_fs_create()` +`local modFsValue, err = mod_fs_create()` ### Parameters - None ### Returns - [ModFs](structs.md#ModFs) +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`struct ModFs *mod_fs_create();` +`struct ModFs *mod_fs_create(RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1426,7 +1430,7 @@ Creates a modfs object for the active mod if it doesn't exist. Returns the modfs Gets the filename at position `index` of the provided `modFs` ### Lua Example -`local stringValue = mod_fs_get_filename(modFs, index)` +`local stringValue, err = mod_fs_get_filename(modFs, index)` ### Parameters | Field | Type | @@ -1436,9 +1440,10 @@ Gets the filename at position `index` of the provided `modFs` ### Returns - `string` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`const char *mod_fs_get_filename(struct ModFs *modFs, u16 index);` +`const char *mod_fs_get_filename(struct ModFs *modFs, u16 index, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1450,7 +1455,7 @@ Gets the filename at position `index` of the provided `modFs` Gets the file object at path `filepath` of the provided `modFs`. This function will return nil for a private modfs file, even if it exists ### Lua Example -`local modFsFileValue = mod_fs_get_file(modFs, filepath)` +`local modFsFileValue, err = mod_fs_get_file(modFs, filepath)` ### Parameters | Field | Type | @@ -1460,9 +1465,10 @@ Gets the file object at path `filepath` of the provided `modFs`. This function w ### Returns - [ModFsFile](structs.md#ModFsFile) +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`struct ModFsFile *mod_fs_get_file(struct ModFs *modFs, const char *filepath);` +`struct ModFsFile *mod_fs_get_file(struct ModFs *modFs, const char *filepath, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1474,7 +1480,7 @@ Gets the file object at path `filepath` of the provided `modFs`. This function w Creates a new file at path `filepath` for the provided `modFs`. Set `text` to true to treat the file as a pure text file, not a binary file. Returns the created file on success ### Lua Example -`local modFsFileValue = mod_fs_create_file(modFs, filepath, text)` +`local modFsFileValue, err = mod_fs_create_file(modFs, filepath, text)` ### Parameters | Field | Type | @@ -1485,9 +1491,10 @@ Creates a new file at path `filepath` for the provided `modFs`. Set `text` to tr ### Returns - [ModFsFile](structs.md#ModFsFile) +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *filepath, bool text);` +`struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *filepath, bool text, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1499,7 +1506,7 @@ Creates a new file at path `filepath` for the provided `modFs`. Set `text` to tr Moves the file at path `oldpath` to `newpath` of the provided `modFs`. Set `overwriteExisting` to true to overwrite the file at path `newpath` if it exists. Returns true on success ### Lua Example -`local booleanValue = mod_fs_move_file(modFs, oldpath, newpath, overwriteExisting)` +`local booleanValue, err = mod_fs_move_file(modFs, oldpath, newpath, overwriteExisting)` ### Parameters | Field | Type | @@ -1511,9 +1518,10 @@ Moves the file at path `oldpath` to `newpath` of the provided `modFs`. Set `over ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_move_file(struct ModFs *modFs, const char *oldpath, const char *newpath, bool overwriteExisting);` +`bool mod_fs_move_file(struct ModFs *modFs, const char *oldpath, const char *newpath, bool overwriteExisting, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1525,7 +1533,7 @@ Moves the file at path `oldpath` to `newpath` of the provided `modFs`. Set `over Copies the file at path `srcpath` to `dstpath` of the provided `modFs`. Set `overwriteExisting` to true to overwrite the file at path `dstpath` if it exists. Returns true on success ### Lua Example -`local booleanValue = mod_fs_copy_file(modFs, srcpath, dstpath, overwriteExisting)` +`local booleanValue, err = mod_fs_copy_file(modFs, srcpath, dstpath, overwriteExisting)` ### Parameters | Field | Type | @@ -1537,9 +1545,10 @@ Copies the file at path `srcpath` to `dstpath` of the provided `modFs`. Set `ove ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const char *dstpath, bool overwriteExisting);` +`bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const char *dstpath, bool overwriteExisting, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1551,7 +1560,7 @@ Copies the file at path `srcpath` to `dstpath` of the provided `modFs`. Set `ove Deletes the file at path `filepath` of the provided `modFs`. Returns true on success ### Lua Example -`local booleanValue = mod_fs_delete_file(modFs, filepath)` +`local booleanValue, err = mod_fs_delete_file(modFs, filepath)` ### Parameters | Field | Type | @@ -1561,9 +1570,10 @@ Deletes the file at path `filepath` of the provided `modFs`. Returns true on suc ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_delete_file(struct ModFs *modFs, const char *filepath);` +`bool mod_fs_delete_file(struct ModFs *modFs, const char *filepath, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1575,7 +1585,7 @@ Deletes the file at path `filepath` of the provided `modFs`. Returns true on suc Deletes all files of the provided `modFs`. Returns true on success ### Lua Example -`local booleanValue = mod_fs_clear(modFs)` +`local booleanValue, err = mod_fs_clear(modFs)` ### Parameters | Field | Type | @@ -1584,9 +1594,10 @@ Deletes all files of the provided `modFs`. Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_clear(struct ModFs *modFs);` +`bool mod_fs_clear(struct ModFs *modFs, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1598,7 +1609,7 @@ Deletes all files of the provided `modFs`. Returns true on success Saves the provided `modFs` to persistent storage. Returns true on success ### Lua Example -`local booleanValue = mod_fs_save(modFs)` +`local booleanValue, err = mod_fs_save(modFs)` ### Parameters | Field | Type | @@ -1607,9 +1618,10 @@ Saves the provided `modFs` to persistent storage. Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_save(struct ModFs *modFs);` +`bool mod_fs_save(struct ModFs *modFs, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1621,7 +1633,7 @@ Saves the provided `modFs` to persistent storage. Returns true on success Removes the provided `modFs` from persistent storage and deletes its object. Returns true on success ### Lua Example -`local booleanValue = mod_fs_delete(modFs)` +`local booleanValue, err = mod_fs_delete(modFs)` ### Parameters | Field | Type | @@ -1630,9 +1642,10 @@ Removes the provided `modFs` from persistent storage and deletes its object. Ret ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_delete(struct ModFs *modFs);` +`bool mod_fs_delete(struct ModFs *modFs, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1644,7 +1657,7 @@ Removes the provided `modFs` from persistent storage and deletes its object. Ret Marks the provided `modFs` as public (i.e. readable by other mods). Returns true on success ### Lua Example -`local booleanValue = mod_fs_set_public(modFs, pub)` +`local booleanValue, err = mod_fs_set_public(modFs, pub)` ### Parameters | Field | Type | @@ -1654,9 +1667,10 @@ Marks the provided `modFs` as public (i.e. readable by other mods). Returns true ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_set_public(struct ModFs *modFs, bool pub);` +`bool mod_fs_set_public(struct ModFs *modFs, bool pub, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1668,7 +1682,7 @@ Marks the provided `modFs` as public (i.e. readable by other mods). Returns true Reads a boolean from a binary modfs `file` ### Lua Example -`local booleanValue = mod_fs_file_read_bool(file)` +`local booleanValue, err = mod_fs_file_read_bool(file)` ### Parameters | Field | Type | @@ -1677,9 +1691,10 @@ Reads a boolean from a binary modfs `file` ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_read_bool(struct ModFsFile *file);` +`bool mod_fs_file_read_bool(struct ModFsFile *file, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1691,7 +1706,7 @@ Reads a boolean from a binary modfs `file` Reads an integer from a binary modfs `file`. `intType` must be one of the `INT_TYPE_*` constants ### Lua Example -`local integerValue = mod_fs_file_read_integer(file, intType)` +`local integerValue, err = mod_fs_file_read_integer(file, intType)` ### Parameters | Field | Type | @@ -1701,9 +1716,10 @@ Reads an integer from a binary modfs `file`. `intType` must be one of the `INT_T ### Returns - `integer` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`lua_Integer mod_fs_file_read_integer(struct ModFsFile *file, enum ModFsFileIntType intType);` +`lua_Integer mod_fs_file_read_integer(struct ModFsFile *file, enum ModFsFileIntType intType, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1715,7 +1731,7 @@ Reads an integer from a binary modfs `file`. `intType` must be one of the `INT_T Reads an floating-point number from a binary modfs `file`. `floatType` must be one of the `FLOAT_TYPE_*` constants ### Lua Example -`local numberValue = mod_fs_file_read_number(file, floatType)` +`local numberValue, err = mod_fs_file_read_number(file, floatType)` ### Parameters | Field | Type | @@ -1725,9 +1741,10 @@ Reads an floating-point number from a binary modfs `file`. `floatType` must be o ### Returns - `number` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`lua_Number mod_fs_file_read_number(struct ModFsFile *file, enum ModFsFileFloatType floatType);` +`lua_Number mod_fs_file_read_number(struct ModFsFile *file, enum ModFsFileFloatType floatType, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1739,7 +1756,7 @@ Reads an floating-point number from a binary modfs `file`. `floatType` must be o Reads a bytestring of `length` bytes from a binary modfs `file` ### Lua Example -`local stringValue = mod_fs_file_read_bytes(file, length)` +`local stringValue, err = mod_fs_file_read_bytes(file, length)` ### Parameters | Field | Type | @@ -1749,9 +1766,10 @@ Reads a bytestring of `length` bytes from a binary modfs `file` ### Returns - `string` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`ByteString mod_fs_file_read_bytes(struct ModFsFile *file, u32 length);` +`ByteString mod_fs_file_read_bytes(struct ModFsFile *file, u32 length, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1763,7 +1781,7 @@ Reads a bytestring of `length` bytes from a binary modfs `file` Reads a string from a binary modfs `file`, or read the whole content of a text modfs `file` ### Lua Example -`local stringValue = mod_fs_file_read_string(file)` +`local stringValue, err = mod_fs_file_read_string(file)` ### Parameters | Field | Type | @@ -1772,9 +1790,10 @@ Reads a string from a binary modfs `file`, or read the whole content of a text m ### Returns - `string` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`const char *mod_fs_file_read_string(struct ModFsFile *file);` +`const char *mod_fs_file_read_string(struct ModFsFile *file, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1786,7 +1805,7 @@ Reads a string from a binary modfs `file`, or read the whole content of a text m Reads a line from a text modfs `file` ### Lua Example -`local stringValue = mod_fs_file_read_line(file)` +`local stringValue, err = mod_fs_file_read_line(file)` ### Parameters | Field | Type | @@ -1795,9 +1814,10 @@ Reads a line from a text modfs `file` ### Returns - `string` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`const char *mod_fs_file_read_line(struct ModFsFile *file);` +`const char *mod_fs_file_read_line(struct ModFsFile *file, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1809,7 +1829,7 @@ Reads a line from a text modfs `file` Writes a boolean to a binary modfs `file`. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_write_bool(file, value)` +`local booleanValue, err = mod_fs_file_write_bool(file, value)` ### Parameters | Field | Type | @@ -1819,9 +1839,10 @@ Writes a boolean to a binary modfs `file`. Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_write_bool(struct ModFsFile *file, bool value);` +`bool mod_fs_file_write_bool(struct ModFsFile *file, bool value, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1833,7 +1854,7 @@ Writes a boolean to a binary modfs `file`. Returns true on success Writes an integer to a binary modfs `file`. `intType` must be one of the `INT_TYPE_*` constants. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_write_integer(file, value, intType)` +`local booleanValue, err = mod_fs_file_write_integer(file, value, intType)` ### Parameters | Field | Type | @@ -1844,9 +1865,10 @@ Writes an integer to a binary modfs `file`. `intType` must be one of the `INT_TY ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_write_integer(struct ModFsFile *file, lua_Integer value, enum ModFsFileIntType intType);` +`bool mod_fs_file_write_integer(struct ModFsFile *file, lua_Integer value, enum ModFsFileIntType intType, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1858,7 +1880,7 @@ Writes an integer to a binary modfs `file`. `intType` must be one of the `INT_TY Writes an floating-point number to a binary modfs `file`. `floatType` must be one of the `FLOAT_TYPE_*` constants. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_write_number(file, value, floatType)` +`local booleanValue, err = mod_fs_file_write_number(file, value, floatType)` ### Parameters | Field | Type | @@ -1869,9 +1891,10 @@ Writes an floating-point number to a binary modfs `file`. `floatType` must be on ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_write_number(struct ModFsFile *file, lua_Number value, enum ModFsFileFloatType floatType);` +`bool mod_fs_file_write_number(struct ModFsFile *file, lua_Number value, enum ModFsFileFloatType floatType, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1883,7 +1906,7 @@ Writes an floating-point number to a binary modfs `file`. `floatType` must be on Writes a bytestring to a modfs `file`. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_write_bytes(file, bytestring)` +`local booleanValue, err = mod_fs_file_write_bytes(file, bytestring)` ### Parameters | Field | Type | @@ -1893,9 +1916,10 @@ Writes a bytestring to a modfs `file`. Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_write_bytes(struct ModFsFile *file, ByteString bytestring);` +`bool mod_fs_file_write_bytes(struct ModFsFile *file, ByteString bytestring, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1907,7 +1931,7 @@ Writes a bytestring to a modfs `file`. Returns true on success Writes a string to a modfs `file`. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_write_string(file, str)` +`local booleanValue, err = mod_fs_file_write_string(file, str)` ### Parameters | Field | Type | @@ -1917,9 +1941,10 @@ Writes a string to a modfs `file`. Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_write_string(struct ModFsFile *file, const char *str);` +`bool mod_fs_file_write_string(struct ModFsFile *file, const char *str, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1931,7 +1956,7 @@ Writes a string to a modfs `file`. Returns true on success Writes a line to a text modfs `file`. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_write_line(file, str)` +`local booleanValue, err = mod_fs_file_write_line(file, str)` ### Parameters | Field | Type | @@ -1941,9 +1966,10 @@ Writes a line to a text modfs `file`. Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_write_line(struct ModFsFile *file, const char *str);` +`bool mod_fs_file_write_line(struct ModFsFile *file, const char *str, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1959,7 +1985,7 @@ If `origin` is `FILE_SEEK_END`, file position is set to `end of file + offset`. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_seek(file, offset, origin)` +`local booleanValue, err = mod_fs_file_seek(file, offset, origin)` ### Parameters | Field | Type | @@ -1970,9 +1996,10 @@ Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFileSeek origin);` +`bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFileSeek origin, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -1985,7 +2012,7 @@ Sets the current position of a modfs `file` to its beginning. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_rewind(file)` +`local booleanValue, err = mod_fs_file_rewind(file)` ### Parameters | Field | Type | @@ -1994,9 +2021,10 @@ Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_rewind(struct ModFsFile *file);` +`bool mod_fs_file_rewind(struct ModFsFile *file, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -2008,7 +2036,7 @@ Returns true on success Returns true if the provided modfs `file` has reached its end of file ### Lua Example -`local booleanValue = mod_fs_file_is_eof(file)` +`local booleanValue, err = mod_fs_file_is_eof(file)` ### Parameters | Field | Type | @@ -2017,9 +2045,10 @@ Returns true if the provided modfs `file` has reached its end of file ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_is_eof(struct ModFsFile *file);` +`bool mod_fs_file_is_eof(struct ModFsFile *file, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -2031,7 +2060,7 @@ Returns true if the provided modfs `file` has reached its end of file Fills a modfs `file` with `byte` repeated `length` times. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_fill(file, byte, length)` +`local booleanValue, err = mod_fs_file_fill(file, byte, length)` ### Parameters | Field | Type | @@ -2042,9 +2071,10 @@ Fills a modfs `file` with `byte` repeated `length` times. Returns true on succes ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_fill(struct ModFsFile *file, u8 byte, u32 length);` +`bool mod_fs_file_fill(struct ModFsFile *file, u8 byte, u32 length, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -2056,7 +2086,7 @@ Fills a modfs `file` with `byte` repeated `length` times. Returns true on succes Erases `length` bytes or characters from a modfs `file`. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_erase(file, length)` +`local booleanValue, err = mod_fs_file_erase(file, length)` ### Parameters | Field | Type | @@ -2066,9 +2096,10 @@ Erases `length` bytes or characters from a modfs `file`. Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_erase(struct ModFsFile *file, u32 length);` +`bool mod_fs_file_erase(struct ModFsFile *file, u32 length, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -2080,7 +2111,7 @@ Erases `length` bytes or characters from a modfs `file`. Returns true on success Marks the provided modfs `file` as text. Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_set_text_mode(file, text)` +`local booleanValue, err = mod_fs_file_set_text_mode(file, text)` ### Parameters | Field | Type | @@ -2090,9 +2121,10 @@ Marks the provided modfs `file` as text. Returns true on success ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text);` +`bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -2104,7 +2136,7 @@ Marks the provided modfs `file` as text. Returns true on success Marks the provided modfs `file` as public (i.e. readable by other mods). Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_set_public(file, pub)` +`local booleanValue, err = mod_fs_file_set_public(file, pub)` ### Parameters | Field | Type | @@ -2114,9 +2146,10 @@ Marks the provided modfs `file` as public (i.e. readable by other mods). Returns ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_set_public(struct ModFsFile *file, bool pub);` +`bool mod_fs_file_set_public(struct ModFsFile *file, bool pub, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -2125,10 +2158,10 @@ Marks the provided modfs `file` as public (i.e. readable by other mods). Returns ## [mod_fs_file_set_compression](#mod_fs_file_set_compression) ### Description -Sets the compression level of the provided modfs `file`. Must be between 0 (no compression) and 9 (most compression). Returns true on success. +Sets the compression level of the provided modfs `file`. Must be between 0 (no compression) and 9 (most compression). Returns true on success ### Lua Example -`local booleanValue = mod_fs_file_set_compression(file, level)` +`local booleanValue, err = mod_fs_file_set_compression(file, level)` ### Parameters | Field | Type | @@ -2138,9 +2171,10 @@ Sets the compression level of the provided modfs `file`. Must be between 0 (no c ### Returns - `boolean` +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) ### C Prototype -`bool mod_fs_file_set_compression(struct ModFsFile *file, s32 level);` +`bool mod_fs_file_set_compression(struct ModFsFile *file, s32 level, RET enum ModFsErrorCode *err);` [:arrow_up_small:](#) @@ -2169,6 +2203,27 @@ Hides script errors raised by `mod_fs` functions. Errors messages are still gene
+## [mod_fs_get_last_error_code](#mod_fs_get_last_error_code) + +### Description +Returns the last error code raised by `mod_fs` functions + +### Lua Example +`local enumValue = mod_fs_get_last_error_code()` + +### Parameters +- None + +### Returns +- [enum ModFsErrorCode](constants.md#enum-ModFsErrorCode) + +### C Prototype +`enum ModFsErrorCode mod_fs_get_last_error_code();` + +[:arrow_up_small:](#) + +
+ ## [mod_fs_get_last_error](#mod_fs_get_last_error) ### Description diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 35ac3c04e..c6e312cf8 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1411,6 +1411,7 @@ - [mod_fs_file_set_public](functions-5.md#mod_fs_file_set_public) - [mod_fs_file_set_compression](functions-5.md#mod_fs_file_set_compression) - [mod_fs_hide_errors](functions-5.md#mod_fs_hide_errors) + - [mod_fs_get_last_error_code](functions-5.md#mod_fs_get_last_error_code) - [mod_fs_get_last_error](functions-5.md#mod_fs_get_last_error)
diff --git a/docs/lua/guides/modfs.md b/docs/lua/guides/modfs.md index 5e840db63..70a55044c 100644 --- a/docs/lua/guides/modfs.md +++ b/docs/lua/guides/modfs.md @@ -12,8 +12,8 @@ Each mod has its own file system, and can allow other mods to read its files. ### File system Each ModFS file system: -- Has a maximum size of **32 MB** (`MOD_FS_MAX_SIZE`). Files can be any size, as long as the cumulative sum of file sizes doesn't exceed this limit. -- Can store at most **512 files** (`MOD_FS_MAX_FILES`). +- Has a maximum size of **128 MB** (`MOD_FS_MAX_SIZE`). Files can be any size, as long as the cumulative sum of file sizes doesn't exceed this limit. +- Can store at most **1024 files** (`MOD_FS_MAX_FILES`). - Is stored on disk as a `.modfs` file, which is a ZIP file, containing all files written in it. The ModFS files are located in the `sav` directory at the usual save file location: @@ -25,7 +25,7 @@ The ModFS files are located in the `sav` directory at the usual save file locati - The maximum filepath length is **256 characters** (`MOD_FS_MAX_PATH`), including the NUL terminator. - Filepaths have the following restrictions: - - Cannot start, end or have two or more consecutive `/` + - Cannot start or end with whitespaces or slashes `/`, and cannot have two or more consecutive slashes `/` - Can contain only valid ASCII characters, no `*` or `\` - Cannot be called `properties.json` (this name is reserved for ModFS internal properties) - Only the following extensions (and extension-less files) are allowed: @@ -141,6 +141,7 @@ print("The ModFS file " .. file.filepath .. " is now empty.") All errors coming from ModFS functions are not blocking. However, they appear in the console and raise the "Mod has script errors" message. - The function [`mod_fs_hide_errors`](../functions-5.md#mod_fs_hide_errors) can suppress the ModFS errors from the console. +- Use the function [`mod_fs_get_last_error_code`](../functions-5.md#mod_fs_get_last_error_code) to retrieve the last error code raised by ModFS. This function always return an error code if an error occurred, even if errors are hidden. - Use the function [`mod_fs_get_last_error`](../functions-5.md#mod_fs_get_last_error) to retrieve the last error raised by ModFS. This function always return an error message if an error occurred, even if errors are hidden.
@@ -255,10 +256,41 @@ file:write_string("some text") ### Handle possible failures -In addition to error messages that can be retrieved with [`mod_fs_get_last_error`](../functions-5.md#mod_fs_get_last_error), almost all ModFS functions have a boolean return value indicating if the function succeeded or failed. +In addition to error messages that can be retrieved with [`mod_fs_get_last_error`](../functions-5.md#mod_fs_get_last_error), all ModFS functions return an error code as second return value. The error code can be one of the following: + +|Error code|Description| +|-|-| +|`MOD_FS_ERR_ALLOC_FAILED`|Memory allocation failed| +|`MOD_FS_ERR_ALREADY_EXISTS`|Tried to create, move or copy an existing ModFS or ModFS file| +|`MOD_FS_ERR_NOT_FOUND`|Tried to move, copy or delete a non-existent ModFS file| +|`MOD_FS_ERR_INVALID_POINTER`|Passed an invalid ModFS or ModFS file pointer| +|`MOD_FS_ERR_INVALID_PARAMETER`|Passed an invalid parameter value| +|`MOD_FS_ERR_FILE_INVALID_INDEX`|Tried to get the filename of an out-of-bounds file index| +|`MOD_FS_ERR_FILE_TYPE_NOT_ALLOWED`|Tried to use a read/write function on a non-supported file type| +|`MOD_FS_ERR_TOTAL_SIZE_EXCEEDED`|Tried to read, copy or write past the maximum size of a ModFS| +|`MOD_FS_ERR_NUM_FILES_EXCEEDED`|Tried to read or create more files than allowed for a ModFS| +|`MOD_FS_ERR_FILEPATH_EMPTY`|Empty filepath| +|`MOD_FS_ERR_FILEPATH_LEN_EXCEEDED`|Filepath too long| +|`MOD_FS_ERR_FILEPATH_RESERVED`|Filepath is reserved and cannot be used for ModFS files| +|`MOD_FS_ERR_FILEPATH_INVALID_CHAR`|Filepath contains invalid characters (non-ASCII, control characters, asterisk or backslash)| +|`MOD_FS_ERR_FILEPATH_MALFORMED`|Filepath is malformed (leading/trailing whitespaces/slashes, consecutive slashes)| +|`MOD_FS_ERR_FILEPATH_INVALID_EXTENSION`|Filepath extension is not in whitelist| +|`MOD_FS_ERR_READ_INVALID_MODPATH`|Modpath couldn't be resolved| +|`MOD_FS_ERR_READ_ZIP`|ZIP decompression failed| +|`MOD_FS_ERR_READ_PROPERTIES`|Properties file JSON is malformed| +|`MOD_FS_ERR_READ_FILE_TRUNCATED`|Read data didn't match the expected size| +|`MOD_FS_ERR_READ_EOF`|Reached end of file while reading| +|`MOD_FS_ERR_WRITE_ZIP`|ZIP compression failed| +|`MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD`|Tried to perform a write operation (create, delete, move, copy, write, set) on another mod ModFS or ModFS file| + +Along with the return value of the function, use this error code to handle errors properly: ```lua -if not modFs:delete_file("somefile") then - print(mod_fs_get_last_error()) +local ok, err = modFs:delete_file("somefile") +if not ok then + print(err, mod_fs_get_last_error()) + if err == MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD then + print("Do not delete other mods ModFS files!") + end end ``` diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index ec2922c1b..e58b133c8 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -2285,11 +2285,34 @@ const char gSmluaConstants[] = "" "MOD_FS_COMPRESSION_MIN=0\n" "MOD_FS_COMPRESSION_MAX=9\n" "MOD_FS_COMPRESSION_DEFAULT=1\n" -"MOD_FS_MAX_SIZE=0x2000000\n" -"MOD_FS_MAX_FILES=0x200\n" +"MOD_FS_MAX_SIZE=0x8000000\n" +"MOD_FS_MAX_FILES=0x400\n" "MOD_FS_MAX_PATH=0x100\n" "MOD_FS_URI_PREFIX='modfs:/'\n" "MOD_FS_URI_FORMAT='modfs:/%s/%s'\n" +"MOD_FS_ERR_NONE=0\n" +"MOD_FS_ERR_ALLOC_FAILED=1\n" +"MOD_FS_ERR_ALREADY_EXISTS=2\n" +"MOD_FS_ERR_NOT_FOUND=3\n" +"MOD_FS_ERR_INVALID_POINTER=4\n" +"MOD_FS_ERR_INVALID_PARAMETER=5\n" +"MOD_FS_ERR_FILE_INVALID_INDEX=6\n" +"MOD_FS_ERR_FILE_TYPE_NOT_ALLOWED=7\n" +"MOD_FS_ERR_TOTAL_SIZE_EXCEEDED=8\n" +"MOD_FS_ERR_NUM_FILES_EXCEEDED=9\n" +"MOD_FS_ERR_FILEPATH_EMPTY=10\n" +"MOD_FS_ERR_FILEPATH_LEN_EXCEEDED=11\n" +"MOD_FS_ERR_FILEPATH_RESERVED=12\n" +"MOD_FS_ERR_FILEPATH_INVALID_CHAR=13\n" +"MOD_FS_ERR_FILEPATH_MALFORMED=14\n" +"MOD_FS_ERR_FILEPATH_INVALID_EXTENSION=15\n" +"MOD_FS_ERR_READ_INVALID_MODPATH=16\n" +"MOD_FS_ERR_READ_ZIP=17\n" +"MOD_FS_ERR_READ_PROPERTIES=18\n" +"MOD_FS_ERR_READ_FILE_TRUNCATED=19\n" +"MOD_FS_ERR_READ_EOF=20\n" +"MOD_FS_ERR_WRITE_ZIP=21\n" +"MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD=22\n" "INT_TYPE_U8=0\n" "INT_TYPE_U16=1\n" "INT_TYPE_U32=2\n" diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 2b05d1a9c..7ffbcc23e 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -22516,9 +22516,13 @@ int smlua_func_mod_fs_exists(lua_State* L) { if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_exists"); return 0; } } - lua_pushboolean(L, mod_fs_exists(modPath)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_exists(modPath, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_get(lua_State* L) { @@ -22536,9 +22540,13 @@ int smlua_func_mod_fs_get(lua_State* L) { if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_get"); return 0; } } - smlua_push_object(L, LOT_MODFS, mod_fs_get(modPath), NULL); + enum ModFsErrorCode err; - return 1; + smlua_push_object(L, LOT_MODFS, mod_fs_get(modPath, &err), NULL); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_reload(lua_State* L) { @@ -22556,9 +22564,13 @@ int smlua_func_mod_fs_reload(lua_State* L) { if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_reload"); return 0; } } - smlua_push_object(L, LOT_MODFS, mod_fs_reload(modPath), NULL); + enum ModFsErrorCode err; - return 1; + smlua_push_object(L, LOT_MODFS, mod_fs_reload(modPath, &err), NULL); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_create(lua_State* L) { @@ -22571,9 +22583,13 @@ int smlua_func_mod_fs_create(lua_State* L) { } - smlua_push_object(L, LOT_MODFS, mod_fs_create(), NULL); + enum ModFsErrorCode err; - return 1; + smlua_push_object(L, LOT_MODFS, mod_fs_create(&err), NULL); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_get_filename(lua_State* L) { @@ -22590,9 +22606,13 @@ int smlua_func_mod_fs_get_filename(lua_State* L) { u16 index = smlua_to_integer(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_get_filename"); return 0; } - lua_pushstring(L, mod_fs_get_filename(modFs, index)); + enum ModFsErrorCode err; - return 1; + lua_pushstring(L, mod_fs_get_filename(modFs, index, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_get_file(lua_State* L) { @@ -22609,9 +22629,13 @@ int smlua_func_mod_fs_get_file(lua_State* L) { const char* filepath = smlua_to_string(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_get_file"); return 0; } - smlua_push_object(L, LOT_MODFSFILE, mod_fs_get_file(modFs, filepath), NULL); + enum ModFsErrorCode err; - return 1; + smlua_push_object(L, LOT_MODFSFILE, mod_fs_get_file(modFs, filepath, &err), NULL); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_create_file(lua_State* L) { @@ -22630,9 +22654,13 @@ int smlua_func_mod_fs_create_file(lua_State* L) { bool text = smlua_to_boolean(L, 3); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "mod_fs_create_file"); return 0; } - smlua_push_object(L, LOT_MODFSFILE, mod_fs_create_file(modFs, filepath, text), NULL); + enum ModFsErrorCode err; - return 1; + smlua_push_object(L, LOT_MODFSFILE, mod_fs_create_file(modFs, filepath, text, &err), NULL); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_move_file(lua_State* L) { @@ -22653,9 +22681,13 @@ int smlua_func_mod_fs_move_file(lua_State* L) { bool overwriteExisting = smlua_to_boolean(L, 4); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "mod_fs_move_file"); return 0; } - lua_pushboolean(L, mod_fs_move_file(modFs, oldpath, newpath, overwriteExisting)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_move_file(modFs, oldpath, newpath, overwriteExisting, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_copy_file(lua_State* L) { @@ -22676,9 +22708,13 @@ int smlua_func_mod_fs_copy_file(lua_State* L) { bool overwriteExisting = smlua_to_boolean(L, 4); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "mod_fs_copy_file"); return 0; } - lua_pushboolean(L, mod_fs_copy_file(modFs, srcpath, dstpath, overwriteExisting)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_copy_file(modFs, srcpath, dstpath, overwriteExisting, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_delete_file(lua_State* L) { @@ -22695,9 +22731,13 @@ int smlua_func_mod_fs_delete_file(lua_State* L) { const char* filepath = smlua_to_string(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_delete_file"); return 0; } - lua_pushboolean(L, mod_fs_delete_file(modFs, filepath)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_delete_file(modFs, filepath, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_clear(lua_State* L) { @@ -22712,9 +22752,13 @@ int smlua_func_mod_fs_clear(lua_State* L) { struct ModFs* modFs = (struct ModFs*)smlua_to_cobject(L, 1, LOT_MODFS); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_clear"); return 0; } - lua_pushboolean(L, mod_fs_clear(modFs)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_clear(modFs, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_save(lua_State* L) { @@ -22729,9 +22773,13 @@ int smlua_func_mod_fs_save(lua_State* L) { struct ModFs* modFs = (struct ModFs*)smlua_to_cobject(L, 1, LOT_MODFS); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_save"); return 0; } - lua_pushboolean(L, mod_fs_save(modFs)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_save(modFs, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_delete(lua_State* L) { @@ -22746,9 +22794,13 @@ int smlua_func_mod_fs_delete(lua_State* L) { struct ModFs* modFs = (struct ModFs*)smlua_to_cobject(L, 1, LOT_MODFS); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_delete"); return 0; } - lua_pushboolean(L, mod_fs_delete(modFs)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_delete(modFs, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_set_public(lua_State* L) { @@ -22765,9 +22817,13 @@ int smlua_func_mod_fs_set_public(lua_State* L) { bool pub = smlua_to_boolean(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_set_public"); return 0; } - lua_pushboolean(L, mod_fs_set_public(modFs, pub)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_set_public(modFs, pub, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_read_bool(lua_State* L) { @@ -22782,9 +22838,13 @@ int smlua_func_mod_fs_file_read_bool(lua_State* L) { struct ModFsFile* file = (struct ModFsFile*)smlua_to_cobject(L, 1, LOT_MODFSFILE); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_file_read_bool"); return 0; } - lua_pushboolean(L, mod_fs_file_read_bool(file)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_read_bool(file, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_read_integer(lua_State* L) { @@ -22801,9 +22861,13 @@ int smlua_func_mod_fs_file_read_integer(lua_State* L) { enum ModFsFileIntType intType = smlua_to_integer(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_read_integer"); return 0; } - lua_pushinteger(L, mod_fs_file_read_integer(file, intType)); + enum ModFsErrorCode err; - return 1; + lua_pushinteger(L, mod_fs_file_read_integer(file, intType, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_read_number(lua_State* L) { @@ -22820,9 +22884,13 @@ int smlua_func_mod_fs_file_read_number(lua_State* L) { enum ModFsFileFloatType floatType = smlua_to_integer(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_read_number"); return 0; } - lua_pushnumber(L, mod_fs_file_read_number(file, floatType)); + enum ModFsErrorCode err; - return 1; + lua_pushnumber(L, mod_fs_file_read_number(file, floatType, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_read_bytes(lua_State* L) { @@ -22839,9 +22907,13 @@ int smlua_func_mod_fs_file_read_bytes(lua_State* L) { u32 length = smlua_to_integer(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_read_bytes"); return 0; } - smlua_push_bytestring(L, mod_fs_file_read_bytes(file, length)); + enum ModFsErrorCode err; - return 1; + smlua_push_bytestring(L, mod_fs_file_read_bytes(file, length, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_read_string(lua_State* L) { @@ -22856,9 +22928,13 @@ int smlua_func_mod_fs_file_read_string(lua_State* L) { struct ModFsFile* file = (struct ModFsFile*)smlua_to_cobject(L, 1, LOT_MODFSFILE); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_file_read_string"); return 0; } - lua_pushstring(L, mod_fs_file_read_string(file)); + enum ModFsErrorCode err; - return 1; + lua_pushstring(L, mod_fs_file_read_string(file, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_read_line(lua_State* L) { @@ -22873,9 +22949,13 @@ int smlua_func_mod_fs_file_read_line(lua_State* L) { struct ModFsFile* file = (struct ModFsFile*)smlua_to_cobject(L, 1, LOT_MODFSFILE); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_file_read_line"); return 0; } - lua_pushstring(L, mod_fs_file_read_line(file)); + enum ModFsErrorCode err; - return 1; + lua_pushstring(L, mod_fs_file_read_line(file, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_write_bool(lua_State* L) { @@ -22892,9 +22972,13 @@ int smlua_func_mod_fs_file_write_bool(lua_State* L) { bool value = smlua_to_boolean(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_write_bool"); return 0; } - lua_pushboolean(L, mod_fs_file_write_bool(file, value)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_write_bool(file, value, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_write_integer(lua_State* L) { @@ -22913,9 +22997,13 @@ int smlua_func_mod_fs_file_write_integer(lua_State* L) { enum ModFsFileIntType intType = smlua_to_integer(L, 3); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "mod_fs_file_write_integer"); return 0; } - lua_pushboolean(L, mod_fs_file_write_integer(file, value, intType)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_write_integer(file, value, intType, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_write_number(lua_State* L) { @@ -22934,9 +23022,13 @@ int smlua_func_mod_fs_file_write_number(lua_State* L) { enum ModFsFileFloatType floatType = smlua_to_integer(L, 3); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "mod_fs_file_write_number"); return 0; } - lua_pushboolean(L, mod_fs_file_write_number(file, value, floatType)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_write_number(file, value, floatType, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_write_bytes(lua_State* L) { @@ -22953,9 +23045,13 @@ int smlua_func_mod_fs_file_write_bytes(lua_State* L) { ByteString bytestring = smlua_to_bytestring(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_write_bytes"); return 0; } - lua_pushboolean(L, mod_fs_file_write_bytes(file, bytestring)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_write_bytes(file, bytestring, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_write_string(lua_State* L) { @@ -22972,9 +23068,13 @@ int smlua_func_mod_fs_file_write_string(lua_State* L) { const char* str = smlua_to_string(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_write_string"); return 0; } - lua_pushboolean(L, mod_fs_file_write_string(file, str)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_write_string(file, str, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_write_line(lua_State* L) { @@ -22991,9 +23091,13 @@ int smlua_func_mod_fs_file_write_line(lua_State* L) { const char* str = smlua_to_string(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_write_line"); return 0; } - lua_pushboolean(L, mod_fs_file_write_line(file, str)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_write_line(file, str, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_seek(lua_State* L) { @@ -23012,9 +23116,13 @@ int smlua_func_mod_fs_file_seek(lua_State* L) { enum ModFsFileSeek origin = smlua_to_integer(L, 3); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "mod_fs_file_seek"); return 0; } - lua_pushboolean(L, mod_fs_file_seek(file, offset, origin)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_seek(file, offset, origin, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_rewind(lua_State* L) { @@ -23029,9 +23137,13 @@ int smlua_func_mod_fs_file_rewind(lua_State* L) { struct ModFsFile* file = (struct ModFsFile*)smlua_to_cobject(L, 1, LOT_MODFSFILE); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_file_rewind"); return 0; } - lua_pushboolean(L, mod_fs_file_rewind(file)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_rewind(file, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_is_eof(lua_State* L) { @@ -23046,9 +23158,13 @@ int smlua_func_mod_fs_file_is_eof(lua_State* L) { struct ModFsFile* file = (struct ModFsFile*)smlua_to_cobject(L, 1, LOT_MODFSFILE); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_file_is_eof"); return 0; } - lua_pushboolean(L, mod_fs_file_is_eof(file)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_is_eof(file, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_fill(lua_State* L) { @@ -23067,9 +23183,13 @@ int smlua_func_mod_fs_file_fill(lua_State* L) { u32 length = smlua_to_integer(L, 3); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "mod_fs_file_fill"); return 0; } - lua_pushboolean(L, mod_fs_file_fill(file, byte, length)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_fill(file, byte, length, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_erase(lua_State* L) { @@ -23086,9 +23206,13 @@ int smlua_func_mod_fs_file_erase(lua_State* L) { u32 length = smlua_to_integer(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_erase"); return 0; } - lua_pushboolean(L, mod_fs_file_erase(file, length)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_erase(file, length, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_set_text_mode(lua_State* L) { @@ -23105,9 +23229,13 @@ int smlua_func_mod_fs_file_set_text_mode(lua_State* L) { bool text = smlua_to_boolean(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_set_text_mode"); return 0; } - lua_pushboolean(L, mod_fs_file_set_text_mode(file, text)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_set_text_mode(file, text, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_set_public(lua_State* L) { @@ -23124,9 +23252,13 @@ int smlua_func_mod_fs_file_set_public(lua_State* L) { bool pub = smlua_to_boolean(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_set_public"); return 0; } - lua_pushboolean(L, mod_fs_file_set_public(file, pub)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_set_public(file, pub, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_file_set_compression(lua_State* L) { @@ -23143,9 +23275,13 @@ int smlua_func_mod_fs_file_set_compression(lua_State* L) { s32 level = smlua_to_integer(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_set_compression"); return 0; } - lua_pushboolean(L, mod_fs_file_set_compression(file, level)); + enum ModFsErrorCode err; - return 1; + lua_pushboolean(L, mod_fs_file_set_compression(file, level, &err)); + + lua_pushinteger(L, err); + + return 2; } int smlua_func_mod_fs_hide_errors(lua_State* L) { @@ -23165,6 +23301,21 @@ int smlua_func_mod_fs_hide_errors(lua_State* L) { return 1; } +int smlua_func_mod_fs_get_last_error_code(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 0) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_get_last_error_code", 0, top); + return 0; + } + + + lua_pushinteger(L, mod_fs_get_last_error_code()); + + return 1; +} + int smlua_func_mod_fs_get_last_error(lua_State* L) { if (L == NULL) { return 0; } @@ -38589,6 +38740,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "mod_fs_file_set_public", smlua_func_mod_fs_file_set_public); smlua_bind_function(L, "mod_fs_file_set_compression", smlua_func_mod_fs_file_set_compression); smlua_bind_function(L, "mod_fs_hide_errors", smlua_func_mod_fs_hide_errors); + smlua_bind_function(L, "mod_fs_get_last_error_code", smlua_func_mod_fs_get_last_error_code); smlua_bind_function(L, "mod_fs_get_last_error", smlua_func_mod_fs_get_last_error); // mod_storage.h diff --git a/src/pc/mods/mod_fs.cpp b/src/pc/mods/mod_fs.cpp index 5dcd7fb8b..e8cac0e25 100644 --- a/src/pc/mods/mod_fs.cpp +++ b/src/pc/mods/mod_fs.cpp @@ -11,7 +11,7 @@ extern "C" { #include #include "pc/utils/json.hpp" -#define C_DEFINE extern "C" +namespace modfs { using json = nlohmann::json; static const json sEmptyJson = {}; @@ -46,18 +46,23 @@ static const char *MOD_FS_FILE_ALLOWED_EXTENSIONS[] = { // - the function that raised it usually returns false or nil static bool sModFsHideErrors = false; +static enum ModFsErrorCode sModFsLastErrorCode; static char sModFsLastError[1024]; static char sModFsErrorFunction[256]; #define mod_fs_reset_last_error() { \ - memset(sModFsLastError, 0, sizeof(sModFsLastError)); \ - snprintf(sModFsErrorFunction, sizeof(sModFsErrorFunction), "%s", __FUNCTION__); \ -} - -#define mod_fs_raise_error(fmt, ...) { \ - snprintf(sModFsLastError, sizeof(sModFsLastError), "%s: " fmt, sModFsErrorFunction, ##__VA_ARGS__); \ - if (!sModFsHideErrors) { \ - LOG_LUA_LINE("%s", sModFsLastError); \ + *err = modfs::sModFsLastErrorCode = MOD_FS_ERR_NONE; \ + memset(modfs::sModFsLastError, 0, sizeof(modfs::sModFsLastError)); \ + snprintf(modfs::sModFsErrorFunction, sizeof(modfs::sModFsErrorFunction), "%s", __FUNCTION__); \ +} + +#define mod_fs_raise_error(errcode, fmt, ...) { \ + if (!*err) { \ + sModFsLastErrorCode = *err = errcode; \ + snprintf(sModFsLastError, sizeof(sModFsLastError), "%s: " fmt, sModFsErrorFunction, ##__VA_ARGS__); \ + if (!sModFsHideErrors) { \ + LOG_LUA_LINE("%s", sModFsLastError); \ + } \ } \ } @@ -147,19 +152,21 @@ static int mod_fs_compare_filepaths(const void *l, const void *r) { return strcmp(lfile->filepath, rfile->filepath); } -static bool mod_fs_check_filepath(struct ModFs *modFs, const char *filepath) { +static bool mod_fs_check_filepath(struct ModFs *modFs, const char *filepath, enum ModFsErrorCode *err) { // check length u32 filepathLength = strlen(filepath); if (filepathLength == 0) { mod_fs_raise_error( - "modPath: %s, filepath: %s - filepath length cannot be 0", modFs->modPath, filepath + MOD_FS_ERR_FILEPATH_EMPTY, + "modPath: %s, filepath: %s - Filepath cannot be empty", modFs->modPath, filepath ); return false; } if (filepathLength > MOD_FS_MAX_PATH - 1) { mod_fs_raise_error( - "modPath: %s, filepath: %s - exceeded filepath length: %u (max is: %u)", modFs->modPath, filepath, filepathLength, MOD_FS_MAX_PATH - 1 + MOD_FS_ERR_FILEPATH_LEN_EXCEEDED, + "modPath: %s, filepath: %s - Exceeded filepath length: %u (max is: %u)", modFs->modPath, filepath, filepathLength, MOD_FS_MAX_PATH - 1 ); return false; } @@ -167,27 +174,48 @@ static bool mod_fs_check_filepath(struct ModFs *modFs, const char *filepath) { // cannot be called properties.json if (strcmp(filepath, MOD_FS_PROPERTIES) == 0) { mod_fs_raise_error( - "modPath: %s, filepath: %s - forbidden filepath: \"" MOD_FS_PROPERTIES "\" is reserved", modFs->modPath, filepath + MOD_FS_ERR_FILEPATH_RESERVED, + "modPath: %s, filepath: %s - Forbidden filepath: \"" MOD_FS_PROPERTIES "\" is reserved", modFs->modPath, filepath ); return false; } // check character validity - // only ascii chars, no control chars, no star, no backslash + // only ascii chars, no control chars, no asterisk, no backslash for (u32 i = 0; i != filepathLength; ++i) { char c = filepath[i]; if (!isascii(c) || iscntrl(c) || c == '*' || c == '\\') { mod_fs_raise_error( - "modPath: %s, filepath: %s - invalid character at position %d: '%c' (%02X)", modFs->modPath, filepath, i, c, (u8) c + MOD_FS_ERR_FILEPATH_INVALID_CHAR, + "modPath: %s, filepath: %s - Invalid character at position %d: '%c' (%02X)", modFs->modPath, filepath, i, c, (u8) c ); return false; } } + // cannot start with a whitespace + if (isspace(filepath[0])) { + mod_fs_raise_error( + MOD_FS_ERR_FILEPATH_MALFORMED, + "modPath: %s, filepath: %s - Filepath cannot start with a whitespace", modFs->modPath, filepath + ); + return false; + } + + // cannot end with a whitespace + if (isspace(filepath[filepathLength - 1])) { + mod_fs_raise_error( + MOD_FS_ERR_FILEPATH_MALFORMED, + "modPath: %s, filepath: %s - Filepath cannot end with a whitespace", modFs->modPath, filepath + ); + return false; + } + // cannot start with a slash if (filepath[0] == '/') { mod_fs_raise_error( - "modPath: %s, filepath: %s - filepath cannot start with a slash '/'", modFs->modPath, filepath + MOD_FS_ERR_FILEPATH_MALFORMED, + "modPath: %s, filepath: %s - Filepath cannot start with a slash '/'", modFs->modPath, filepath ); return false; } @@ -195,7 +223,8 @@ static bool mod_fs_check_filepath(struct ModFs *modFs, const char *filepath) { // cannot end with a slash if (filepath[filepathLength - 1] == '/') { mod_fs_raise_error( - "modPath: %s, filepath: %s - filepath cannot end with a slash '/'", modFs->modPath, filepath + MOD_FS_ERR_FILEPATH_MALFORMED, + "modPath: %s, filepath: %s - Filepath cannot end with a slash '/'", modFs->modPath, filepath ); return false; } @@ -203,7 +232,8 @@ static bool mod_fs_check_filepath(struct ModFs *modFs, const char *filepath) { // no two consecutive slashes if (strstr(filepath, "//")) { mod_fs_raise_error( - "modPath: %s, filepath: %s - two or more consecutive slashes '/' are not allowed", modFs->modPath, filepath + MOD_FS_ERR_FILEPATH_MALFORMED, + "modPath: %s, filepath: %s - Two or more consecutive slashes '/' are not allowed", modFs->modPath, filepath ); return false; } @@ -221,6 +251,7 @@ static bool mod_fs_check_filepath(struct ModFs *modFs, const char *filepath) { } if (!allowedExtension) { mod_fs_raise_error( + MOD_FS_ERR_FILEPATH_INVALID_EXTENSION, "modPath: %s, filepath: %s - file extension not allowed: %s", modFs->modPath, filepath, lastDot ); return false; @@ -230,40 +261,17 @@ static bool mod_fs_check_filepath(struct ModFs *modFs, const char *filepath) { return true; } -static bool mod_fs_check_file_content(struct ModFs *modFs, struct ModFsFile *file) { - if (!file->data.bin || file->size < 4) { - return true; - } - - // Reject Windows executable files - if (memcmp(file->data.bin, "MZ", 2) == 0) { - mod_fs_raise_error( - "modPath: %s, filepath: %s - Binary file cannot start with \"MZ\" bytes", modFs->modPath, file->filepath - ); - return false; - } - - // Reject ELF files - if (memcmp(file->data.bin, "\177ELF", 4) == 0) { - mod_fs_raise_error( - "modPath: %s, filepath: %s - Binary file cannot start with \"\\x7fELF\" bytes", modFs->modPath, file->filepath - ); - return false; - } - - return true; -} - // // ctor, dtor // -static struct ModFs *mod_fs_new() { +static struct ModFs *mod_fs_new(enum ModFsErrorCode *err) { if (gLuaActiveMod) { struct ModFs *modFs = mod_fs_alloc(); if (!modFs) { mod_fs_raise_error( - "failed to allocate modfs object" + MOD_FS_ERR_ALLOC_FAILED, + "Failed to allocate ModFS object" ); return NULL; } @@ -423,7 +431,10 @@ static bool mod_fs_file_detect_text_mode(struct ModFsFile *file) { } #define mod_fs_read_raise_error_zip() { \ - mod_fs_read_raise_error("modPath: %s - cannot read zip file: %s", modFs->modPath, mz_zip_get_error_string(mz_zip_get_last_error(zip))); \ + mod_fs_read_raise_error( \ + MOD_FS_ERR_READ_ZIP, \ + "modPath: %s - Cannot read zip file: %s", modFs->modPath, mz_zip_get_error_string(mz_zip_get_last_error(zip)) \ + ); \ } static bool mod_fs_read_properties(mz_zip_archive *zip, json &properties, std::string &error) { @@ -439,7 +450,7 @@ static bool mod_fs_read_properties(mz_zip_archive *zip, json &properties, std::s size_t fileSize; void *fileBuf = mz_zip_reader_extract_to_heap(zip, fileIndex, &fileSize, 0); if (!fileBuf) { - error = "cannot read file \"" MOD_FS_PROPERTIES "\": " + std::string(mz_zip_get_error_string(mz_zip_get_last_error(zip))); + error = "Cannot read file \"" MOD_FS_PROPERTIES "\": " + std::string(mz_zip_get_error_string(mz_zip_get_last_error(zip))); return false; } std::string textBuf((const char *) fileBuf, fileSize); @@ -449,7 +460,7 @@ static bool mod_fs_read_properties(mz_zip_archive *zip, json &properties, std::s try { properties = json::parse(textBuf); } catch (const json::parse_error& e) { - error = e.what(); + error = "Cannot read file \"" MOD_FS_PROPERTIES "\": " + std::string(e.what()); return false; } @@ -457,7 +468,7 @@ static bool mod_fs_read_properties(mz_zip_archive *zip, json &properties, std::s return true; } -static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExistenceOnly) { +static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExistenceOnly, enum ModFsErrorCode *err) { FILE *f = mod_fs_get_file_handle(modPath, "rb"); if (f) { mz_zip_archive zip[1] = {0}; @@ -466,7 +477,8 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis // get true modPath and mod if (!mod_fs_get_modpath(modPath, modFs->modPath)) { mod_fs_read_raise_error( - "unable to retrieve modPath from %s", modPath + MOD_FS_ERR_READ_INVALID_MODPATH, + "Unable to retrieve modPath from: %s", modPath ); } char activeModPath[SYS_MAX_PATH]; @@ -483,7 +495,8 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis zipBuf = malloc(zipSize); if (!zipBuf || fread(zipBuf, 1, zipSize, f) < zipSize) { mod_fs_read_raise_error( - "modPath: %s - cannot read zip file", modFs->modPath + MOD_FS_ERR_READ_ZIP, + "modPath: %s - Cannot read zip file", modFs->modPath ); } fclose(f); @@ -499,14 +512,15 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis std::string error; if (!mod_fs_read_properties(zip, properties, error)) { mod_fs_read_raise_error( + MOD_FS_ERR_READ_PROPERTIES, "modPath: %s - %s", modFs->modPath, error.c_str() ); } - // check if modfs is public + // check if ModFS is public modFs->isPublic = mod_fs_read_property(properties, { "isPublic" }, MOD_FS_IS_PUBLIC_DEFAULT); if (!mod_fs_is_active_mod(modFs) && !modFs->isPublic) { - // don't raise an error, user should not know if a private modfs file exists + // don't raise an error, user should not know if a private ModFS file exists mod_fs_read_return (false); } if (checkExistenceOnly) { @@ -531,17 +545,17 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis // check filepath const char *filepath = fileStat.m_filename; - if (!mod_fs_check_filepath(modFs, filepath)) { - mod_fs_read_raise_error( - "modPath: %s - invalid filepath: %s", modFs->modPath, filepath - ); + if (!mod_fs_check_filepath(modFs, filepath, err)) { + // mod_fs_check_filepath already sets the error + mod_fs_read_return (false); } memcpy(file.filepath, filepath, strlen(filepath)); // check file size if (fileStat.m_uncomp_size > MOD_FS_MAX_SIZE) { mod_fs_read_raise_error( - "modPath: %s, filepath: %s - exceeded file size: %llu (max is: %u)", modFs->modPath, file.filepath, (u64) fileStat.m_uncomp_size, MOD_FS_MAX_SIZE + MOD_FS_ERR_TOTAL_SIZE_EXCEEDED, + "modPath: %s, filepath: %s - Exceeded file size: %llu (max is: %u)", modFs->modPath, file.filepath, (u64) fileStat.m_uncomp_size, MOD_FS_MAX_SIZE ); } file.size = file.capacity = fileStat.m_uncomp_size; @@ -550,7 +564,8 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis modFs->totalSize += file.size; if (modFs->totalSize > MOD_FS_MAX_SIZE) { mod_fs_read_raise_error( - "modPath: %s - exceeded total size: %u (max is: %u)", modFs->modPath, modFs->totalSize, MOD_FS_MAX_SIZE + MOD_FS_ERR_TOTAL_SIZE_EXCEEDED, + "modPath: %s - Exceeded total size: %u (max is: %u)", modFs->modPath, modFs->totalSize, MOD_FS_MAX_SIZE ); } @@ -569,7 +584,8 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis // check number of files if (modFs->numFiles > MOD_FS_MAX_FILES) { mod_fs_read_raise_error( - "modPath: %s - exceeded number of files: %u (max is: %u)", modFs->modPath, numFiles, MOD_FS_MAX_FILES + MOD_FS_ERR_NUM_FILES_EXCEEDED, + "modPath: %s - Exceeded number of files: %u (max is: %u)", modFs->modPath, numFiles, MOD_FS_MAX_FILES ); } } @@ -580,7 +596,8 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis modFs->files = (struct ModFsFile **) calloc(modFs->numFiles, sizeof(struct ModFsFile *)); if (!modFs->files) { mod_fs_read_raise_error( - "modPath: %s - failed to allocate buffer for modfs files", modFs->modPath + MOD_FS_ERR_ALLOC_FAILED, + "modPath: %s - Failed to allocate buffer for ModFS files", modFs->modPath ); } } else { @@ -599,15 +616,17 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis // check file size if (fileSize != fileRef.size) { mod_fs_read_raise_error( - "modPath: %s, filepath: %s - truncated data: read size is %llu (expected: %u)", modFs->modPath, fileRef.filepath, (u64) fileSize, fileRef.size + MOD_FS_ERR_READ_FILE_TRUNCATED, + "modPath: %s, filepath: %s - Truncated data: read size is %llu (expected: %u)", modFs->modPath, fileRef.filepath, (u64) fileSize, fileRef.size ); } - // create modfs file + // create ModFS file struct ModFsFile *file = modFs->files[i] = mod_fs_alloc(); if (!file) { mod_fs_read_raise_error( - "modPath: %s, filepath: %s - failed to allocate modfs file object", modFs->modPath, file->filepath + MOD_FS_ERR_ALLOC_FAILED, + "modPath: %s, filepath: %s - Failed to allocate ModFS file object", modFs->modPath, file->filepath ); } memcpy(file, &fileRef, sizeof(struct ModFsFile)); @@ -616,7 +635,8 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis file->data.bin = (u8 *) malloc(file->capacity); if (!file->data.bin) { mod_fs_read_raise_error( - "modPath: %s, filepath: %s - failed to allocate buffer for modfs file data", modFs->modPath, file->filepath + MOD_FS_ERR_ALLOC_FAILED, + "modPath: %s, filepath: %s - Failed to allocate buffer for ModFS file data", modFs->modPath, file->filepath ); } memcpy(file->data.bin, fileBuf, file->size); @@ -628,13 +648,6 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis const json &fileProperties = mod_fs_read_properties_for_filepath(properties, file->filepath); file->isText = mod_fs_read_property(fileProperties, { "isText" }, isText); - // check file content if binary - if (!isText && !mod_fs_check_file_content(modFs, file)) { - mod_fs_read_raise_error( - "modPath: %s, filepath: %s - Invalid file data", modFs->modPath, file->filepath - ); - } - // read compressionLevel property file->compressionLevel = mod_fs_read_property(fileProperties, { "compressionLevel" }, MOD_FS_COMPRESSION_DEFAULT); } @@ -652,18 +665,21 @@ static bool mod_fs_read(const char *modPath, struct ModFs *modFs, bool checkExis // Write // -#define mod_fs_write_raise_error(...) { \ - mod_fs_raise_error("cannot save modfs for the active mod: " __VA_ARGS__); \ +#define mod_fs_write_raise_error(errcode, ...) { \ + mod_fs_raise_error(errcode, "Cannot save ModFS for the active mod: " __VA_ARGS__); \ mz_zip_writer_end(zip); \ fclose(f); \ return false; \ } #define mod_fs_write_raise_error_zip() { \ - mod_fs_write_raise_error("%s", mz_zip_get_error_string(mz_zip_get_last_error(zip))); \ + mod_fs_write_raise_error( \ + MOD_FS_ERR_WRITE_ZIP, \ + "%s", mz_zip_get_error_string(mz_zip_get_last_error(zip)) \ + ); \ } -static bool mod_fs_write(struct ModFs *modFs) { +static bool mod_fs_write(struct ModFs *modFs, enum ModFsErrorCode *err) { FILE *f = mod_fs_get_file_handle(modFs->modPath, "wb"); if (f) { mz_zip_archive zip[1] = {0}; @@ -673,18 +689,9 @@ static bool mod_fs_write(struct ModFs *modFs) { mod_fs_write_raise_error_zip(); } - // add each modfs file to the zip archive + // add each ModFS file to the zip archive for (u16 i = 0; i != modFs->numFiles; ++i) { struct ModFsFile *file = modFs->files[i]; - - // check file content before writing if binary - const bool isText = mod_fs_file_detect_text_mode(file); - if (!isText && !mod_fs_check_file_content(modFs, file)) { - mod_fs_write_raise_error( - "filepath: %s - Invalid file data", file->filepath - ); - } - if (!mz_zip_writer_add_mem(zip, file->filepath, file->data.bin, file->size, file->compressionLevel)) { mod_fs_write_raise_error_zip(); } @@ -719,40 +726,44 @@ static bool mod_fs_write(struct ModFs *modFs) { // template -static bool mod_fs_check_pointer(T *ptr, const char *typeName) { +static bool mod_fs_check_pointer(T *ptr, const char *typeName, enum ModFsErrorCode *err) { if (!mod_fs_is_valid_pointer(ptr)) { mod_fs_raise_error( - "pointer is not a valid %s object", typeName + MOD_FS_ERR_INVALID_POINTER, + "Pointer is not a valid %s object", typeName ); return false; } return true; } -static bool mod_fs_check_write(struct ModFs *modFs, const char *action) { +static bool mod_fs_check_write(struct ModFs *modFs, const char *action, enum ModFsErrorCode *err) { if (!mod_fs_is_active_mod(modFs)) { mod_fs_raise_error( - "modPath: %s - %s other mods modfs is not allowed", modFs->modPath, action + MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD, + "modPath: %s - %s other mods ModFS is not allowed", modFs->modPath, action ); return false; } return true; } -static bool mod_fs_file_check_write(struct ModFsFile *file) { +static bool mod_fs_file_check_write(struct ModFsFile *file, enum ModFsErrorCode *err) { if (!mod_fs_is_active_mod(file->modFs)) { mod_fs_raise_error( - "modPath: %s, filepath: %s - writing to files in other mods modfs is not allowed", file->modFs->modPath, file->filepath + MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD, + "modPath: %s, filepath: %s - Writing to files in other mods ModFS is not allowed", file->modFs->modPath, file->filepath ); return false; } return true; } -static bool mod_fs_file_check_file_type(struct ModFsFile *file, bool isText, bool write, const char *dataName) { +static bool mod_fs_file_check_file_type(struct ModFsFile *file, bool isText, bool write, const char *dataName, enum ModFsErrorCode *err) { if (file->isText != isText) { mod_fs_raise_error( - "modPath: %s, filepath: %s - cannot %s %s %s a %s file", file->modFs->modPath, file->filepath, + MOD_FS_ERR_FILE_TYPE_NOT_ALLOWED, + "modPath: %s, filepath: %s - Cannot %s %s %s a %s file", file->modFs->modPath, file->filepath, (write ? "write" : "read"), dataName, (write ? "to" : "from"), @@ -763,12 +774,15 @@ static bool mod_fs_file_check_file_type(struct ModFsFile *file, bool isText, boo return true; } -static bool mod_fs_file_check_parameter(struct ModFsFile *file, u8 parameter, u8 parameterMax, const char *parameterName) { - if (parameter >= parameterMax) { +static bool mod_fs_file_check_parameter(struct ModFsFile *file, int parameter, int parameterMin, int parameterMax, const char *parameterName, enum ModFsErrorCode *err) { + if (parameter < parameterMin || parameter > parameterMax) { mod_fs_raise_error( - "modPath: %s, filepath: %s - invalid %s: %u", file->modFs->modPath, file->filepath, + MOD_FS_ERR_INVALID_PARAMETER, + "modPath: %s, filepath: %s - Invalid %s: %d (must be between %d and %d inclusive)", file->modFs->modPath, file->filepath, parameterName, - parameter + parameter, + parameterMin, + parameterMax ); return false; } @@ -779,7 +793,7 @@ static bool mod_fs_file_check_parameter(struct ModFsFile *file, u8 parameter, u8 // FS management // -static struct ModFs *mod_fs_get_or_load(const char *modPath, bool loadIfNotFound) { +static struct ModFs *mod_fs_get_or_load(const char *modPath, bool loadIfNotFound, enum ModFsErrorCode *err) { for (auto &item : sModFsList) { // active mod fs @@ -795,11 +809,12 @@ static struct ModFs *mod_fs_get_or_load(const char *modPath, bool loadIfNotFound // try to load it if (loadIfNotFound) { struct ModFs temp = {0}; - if (mod_fs_read(modPath, &temp, false)) { + if (mod_fs_read(modPath, &temp, false, err)) { struct ModFs *modFs = mod_fs_alloc(); if (!modFs) { mod_fs_raise_error( - "failed to allocate modfs object" + MOD_FS_ERR_ALLOC_FAILED, + "Failed to allocate ModFS object" ); return NULL; } @@ -815,33 +830,28 @@ static struct ModFs *mod_fs_get_or_load(const char *modPath, bool loadIfNotFound return NULL; } -C_DEFINE bool mod_fs_exists(OPTIONAL const char *modPath) { - mod_fs_reset_last_error(); - - struct ModFs *modFs = mod_fs_get_or_load(modPath, false); +static bool mod_fs_exists(const char *modPath, enum ModFsErrorCode *err) { + struct ModFs *modFs = mod_fs_get_or_load(modPath, false, err); if (modFs) { return true; } struct ModFs header = {0}; - if (!mod_fs_read(modPath, &header, true)) { + if (!mod_fs_read(modPath, &header, true, err)) { return false; } return true; } -C_DEFINE struct ModFs *mod_fs_get(OPTIONAL const char *modPath) { - mod_fs_reset_last_error(); - - return mod_fs_get_or_load(modPath, true); +static struct ModFs *mod_fs_get(const char *modPath, enum ModFsErrorCode *err) { + return mod_fs_get_or_load(modPath, true, err); } -C_DEFINE struct ModFs *mod_fs_reload(OPTIONAL const char *modPath) { - mod_fs_reset_last_error(); +static struct ModFs *mod_fs_reload(const char *modPath, enum ModFsErrorCode *err) { - // remove modfs object if already loaded - struct ModFs *modFs = mod_fs_get_or_load(modPath, false); + // remove ModFS object if already loaded + struct ModFs *modFs = mod_fs_get_or_load(modPath, false, err); if (modFs) { sModFsList.erase(std::find(sModFsList.begin(), sModFsList.end(), modFs)); mod_fs_destroy(modFs); @@ -849,17 +859,16 @@ C_DEFINE struct ModFs *mod_fs_reload(OPTIONAL const char *modPath) { } // reload - return mod_fs_get(modPath); + return modfs::mod_fs_get(modPath, err); } -C_DEFINE struct ModFs *mod_fs_create() { - mod_fs_reset_last_error(); - - if (!mod_fs_exists(NULL)) { - struct ModFs *modFs = mod_fs_new(); +static struct ModFs *mod_fs_create(enum ModFsErrorCode *err) { + if (!modfs::mod_fs_exists(NULL, err)) { + struct ModFs *modFs = mod_fs_new(err); if (!modFs) { mod_fs_raise_error( - "cannot create modfs for the active mod" + MOD_FS_ERR_ALLOC_FAILED, + "Cannot create ModFS for the active mod" ); return NULL; } @@ -869,7 +878,8 @@ C_DEFINE struct ModFs *mod_fs_create() { } mod_fs_raise_error( - "a modfs already exists for the active mod; use `mod_fs_get()` instead" + MOD_FS_ERR_ALREADY_EXISTS, + "A ModFS already exists for the active mod; use `mod_fs_get()` instead" ); return NULL; } @@ -878,16 +888,15 @@ C_DEFINE struct ModFs *mod_fs_create() { // File management // -C_DEFINE const char *mod_fs_get_filename(struct ModFs *modFs, u16 index) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { +static const char *mod_fs_get_filename(struct ModFs *modFs, u16 index, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { return NULL; } if (index >= modFs->numFiles) { mod_fs_raise_error( - "modPath: %s - file index out of bounds: %u (num files: %u)", modFs->modPath, index, modFs->numFiles + MOD_FS_ERR_FILE_INVALID_INDEX, + "modPath: %s - File index out of bounds: %u (num files: %u)", modFs->modPath, index, modFs->numFiles ); return NULL; } @@ -895,10 +904,8 @@ C_DEFINE const char *mod_fs_get_filename(struct ModFs *modFs, u16 index) { return modFs->files[index]->filepath; } -C_DEFINE struct ModFsFile *mod_fs_get_file(struct ModFs *modFs, const char *filepath) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { +static struct ModFsFile *mod_fs_get_file(struct ModFs *modFs, const char *filepath, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { return NULL; } @@ -911,35 +918,35 @@ C_DEFINE struct ModFsFile *mod_fs_get_file(struct ModFs *modFs, const char *file return NULL; } -C_DEFINE struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *filepath, bool text) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { +static struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *filepath, bool text, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { return NULL; } - // cannot create new files in other mods modfs - if (!mod_fs_check_write(modFs, "creating files in")) { + // cannot create new files in other mods ModFS + if (!mod_fs_check_write(modFs, "Creating files in", err)) { return NULL; } // check number of files if (modFs->numFiles == MOD_FS_MAX_FILES) { mod_fs_raise_error( - "modPath: %s - reached max number of files: %u", modFs->modPath, MOD_FS_MAX_FILES + MOD_FS_ERR_NUM_FILES_EXCEEDED, + "modPath: %s - Reached max number of files: %u", modFs->modPath, MOD_FS_MAX_FILES ); return NULL; } // check filepath - if (!mod_fs_check_filepath(modFs, filepath)) { + if (!mod_fs_check_filepath(modFs, filepath, err)) { return NULL; } // check existing file - if (mod_fs_get_file(modFs, filepath)) { + if (modfs::mod_fs_get_file(modFs, filepath, err)) { mod_fs_raise_error( - "modPath: %s - file %s already exists; use `mod_fs_get_file` instead", modFs->modPath, filepath + MOD_FS_ERR_ALREADY_EXISTS, + "modPath: %s - File %s already exists; use `mod_fs_get_file` instead", modFs->modPath, filepath ); return NULL; } @@ -948,7 +955,8 @@ C_DEFINE struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *f struct ModFsFile *file = mod_fs_alloc(); if (!file) { mod_fs_raise_error( - "modPath: %s, filepath: %s - failed to allocate modfs file object", modFs->modPath, filepath + MOD_FS_ERR_ALLOC_FAILED, + "modPath: %s, filepath: %s - Failed to allocate ModFS file object", modFs->modPath, filepath ); return NULL; } @@ -966,7 +974,8 @@ C_DEFINE struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *f struct ModFsFile **files = (struct ModFsFile **) realloc(modFs->files, (modFs->numFiles + 1) * sizeof(struct ModFsFile *)); if (!files) { mod_fs_raise_error( - "modPath: %s, filepath: %s - failed to reallocate buffer of modfs files", modFs->modPath, filepath + MOD_FS_ERR_ALLOC_FAILED, + "modPath: %s, filepath: %s - Failed to reallocate buffer of ModFS files", modFs->modPath, filepath ); mod_fs_free(file); return NULL; @@ -979,80 +988,124 @@ C_DEFINE struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *f return file; } -C_DEFINE bool mod_fs_move_file(struct ModFs *modFs, const char *oldpath, const char *newpath, bool overwriteExisting) { - mod_fs_reset_last_error(); +static bool mod_fs_delete_file(struct ModFs *modFs, const char *filepath, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { + return false; + } - if (!mod_fs_check_pointer(modFs, "modfs")) { + // cannot delete files in other mods ModFS + if (!mod_fs_check_write(modFs, "Deleting files in", err)) { return false; } - // cannot move files in other mods modfs - if (!mod_fs_check_write(modFs, "moving files in")) { + // get file + for (u16 i = 0; i != modFs->numFiles; ++i) { + struct ModFsFile *file = modFs->files[i]; + if (strcmp(file->filepath, filepath) == 0) { + + // delete file + modFs->totalSize -= file->size; + mod_fs_file_destroy(file); + mod_fs_free(file); + + // remove file from list + memmove(modFs->files + i, modFs->files + (i + 1), (modFs->numFiles - i - 1) * sizeof(struct ModFsFile *)); + modFs->numFiles--; + return true; + } + } + + mod_fs_raise_error( + MOD_FS_ERR_NOT_FOUND, + "modPath: %s - File %s doesn't exist", modFs->modPath, filepath + ); + return false; +} + +static bool mod_fs_move_file(struct ModFs *modFs, const char *oldpath, const char *newpath, bool overwriteExisting, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { + return false; + } + + // cannot move files in other mods ModFS + if (!mod_fs_check_write(modFs, "Moving files in", err)) { return false; } // check new filepath - if (!mod_fs_check_filepath(modFs, newpath)) { + if (!mod_fs_check_filepath(modFs, newpath, err)) { return false; } + // Do nothing if old and new paths are the same + if (strcmp(oldpath, newpath) == 0) { + return true; + } + // get file - struct ModFsFile *oldfile = mod_fs_get_file(modFs, oldpath); + struct ModFsFile *oldfile = modfs::mod_fs_get_file(modFs, oldpath, err); if (!oldfile) { mod_fs_raise_error( - "modPath: %s - file %s doesn't exist", modFs->modPath, oldpath + MOD_FS_ERR_NOT_FOUND, + "modPath: %s - File %s doesn't exist", modFs->modPath, oldpath ); return false; } // if overwriteExisting is not set, check if the newpath points to an existing file - struct ModFsFile *newfile = mod_fs_get_file(modFs, newpath); + struct ModFsFile *newfile = modfs::mod_fs_get_file(modFs, newpath, err); if (newfile && !overwriteExisting) { mod_fs_raise_error( - "modPath: %s - file %s already exists; set `overwriteExisting` to true to replace this file", modFs->modPath, newpath + MOD_FS_ERR_ALREADY_EXISTS, + "modPath: %s - File %s already exists; set `overwriteExisting` to true to replace this file", modFs->modPath, newpath ); return false; } // rename file - if (newfile && !mod_fs_delete_file(modFs, newpath)) { + if (newfile && !modfs::mod_fs_delete_file(modFs, newpath, err)) { return false; } snprintf(oldfile->filepath, MOD_FS_MAX_PATH, "%s", newpath); return true; } -C_DEFINE bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const char *dstpath, bool overwriteExisting) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { +static bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const char *dstpath, bool overwriteExisting, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { return false; } - // cannot copy files in other mods modfs - if (!mod_fs_check_write(modFs, "copying files in")) { + // cannot copy files in other mods ModFS + if (!mod_fs_check_write(modFs, "copying files in", err)) { return false; } // check dest filepath - if (!mod_fs_check_filepath(modFs, dstpath)) { + if (!mod_fs_check_filepath(modFs, dstpath, err)) { return false; } + // Do nothing if src and dst paths are the same + if (strcmp(srcpath, dstpath) == 0) { + return true; + } + // get file - struct ModFsFile *srcfile = mod_fs_get_file(modFs, srcpath); + struct ModFsFile *srcfile = modfs::mod_fs_get_file(modFs, srcpath, err); if (!srcfile) { mod_fs_raise_error( - "modPath: %s - file %s doesn't exist", modFs->modPath, srcpath + MOD_FS_ERR_NOT_FOUND, + "modPath: %s - File %s doesn't exist", modFs->modPath, srcpath ); return false; } // if overwriteExisting is not set, check if the newpath points to an existing file - struct ModFsFile *dstfile = mod_fs_get_file(modFs, dstpath); + struct ModFsFile *dstfile = modfs::mod_fs_get_file(modFs, dstpath, err); if (dstfile && !overwriteExisting) { mod_fs_raise_error( - "modPath: %s - file %s already exists; set `overwriteExisting` to true to replace this file", modFs->modPath, dstpath + MOD_FS_ERR_ALREADY_EXISTS, + "modPath: %s - File %s already exists; set `overwriteExisting` to true to replace this file", modFs->modPath, dstpath ); return false; } @@ -1064,24 +1117,25 @@ C_DEFINE bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const c } if (newTotalSize > MOD_FS_MAX_SIZE) { mod_fs_raise_error( - "modPath: %s - cannot copy file %s: exceeding total size: %u (max is: %u)", modFs->modPath, srcpath, newTotalSize, MOD_FS_MAX_SIZE + MOD_FS_ERR_TOTAL_SIZE_EXCEEDED, + "modPath: %s - Cannot copy file %s: exceeding total size: %u (max is: %u)", modFs->modPath, srcpath, newTotalSize, MOD_FS_MAX_SIZE ); return false; } - modFs->totalSize = newTotalSize; // copy file u8 *buffer = (u8 *) malloc(srcfile->size); if (!buffer) { mod_fs_raise_error( - "modPath: %s, filepath: %s - failed to allocate buffer for modfs file data", modFs->modPath, dstfile->filepath + MOD_FS_ERR_ALLOC_FAILED, + "modPath: %s, filepath: %s - Failed to allocate buffer for ModFS file data", modFs->modPath, dstfile->filepath ); return false; } if (dstfile) { free(dstfile->data.bin); } else { - dstfile = mod_fs_create_file(modFs, dstpath, srcfile->isText); + dstfile = modfs::mod_fs_create_file(modFs, dstpath, srcfile->isText, err); if (!dstfile) { free(buffer); return false; @@ -1093,53 +1147,17 @@ C_DEFINE bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const c dstfile->size = dstfile->capacity = srcfile->size; dstfile->data.bin = buffer; dstfile->offset = 0; + modFs->totalSize = newTotalSize; return true; } -C_DEFINE bool mod_fs_delete_file(struct ModFs *modFs, const char *filepath) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { +static bool mod_fs_clear(struct ModFs *modFs, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { return false; } - // cannot delete files in other mods modfs - if (!mod_fs_check_write(modFs, "deleting files in")) { - return false; - } - - // get file - for (u16 i = 0; i != modFs->numFiles; ++i) { - struct ModFsFile *file = modFs->files[i]; - if (strcmp(file->filepath, filepath) == 0) { - - // delete file - modFs->totalSize -= file->size; - mod_fs_file_destroy(file); - mod_fs_free(file); - - // remove file from list - memmove(modFs->files + i, modFs->files + (i + 1), (modFs->numFiles - i - 1) * sizeof(struct ModFsFile *)); - modFs->numFiles--; - return true; - } - } - - mod_fs_raise_error( - "modPath: %s - file %s doesn't exist", modFs->modPath, filepath - ); - return false; -} - -C_DEFINE bool mod_fs_clear(struct ModFs *modFs) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { - return false; - } - - // cannot delete files in other mods modfs - if (!mod_fs_check_write(modFs, "deleting files in")) { + // cannot delete files in other mods ModFS + if (!mod_fs_check_write(modFs, "Deleting files in", err)) { return false; } @@ -1156,30 +1174,26 @@ C_DEFINE bool mod_fs_clear(struct ModFs *modFs) { return true; } -C_DEFINE bool mod_fs_save(struct ModFs *modFs) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { +static bool mod_fs_save(struct ModFs *modFs, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { return false; } - // cannot save other mods modfs - if (!mod_fs_check_write(modFs, "saving over")) { + // cannot save other mods ModFS + if (!mod_fs_check_write(modFs, "Saving over", err)) { return false; } - return mod_fs_write(modFs); + return mod_fs_write(modFs, err); } -C_DEFINE bool mod_fs_delete(struct ModFs *modFs) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { +static bool mod_fs_delete(struct ModFs *modFs, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { return false; } - // cannot delete other mods modfs - if (!mod_fs_check_write(modFs, "deleting")) { + // cannot delete other mods ModFS + if (!mod_fs_check_write(modFs, "Deleting", err)) { return false; } @@ -1194,15 +1208,13 @@ C_DEFINE bool mod_fs_delete(struct ModFs *modFs) { return true; } -C_DEFINE bool mod_fs_set_public(struct ModFs *modFs, bool pub) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(modFs, "modfs")) { +static bool mod_fs_set_public(struct ModFs *modFs, bool pub, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(modFs, "ModFS", err)) { return false; } - // cannot change public flag of other mods modfs - if (!mod_fs_check_write(modFs, "changing public flag of")) { + // cannot change public flag of other mods ModFS + if (!mod_fs_check_write(modFs, "Changing public flag of", err)) { return false; } @@ -1214,11 +1226,12 @@ C_DEFINE bool mod_fs_set_public(struct ModFs *modFs, bool pub) { // Read data // -static bool mod_fs_file_read_check_eof(struct ModFsFile *file, u32 size) { +static bool mod_fs_file_read_check_eof(struct ModFsFile *file, u32 size, enum ModFsErrorCode *err) { if (file->offset + size > file->size) { file->offset = file->size; mod_fs_raise_error( - "modPath: %s, filepath: %s - reached end of file", file->modFs->modPath, file->filepath + MOD_FS_ERR_READ_EOF, + "modPath: %s, filepath: %s - Reached end of file", file->modFs->modPath, file->filepath ); return true; } @@ -1226,8 +1239,8 @@ static bool mod_fs_file_read_check_eof(struct ModFsFile *file, u32 size) { } template -static T mod_fs_file_read_data(struct ModFsFile *file, T defaultValue) { - if (mod_fs_file_read_check_eof(file, sizeof(T))) { +static T mod_fs_file_read_data(struct ModFsFile *file, T defaultValue, enum ModFsErrorCode *err) { + if (mod_fs_file_read_check_eof(file, sizeof(T), err)) { return defaultValue; } T value; @@ -1236,7 +1249,7 @@ static T mod_fs_file_read_data(struct ModFsFile *file, T defaultValue) { return value; } -static const char *mod_fs_file_read_string_buffer(struct ModFsFile *file, u32 length, bool skipNextChar) { +static const char *mod_fs_file_read_string_buffer(struct ModFsFile *file, u32 length, bool skipNextChar, enum ModFsErrorCode *err) { static char *sModFsFileReadStringBuf = NULL; static u32 sModFsFileReadStringBufLength = 0; @@ -1247,7 +1260,8 @@ static const char *mod_fs_file_read_string_buffer(struct ModFsFile *file, u32 le if (!sModFsFileReadStringBuf) { sModFsFileReadStringBufLength = 0; mod_fs_raise_error( - "modPath: %s, filepath: %s - unable to allocate temporary buffer of length: %u", + MOD_FS_ERR_ALLOC_FAILED, + "modPath: %s, filepath: %s - Unable to allocate temporary buffer of length: %u", file->modFs->modPath, file->filepath, length ); return NULL; @@ -1261,90 +1275,83 @@ static const char *mod_fs_file_read_string_buffer(struct ModFsFile *file, u32 le return sModFsFileReadStringBuf; } -C_DEFINE bool mod_fs_file_read_bool(struct ModFsFile *file) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_read_bool(struct ModFsFile *file, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } // binary only - if (!mod_fs_file_check_file_type(file, false, false, "bool")) { + if (!mod_fs_file_check_file_type(file, false, false, "bool", err)) { return false; } - return mod_fs_file_read_data(file, false); + return mod_fs_file_read_data(file, false, err); } -C_DEFINE lua_Integer mod_fs_file_read_integer(struct ModFsFile *file, enum ModFsFileIntType intType) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static lua_Integer mod_fs_file_read_integer(struct ModFsFile *file, enum ModFsFileIntType intType, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return 0; } // binary only - if (!mod_fs_file_check_file_type(file, false, false, "integer")) { + if (!mod_fs_file_check_file_type(file, false, false, "integer", err)) { return 0; } // check intType - if (!mod_fs_file_check_parameter(file, intType, INT_TYPE_MAX, "intType")) { + if (!mod_fs_file_check_parameter(file, intType, 0, INT_TYPE_MAX - 1, "intType", err)) { return 0; } switch (intType) { - case INT_TYPE_U8: return mod_fs_file_read_data(file, 0); - case INT_TYPE_U16: return mod_fs_file_read_data(file, 0); - case INT_TYPE_U32: return mod_fs_file_read_data(file, 0); - case INT_TYPE_U64: return mod_fs_file_read_data(file, 0); - case INT_TYPE_S8: return mod_fs_file_read_data(file, 0); - case INT_TYPE_S16: return mod_fs_file_read_data(file, 0); - case INT_TYPE_S32: return mod_fs_file_read_data(file, 0); - case INT_TYPE_S64: return mod_fs_file_read_data(file, 0); + case INT_TYPE_U8: return mod_fs_file_read_data(file, 0, err); + case INT_TYPE_U16: return mod_fs_file_read_data(file, 0, err); + case INT_TYPE_U32: return mod_fs_file_read_data(file, 0, err); + case INT_TYPE_U64: return mod_fs_file_read_data(file, 0, err); + case INT_TYPE_S8: return mod_fs_file_read_data(file, 0, err); + case INT_TYPE_S16: return mod_fs_file_read_data(file, 0, err); + case INT_TYPE_S32: return mod_fs_file_read_data(file, 0, err); + case INT_TYPE_S64: return mod_fs_file_read_data(file, 0, err); default: return 0; } } -C_DEFINE lua_Number mod_fs_file_read_number(struct ModFsFile *file, enum ModFsFileFloatType floatType) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static lua_Number mod_fs_file_read_number(struct ModFsFile *file, enum ModFsFileFloatType floatType, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return 0; } // binary only - if (!mod_fs_file_check_file_type(file, false, false, "number")) { + if (!mod_fs_file_check_file_type(file, false, false, "number", err)) { return 0; } // check intType - if (!mod_fs_file_check_parameter(file, floatType, FLOAT_TYPE_MAX, "floatType")) { + if (!mod_fs_file_check_parameter(file, floatType, 0, FLOAT_TYPE_MAX - 1, "floatType", err)) { return 0; } switch (floatType) { - case FLOAT_TYPE_F32: return mod_fs_file_read_data(file, 0); - case FLOAT_TYPE_F64: return mod_fs_file_read_data(file, 0); + case FLOAT_TYPE_F32: return mod_fs_file_read_data(file, 0, err); + case FLOAT_TYPE_F64: return mod_fs_file_read_data(file, 0, err); default: return 0; } } -C_DEFINE ByteString mod_fs_file_read_bytes(struct ModFsFile *file, u32 length) { - mod_fs_reset_last_error(); +static ByteString mod_fs_file_read_bytes(struct ModFsFile *file, u32 length, enum ModFsErrorCode *err) { ByteString bytestring = { NULL, 0 }; - if (!mod_fs_check_pointer(file, "modfs file")) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return bytestring; } // binary only - if (!mod_fs_file_check_file_type(file, false, false, "bytes")) { + if (!mod_fs_file_check_file_type(file, false, false, "bytes", err)) { return bytestring; } // check eof - if (mod_fs_file_read_check_eof(file, length)) { + if (mod_fs_file_read_check_eof(file, length, err)) { return bytestring; } @@ -1354,20 +1361,18 @@ C_DEFINE ByteString mod_fs_file_read_bytes(struct ModFsFile *file, u32 length) { return bytestring; } -C_DEFINE const char *mod_fs_file_read_string(struct ModFsFile *file) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static const char *mod_fs_file_read_string(struct ModFsFile *file, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return NULL; } - if (mod_fs_file_read_check_eof(file, 1)) { + if (mod_fs_file_read_check_eof(file, 1, err)) { return NULL; } // for text files, returns the whole content from offset if (file->isText) { - return mod_fs_file_read_string_buffer(file, file->size - file->offset, false); + return mod_fs_file_read_string_buffer(file, file->size - file->offset, false, err); } // for binary, stops at the first NUL char or at the end of the file @@ -1377,22 +1382,20 @@ C_DEFINE const char *mod_fs_file_read_string(struct ModFsFile *file) { for (const char *c = start; *c && c < end; c++) { length++; } - return mod_fs_file_read_string_buffer(file, length, true); + return mod_fs_file_read_string_buffer(file, length, true, err); } -C_DEFINE const char *mod_fs_file_read_line(struct ModFsFile *file) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static const char *mod_fs_file_read_line(struct ModFsFile *file, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return NULL; } // text only - if (!mod_fs_file_check_file_type(file, true, false, "line")) { + if (!mod_fs_file_check_file_type(file, true, false, "line", err)) { return 0; } - if (mod_fs_file_read_check_eof(file, 1)) { + if (mod_fs_file_read_check_eof(file, 1, err)) { return NULL; } @@ -1403,14 +1406,14 @@ C_DEFINE const char *mod_fs_file_read_line(struct ModFsFile *file) { for (const char *c = start; *c != '\n' && c < end; c++) { length++; } - return mod_fs_file_read_string_buffer(file, length, true); + return mod_fs_file_read_string_buffer(file, length, true, err); } // // Write data // -static bool mod_fs_file_write_resize_buffer(struct ModFsFile *file, u32 size) { +static bool mod_fs_file_write_resize_buffer(struct ModFsFile *file, u32 size, enum ModFsErrorCode *err) { // compute and check new sizes file->offset = MIN(file->offset, file->size); @@ -1418,7 +1421,8 @@ static bool mod_fs_file_write_resize_buffer(struct ModFsFile *file, u32 size) { u32 newTotalSize = file->modFs->totalSize + (newFileSize - file->size); if (newTotalSize > MOD_FS_MAX_SIZE) { mod_fs_raise_error( - "modPath: %s, filepath: %s - cannot write to file: exceeding total size: %u (max is: %u)", file->modFs->modPath, file->filepath, newTotalSize, MOD_FS_MAX_SIZE + MOD_FS_ERR_TOTAL_SIZE_EXCEEDED, + "modPath: %s, filepath: %s - Cannot write to file: exceeding total size: %u (max is: %u)", file->modFs->modPath, file->filepath, newTotalSize, MOD_FS_MAX_SIZE ); return false; } @@ -1429,7 +1433,8 @@ static bool mod_fs_file_write_resize_buffer(struct ModFsFile *file, u32 size) { u8 *buffer = (u8 *) realloc(file->data.bin, newCapacity); if (!buffer) { mod_fs_raise_error( - "modPath: %s, filepath: %s - failed to reallocate buffer of modfs file data", file->modFs->modPath, file->filepath + MOD_FS_ERR_ALLOC_FAILED, + "modPath: %s, filepath: %s - Failed to reallocate buffer of ModFS file data", file->modFs->modPath, file->filepath ); return false; } @@ -1442,8 +1447,8 @@ static bool mod_fs_file_write_resize_buffer(struct ModFsFile *file, u32 size) { } template -static bool mod_fs_file_write_data(struct ModFsFile *file, T value) { - if (mod_fs_file_write_resize_buffer(file, sizeof(T))) { +static bool mod_fs_file_write_data(struct ModFsFile *file, T value, enum ModFsErrorCode *err) { + if (mod_fs_file_write_resize_buffer(file, sizeof(T), err)) { memcpy(file->data.bin + file->offset, &value, sizeof(T)); file->offset += sizeof(T); return true; @@ -1451,109 +1456,101 @@ static bool mod_fs_file_write_data(struct ModFsFile *file, T value) { return false; } -C_DEFINE bool mod_fs_file_write_bool(struct ModFsFile *file, bool value) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_write_bool(struct ModFsFile *file, bool value, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot write to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot write to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } // binary only - if (!mod_fs_file_check_file_type(file, false, true, "bool")) { + if (!mod_fs_file_check_file_type(file, false, true, "bool", err)) { return false; } - return mod_fs_file_write_data(file, value); + return mod_fs_file_write_data(file, value, err); } -C_DEFINE bool mod_fs_file_write_integer(struct ModFsFile *file, lua_Integer value, enum ModFsFileIntType intType) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_write_integer(struct ModFsFile *file, lua_Integer value, enum ModFsFileIntType intType, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot write to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot write to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } // binary only - if (!mod_fs_file_check_file_type(file, false, true, "integer")) { + if (!mod_fs_file_check_file_type(file, false, true, "integer", err)) { return false; } // check intType - if (!mod_fs_file_check_parameter(file, intType, INT_TYPE_MAX, "intType")) { + if (!mod_fs_file_check_parameter(file, intType, 0, INT_TYPE_MAX - 1, "intType", err)) { return false; } switch (intType) { - case INT_TYPE_U8: return mod_fs_file_write_data(file, value); - case INT_TYPE_U16: return mod_fs_file_write_data(file, value); - case INT_TYPE_U32: return mod_fs_file_write_data(file, value); - case INT_TYPE_U64: return mod_fs_file_write_data(file, value); - case INT_TYPE_S8: return mod_fs_file_write_data(file, value); - case INT_TYPE_S16: return mod_fs_file_write_data(file, value); - case INT_TYPE_S32: return mod_fs_file_write_data(file, value); - case INT_TYPE_S64: return mod_fs_file_write_data(file, value); + case INT_TYPE_U8: return mod_fs_file_write_data(file, value, err); + case INT_TYPE_U16: return mod_fs_file_write_data(file, value, err); + case INT_TYPE_U32: return mod_fs_file_write_data(file, value, err); + case INT_TYPE_U64: return mod_fs_file_write_data(file, value, err); + case INT_TYPE_S8: return mod_fs_file_write_data(file, value, err); + case INT_TYPE_S16: return mod_fs_file_write_data(file, value, err); + case INT_TYPE_S32: return mod_fs_file_write_data(file, value, err); + case INT_TYPE_S64: return mod_fs_file_write_data(file, value, err); default: return false; } } -C_DEFINE bool mod_fs_file_write_number(struct ModFsFile *file, lua_Number value, enum ModFsFileFloatType floatType) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_write_number(struct ModFsFile *file, lua_Number value, enum ModFsFileFloatType floatType, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot write to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot write to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } // binary only - if (!mod_fs_file_check_file_type(file, false, true, "number")) { + if (!mod_fs_file_check_file_type(file, false, true, "number", err)) { return false; } // check floatType - if (!mod_fs_file_check_parameter(file, floatType, FLOAT_TYPE_MAX, "floatType")) { + if (!mod_fs_file_check_parameter(file, floatType, 0, FLOAT_TYPE_MAX - 1, "floatType", err)) { return false; } switch (floatType) { - case FLOAT_TYPE_F32: return mod_fs_file_write_data(file, value); - case FLOAT_TYPE_F64: return mod_fs_file_write_data(file, value); + case FLOAT_TYPE_F32: return mod_fs_file_write_data(file, value, err); + case FLOAT_TYPE_F64: return mod_fs_file_write_data(file, value, err); default: return false; } } -C_DEFINE bool mod_fs_file_write_bytes(struct ModFsFile *file, ByteString bytestring) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_write_bytes(struct ModFsFile *file, ByteString bytestring, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot write to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot write to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } // binary only - if (!mod_fs_file_check_file_type(file, false, true, "bytes")) { + if (!mod_fs_file_check_file_type(file, false, true, "bytes", err)) { return false; } u32 length = bytestring.length; - if (mod_fs_file_write_resize_buffer(file, length)) { + if (mod_fs_file_write_resize_buffer(file, length, err)) { memcpy(file->data.bin + file->offset, bytestring.bytes, length); file->offset += length; return true; @@ -1561,20 +1558,18 @@ C_DEFINE bool mod_fs_file_write_bytes(struct ModFsFile *file, ByteString bytestr return false; } -C_DEFINE bool mod_fs_file_write_string(struct ModFsFile *file, const char *str) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_write_string(struct ModFsFile *file, const char *str, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot write to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot write to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } u32 length = strlen(str) + (file->isText ? 0 : 1); // binary writes the NULL char - if (mod_fs_file_write_resize_buffer(file, length)) { + if (mod_fs_file_write_resize_buffer(file, length, err)) { memcpy(file->data.bin + file->offset, str, length); file->offset += length; return true; @@ -1582,25 +1577,23 @@ C_DEFINE bool mod_fs_file_write_string(struct ModFsFile *file, const char *str) return false; } -C_DEFINE bool mod_fs_file_write_line(struct ModFsFile *file, const char *str) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_write_line(struct ModFsFile *file, const char *str, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot write to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot write to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } // text only - if (!mod_fs_file_check_file_type(file, true, true, "line")) { + if (!mod_fs_file_check_file_type(file, true, true, "line", err)) { return false; } u32 length = strlen(str); - if (mod_fs_file_write_resize_buffer(file, length + 1)) { // '\n' + if (mod_fs_file_write_resize_buffer(file, length + 1, err)) { // '\n' memcpy(file->data.text + file->offset, str, length); file->offset += length; file->data.text[file->offset++] = '\n'; @@ -1613,15 +1606,13 @@ C_DEFINE bool mod_fs_file_write_line(struct ModFsFile *file, const char *str) { // File misc // -C_DEFINE bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFileSeek origin) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFileSeek origin, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } // check origin - if (!mod_fs_file_check_parameter(file, origin, FILE_SEEK_MAX, "origin")) { + if (!mod_fs_file_check_parameter(file, origin, 0, FILE_SEEK_MAX - 1, "origin", err)) { return false; } @@ -1636,10 +1627,8 @@ C_DEFINE bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFil return true; } -C_DEFINE bool mod_fs_file_rewind(struct ModFsFile *file) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_rewind(struct ModFsFile *file, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } @@ -1647,29 +1636,25 @@ C_DEFINE bool mod_fs_file_rewind(struct ModFsFile *file) { return true; } -C_DEFINE bool mod_fs_file_is_eof(struct ModFsFile *file) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_is_eof(struct ModFsFile *file, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } return file->offset >= file->size; } -C_DEFINE bool mod_fs_file_fill(struct ModFsFile *file, u8 byte, u32 length) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_fill(struct ModFsFile *file, u8 byte, u32 length, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot write to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot write to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } - if (mod_fs_file_write_resize_buffer(file, length)) { + if (mod_fs_file_write_resize_buffer(file, length, err)) { memset(file->data.bin + file->offset, byte, length); file->offset += length; return true; @@ -1677,15 +1662,13 @@ C_DEFINE bool mod_fs_file_fill(struct ModFsFile *file, u8 byte, u32 length) { return false; } -C_DEFINE bool mod_fs_file_erase(struct ModFsFile *file, u32 length) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_erase(struct ModFsFile *file, u32 length, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot erase data from files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot erase data from files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } @@ -1696,10 +1679,8 @@ C_DEFINE bool mod_fs_file_erase(struct ModFsFile *file, u32 length) { return true; } -C_DEFINE bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } @@ -1707,15 +1688,13 @@ C_DEFINE bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text) { return true; } -C_DEFINE bool mod_fs_file_set_public(struct ModFsFile *file, bool pub) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_set_public(struct ModFsFile *file, bool pub, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot change public flag to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot change public flag to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } @@ -1723,22 +1702,18 @@ C_DEFINE bool mod_fs_file_set_public(struct ModFsFile *file, bool pub) { return true; } -C_DEFINE bool mod_fs_file_set_compression(struct ModFsFile *file, s32 level) { - mod_fs_reset_last_error(); - - if (!mod_fs_check_pointer(file, "modfs file")) { +static bool mod_fs_file_set_compression(struct ModFsFile *file, s32 level, enum ModFsErrorCode *err) { + if (!mod_fs_check_pointer(file, "ModFS file", err)) { return false; } - // cannot change compress level to files in other mods modfs - if (!mod_fs_file_check_write(file)) { + // cannot change compress level to files in other mods ModFS + if (!mod_fs_file_check_write(file, err)) { return false; } - if (level < MOD_FS_COMPRESSION_MIN || level > MOD_FS_COMPRESSION_MAX) { - mod_fs_raise_error( - "compress level must be between %d and %d inclusive", MOD_FS_COMPRESSION_MIN, MOD_FS_COMPRESSION_MAX - ); + // check level + if (!mod_fs_file_check_parameter(file, level, MOD_FS_COMPRESSION_MIN, MOD_FS_COMPRESSION_MAX, "level", err)) { return false; } @@ -1750,11 +1725,15 @@ C_DEFINE bool mod_fs_file_set_compression(struct ModFsFile *file, s32 level) { // Errors // -C_DEFINE void mod_fs_hide_errors(bool hide) { +static void mod_fs_hide_errors(bool hide) { sModFsHideErrors = hide; } -C_DEFINE const char *mod_fs_get_last_error() { +static enum ModFsErrorCode mod_fs_get_last_error_code() { + return sModFsLastErrorCode; +} + +static const char *mod_fs_get_last_error() { return *sModFsLastError ? sModFsLastError : NULL; } @@ -1783,19 +1762,20 @@ static bool mod_fs_extract_modpath_and_filepath(const char *uri, char *modPath, return true; } -C_DEFINE bool mod_fs_read_file_from_uri(const char *uri, void **buffer, u32 *length) { +static bool mod_fs_read_file_from_uri(const char *uri, void **buffer, u32 *length) { char modPath[SYS_MAX_PATH]; char filepath[MOD_FS_MAX_PATH]; if (!mod_fs_extract_modpath_and_filepath(uri, modPath, filepath)) { return false; } - struct ModFs *modFs = mod_fs_get(modPath); + enum ModFsErrorCode err = MOD_FS_ERR_NONE; + struct ModFs *modFs = modfs::mod_fs_get(modPath, &err); if (!modFs) { return false; } - struct ModFsFile *file = mod_fs_get_file(modFs, filepath); + struct ModFsFile *file = modfs::mod_fs_get_file(modFs, filepath, &err); if (!file || !file->data.bin || !file->size) { return false; } @@ -1809,9 +1789,9 @@ C_DEFINE bool mod_fs_read_file_from_uri(const char *uri, void **buffer, u32 *len return true; } -C_DEFINE void mod_fs_shutdown() { +static void mod_fs_shutdown() { - // Close all modfs + // Close all ModFS for (auto &modFs : sModFsList) { mod_fs_destroy(modFs); mod_fs_free(modFs); @@ -1819,6 +1799,207 @@ C_DEFINE void mod_fs_shutdown() { sModFsList.clear(); // Reset error state - mod_fs_reset_last_error(); + sModFsLastErrorCode = MOD_FS_ERR_NONE; + memset(sModFsLastError, 0, sizeof(sModFsLastError)); sModFsHideErrors = false; } + +} + +// +// C API +// + +extern "C" { + +bool mod_fs_exists(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_exists(modPath, err); +} + +struct ModFs *mod_fs_get(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_get(modPath, err); +} + +struct ModFs *mod_fs_reload(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_reload(modPath, err); +} + +struct ModFs *mod_fs_create(RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_create(err); +} + +const char *mod_fs_get_filename(struct ModFs *modFs, u16 index, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_get_filename(modFs, index, err); +} + +struct ModFsFile *mod_fs_get_file(struct ModFs *modFs, const char *filepath, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_get_file(modFs, filepath, err); +} + +struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *filepath, bool text, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_create_file(modFs, filepath, text, err); +} + +bool mod_fs_move_file(struct ModFs *modFs, const char *oldpath, const char *newpath, bool overwriteExisting, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_move_file(modFs, oldpath, newpath, overwriteExisting, err); +} + +bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const char *dstpath, bool overwriteExisting, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_copy_file(modFs, srcpath, dstpath, overwriteExisting, err); +} + +bool mod_fs_delete_file(struct ModFs *modFs, const char *filepath, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_delete_file(modFs, filepath, err); +} + +bool mod_fs_clear(struct ModFs *modFs, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_clear(modFs, err); +} + +bool mod_fs_save(struct ModFs *modFs, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_save(modFs, err); +} + +bool mod_fs_delete(struct ModFs *modFs, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_delete(modFs, err); +} + +bool mod_fs_set_public(struct ModFs *modFs, bool pub, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_set_public(modFs, pub, err); +} + +bool mod_fs_file_read_bool(struct ModFsFile *file, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_read_bool(file, err); +} + +lua_Integer mod_fs_file_read_integer(struct ModFsFile *file, enum ModFsFileIntType intType, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_read_integer(file, intType, err); +} + +lua_Number mod_fs_file_read_number(struct ModFsFile *file, enum ModFsFileFloatType floatType, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_read_number(file, floatType, err); +} + +ByteString mod_fs_file_read_bytes(struct ModFsFile *file, u32 length, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_read_bytes(file, length, err); +} + +const char *mod_fs_file_read_string(struct ModFsFile *file, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_read_string(file, err); +} + +const char *mod_fs_file_read_line(struct ModFsFile *file, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_read_line(file, err); +} + +bool mod_fs_file_write_bool(struct ModFsFile *file, bool value, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_write_bool(file, value, err); +} + +bool mod_fs_file_write_integer(struct ModFsFile *file, lua_Integer value, enum ModFsFileIntType intType, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_write_integer(file, value, intType, err); +} + +bool mod_fs_file_write_number(struct ModFsFile *file, lua_Number value, enum ModFsFileFloatType floatType, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_write_number(file, value, floatType, err); +} + +bool mod_fs_file_write_bytes(struct ModFsFile *file, ByteString bytestring, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_write_bytes(file, bytestring, err); +} + +bool mod_fs_file_write_string(struct ModFsFile *file, const char *str, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_write_string(file, str, err); +} + +bool mod_fs_file_write_line(struct ModFsFile *file, const char *str, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_write_line(file, str, err); +} + +bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFileSeek origin, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_seek(file, offset, origin, err); +} + +bool mod_fs_file_rewind(struct ModFsFile *file, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_rewind(file, err); +} + +bool mod_fs_file_is_eof(struct ModFsFile *file, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_is_eof(file, err); +} + +bool mod_fs_file_fill(struct ModFsFile *file, u8 byte, u32 length, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_fill(file, byte, length, err); +} + +bool mod_fs_file_erase(struct ModFsFile *file, u32 length, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_erase(file, length, err); +} + +bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_set_text_mode(file, text, err); +} + +bool mod_fs_file_set_public(struct ModFsFile *file, bool pub, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_set_public(file, pub, err); +} + +bool mod_fs_file_set_compression(struct ModFsFile *file, s32 level, RET enum ModFsErrorCode *err) { + mod_fs_reset_last_error(); + return modfs::mod_fs_file_set_compression(file, level, err); +} + +void mod_fs_hide_errors(bool hide) { + return modfs::mod_fs_hide_errors(hide); +} + +enum ModFsErrorCode mod_fs_get_last_error_code() { + return modfs::mod_fs_get_last_error_code(); +} + +const char *mod_fs_get_last_error() { + return modfs::mod_fs_get_last_error(); +} + +bool mod_fs_read_file_from_uri(const char *uri, void **buffer, u32 *length) { + return modfs::mod_fs_read_file_from_uri(uri, buffer, length); +} + +void mod_fs_shutdown() { + return modfs::mod_fs_shutdown(); +} + +} diff --git a/src/pc/mods/mod_fs.h b/src/pc/mods/mod_fs.h index 078106593..61423228a 100644 --- a/src/pc/mods/mod_fs.h +++ b/src/pc/mods/mod_fs.h @@ -7,14 +7,48 @@ #define MOD_FS_COMPRESSION_MIN 0 #define MOD_FS_COMPRESSION_MAX 9 #define MOD_FS_COMPRESSION_DEFAULT 1 -#define MOD_FS_MAX_SIZE 0x2000000 // 32 MB -#define MOD_FS_MAX_FILES 0x200 +#define MOD_FS_MAX_SIZE 0x8000000 // 128 MB +#define MOD_FS_MAX_FILES 0x400 #define MOD_FS_MAX_PATH 0x100 #define MOD_FS_URI_PREFIX "modfs:/" #define MOD_FS_URI_FORMAT "modfs:/%s/%s" // modPath, filepath #define is_mod_fs_file(filepath) (memcmp(filepath, MOD_FS_URI_PREFIX, sizeof(MOD_FS_URI_PREFIX) - 1) == 0) +enum ModFsErrorCode { + MOD_FS_ERR_NONE, + + // Common errors + MOD_FS_ERR_ALLOC_FAILED, // Memory allocation failed + MOD_FS_ERR_ALREADY_EXISTS, // Tried to create, move or copy an existing ModFS or ModFS file + MOD_FS_ERR_NOT_FOUND, // Tried to move, copy or delete a non-existent ModFS file + MOD_FS_ERR_INVALID_POINTER, // Passed an invalid ModFS or ModFS file pointer + MOD_FS_ERR_INVALID_PARAMETER, // Passed an invalid parameter value + MOD_FS_ERR_FILE_INVALID_INDEX, // Tried to get the filename of an out-of-bounds file index + MOD_FS_ERR_FILE_TYPE_NOT_ALLOWED, // Tried to use a read/write function on a non-supported file type + MOD_FS_ERR_TOTAL_SIZE_EXCEEDED, // Tried to read, copy or write past the maximum size of a ModFS + MOD_FS_ERR_NUM_FILES_EXCEEDED, // Tried to read or create more files than allowed for a ModFS + + // Filepath errors + MOD_FS_ERR_FILEPATH_EMPTY, // Empty filepath + MOD_FS_ERR_FILEPATH_LEN_EXCEEDED, // Filepath too long + MOD_FS_ERR_FILEPATH_RESERVED, // Filepath is reserved and cannot be used for ModFS files + MOD_FS_ERR_FILEPATH_INVALID_CHAR, // Filepath contains invalid characters (non-ASCII, control characters, asterisk or backslash) + MOD_FS_ERR_FILEPATH_MALFORMED, // Filepath is malformed (leading/trailing whitespaces/slashes, consecutive slashes) + MOD_FS_ERR_FILEPATH_INVALID_EXTENSION, // Filepath extension is not in whitelist + + // Read errors + MOD_FS_ERR_READ_INVALID_MODPATH, // Modpath couldn't be resolved + MOD_FS_ERR_READ_ZIP, // ZIP decompression failed + MOD_FS_ERR_READ_PROPERTIES, // Properties file JSON is malformed + MOD_FS_ERR_READ_FILE_TRUNCATED, // Read data didn't match the expected size + MOD_FS_ERR_READ_EOF, // Reached end of file while reading + + // Write errors + MOD_FS_ERR_WRITE_ZIP, // ZIP compression failed + MOD_FS_ERR_WRITE_NOT_ACTIVE_MOD, // Tried to perform a write operation (create, delete, move, copy, write, set) on another mod ModFS or ModFS file +}; + enum ModFsFileIntType { INT_TYPE_U8, INT_TYPE_U16, @@ -104,132 +138,132 @@ struct ModFs { /* |description| Checks the existence of a modfs at path `modPath` or for the active mod if not provided. Checking for the existence of a private modfs will return false, even if it exists |descriptionEnd| */ -bool mod_fs_exists(OPTIONAL const char *modPath); +bool mod_fs_exists(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err); /* |description| Gets the modfs object at path `modPath` or the active mod one if not provided. This function will return nil for a private modfs, even if it exists |descriptionEnd| */ -struct ModFs *mod_fs_get(OPTIONAL const char *modPath); +struct ModFs *mod_fs_get(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err); /* |description| Reloads the modfs object at path `modPath`. This function will return nil for a private modfs, even if it exists |descriptionEnd| */ -struct ModFs *mod_fs_reload(OPTIONAL const char *modPath); +struct ModFs *mod_fs_reload(OPTIONAL const char *modPath, RET enum ModFsErrorCode *err); /* |description| Creates a modfs object for the active mod if it doesn't exist. Returns the modfs object on success |descriptionEnd| */ -struct ModFs *mod_fs_create(); +struct ModFs *mod_fs_create(RET enum ModFsErrorCode *err); /* |description| Gets the filename at position `index` of the provided `modFs` |descriptionEnd| */ -const char *mod_fs_get_filename(struct ModFs *modFs, u16 index); +const char *mod_fs_get_filename(struct ModFs *modFs, u16 index, RET enum ModFsErrorCode *err); /* |description| Gets the file object at path `filepath` of the provided `modFs`. This function will return nil for a private modfs file, even if it exists |descriptionEnd| */ -struct ModFsFile *mod_fs_get_file(struct ModFs *modFs, const char *filepath); +struct ModFsFile *mod_fs_get_file(struct ModFs *modFs, const char *filepath, RET enum ModFsErrorCode *err); /* |description| Creates a new file at path `filepath` for the provided `modFs`. Set `text` to true to treat the file as a pure text file, not a binary file. Returns the created file on success |descriptionEnd| */ -struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *filepath, bool text); +struct ModFsFile *mod_fs_create_file(struct ModFs *modFs, const char *filepath, bool text, RET enum ModFsErrorCode *err); /* |description| Moves the file at path `oldpath` to `newpath` of the provided `modFs`. Set `overwriteExisting` to true to overwrite the file at path `newpath` if it exists. Returns true on success |descriptionEnd| */ -bool mod_fs_move_file(struct ModFs *modFs, const char *oldpath, const char *newpath, bool overwriteExisting); +bool mod_fs_move_file(struct ModFs *modFs, const char *oldpath, const char *newpath, bool overwriteExisting, RET enum ModFsErrorCode *err); /* |description| Copies the file at path `srcpath` to `dstpath` of the provided `modFs`. Set `overwriteExisting` to true to overwrite the file at path `dstpath` if it exists. Returns true on success |descriptionEnd| */ -bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const char *dstpath, bool overwriteExisting); +bool mod_fs_copy_file(struct ModFs *modFs, const char *srcpath, const char *dstpath, bool overwriteExisting, RET enum ModFsErrorCode *err); /* |description| Deletes the file at path `filepath` of the provided `modFs`. Returns true on success |descriptionEnd| */ -bool mod_fs_delete_file(struct ModFs *modFs, const char *filepath); +bool mod_fs_delete_file(struct ModFs *modFs, const char *filepath, RET enum ModFsErrorCode *err); /* |description| Deletes all files of the provided `modFs`. Returns true on success |descriptionEnd| */ -bool mod_fs_clear(struct ModFs *modFs); +bool mod_fs_clear(struct ModFs *modFs, RET enum ModFsErrorCode *err); /* |description| Saves the provided `modFs` to persistent storage. Returns true on success |descriptionEnd| */ -bool mod_fs_save(struct ModFs *modFs); +bool mod_fs_save(struct ModFs *modFs, RET enum ModFsErrorCode *err); /* |description| Removes the provided `modFs` from persistent storage and deletes its object. Returns true on success |descriptionEnd| */ -bool mod_fs_delete(struct ModFs *modFs); +bool mod_fs_delete(struct ModFs *modFs, RET enum ModFsErrorCode *err); /* |description| Marks the provided `modFs` as public (i.e. readable by other mods). Returns true on success |descriptionEnd| */ -bool mod_fs_set_public(struct ModFs *modFs, bool pub); +bool mod_fs_set_public(struct ModFs *modFs, bool pub, RET enum ModFsErrorCode *err); /* |description| Reads a boolean from a binary modfs `file` |descriptionEnd| */ -bool mod_fs_file_read_bool(struct ModFsFile *file); +bool mod_fs_file_read_bool(struct ModFsFile *file, RET enum ModFsErrorCode *err); /* |description| Reads an integer from a binary modfs `file`. `intType` must be one of the `INT_TYPE_*` constants |descriptionEnd| */ -lua_Integer mod_fs_file_read_integer(struct ModFsFile *file, enum ModFsFileIntType intType); +lua_Integer mod_fs_file_read_integer(struct ModFsFile *file, enum ModFsFileIntType intType, RET enum ModFsErrorCode *err); /* |description| Reads an floating-point number from a binary modfs `file`. `floatType` must be one of the `FLOAT_TYPE_*` constants |descriptionEnd| */ -lua_Number mod_fs_file_read_number(struct ModFsFile *file, enum ModFsFileFloatType floatType); +lua_Number mod_fs_file_read_number(struct ModFsFile *file, enum ModFsFileFloatType floatType, RET enum ModFsErrorCode *err); /* |description| Reads a bytestring of `length` bytes from a binary modfs `file` |descriptionEnd| */ -ByteString mod_fs_file_read_bytes(struct ModFsFile *file, u32 length); +ByteString mod_fs_file_read_bytes(struct ModFsFile *file, u32 length, RET enum ModFsErrorCode *err); /* |description| Reads a string from a binary modfs `file`, or read the whole content of a text modfs `file` |descriptionEnd| */ -const char *mod_fs_file_read_string(struct ModFsFile *file); +const char *mod_fs_file_read_string(struct ModFsFile *file, RET enum ModFsErrorCode *err); /* |description| Reads a line from a text modfs `file` |descriptionEnd| */ -const char *mod_fs_file_read_line(struct ModFsFile *file); +const char *mod_fs_file_read_line(struct ModFsFile *file, RET enum ModFsErrorCode *err); /* |description| Writes a boolean to a binary modfs `file`. Returns true on success |descriptionEnd| */ -bool mod_fs_file_write_bool(struct ModFsFile *file, bool value); +bool mod_fs_file_write_bool(struct ModFsFile *file, bool value, RET enum ModFsErrorCode *err); /* |description| Writes an integer to a binary modfs `file`. `intType` must be one of the `INT_TYPE_*` constants. Returns true on success |descriptionEnd| */ -bool mod_fs_file_write_integer(struct ModFsFile *file, lua_Integer value, enum ModFsFileIntType intType); +bool mod_fs_file_write_integer(struct ModFsFile *file, lua_Integer value, enum ModFsFileIntType intType, RET enum ModFsErrorCode *err); /* |description| Writes an floating-point number to a binary modfs `file`. `floatType` must be one of the `FLOAT_TYPE_*` constants. Returns true on success |descriptionEnd| */ -bool mod_fs_file_write_number(struct ModFsFile *file, lua_Number value, enum ModFsFileFloatType floatType); +bool mod_fs_file_write_number(struct ModFsFile *file, lua_Number value, enum ModFsFileFloatType floatType, RET enum ModFsErrorCode *err); /* |description| Writes a bytestring to a modfs `file`. Returns true on success |descriptionEnd| */ -bool mod_fs_file_write_bytes(struct ModFsFile *file, ByteString bytestring); +bool mod_fs_file_write_bytes(struct ModFsFile *file, ByteString bytestring, RET enum ModFsErrorCode *err); /* |description| Writes a string to a modfs `file`. Returns true on success |descriptionEnd| */ -bool mod_fs_file_write_string(struct ModFsFile *file, const char *str); +bool mod_fs_file_write_string(struct ModFsFile *file, const char *str, RET enum ModFsErrorCode *err); /* |description| Writes a line to a text modfs `file`. Returns true on success |descriptionEnd| */ -bool mod_fs_file_write_line(struct ModFsFile *file, const char *str); +bool mod_fs_file_write_line(struct ModFsFile *file, const char *str, RET enum ModFsErrorCode *err); /* |description| Sets the current position of a modfs `file`. @@ -238,49 +272,54 @@ If `origin` is `FILE_SEEK_CUR`, `offset` is added to file current position. If `origin` is `FILE_SEEK_END`, file position is set to `end of file + offset`. Returns true on success |descriptionEnd| */ -bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFileSeek origin); +bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFileSeek origin, RET enum ModFsErrorCode *err); /* |description| Sets the current position of a modfs `file` to its beginning. Returns true on success |descriptionEnd| */ -bool mod_fs_file_rewind(struct ModFsFile *file); +bool mod_fs_file_rewind(struct ModFsFile *file, RET enum ModFsErrorCode *err); /* |description| Returns true if the provided modfs `file` has reached its end of file |descriptionEnd| */ -bool mod_fs_file_is_eof(struct ModFsFile *file); +bool mod_fs_file_is_eof(struct ModFsFile *file, RET enum ModFsErrorCode *err); /* |description| Fills a modfs `file` with `byte` repeated `length` times. Returns true on success |descriptionEnd| */ -bool mod_fs_file_fill(struct ModFsFile *file, u8 byte, u32 length); +bool mod_fs_file_fill(struct ModFsFile *file, u8 byte, u32 length, RET enum ModFsErrorCode *err); /* |description| Erases `length` bytes or characters from a modfs `file`. Returns true on success |descriptionEnd| */ -bool mod_fs_file_erase(struct ModFsFile *file, u32 length); +bool mod_fs_file_erase(struct ModFsFile *file, u32 length, RET enum ModFsErrorCode *err); /* |description| Marks the provided modfs `file` as text. Returns true on success |descriptionEnd| */ -bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text); +bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text, RET enum ModFsErrorCode *err); /* |description| Marks the provided modfs `file` as public (i.e. readable by other mods). Returns true on success |descriptionEnd| */ -bool mod_fs_file_set_public(struct ModFsFile *file, bool pub); +bool mod_fs_file_set_public(struct ModFsFile *file, bool pub, RET enum ModFsErrorCode *err); /* |description| -Sets the compression level of the provided modfs `file`. Must be between 0 (no compression) and 9 (most compression). Returns true on success. +Sets the compression level of the provided modfs `file`. Must be between 0 (no compression) and 9 (most compression). Returns true on success |descriptionEnd| */ -bool mod_fs_file_set_compression(struct ModFsFile *file, s32 level); +bool mod_fs_file_set_compression(struct ModFsFile *file, s32 level, RET enum ModFsErrorCode *err); /* |description| Hides script errors raised by `mod_fs` functions. Errors messages are still generated and can be retrieved with `mod_fs_get_last_error()` |descriptionEnd| */ void mod_fs_hide_errors(bool hide); +/* |description| +Returns the last error code raised by `mod_fs` functions +|descriptionEnd| */ +enum ModFsErrorCode mod_fs_get_last_error_code(); + /* |description| Returns the last error message generated by `mod_fs` functions or nil if no error occurred |descriptionEnd| */