g_creat
g_chdir
g_utime
+g_close
<SUBSECTION Private>
g_file_error_quark
#include "gdbusconnection.h"
#include "gdbusintrospection.h"
#include "gdbuserror.h"
+#include "glib/gstdio.h"
#include <string.h>
#include <stdio.h>
fds = g_unix_fd_list_steal_fds (fd_list, &n_fds);
result = g_unix_input_stream_new (fds[0], TRUE);
for (i = 1; i < n_fds; i++)
- close (fds[i]);
+ (void) g_close (fds[i], NULL);
g_free (fds);
}
#include "ginputstream.h"
#include "gmemoryinputstream.h"
#include "giostream.h"
+#include "glib/gstdio.h"
#include "gsocketcontrolmessage.h"
#include "gsocketconnection.h"
#include "gsocketoutputstream.h"
{
/* TODO: really want a append_steal() */
g_unix_fd_list_append (worker->read_fd_list, fds[n], NULL);
- close (fds[n]);
+ (void) g_close (fds[n], NULL);
}
}
g_free (fds);
#include "gsocketservice.h"
#include "gthreadedsocketservice.h"
#include "gresolver.h"
+#include "glib/gstdio.h"
#include "ginetaddress.h"
#include "ginetsocketaddress.h"
#include "ginputstream.h"
bytes_written += ret;
bytes_remaining -= ret;
}
- close (fd);
+ if (!g_close (fd, error))
+ goto out;
file_escaped = g_uri_escape_string (server->nonce_file, "/\\", FALSE);
server->client_address = g_strdup_printf ("nonce-tcp:host=%s,port=%d,noncefile=%s",
host,
#include "gcontenttypeprivate.h"
#include "gdesktopappinfo.h"
+#ifdef G_OS_UNIX
+#include "glib-unix.h"
+#endif
#include "gfile.h"
#include "gioerror.h"
#include "gthemedicon.h"
desktop_id = g_path_get_basename (filename);
- close (fd);
+ /* FIXME - actually handle error */
+ (void) g_close (fd, NULL);
res = g_file_set_contents (filename, data, data_size, error);
g_free (data);
#endif
#include "gfile.h"
+#include "glib/gstdio.h"
#ifdef G_OS_UNIX
#include "glib-unix.h"
#endif
gpointer progress_callback_data,
GError **error)
{
- int buffer[2];
+ int buffer[2] = { -1, -1 };
gboolean res;
goffset total_size;
loff_t offset_in;
if (progress_callback)
progress_callback (offset_in, total_size, progress_callback_data);
+ if (!g_close (buffer[0], error))
+ goto out;
+ buffer[0] = -1;
+ if (!g_close (buffer[1], error))
+ goto out;
+ buffer[1] = -1;
out:
- close (buffer[0]);
- close (buffer[1]);
+ if (buffer[0] != -1)
+ (void) g_close (buffer[0], NULL);
+ if (buffer[1] != -1)
+ (void) g_close (buffer[1], NULL);
return res;
}
#include "gioerror.h"
#include <glib/gstdio.h>
#include "glibintl.h"
+#ifdef G_OS_UNIX
+#include "glib-unix.h"
+#endif
#ifdef G_OS_WIN32
#include <windows.h>
if (ret == 0 && S_ISDIR (buf.st_mode))
{
- close (fd);
+ (void) g_close (fd, NULL);
g_set_error_literal (error, G_IO_ERROR,
G_IO_ERROR_IS_DIRECTORY,
_("Can't open directory"));
return FALSE;
}
- close (fd);
+ (void) g_close (fd, NULL);
/* TODO: Maybe we should verify that you can delete the file from the trash
before moving it? OTOH, that is hard, as it needs a recursive scan */
#include <gvfs.h>
#ifndef G_OS_WIN32
+#include "glib-unix.h"
#include "glib-private.h"
#endif
#include "glibintl.h"
ssize_t res;
res = read (fd, sniff_buffer, sniff_length);
- close (fd);
+ (void) g_close (fd, NULL);
if (res >= 0)
{
g_free (content_type);
#include "glibintl.h"
#ifdef G_OS_UNIX
+#include "glib-unix.h"
#include "gfiledescriptorbased.h"
#endif
GError **error)
{
GLocalFileInputStream *file;
- int res;
file = G_LOCAL_FILE_INPUT_STREAM (stream);
if (file->priv->fd == -1)
return TRUE;
- while (1)
+ if (!g_close (file->priv->fd, NULL))
{
- res = close (file->priv->fd);
- if (res == -1)
- {
- int errsv = errno;
-
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_errno (errsv),
- _("Error closing file: %s"),
- g_strerror (errsv));
- }
- break;
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error closing file: %s"),
+ g_strerror (errsv));
+ return FALSE;
}
- return res != -1;
+ return TRUE;
}
GError **error)
{
GLocalFileStat final_stat;
- int res;
#ifdef HAVE_FSYNC
if (file->priv->sync_on_close &&
if (_fstati64 (file->priv->fd, &final_stat) == 0)
file->priv->etag = _g_local_file_info_create_etag (&final_stat);
- res = close (file->priv->fd);
- if (res == -1)
+ if (!g_close (file->priv->fd, NULL))
{
int errsv = errno;
if (fstat (file->priv->fd, &final_stat) == 0)
file->priv->etag = _g_local_file_info_create_etag (&final_stat);
- while (1)
+ if (!g_close (file->priv->fd, NULL))
{
- res = close (file->priv->fd);
- if (res == -1)
- {
- int errsv = errno;
-
- g_set_error (error, G_IO_ERROR,
- g_io_error_from_errno (errsv),
- _("Error closing file: %s"),
- g_strerror (errsv));
- }
- break;
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error closing file: %s"),
+ g_strerror (errsv));
+ goto err_out;
}
-
- return res != -1;
-
-#else
-
- return TRUE;
#endif
-
+
+ return TRUE;
err_out:
#ifndef G_OS_WIN32
/* A simple try to close the fd in case we fail before the actual close */
- close (file->priv->fd);
+ (void) g_close (file->priv->fd, NULL);
#endif
if (file->priv->tmp_filename)
g_unlink (file->priv->tmp_filename);
original_stat.st_gid != tmp_statbuf.st_gid ||
original_stat.st_mode != tmp_statbuf.st_mode)
{
- close (tmpfd);
+ (void) g_close (tmpfd, NULL);
g_unlink (tmp_filename);
g_free (tmp_filename);
goto fallback_strategy;
}
}
- close (fd);
+ (void) g_close (fd, NULL);
*temp_filename = tmp_filename;
return tmpfd;
}
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Backup file creation failed"));
g_unlink (backup_filename);
- close (bfd);
+ (void) g_close (bfd, NULL);
g_free (backup_filename);
goto err_out;
}
G_IO_ERROR_CANT_CREATE_BACKUP,
_("Backup file creation failed"));
g_unlink (backup_filename);
- close (bfd);
+ (void) g_close (bfd, NULL);
g_free (backup_filename);
goto err_out;
}
- close (bfd);
+ (void) g_close (bfd, NULL);
g_free (backup_filename);
/* Seek back to the start of the file after the backup copy */
if (flags & G_FILE_CREATE_REPLACE_DESTINATION)
{
- close (fd);
+ (void) g_close (fd, NULL);
if (g_unlink (filename) != 0)
{
return fd;
err_out:
- close (fd);
+ (void) g_close (fd, NULL);
err_out2:
return -1;
}
#include "ginitable.h"
#include "giomodule-priv.h"
#include "glibintl.h"
+#include "glib/gstdio.h"
#include "gnetworkingprivate.h"
#include "gnetworkmonitor.h"
#include "gsocket.h"
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
_("Could not create network monitor: %s"),
g_strerror (errno));
- close (sockfd);
+ (void) g_close (sockfd, NULL);
return FALSE;
}
if (error)
{
g_prefix_error (error, "%s", _("Could not create network monitor: "));
- close (sockfd);
+ (void) g_close (sockfd, NULL);
return FALSE;
}
#endif
}
-
/**
* g_unix_signal_source_new:
* @signum: A signal number
#include "gspawn.h"
#include "gthread.h"
+#include "glib/gstdio.h"
#include "genviron.h"
#include "gmem.h"
* on a file descriptor twice, and another thread has
* re-opened it since the first close)
*/
-static gint
+static void
close_and_invalidate (gint *fd)
{
- gint ret;
-
if (*fd < 0)
- return -1;
+ return;
else
{
- again:
- ret = close (*fd);
- if (ret == -1 && errno == EINTR)
- goto again;
+ (void) g_close (*fd, NULL);
*fd = -1;
}
-
- return ret;
}
/* Some versions of OS X define READ_OK in public headers */
return utime (filename, utb);
#endif
}
+
+/**
+ * g_close:
+ * @fd: A file descriptor
+ * @error: a #GError
+ *
+ * This wraps the close() call; in case of error, %errno will be
+ * preserved, but the error will also be stored as a #GError in @error.
+ *
+ * Besides using #GError, there is another major reason to prefer this
+ * function over the call provided by the system; on Unix, it will
+ * attempt to correctly handle %EINTR, which has platform-specific
+ * semantics.
+ */
+gboolean
+g_close (gint fd,
+ GError **error)
+{
+ int res;
+ res = close (fd);
+ /* Just ignore EINTR for now; a retry loop is the wrong thing to do
+ * on Linux at least. Anyone who wants to add a conditional check
+ * for e.g. HP-UX is welcome to do so later...
+ *
+ * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
+ * https://bugzilla.gnome.org/show_bug.cgi?id=682819
+ * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
+ * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
+ */
+ if (G_UNLIKELY (res == -1 && errno == EINTR))
+ return TRUE;
+ else if (res == -1)
+ {
+ int errsv = errno;
+ g_set_error_literal (error, G_FILE_ERROR,
+ g_file_error_from_errno (errsv),
+ g_strerror (errsv));
+ errno = errsv;
+ return FALSE;
+ }
+ return TRUE;
+}
+
#endif /* G_OS_UNIX */
+GLIB_AVAILABLE_IN_2_36
+gboolean g_close (gint fd,
+ GError **error);
+
G_END_DECLS
#endif /* __G_STDIO_H__ */