diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 406b58fd..1502301b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,10 +31,10 @@ jobs: # if this check fails, you have to update the number of auto types known and the list of auto types in the check below - name: Check auto types are up-to-date run: | - [[ "$(find src -type f -name '*.[ch]' -exec awk '/^#define auto_[\W]*/ {print $2}' '{}' \; | sort -u | wc -l)" == "6" ]] || exit -1 + [[ "$(find src -type f -name '*.[ch]' -exec awk '/^#define auto_[\W]*/ {print $2}' '{}' \; | sort -u | wc -l)" == "8" ]] || exit -1 - name: Check auto types are initialized run: | - grep -P 'auto_(char|gchar|gcharv|guchar|jid|sqlite)[\w *]*;$' -r src && exit -1 || true + grep -P 'auto_(char|gchar|gcharv|guchar|jid|sqlite|gfd|FILE)[\w *]*;$' -r src && exit -1 || true - name: Run clang-format uses: jidicula/clang-format-action@v4.11.0 with: diff --git a/src/common.c b/src/common.c index 97447381..85bc60e0 100644 --- a/src/common.c +++ b/src/common.c @@ -130,6 +130,36 @@ auto_free_char(char** str) free(*str); } +/** + * Closes the file descriptor. + * + * @param fd file descriptor handle. If NULL, no action is taken. + */ +void +auto_close_gfd(gint* fd) +{ + if (fd == NULL) + return; + + if (close(*fd) == EOF) + log_error(g_strerror(errno)); +} + +/** + * Closes file stream + * + * @param fd file descriptor handle opened with fopen. If NULL, no action is taken. + */ +void +auto_close_FILE(FILE** fd) +{ + if (fd == NULL) + return; + + if (fclose(*fd) == EOF) + log_error(g_strerror(errno)); +} + static gboolean _load_keyfile(prof_keyfile_t* keyfile) { diff --git a/src/common.h b/src/common.h index 5996c5d5..9ebafa66 100644 --- a/src/common.h +++ b/src/common.h @@ -104,6 +104,14 @@ void auto_free_guchar(guchar** str); */ #define auto_guchar __attribute__((__cleanup__(auto_free_guchar))) +#define auto_gfd __attribute__((__cleanup__(auto_close_gfd))) + +void auto_close_gfd(gint* fd); + +#define auto_FILE __attribute__((__cleanup__(auto_close_FILE))) + +void auto_close_FILE(FILE** fd); + #if defined(__OpenBSD__) #define STR_MAYBE_NULL(p) (p) ?: "(null)" #else diff --git a/src/tools/aesgcm_download.c b/src/tools/aesgcm_download.c index 7fdc7174..04e837cc 100644 --- a/src/tools/aesgcm_download.c +++ b/src/tools/aesgcm_download.c @@ -64,8 +64,8 @@ aesgcm_file_get(void* userdata) { AESGCMDownload* aesgcm_dl = (AESGCMDownload*)userdata; - char* https_url = NULL; - char* fragment = NULL; + auto_char char* https_url = NULL; + auto_char char* fragment = NULL; // Convert the aesgcm:// URL to a https:// URL and extract the encoded key // and tag stored in the URL fragment. @@ -79,8 +79,8 @@ aesgcm_file_get(void* userdata) // Create a temporary file used for storing the ciphertext that is to be // retrieved from the https:// URL. - gchar* tmpname = NULL; - gint tmpfd; + auto_gchar char* tmpname = NULL; + auto_gfd gint tmpfd = 0; if ((tmpfd = g_file_open_tmp("profanity.XXXXXX", &tmpname, NULL)) == -1) { http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, "Downloading '%s' failed: Unable to create " @@ -91,7 +91,7 @@ aesgcm_file_get(void* userdata) } // Open the target file for storing the cleartext. - FILE* outfh = fopen(aesgcm_dl->filename, "wb"); + auto_FILE FILE* outfh = fopen(aesgcm_dl->filename, "wb"); if (outfh == NULL) { http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, "Downloading '%s' failed: Unable to open " @@ -115,16 +115,13 @@ aesgcm_file_get(void* userdata) http_file_get(http_dl); // TODO(wstrm): Verify result. - FILE* tmpfh = fopen(tmpname, "rb"); + auto_FILE FILE* tmpfh = fopen(tmpname, "rb"); if (tmpfh == NULL) { http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, "Downloading '%s' failed: Unable to open " "temporary file at '%s' for reading (%s).", aesgcm_dl->url, tmpname, g_strerror(errno)); - if (fclose(outfh) == EOF) { - cons_show_error(g_strerror(errno)); - } return NULL; } @@ -132,11 +129,6 @@ aesgcm_file_get(void* userdata) crypt_res = omemo_decrypt_file(tmpfh, outfh, http_dl->bytes_received, fragment); - if (fclose(tmpfh) == EOF) { - cons_show_error(g_strerror(errno)); - } - - close(tmpfd); remove(tmpname); g_free(tmpname); @@ -147,13 +139,6 @@ aesgcm_file_get(void* userdata) https_url, gcry_strerror(crypt_res)); } - if (fclose(outfh) == EOF) { - cons_show_error(g_strerror(errno)); - } - - free(https_url); - free(fragment); - if (aesgcm_dl->cmd_template != NULL) { gchar** argv = format_call_external_argv(aesgcm_dl->cmd_template, aesgcm_dl->filename,