From da536e7e42eadff302b4da013d256bc89e2dfebe Mon Sep 17 00:00:00 2001 From: Soeren Sandmann Date: Sun, 17 Apr 2005 00:16:51 +0000 Subject: [PATCH] Save the errno in various places Sat Apr 16 20:15:44 2005 Soeren Sandmann * glib/gfileutils.c (g_file_replace): Save the errno in various places * glib/gfileutils.c (set_umask_permissions): Fork a child and do chmod() to the umask() permissions there. --- ChangeLog | 8 +++ ChangeLog.pre-2-10 | 8 +++ ChangeLog.pre-2-12 | 8 +++ ChangeLog.pre-2-8 | 8 +++ glib/gfileutils.c | 153 ++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 170 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index a69d097c2..610b1f99a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Sat Apr 16 20:15:44 2005 Soeren Sandmann + + * glib/gfileutils.c (g_file_replace): Save the errno in various + places + + * glib/gfileutils.c (set_umask_permissions): Fork a child and do + chmod() to the umask() permissions there. + 2005-04-10 Matthias Clasen * glib/gmessages.h (g_debug): Use G_LOG_LEVEL_DEBUG in diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index a69d097c2..610b1f99a 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,11 @@ +Sat Apr 16 20:15:44 2005 Soeren Sandmann + + * glib/gfileutils.c (g_file_replace): Save the errno in various + places + + * glib/gfileutils.c (set_umask_permissions): Fork a child and do + chmod() to the umask() permissions there. + 2005-04-10 Matthias Clasen * glib/gmessages.h (g_debug): Use G_LOG_LEVEL_DEBUG in diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index a69d097c2..610b1f99a 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,11 @@ +Sat Apr 16 20:15:44 2005 Soeren Sandmann + + * glib/gfileutils.c (g_file_replace): Save the errno in various + places + + * glib/gfileutils.c (set_umask_permissions): Fork a child and do + chmod() to the umask() permissions there. + 2005-04-10 Matthias Clasen * glib/gmessages.h (g_debug): Use G_LOG_LEVEL_DEBUG in diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index a69d097c2..610b1f99a 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,11 @@ +Sat Apr 16 20:15:44 2005 Soeren Sandmann + + * glib/gfileutils.c (g_file_replace): Save the errno in various + places + + * glib/gfileutils.c (set_umask_permissions): Fork a child and do + chmod() to the umask() permissions there. + 2005-04-10 Matthias Clasen * glib/gmessages.h (g_debug): Use G_LOG_LEVEL_DEBUG in diff --git a/glib/gfileutils.c b/glib/gfileutils.c index d2263ea38..b3c1565a2 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -816,7 +817,6 @@ g_file_get_contents (const gchar *filename, #endif - static gboolean rename_file (const char *old_name, const char *new_name, @@ -828,7 +828,7 @@ rename_file (const char *old_name, int save_errno = errno; gchar *display_old_name = g_filename_display_name (old_name); gchar *display_new_name = g_filename_display_name (new_name); - + g_set_error (err, G_FILE_ERROR, g_file_error_from_errno (save_errno), @@ -846,6 +846,114 @@ rename_file (const char *old_name, return TRUE; } +static gboolean +set_umask_permissions (int fd, + GError **err) +{ +#ifdef G_OS_WIN32 + + return TRUE; + +#else + /* All of this function is just to work around the fact that + * there is no way to get the umask without changing it. + * + * We can't just change-and-reset the umask because that would + * lead to a race condition if another thread tried to change + * the umask in between the getting and the setting of the umask. + * So we have to do the whole thing in a child process. + */ + + int save_errno; + pid_t pid; + + pid = fork (); + + if (pid == -1) + { + save_errno = errno; + g_set_error (err, + G_FILE_ERROR, + g_file_error_from_errno (save_errno), + _("Could not change file mode: fork() failed: %s"), + g_strerror (save_errno)); + + return FALSE; + } + else if (pid == 0) + { + /* child */ + mode_t mask = umask (0666); + + errno = 0; + if (fchmod (fd, 0666 & ~mask) == -1) + _exit (errno); + else + _exit (0); + + return TRUE; /* To quiet gcc */ + } + else + { + /* parent */ + int status; + + errno = 0; + if (waitpid (pid, &status, 0) == -1) + { + save_errno = errno; + + g_set_error (err, + G_FILE_ERROR, + g_file_error_from_errno (save_errno), + _("Could not change file mode: waitpid() failed: %s"), + g_strerror (save_errno)); + + return FALSE; + } + + if (WIFEXITED (status)) + { + save_errno = WEXITSTATUS (status); + + if (save_errno == 0) + { + return TRUE; + } + else + { + g_set_error (err, + G_FILE_ERROR, + g_file_error_from_errno (save_errno), + _("Could not change file mode: chmod() failed: %s"), + g_strerror (save_errno)); + + return FALSE; + } + } + else if (WIFSIGNALED (status)) + { + g_set_error (err, + G_FILE_ERROR, + G_FILE_ERROR_FAILED, + _("Could not change file mode: Child terminated by signal: %s"), + g_strsignal (WTERMSIG (status))); + + return FALSE; + } + else + { + /* This shouldn't happen */ + g_set_error (err, + G_FILE_ERROR, + G_FILE_ERROR_FAILED, + _("Could not change file mode: Child terminated abnormally")); + return FALSE; + } + } +#endif +} + static gchar * write_to_temp_file (const gchar *contents, gssize length, @@ -865,11 +973,11 @@ write_to_temp_file (const gchar *contents, errno = 0; fd = g_mkstemp (tmp_name); - save_errno = errno; display_name = g_filename_display_name (tmp_name); if (fd == -1) { + save_errno = errno; g_set_error (err, G_FILE_ERROR, g_file_error_from_errno (save_errno), @@ -879,16 +987,25 @@ write_to_temp_file (const gchar *contents, goto out; } + if (!set_umask_permissions (fd, err)) + { + close (fd); + g_unlink (tmp_name); + + goto out; + } + errno = 0; file = fdopen (fd, "wb"); if (!file) { + save_errno = errno; g_set_error (err, G_FILE_ERROR, - g_file_error_from_errno (errno), + g_file_error_from_errno (save_errno), _("Failed to open file '%s' for writing: fdopen() failed: %s"), display_name, - g_strerror (errno)); + g_strerror (save_errno)); close (fd); g_unlink (tmp_name); @@ -903,15 +1020,17 @@ write_to_temp_file (const gchar *contents, errno = 0; n_written = fwrite (contents, 1, length, file); - + if (n_written < length) { + save_errno = errno; + g_set_error (err, G_FILE_ERROR, - g_file_error_from_errno (errno), + g_file_error_from_errno (save_errno), _("Failed to write file '%s': fwrite() failed: %s"), display_name, - g_strerror (errno)); + g_strerror (save_errno)); fclose (file); g_unlink (tmp_name); @@ -922,21 +1041,23 @@ write_to_temp_file (const gchar *contents, errno = 0; if (fclose (file) == EOF) - { + { + save_errno = 0; + g_set_error (err, G_FILE_ERROR, - g_file_error_from_errno (errno), + g_file_error_from_errno (save_errno), _("Failed to close file '%s': fclose() failed: %s"), display_name, - g_strerror (errno)); + g_strerror (save_errno)); g_unlink (tmp_name); goto out; } - - retval = g_strdup (tmp_name); + retval = g_strdup (tmp_name); + out: g_free (tmp_name); g_free (display_name); @@ -1039,12 +1160,14 @@ g_file_replace (const gchar *filename, { gchar *display_filename = g_filename_display_name (filename); + save_errno = errno; + g_set_error (error, G_FILE_ERROR, - g_file_error_from_errno (errno), + g_file_error_from_errno (save_errno), _("Existing file '%s' could not be removed: g_unlink() failed: %s"), display_filename, - g_strerror (errno)); + g_strerror (save_errno)); g_free (display_filename); g_unlink (tmp_filename); -- 2.34.1