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| */