Branch: refs/heads/master Author: Jiří Techet techet@gmail.com Committer: Jiří Techet techet@gmail.com Date: Fri, 13 Sep 2024 12:04:54 UTC Commit: 458a77adb0a7c7b3d649bcaedfcbd07604c5dd5f https://github.com/geany/geany/commit/458a77adb0a7c7b3d649bcaedfcbd07604c5dd...
Log Message: ----------- Modify utils_write_file() to always use g_file_replace_contents()
From having a look at where this function is used, by Geany it's used only to store configuration files in the .config directory and some auxiliary functions like writing the export file by the exporter plugin. In the geany-plugins project this function is used only for saving configuration files.
Before this patch, the fwrite() method was used by default for saving configuration files (because g_file_replace_contents() normally used by Geany wasn't used in this function) which wasn't very safe and could lead to configuration file loss under some extreme conditions.
The documentation of this function was changed to reflect the situation better than now - the previous comment made the impression that file permissions were always preserved with this method but it wasn't the case and depended on the exact configuration.
Modified Paths: -------------- src/utils.c
Modified: src/utils.c 69 lines changed, 23 insertions(+), 46 deletions(-) =================================================================== @@ -208,9 +208,12 @@ gboolean utils_is_opening_brace(gchar c, gboolean include_angles) * If the file doesn't exist, it will be created. * If it already exists, it will be overwritten. * - * @warning You should use @c g_file_set_contents() instead if you don't need - * file permissions and other metadata to be preserved, as that always handles - * disk exhaustion safely. + * @warning Currently, this function uses g_file_replace_contents() to save + * files which offers a reasonable balence between data safety during save + * and other factors such as handling symlinks, remote files, or platform- + * dependent aspects. However, plugins with special requirements should + * not rely on the exact implementation of this function and should rather + * implement file saving by themselves. * * @param filename The filename of the file to write, in locale encoding. * @param text The text to write into the file. @@ -221,55 +224,29 @@ gboolean utils_is_opening_brace(gchar c, gboolean include_angles) GEANY_API_SYMBOL gint utils_write_file(const gchar *filename, const gchar *text) { + GError *error = NULL; + gboolean success; + GFile *fp; + g_return_val_if_fail(filename != NULL, ENOENT); g_return_val_if_fail(text != NULL, EINVAL);
- if (file_prefs.use_safe_file_saving) + fp = g_file_new_for_path(filename); + + success = g_file_replace_contents(fp, text, strlen(text), NULL, FALSE, + G_FILE_CREATE_NONE, NULL, NULL, &error); + + g_object_unref(fp); + + if (error) { - GError *error = NULL; - if (! g_file_set_contents(filename, text, -1, &error)) - { - geany_debug("%s: could not write to file %s (%s)", G_STRFUNC, filename, error->message); - g_error_free(error); - return EIO; - } + geany_debug("%s: could not write to file %s (%s)", G_STRFUNC, filename, error->message); + g_error_free(error); } - else - { - FILE *fp; - gsize bytes_written, len; - gboolean fail = FALSE; - - if (filename == NULL) - return ENOENT; - - len = strlen(text); - errno = 0; - fp = g_fopen(filename, "w"); - if (fp == NULL) - fail = TRUE; - else - { - bytes_written = fwrite(text, sizeof(gchar), len, fp); + else if (!success) + geany_debug("%s: could not write to file %s", G_STRFUNC, filename);
- if (len != bytes_written) - { - fail = TRUE; - geany_debug( - "utils_write_file(): written only %"G_GSIZE_FORMAT" bytes, had to write %"G_GSIZE_FORMAT" bytes to %s", - bytes_written, len, filename); - } - if (fclose(fp) != 0) - fail = TRUE; - } - if (fail) - { - geany_debug("utils_write_file(): could not write to file %s (%s)", - filename, g_strerror(errno)); - return FALLBACK(errno, EIO); - } - } - return 0; + return success ? 0 : EIO; }
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).