diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 83a136b96..f26ff618f 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -70,3 +70,27 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONARQUBE_SCANNER_PARAMS: '{"sonar.host.url":"https://sonarcloud.io"}' + custom-anaysis: + name: Custom Analysis + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: "@since standardization" + run: | + # look for all instances of @since, then look for any that do not meet the required pattern. @since release x.x.x + if grep --include=\*.{c,h,cpp,hpp} -rnw . -e ".*@since .*" | grep -qv ".* @since release v[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]].*"; then + # at this point the check has failed, but we want to give some info to the user. i have found it difficult to get the status code + # and print out the offending lines without this duplication + # get all instances of @since, offending and not offending + grep --include=\*.{c,h,cpp,hpp} -rnw . -e "@since .*" | \ + # find all instances that do not meet the required pattern + grep -v ".* @since release v[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]].*" | \ + # print an error message, including line number with -n from grep. mention supported format. + xargs -I{} echo "Static Analysis Failed: \"{}\" Supported format is \"@since release vX.X.X\"" + exit 1 + else + exit 0 + fi + diff --git a/ChangeLog.md b/ChangeLog.md index 76cb6ebf8..ec5ab6617 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,13 +4,13 @@ All notable changes to stumpless will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased For a detailed look at the project's future, including planned features and bug fixes, check out the [roadmap](https://github.com/goatshriek/stumpless/blob/master/docs/roadmap.md). - ## [2.2.0] - 2023-08-08 +### Added + - @since format check enforcement in CI pipeline. ### Fixed - Deadlock potential in `stumpless_set_entry_hostname` and `stumpless_set_entry_procid` when validation fails. diff --git a/include/private/config/journald_supported.h b/include/private/config/journald_supported.h index 74103cc25..f21da3683 100644 --- a/include/private/config/journald_supported.h +++ b/include/private/config/journald_supported.h @@ -36,7 +36,7 @@ * This function is safe to call from threads that may be asynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param element The element to initialize. */ @@ -57,7 +57,7 @@ journald_init_journald_element( struct stumpless_element *element ); * This function is safe to call from threads that may be asynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param param The param to initialize. */ diff --git a/include/private/config/locale/bg-bg.h b/include/private/config/locale/bg-bg.h index 3e1d4fd30..64d946876 100644 --- a/include/private/config/locale/bg-bg.h +++ b/include/private/config/locale/bg-bg.h @@ -116,6 +116,10 @@ "a MULTI_SZ registry value was neither empty nor terminated with two NULL" \ " characters" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "невалидната тежест" diff --git a/include/private/config/locale/bn-in.h b/include/private/config/locale/bn-in.h index ad5e50c82..ad09ea933 100644 --- a/include/private/config/locale/bn-in.h +++ b/include/private/config/locale/bn-in.h @@ -16,8 +16,8 @@ * limitations under the License. */ -#ifndef __STUMPLESS_PRIVATE_CONFIG_LOCALE_EN_US_H -# define __STUMPLESS_PRIVATE_CONFIG_LOCALE_EN_US_H +#ifndef __STUMPLESS_PRIVATE_CONFIG_LOCALE_BN_IN_H +# define __STUMPLESS_PRIVATE_CONFIG_LOCALE_BN_IN_H # define L10N_BIND_UNIX_SOCKET_FAILED_ERROR_MESSAGE \ "স্থানীয় ইউনিক্স সকেটের"\ @@ -113,6 +113,10 @@ "একটি MULTI_SZ রেজিস্ট্রি মান খালি ছিল না" \ "বা দুটি NULL অক্ষর দিয়ে শেষ করা হয়নি" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "অসফল severity" @@ -259,4 +263,4 @@ L"উইন্ডোজ ইভেন্ট লগ সোর্সের স্ # define L10N_WSAGETLASTERROR_ERROR_CODE_TYPE \ "ব্যর্থ কলের পরে WSAGEtLastError এর ফলাফল" -#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_BN_IN_H */ +#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_BN_IN_H */ diff --git a/include/private/config/locale/cz-cz.h b/include/private/config/locale/cz-cz.h index 0eb396474..eb6d8edc1 100644 --- a/include/private/config/locale/cz-cz.h +++ b/include/private/config/locale/cz-cz.h @@ -112,6 +112,10 @@ "a MULTI_SZ registry value was neither empty nor terminated with two NULL" \ " characters" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "neplatná služba" @@ -268,4 +272,4 @@ L"Stumpless registration of Windows Event Log Source" # define L10N_WSAGETLASTERROR_ERROR_CODE_TYPE \ "výsledek WSAGetLastError po selhání volání" -#endif //STUMPLESS_CZ_CZ_H +#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_CZ_CZ_H */ diff --git a/include/private/config/locale/da-dk.h b/include/private/config/locale/da-dk.h index 5a3be3d0f..6b602d708 100644 --- a/include/private/config/locale/da-dk.h +++ b/include/private/config/locale/da-dk.h @@ -108,6 +108,10 @@ "en MULTI_SZ registreringsdatabase værdi var hverken tom eller Afsluttet " \ " characters med to NULL's" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "den ugyldige alvorlighed" diff --git a/include/private/config/locale/de-de.h b/include/private/config/locale/de-de.h index e999165df..9745cafe9 100644 --- a/include/private/config/locale/de-de.h +++ b/include/private/config/locale/de-de.h @@ -123,6 +123,10 @@ "a MULTI_SZ registry value was neither empty nor terminated with two NULL" \ " characters" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "Ungültiger Schweregrad" diff --git a/include/private/config/locale/el-gr.h b/include/private/config/locale/el-gr.h index 96dbf2106..eebedc8fe 100644 --- a/include/private/config/locale/el-gr.h +++ b/include/private/config/locale/el-gr.h @@ -114,6 +114,10 @@ "a MULTI_SZ registry value was neither empty nor terminated with two NULL" \ " characters" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "μη έγκυρη σοβαρότητα" @@ -271,4 +275,4 @@ L"Stumpless registration of Windows Event Log Source" # define L10N_WSAGETLASTERROR_ERROR_CODE_TYPE \ "το αποτέλεσμα της WSAGetLastError εφόσον απότυχε η κλήση της συνάρτησης" -#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_EN_US_H */ \ No newline at end of file +#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_EL_GR_H */ diff --git a/include/private/config/locale/en-us.h b/include/private/config/locale/en-us.h index d932cc0af..2af5597bb 100644 --- a/include/private/config/locale/en-us.h +++ b/include/private/config/locale/en-us.h @@ -112,6 +112,9 @@ "a MULTI_SZ registry value was neither empty nor terminated with two NULL" \ " characters" +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "the invalid severity" diff --git a/include/private/config/locale/es-es.h b/include/private/config/locale/es-es.h index 854dcd88f..a03f6a1e5 100644 --- a/include/private/config/locale/es-es.h +++ b/include/private/config/locale/es-es.h @@ -108,6 +108,10 @@ # define L10N_INVALID_MULTI_SZ_ERROR_MESSAGE \ "un valor de registro MULTI_SZ no estaba ni vacío ni terminado con dos NULL" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "la gravedad inválida" @@ -253,4 +257,4 @@ L"registro de Stumpless del Registro de Eventos de Windows" # define L10N_WSAGETLASTERROR_ERROR_CODE_TYPE \ "el resultado de WSAGetLastError despues que la llamada fallara" -#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_ES_ES_H */ +#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_ES_ES_H */ diff --git a/include/private/config/locale/fr-fr.h b/include/private/config/locale/fr-fr.h index 2b81de3f5..ce041936e 100644 --- a/include/private/config/locale/fr-fr.h +++ b/include/private/config/locale/fr-fr.h @@ -107,6 +107,10 @@ # define L10N_INVALID_MULTI_SZ_ERROR_MESSAGE \ "la valeur d'un registre MULTI_SZ n'était ni vide ni terminée par deux NULL" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "la sévérité invalide" diff --git a/include/private/config/locale/he-il.h b/include/private/config/locale/he-il.h index 452bd6c86..4b79bcce6 100644 --- a/include/private/config/locale/he-il.h +++ b/include/private/config/locale/he-il.h @@ -110,6 +110,10 @@ # define L10N_INVALID_MULTI_SZ_ERROR_MESSAGE \ "NULL לא היה ריק ולא הסתיים עם שני תווי MULTI_SZ ערך רישום של" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "שאינו חוקי Severity-ה" diff --git a/include/private/config/locale/hi-in.h b/include/private/config/locale/hi-in.h index 7401c93ba..31e3949a8 100644 --- a/include/private/config/locale/hi-in.h +++ b/include/private/config/locale/hi-in.h @@ -109,6 +109,10 @@ "एक MULTI_SZ रजिस्ट्री मान न तो खाली था और न ही दो NULL" \ " अक्षर " +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "अमान्य गंभीरता" diff --git a/include/private/config/locale/it-it.h b/include/private/config/locale/it-it.h index b4469f534..7eb41dd5d 100644 --- a/include/private/config/locale/it-it.h +++ b/include/private/config/locale/it-it.h @@ -108,6 +108,10 @@ "un valore MULTI_SZ nel registro non è nè vuoto nè terminato con due" \ " caratteri nullo" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "gravità non valida" diff --git a/include/private/config/locale/pl-pl.h b/include/private/config/locale/pl-pl.h index 1544f03f8..9d1fdd1ce 100644 --- a/include/private/config/locale/pl-pl.h +++ b/include/private/config/locale/pl-pl.h @@ -114,6 +114,10 @@ "a MULTI_SZ registry value was neither empty nor terminated with two NULL" \ " characters" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "nieprawidłowa usługa" @@ -271,4 +275,4 @@ L"Stumpless registration of Windows Event Log Source" # define L10N_WSAGETLASTERROR_ERROR_CODE_TYPE \ "wynik WSAGetLastError po niepowodzeniu połączenia" -#endif //STUMPLESS_PL_PL_H +#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_PL_PL_H */ diff --git a/include/private/config/locale/pt-br.h b/include/private/config/locale/pt-br.h index 14892bef1..7994a130c 100644 --- a/include/private/config/locale/pt-br.h +++ b/include/private/config/locale/pt-br.h @@ -108,6 +108,10 @@ "um valor de registro MULTI_SZ não estava nem vazio nem finalizado" \ "com dois caracteres NULL" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "a gravidade inválida" @@ -253,4 +257,4 @@ L"Registro do Stumpless no Windows Event Log Source" # define L10N_WSAGETLASTERROR_ERROR_CODE_TYPE \ "o resultado de WSAGetLastError depois da chamada com erro" -#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_EN_US_H */ +#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_PT_BR_H */ diff --git a/include/private/config/locale/sk-sk.h b/include/private/config/locale/sk-sk.h index 47359ba3a..59a41e0cc 100644 --- a/include/private/config/locale/sk-sk.h +++ b/include/private/config/locale/sk-sk.h @@ -122,6 +122,10 @@ "a MULTI_SZ registry value was neither empty nor terminated with two NULL" \ " characters" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "neplatná služba" @@ -284,4 +288,4 @@ L"Stumpless registration of Windows Event Log Source" # define L10N_WSAGETLASTERROR_ERROR_CODE_TYPE \ "výsledok WSAGetLastError po zlyhaní volania" -#endif //STUMPLESS_SK_SK_H +#endif /* __STUMPLESS_PRIVATE_CONFIG_LOCALE_SK_SK_H */ diff --git a/include/private/config/locale/sv-se.h b/include/private/config/locale/sv-se.h index 83c6c5ad3..d8129a46a 100644 --- a/include/private/config/locale/sv-se.h +++ b/include/private/config/locale/sv-se.h @@ -123,6 +123,10 @@ "a MULTI_SZ registry value was neither empty nor terminated with two NULL" \ " characters" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "den ogiltiga allvarligheten" diff --git a/include/private/config/locale/sw-ke.h b/include/private/config/locale/sw-ke.h index 1b27e9395..01e0ea535 100644 --- a/include/private/config/locale/sw-ke.h +++ b/include/private/config/locale/sw-ke.h @@ -112,6 +112,10 @@ "thamani ya usajili wa MULTI_SZ haikuwa tupu wala haikumalizika na herufi" \ " mbili za NULL" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "ukali batili" diff --git a/include/private/config/locale/zh-cn.h b/include/private/config/locale/zh-cn.h index 56fda7e6d..e34765cfe 100644 --- a/include/private/config/locale/zh-cn.h +++ b/include/private/config/locale/zh-cn.h @@ -112,6 +112,10 @@ # define L10N_INVALID_MULTI_SZ_ERROR_MESSAGE \ "MULTI_SZ注册表值既不为空,也不以两个NULL字符结束" +// todo translate +# define L10N_INVALID_PARAM_ERROR_MESSAGE \ +"the string is not of the name=\"value\" format" + # define L10N_INVALID_SEVERITY_ERROR_CODE_TYPE \ "severity无效" diff --git a/include/private/error.h b/include/private/error.h index 4a3b7a271..90f1cd2a1 100644 --- a/include/private/error.h +++ b/include/private/error.h @@ -145,6 +145,10 @@ COLD_FUNCTION void raise_invalid_id( void ); +COLD_FUNCTION +void +raise_invalid_param( void ); + COLD_FUNCTION void raise_invalid_severity( int severity ); @@ -313,7 +317,7 @@ raise_windows_failure( const char *message, int code, const char *code_type ); * cancelled, as the lock used to control access to the error stream may not * be released after a cancellation. * - * @since v2.1.0. + * @since release v2.1.0. * * @param msg The message to be written to the error stream. * diff --git a/include/private/target/journald.h b/include/private/target/journald.h index d098e4676..4bd38cded 100644 --- a/include/private/target/journald.h +++ b/include/private/target/journald.h @@ -37,7 +37,7 @@ * This function is safe to call from threads that may be asynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param flattened A buffer to write the flattened name to. * @@ -65,7 +65,7 @@ get_journald_field_name( char *flattened, const char *raw, size_t size ); * This function is not safe to call from threads that may be asynchronously * cancelled, as the memory allocation function may not be AC-Safe itself. * - * @since v2.1.0 + * @since release v2.1.0 * * @param field_count The number of fields the buffer must have. */ @@ -87,7 +87,7 @@ init_fields( size_t field_count ); * This function is not safe to call from threads that may be asynchronously * cancelled, as the memory allocation function may not be AC-Safe itself. * - * @since v2.1.0 + * @since release v2.1.0 */ void init_fixed_fields( void ); @@ -107,7 +107,7 @@ init_fixed_fields( void ); * This function is not safe to call from threads that may be asynchronously * cancelled, as the memory deallocation function may not be AC-Safe itself. * - * @since v2.1.0 + * @since release v2.1.0 */ void journald_free_thread( void ); @@ -127,7 +127,7 @@ journald_free_thread( void ); * Logging to journald targets is not async cancellation safe as it uses locks * that may not be released if a thread is cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry to load the facility from. */ @@ -149,7 +149,7 @@ load_facility( const struct stumpless_entry *entry ); * Logging to journald targets is not async cancellation safe as it uses locks * that may not be released if a thread is cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry to load the identifier from. */ @@ -171,7 +171,7 @@ load_identifier( const struct stumpless_entry *entry ); * Logging to journald targets is not async cancellation safe as it uses locks * that may not be released if a thread is cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry to load the message from. * @@ -196,7 +196,7 @@ load_message( const struct stumpless_entry *entry ); * Logging to journald targets is not async cancellation safe as it uses locks * that may not be released if a thread is cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry to load the msgid from. */ @@ -215,7 +215,7 @@ load_msgid( const struct stumpless_entry *entry ); * **Async Cancel Safety: AC-Safe** * Logging to journald targets is async cancellation safe. * - * @since v2.1.0 + * @since release v2.1.0 * * @return The size of the loaded pid, including the field prefix. */ @@ -237,7 +237,7 @@ load_pid( void ); * Logging to journald targets is not async cancellation safe as it uses locks * that may not be released if a thread is cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry to load the priority from. */ @@ -260,7 +260,7 @@ load_priority( const struct stumpless_entry *entry ); * Logging to journald targets is not async cancellation safe as it uses locks * that may not be released if a thread is cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry to load the fields from. * @@ -284,7 +284,7 @@ load_sd_fields( const struct stumpless_entry *entry ); * **Async Cancel Safety: AC-Safe** * Logging to journald targets is async cancellation safe. * - * @since v2.1.0 + * @since release v2.1.0 * * @return The size of the loaded timestamp, including the field prefix. */ @@ -305,7 +305,7 @@ load_timestamp( void ); * Logging to journald targets is not async cancellation safe as it relies on * sd_journal_sendv which is not documented as such. * - * @since v2.1.0 + * @since release v2.1.0 * * @param target Where to send the entry. * @@ -334,7 +334,7 @@ send_entry_to_journald_target( const struct stumpless_target *target, * This function is not async cancellation safe as it may leave the buffers in * an inconsistent state. * - * @since v2.1.0 + * @since release v2.1.0 */ void set_field_bases( void ); diff --git a/include/stumpless/config/journald_supported.h b/include/stumpless/config/journald_supported.h index 61b2b2f01..3bf1a6caa 100644 --- a/include/stumpless/config/journald_supported.h +++ b/include/stumpless/config/journald_supported.h @@ -48,7 +48,7 @@ extern "C" { * This function is not safe to call from threads that may be asynchronously * cancelled, due to the use of a lock which could be left locked. * - * @since v2.1.0 + * @since release v2.1.0 * * @param element The element to get the function of. * @@ -76,7 +76,7 @@ stumpless_get_element_journald_namer( const struct stumpless_element *element ); * This function is not safe to call from threads that may be asynchronously * cancelled, due to the use of a lock which could be left locked. * - * @since v2.1.0 + * @since release v2.1.0 * * @param param The param to get the function of. * @@ -104,7 +104,7 @@ stumpless_get_param_journald_namer( const struct stumpless_param *param ); * This function is not safe to call from threads that may be asynchronously * cancelled, due to the use of a lock which could be left locked. * - * @since v2.1.0 + * @since release v2.1.0 * * @param element The element to set the function of. * @@ -134,7 +134,7 @@ stumpless_set_element_journald_namer( struct stumpless_element *element, * This function is not safe to call from threads that may be asynchronously * cancelled, due to the use of a lock which could be left locked. * - * @since v2.1.0 + * @since release v2.1.0 * * @param param The param to set the function of. * diff --git a/include/stumpless/element.h b/include/stumpless/element.h index 3e9b913d3..d3f9674fd 100644 --- a/include/stumpless/element.h +++ b/include/stumpless/element.h @@ -61,7 +61,7 @@ struct stumpless_entry; * This function must be safe to call from threads that may be asynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry that the param is part of. * diff --git a/include/stumpless/entry.h b/include/stumpless/entry.h index 29a1d286f..8a556fe55 100644 --- a/include/stumpless/entry.h +++ b/include/stumpless/entry.h @@ -953,7 +953,7 @@ stumpless_load_entry( struct stumpless_entry *entry, * This function has the same behavior as stumpless_load_entry_str, except it * does not create a new entry, instead loading an existing struct. * - * @since version v2.2.0 + * @since release v2.2.0 * * @param facility The facility code of the event this entry describes. This * should be a \c STUMPLESS_FACILITY value. @@ -1056,7 +1056,7 @@ stumpless_new_entry( enum stumpless_facility facility, * This function is not safe to call from threads that may be asynchronously * cancelled, due to the use of memory management functions. * - * @since version v2.1.0 + * @since release v2.1.0 * * @param facility The facility code of the event this entry describes. This * should be a \c STUMPLESS_FACILITY value. diff --git a/include/stumpless/error.h b/include/stumpless/error.h index 2286a7e36..1863cc8d0 100644 --- a/include/stumpless/error.h +++ b/include/stumpless/error.h @@ -126,8 +126,13 @@ extern "C" { * * @since release v2.1.0 */\ - ERROR( STUMPLESS_WINDOWS_FAILURE, 28 ) - + ERROR( STUMPLESS_WINDOWS_FAILURE, 28 ) \ +/** + * The format of the given string is incorrect. + * + * @since release v2.2.0 + */\ + ERROR( STUMPLESS_INVALID_PARAM_STRING, 29 ) /** * An (enum) identifier of the types of errors that might be encountered. @@ -203,7 +208,7 @@ stumpless_get_error( void ); * This function is safe to call from threads that may be asynchronously * cancelled. * - * @since Release v1.5.0 + * @since release v1.5.0 * * @param err The error to get the id from. This must not be NULL. * @@ -228,7 +233,7 @@ stumpless_get_error_id( const struct stumpless_error *err ); * This function is safe to call from threads that may be asynchronously * cancelled. * - * @since Release v1.6.0 + * @since release v1.6.0 * * @param id The error id to get the error string from. * diff --git a/include/stumpless/param.h b/include/stumpless/param.h index 20f0c008d..948614c70 100644 --- a/include/stumpless/param.h +++ b/include/stumpless/param.h @@ -59,7 +59,7 @@ struct stumpless_entry; * This function must be safe to call from threads that may be asynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry that the param is part of. * @@ -328,6 +328,34 @@ STUMPLESS_PUBLIC_FUNCTION struct stumpless_param * stumpless_new_param( const char *name, const char *value ); +/** + * Creates a new param given a string by parsing the string and calling stumpless_new_param. + * + * **Thread Safety: MT-Safe + * This function is thread safe, assuming the the given string is not changed + * by other threads during execution. + * + * **Async Signal Safety: AS-Unsafe heap** + * This function is not safe to call from signal handlers since it calls + * stumpless_new_param() which has usage of memory management functions. + * + * **Async Cancel Safety: AC_Unsafe heap** + * This function is not safe to call from threads that may be asynchronously + * cancelled, since it calls stumpless_new_param() which has usage of + * memory management functions. + * + * @since release v2.2.0 + * + * @param string The string to create the stumpless_param from. + * + * @return The created param, if no error is encountered. If an error is + * encountered, NULL is returned and an error code set appropriately. + */ + +STUMPLESS_PUBLIC_FUNCTION +struct stumpless_param * +stumpless_new_param_from_string( const char *string ); + /** * Sets the name of the given param. * diff --git a/include/stumpless/target.h b/include/stumpless/target.h index 9ec701adf..cd4801395 100644 --- a/include/stumpless/target.h +++ b/include/stumpless/target.h @@ -466,7 +466,7 @@ stumpless_close_target( struct stumpless_target *target ); * This function is safe to call from threads that may be ansynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @return The current stream where messages are logged to on setting the * the CONS option. @@ -811,7 +811,7 @@ stumpless_open_target( struct stumpless_target *target ); * This function is safe to call from threads that may be ansynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param stream The stream to write logs to. If this is NULL then the messages * intended for the console stream will be ignored. diff --git a/include/stumpless/target/function.h b/include/stumpless/target/function.h index 0193839cd..9350f994f 100644 --- a/include/stumpless/target/function.h +++ b/include/stumpless/target/function.h @@ -73,7 +73,7 @@ typedef int ( *stumpless_log_func_t )( const struct stumpless_target *, * This function is not safe to call from threads that may be asynchronously * cancelled, as the memory deallocation function may not be AC-Safe itself. * - * @since v2.1.0 + * @since release v2.1.0 * * @param target The function target to close. */ @@ -102,7 +102,7 @@ stumpless_close_function_target( const struct stumpless_target *target ); * This function is not safe to call from threads that may be asynchronously * cancelled, as the memory allocation function may not be AC-Safe itself. * - * @since v2.1.0 + * @since release v2.1.0 * * @param name The name of the logging target. * diff --git a/include/stumpless/target/journald.h b/include/stumpless/target/journald.h index 5387a747f..d25504c84 100644 --- a/include/stumpless/target/journald.h +++ b/include/stumpless/target/journald.h @@ -69,7 +69,7 @@ extern "C" { * This function is not safe to call from threads that may be asynchronously * cancelled, as the memory deallocation function may not be AC-Safe itself. * - * @since v2.1.0 + * @since release v2.1.0 * * @param target The journald target to close. */ @@ -98,7 +98,7 @@ stumpless_close_journald_target( const struct stumpless_target *target ); * This function is safe to call from threads that may be asynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry that the param is part of. * @@ -144,7 +144,7 @@ stumpless_flatten_element_name( const struct stumpless_entry *entry, * This function is safe to call from threads that may be asynchronously * cancelled. * - * @since v2.1.0 + * @since release v2.1.0 * * @param entry The entry that the param is part of. * @@ -185,7 +185,7 @@ stumpless_flatten_param_name( const struct stumpless_entry *entry, * This function is not safe to call from threads that may be asynchronously * cancelled, as the memory allocation function may not be AC-Safe itself. * - * @since v2.1.0 + * @since release v2.1.0 * * @param name The name of the logging target. * diff --git a/src/error.c b/src/error.c index 4c3f6585b..71e7e68e4 100644 --- a/src/error.c +++ b/src/error.c @@ -399,3 +399,11 @@ write_to_error_stream( const char *msg, size_t msg_size ) { config_write_bool( &error_stream_free, true ); } + +void +raise_invalid_param( void ) { + raise_error( STUMPLESS_INVALID_PARAM_STRING, + L10N_INVALID_PARAM_ERROR_MESSAGE, + 0, + NULL ); +} diff --git a/src/param.c b/src/param.c index d2f05d5a4..174808b96 100644 --- a/src/param.c +++ b/src/param.c @@ -142,6 +142,76 @@ stumpless_new_param( const char *name, const char *value ) { return result; } +struct stumpless_param * +stumpless_new_param_from_string( const char *string ) { + + VALIDATE_ARG_NOT_NULL( string ); + + int i; + size_t name_len = 0; + size_t name_start = 0; + size_t value_len = 0; + size_t value_start = 0; + char *name; + char *value; + struct stumpless_param *result; + + /* Check that the characters in 'name' are allowed. */ + for (i = 0; string[i] != '='; i++) { + if (!((string[i] >= 'a' && string[i] <= 'z') || + (string[i] >= 'A' && string[i] <= 'Z') || + (string[i] >= '0' && string[i] <= '9') || + (string[i] == '-') || + (string[i] == '.') || + (string[i] == '_'))){ + raise_invalid_param( ); + return NULL; + } + } + + /* Check if the character after the '=' is '"', else raise an error. */ + if (string[i + 1] != '"'){ + raise_invalid_param( ); + return NULL; + } + + name_len = i; + /* We add 1 to the length for the '\0' character. */ + name = alloc_mem( name_len + 1 ); + /* We make this addition to skip '=' and '"' characters. */ + i += 2; + value_start = i; + + /* Iterate to the end of the 'value' string. */ + //for (; string[i] != '\0'; i++){} + while (string[i] != '\0'){ + i++; + } + /* If the final character isn't '"' we raise an error. */ + if (string[i - 1] != '"') { + raise_invalid_param( ); + /* We need to free name here to avoid memory leaks */ + free_mem( name ); + return NULL; + } else { + /* We make this substraction for the 2 '"' characters and for the '=' character. */ + value_len = i - name_len - 3; + } + + /* We add 1 to the length for the '\0' character. */ + value = alloc_mem( value_len + 1 ); + + memcpy(name, string + name_start, name_len); + name[name_len] = '\0'; + memcpy(value, string + value_start, value_len); + value[value_len] = '\0'; + result = stumpless_new_param(name, value); + free_mem( name ); + free_mem( value ); + + return result; +} + struct stumpless_param * stumpless_set_param_name( struct stumpless_param *param, const char *name ) { size_t new_size; diff --git a/src/windows/stumpless.def b/src/windows/stumpless.def index 5397d84d8..082988721 100644 --- a/src/windows/stumpless.def +++ b/src/windows/stumpless.def @@ -212,10 +212,11 @@ EXPORTS stumpless_set_entry_hostname @197 ; added in v2.2.0 - stumpless_load_element @198 - stumpless_load_entry @199 - stumpless_load_entry_str @200 - stumpless_load_param @201 + stumpless_new_param_from_string @198 + stumpless_load_element @199 + stumpless_load_entry @200 + stumpless_load_entry_str @201 + stumpless_load_param @202 stumpless_unload_element_and_contents @203 stumpless_unload_element_only @204 stumpless_unload_entry_and_contents @205 diff --git a/test/function/param.cpp b/test/function/param.cpp index e377c5ce7..b30f094c0 100644 --- a/test/function/param.cpp +++ b/test/function/param.cpp @@ -628,4 +628,90 @@ namespace { stumpless_free_all( ); } + + TEST( ParamFromStringTest, New ) { + struct stumpless_param *param; + const char *param_string = "test-param-name=\"test-param-value\""; + + size_t name_length = strlen("test-param-name"); + size_t value_length = strlen("test-param-value"); + + param = stumpless_new_param_from_string( param_string ); + ASSERT_NOT_NULL( param ); + EXPECT_NO_ERROR; + + ASSERT_EQ( name_length, param->name_length ); + ASSERT_NOT_NULL( param->name ); + ASSERT_EQ( 0, memcmp( param->name, "test-param-name", name_length ) ); + + ASSERT_EQ( value_length, param->value_length ); + ASSERT_NOT_NULL( param->value ); + ASSERT_EQ( 0, memcmp( param->value, "test-param-value", value_length ) ); + + stumpless_destroy_param( param ); + + stumpless_free_all( ); + } + + TEST( ParamFromStringTest, NullName ) { + struct stumpless_param *param; + const struct stumpless_error *error; + + param = stumpless_new_param_from_string( NULL ); + + EXPECT_ERROR_ID_EQ( STUMPLESS_ARGUMENT_EMPTY ); + + stumpless_destroy_param( param ); + + stumpless_free_all( ); + } + + TEST( ParamFromStringTest, InvalidName ) { + struct stumpless_param *param; + const struct stumpless_error *error; + + param = stumpless_new_param_from_string( "test-param-na=me=\"test-param-value\"" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "test-param-name\"test-param-value\"" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "test-param]-name=\"test-value\"" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "test-p\"aram-name=\"test-value\"" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "!test-param-name=\"test-value\"" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "test-param,name=\"test-value\"" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "test-param-name%%=\"test-value\"" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "test-param-name==\"test-value\"" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "test-param-name=\"test-value" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + param = stumpless_new_param_from_string( "" ); + EXPECT_NULL( param ); + EXPECT_ERROR_ID_EQ( STUMPLESS_INVALID_PARAM_STRING ); + + stumpless_destroy_param( param ); + + stumpless_free_all( ); + } }