static gssize g_local_file_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { GLocalFileOutputStream *file; gssize res; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); while (1) { if (g_cancellable_set_error_if_cancelled (cancellable, error)) return -1; res = write (file->priv->fd, buffer, count); if (res == -1) { int errsv = errno; if (errsv == EINTR) continue; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to file: %s"), g_strerror (errsv)); } break; } return res; }
static gboolean g_local_file_output_stream_seek (GFileOutputStream *stream, goffset offset, GSeekType type, GCancellable *cancellable, GError **error) { GLocalFileOutputStream *file; off_t pos; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); pos = lseek (file->priv->fd, offset, seek_type_to_lseek (type)); if (pos == (off_t)-1) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error seeking in file: %s"), g_strerror (errsv)); return FALSE; } return TRUE; }
static int g_local_file_output_stream_get_fd (GFileDescriptorBased *fd_based) { GLocalFileOutputStream *stream = G_LOCAL_FILE_OUTPUT_STREAM (fd_based); return stream->priv->fd; }
static char * g_local_file_output_stream_get_etag (GFileOutputStream *stream) { GLocalFileOutputStream *file; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); return g_strdup (file->priv->etag); }
static void g_local_file_output_stream_finalize (GObject *object) { GLocalFileOutputStream *file; file = G_LOCAL_FILE_OUTPUT_STREAM (object); g_free (file->priv->tmp_filename); g_free (file->priv->original_filename); g_free (file->priv->backup_filename); g_free (file->priv->etag); G_OBJECT_CLASS (g_local_file_output_stream_parent_class)->finalize (object); }
static gboolean g_local_file_io_stream_close (GIOStream *stream, GCancellable *cancellable, GError **error) { GLocalFileIOStream *file = G_LOCAL_FILE_IO_STREAM (stream); /* There are shortcutted and can't fail */ g_output_stream_close (file->output_stream, cancellable, NULL); g_input_stream_close (file->input_stream, cancellable, NULL); return _g_local_file_output_stream_really_close (G_LOCAL_FILE_OUTPUT_STREAM (file->output_stream), cancellable, error); }
static gboolean g_local_file_output_stream_can_seek (GFileOutputStream *stream) { GLocalFileOutputStream *file; off_t pos; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); pos = lseek (file->priv->fd, 0, SEEK_CUR); if (pos == (off_t)-1 && errno == ESPIPE) return FALSE; return TRUE; }
static goffset g_local_file_output_stream_tell (GFileOutputStream *stream) { GLocalFileOutputStream *file; off_t pos; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); pos = lseek (file->priv->fd, 0, SEEK_CUR); if (pos == (off_t)-1) return 0; return pos; }
static gboolean g_local_file_output_stream_close (GOutputStream *stream, GCancellable *cancellable, GError **error) { GLocalFileOutputStream *file; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); if (file->priv->do_close) return _g_local_file_output_stream_really_close (file, cancellable, error); return TRUE; }
static GFileInfo * g_local_file_output_stream_query_info (GFileOutputStream *stream, char *attributes, GCancellable *cancellable, GError **error) { GLocalFileOutputStream *file; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); if (g_cancellable_set_error_if_cancelled (cancellable, error)) return NULL; return _g_local_file_info_get_from_fd (file->priv->fd, attributes, error); }
static gboolean g_local_file_output_stream_truncate (GFileOutputStream *stream, goffset size, GCancellable *cancellable, GError **error) { GLocalFileOutputStream *file; int res; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); restart: #ifdef G_OS_WIN32 res = g_win32_ftruncate (file->priv->fd, size); #else res = ftruncate (file->priv->fd, size); #endif if (res == -1) { int errsv = errno; if (errsv == EINTR) { if (g_cancellable_set_error_if_cancelled (cancellable, error)) return FALSE; goto restart; } g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error truncating file: %s"), g_strerror (errsv)); return FALSE; } return TRUE; }
static gboolean g_local_file_output_stream_close (GOutputStream *stream, GCancellable *cancellable, GError **error) { GLocalFileOutputStream *file; GLocalFileStat final_stat; int res; file = G_LOCAL_FILE_OUTPUT_STREAM (stream); #ifdef G_OS_WIN32 /* Must close before renaming on Windows, so just do the close first * in all cases for now. */ 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) { 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; } #endif if (file->priv->tmp_filename) { /* We need to move the temp file to its final place, * and possibly create the backup file */ if (file->priv->backup_filename) { if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; #ifdef HAVE_LINK /* create original -> backup link, the original is then renamed over */ if (g_unlink (file->priv->backup_filename) != 0 && errno != ENOENT) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error removing old backup link: %s"), g_strerror (errsv)); goto err_out; } if (link (file->priv->original_filename, file->priv->backup_filename) != 0) { /* link failed or is not supported, try rename */ if (g_rename (file->priv->original_filename, file->priv->backup_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error creating backup copy: %s"), g_strerror (errsv)); goto err_out; } } #else /* If link not supported, just rename... */ if (g_rename (file->priv->original_filename, file->priv->backup_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP, _("Error creating backup copy: %s"), g_strerror (errsv)); goto err_out; } #endif } if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; /* tmp -> original */ if (g_rename (file->priv->tmp_filename, file->priv->original_filename) != 0) { int errsv = errno; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), _("Error renaming temporary file: %s"), g_strerror (errsv)); goto err_out; } } if (g_cancellable_set_error_if_cancelled (cancellable, error)) goto err_out; #ifndef G_OS_WIN32 /* Already did the fstat() and close() above on Win32 */ if (fstat (file->priv->fd, &final_stat) == 0) file->priv->etag = _g_local_file_info_create_etag (&final_stat); while (1) { 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; } return res != -1; #else return TRUE; #endif 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); #endif return FALSE; }