6766e4140319a4c2be1d3cace970591171d38de1
[platform/upstream/glib.git] / gio / glocalfileoutputstream.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include <config.h>
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #include <errno.h>
32 #include <string.h>
33
34 #include <glib.h>
35 #include <glib/gstdio.h>
36 #include "glibintl.h"
37 #include "gioerror.h"
38 #include "glocalfileoutputstream.h"
39 #include "glocalfileinfo.h"
40
41 #include "gioalias.h"
42
43 #define g_local_file_output_stream_get_type _g_local_file_output_stream_get_type
44 G_DEFINE_TYPE (GLocalFileOutputStream, g_local_file_output_stream, G_TYPE_FILE_OUTPUT_STREAM);
45
46 /* Some of the file replacement code was based on the code from gedit,
47  * relicenced to LGPL with permissions from the authors.
48  */
49
50 #define BACKUP_EXTENSION "~"
51
52 struct _GLocalFileOutputStreamPrivate {
53   char *tmp_filename;
54   char *original_filename;
55   char *backup_filename;
56   char *etag;
57   int fd;
58 };
59
60 static gssize     g_local_file_output_stream_write        (GOutputStream      *stream,
61                                                            const void         *buffer,
62                                                            gsize               count,
63                                                            GCancellable       *cancellable,
64                                                            GError            **error);
65 static gboolean   g_local_file_output_stream_close        (GOutputStream      *stream,
66                                                            GCancellable       *cancellable,
67                                                            GError            **error);
68 static GFileInfo *g_local_file_output_stream_query_info   (GFileOutputStream  *stream,
69                                                            char               *attributes,
70                                                            GCancellable       *cancellable,
71                                                            GError            **error);
72 static char *     g_local_file_output_stream_get_etag     (GFileOutputStream  *stream);
73 static goffset    g_local_file_output_stream_tell         (GFileOutputStream  *stream);
74 static gboolean   g_local_file_output_stream_can_seek     (GFileOutputStream  *stream);
75 static gboolean   g_local_file_output_stream_seek         (GFileOutputStream  *stream,
76                                                            goffset             offset,
77                                                            GSeekType           type,
78                                                            GCancellable       *cancellable,
79                                                            GError            **error);
80 static gboolean   g_local_file_output_stream_can_truncate (GFileOutputStream  *stream);
81 static gboolean   g_local_file_output_stream_truncate     (GFileOutputStream  *stream,
82                                                            goffset             size,
83                                                            GCancellable       *cancellable,
84                                                            GError            **error);
85
86 static void
87 g_local_file_output_stream_finalize (GObject *object)
88 {
89   GLocalFileOutputStream *file;
90   
91   file = G_LOCAL_FILE_OUTPUT_STREAM (object);
92   
93   g_free (file->priv->tmp_filename);
94   g_free (file->priv->original_filename);
95   g_free (file->priv->backup_filename);
96   g_free (file->priv->etag);
97   
98   if (G_OBJECT_CLASS (g_local_file_output_stream_parent_class)->finalize)
99     (*G_OBJECT_CLASS (g_local_file_output_stream_parent_class)->finalize) (object);
100 }
101
102 static void
103 g_local_file_output_stream_class_init (GLocalFileOutputStreamClass *klass)
104 {
105   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
106   GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
107   GFileOutputStreamClass *file_stream_class = G_FILE_OUTPUT_STREAM_CLASS (klass);
108   
109   g_type_class_add_private (klass, sizeof (GLocalFileOutputStreamPrivate));
110   
111   gobject_class->finalize = g_local_file_output_stream_finalize;
112
113   stream_class->write_fn = g_local_file_output_stream_write;
114   stream_class->close_fn = g_local_file_output_stream_close;
115   file_stream_class->query_info = g_local_file_output_stream_query_info;
116   file_stream_class->get_etag = g_local_file_output_stream_get_etag;
117   file_stream_class->tell = g_local_file_output_stream_tell;
118   file_stream_class->can_seek = g_local_file_output_stream_can_seek;
119   file_stream_class->seek = g_local_file_output_stream_seek;
120   file_stream_class->can_truncate = g_local_file_output_stream_can_truncate;
121   file_stream_class->truncate_fn = g_local_file_output_stream_truncate;
122 }
123
124 static void
125 g_local_file_output_stream_init (GLocalFileOutputStream *stream)
126 {
127   stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
128                                               G_TYPE_LOCAL_FILE_OUTPUT_STREAM,
129                                               GLocalFileOutputStreamPrivate);
130 }
131
132 static gssize
133 g_local_file_output_stream_write (GOutputStream  *stream,
134                                   const void     *buffer,
135                                   gsize           count,
136                                   GCancellable   *cancellable,
137                                   GError        **error)
138 {
139   GLocalFileOutputStream *file;
140   gssize res;
141
142   file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
143
144   while (1)
145     {
146       if (g_cancellable_set_error_if_cancelled (cancellable, error))
147         return -1;
148       res = write (file->priv->fd, buffer, count);
149       if (res == -1)
150         {
151           if (errno == EINTR)
152             continue;
153           
154           g_set_error (error, G_IO_ERROR,
155                        g_io_error_from_errno (errno),
156                        _("Error writing to file: %s"),
157                        g_strerror (errno));
158         }
159       
160       break;
161     }
162   
163   return res;
164 }
165
166 static gboolean
167 g_local_file_output_stream_close (GOutputStream  *stream,
168                                   GCancellable   *cancellable,
169                                   GError        **error)
170 {
171   GLocalFileOutputStream *file;
172   struct stat final_stat;
173   int res;
174
175   file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
176
177   if (file->priv->tmp_filename)
178     {
179       /* We need to move the temp file to its final place,
180        * and possibly create the backup file
181        */
182
183       if (file->priv->backup_filename)
184         {
185           if (g_cancellable_set_error_if_cancelled (cancellable, error))
186             goto err_out;
187           
188 #ifdef HAVE_LINK
189           /* create original -> backup link, the original is then renamed over */
190           if (unlink (file->priv->backup_filename) != 0 &&
191               errno != ENOENT)
192             {
193               g_set_error (error, G_IO_ERROR,
194                            G_IO_ERROR_CANT_CREATE_BACKUP,
195                            _("Error removing old backup link: %s"),
196                            g_strerror (errno));
197               goto err_out;
198             }
199
200           if (link (file->priv->original_filename, file->priv->backup_filename) != 0)
201             {
202               g_set_error (error, G_IO_ERROR,
203                            G_IO_ERROR_CANT_CREATE_BACKUP,
204                            _("Error creating backup link: %s"),
205                            g_strerror (errno));
206               goto err_out;
207             }
208 #else
209             /* If link not supported, just rename... */
210           if (!rename (file->priv->original_filename, file->priv->backup_filename) != 0)
211             {
212               g_set_error (error, G_IO_ERROR,
213                            G_IO_ERROR_CANT_CREATE_BACKUP,
214                            _("Error creating backup copy: %s"),
215                            g_strerror (errno));
216               goto err_out;
217             }
218 #endif
219         }
220       
221
222       if (g_cancellable_set_error_if_cancelled (cancellable, error))
223         goto err_out;
224
225       /* tmp -> original */
226       if (rename (file->priv->tmp_filename, file->priv->original_filename) != 0)
227         {
228           g_set_error (error, G_IO_ERROR,
229                        g_io_error_from_errno (errno),
230                        _("Error renaming temporary file: %s"),
231                        g_strerror (errno));
232           goto err_out;
233         }
234     }
235   
236   if (g_cancellable_set_error_if_cancelled (cancellable, error))
237     goto err_out;
238       
239   if (fstat (file->priv->fd, &final_stat) == 0)
240     file->priv->etag = _g_local_file_info_create_etag (&final_stat);
241
242   while (1)
243     {
244       res = close (file->priv->fd);
245       if (res == -1)
246         {
247           g_set_error (error, G_IO_ERROR,
248                        g_io_error_from_errno (errno),
249                        _("Error closing file: %s"),
250                        g_strerror (errno));
251         }
252       break;
253     }
254   
255   return res != -1;
256
257  err_out:
258   /* A simple try to close the fd in case we fail before the actual close */
259   close (file->priv->fd);
260   return FALSE;
261 }
262
263 static char *
264 g_local_file_output_stream_get_etag (GFileOutputStream *stream)
265 {
266   GLocalFileOutputStream *file;
267
268   file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
269   
270   return g_strdup (file->priv->etag);
271 }
272
273 static goffset
274 g_local_file_output_stream_tell (GFileOutputStream *stream)
275 {
276   GLocalFileOutputStream *file;
277   off_t pos;
278
279   file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
280   
281   pos = lseek (file->priv->fd, 0, SEEK_CUR);
282
283   if (pos == (off_t)-1)
284     return 0;
285   
286   return pos;
287 }
288
289 static gboolean
290 g_local_file_output_stream_can_seek (GFileOutputStream *stream)
291 {
292   GLocalFileOutputStream *file;
293   off_t pos;
294
295   file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
296   
297   pos = lseek (file->priv->fd, 0, SEEK_CUR);
298
299   if (pos == (off_t)-1 &&
300       errno == ESPIPE)
301     return FALSE;
302   
303   return TRUE;
304 }
305
306 static int
307 seek_type_to_lseek (GSeekType type)
308 {
309   switch (type)
310     {
311     default:
312     case G_SEEK_CUR:
313       return SEEK_CUR;
314       
315     case G_SEEK_SET:
316       return SEEK_SET;
317       
318     case G_SEEK_END:
319       return SEEK_END;
320     }
321 }
322
323 static gboolean
324 g_local_file_output_stream_seek (GFileOutputStream  *stream,
325                                  goffset             offset,
326                                  GSeekType           type,
327                                  GCancellable       *cancellable,
328                                  GError            **error)
329 {
330   GLocalFileOutputStream *file;
331   off_t pos;
332
333   file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
334
335   pos = lseek (file->priv->fd, offset, seek_type_to_lseek (type));
336
337   if (pos == (off_t)-1)
338     {
339       g_set_error (error, G_IO_ERROR,
340                    g_io_error_from_errno (errno),
341                    _("Error seeking in file: %s"),
342                    g_strerror (errno));
343       return FALSE;
344     }
345   
346   return TRUE;
347 }
348
349 static gboolean
350 g_local_file_output_stream_can_truncate (GFileOutputStream *stream)
351 {
352   /* We can't truncate pipes and stuff where we can't seek */
353   return g_local_file_output_stream_can_seek (stream);
354 }
355
356 static gboolean
357 g_local_file_output_stream_truncate (GFileOutputStream  *stream,
358                                      goffset             size,
359                                      GCancellable       *cancellable,
360                                      GError            **error)
361 {
362   GLocalFileOutputStream *file;
363   int res;
364
365   file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
366
367  restart:
368   res = ftruncate (file->priv->fd, size);
369   
370   if (res == -1)
371     {
372       if (errno == EINTR)
373         {
374           if (g_cancellable_set_error_if_cancelled (cancellable, error))
375             return FALSE;
376           goto restart;
377         }
378
379       g_set_error (error, G_IO_ERROR,
380                    g_io_error_from_errno (errno),
381                    _("Error truncating file: %s"),
382                    g_strerror (errno));
383       return FALSE;
384     }
385   
386   return TRUE;
387 }
388
389
390 static GFileInfo *
391 g_local_file_output_stream_query_info (GFileOutputStream  *stream,
392                                        char               *attributes,
393                                        GCancellable       *cancellable,
394                                        GError            **error)
395 {
396   GLocalFileOutputStream *file;
397
398   file = G_LOCAL_FILE_OUTPUT_STREAM (stream);
399
400   if (g_cancellable_set_error_if_cancelled (cancellable, error))
401     return NULL;
402   
403   return _g_local_file_info_get_from_fd (file->priv->fd,
404                                          attributes,
405                                          error);
406 }
407
408 GFileOutputStream *
409 _g_local_file_output_stream_create  (const char        *filename,
410                                      GFileCreateFlags   flags,
411                                      GCancellable      *cancellable,
412                                      GError           **error)
413 {
414   GLocalFileOutputStream *stream;
415   int mode;
416   int fd;
417
418   if (g_cancellable_set_error_if_cancelled (cancellable, error))
419     return NULL;
420
421   if (flags & G_FILE_CREATE_FLAGS_PRIVATE)
422     mode = 0600;
423   else
424     mode = 0666;
425   
426   fd = g_open (filename,
427                O_CREAT | O_EXCL | O_WRONLY,
428                0666);
429   if (fd == -1)
430     {
431       int errsv = errno;
432
433       if (errsv == EINVAL)
434         /* This must be an invalid filename, on e.g. FAT */
435         g_set_error (error, G_IO_ERROR,
436                      G_IO_ERROR_INVALID_FILENAME,
437                      _("Invalid filename"));
438       else
439         g_set_error (error, G_IO_ERROR,
440                      g_io_error_from_errno (errsv),
441                      _("Error opening file '%s': %s"),
442                      filename, g_strerror (errsv));
443       return NULL;
444     }
445   
446   stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL);
447   stream->priv->fd = fd;
448   return G_FILE_OUTPUT_STREAM (stream);
449 }
450
451 GFileOutputStream *
452 _g_local_file_output_stream_append  (const char        *filename,
453                                      GFileCreateFlags   flags,
454                                      GCancellable      *cancellable,
455                                      GError           **error)
456 {
457   GLocalFileOutputStream *stream;
458   int mode;
459   int fd;
460
461   if (g_cancellable_set_error_if_cancelled (cancellable, error))
462     return NULL;
463
464   if (flags & G_FILE_CREATE_FLAGS_PRIVATE)
465     mode = 0600;
466   else
467     mode = 0666;
468
469   fd = g_open (filename,
470                O_CREAT | O_APPEND | O_WRONLY,
471                mode);
472   if (fd == -1)
473     {
474       int errsv = errno;
475
476       if (errsv == EINVAL)
477         /* This must be an invalid filename, on e.g. FAT */
478         g_set_error (error, G_IO_ERROR,
479                      G_IO_ERROR_INVALID_FILENAME,
480                      _("Invalid filename"));
481       else
482         g_set_error (error, G_IO_ERROR,
483                      g_io_error_from_errno (errsv),
484                      _("Error opening file '%s': %s"),
485                      filename, g_strerror (errsv));
486       return NULL;
487     }
488   
489   stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL);
490   stream->priv->fd = fd;
491   
492   return G_FILE_OUTPUT_STREAM (stream);
493 }
494
495 static char *
496 create_backup_filename (const char *filename)
497 {
498   return g_strconcat (filename, BACKUP_EXTENSION, NULL);
499 }
500
501 #define BUFSIZE 8192 /* size of normal write buffer */
502
503 static gboolean
504 copy_file_data (gint     sfd,
505                 gint     dfd,
506                 GError **error)
507 {
508   gboolean ret = TRUE;
509   gpointer buffer;
510   const gchar *write_buffer;
511   gssize bytes_read;
512   gssize bytes_to_write;
513   gssize bytes_written;
514   
515   buffer = g_malloc (BUFSIZE);
516   
517   do
518     {
519       bytes_read = read (sfd, buffer, BUFSIZE);
520       if (bytes_read == -1)
521         {
522           if (errno == EINTR)
523             continue;
524           
525           g_set_error (error, G_IO_ERROR,
526                        g_io_error_from_errno (errno),
527                        _("Error reading from file: %s"),
528                        g_strerror (errno));
529           ret = FALSE;
530           break;
531         }
532       
533       bytes_to_write = bytes_read;
534       write_buffer = buffer;
535       
536       do
537         {
538           bytes_written = write (dfd, write_buffer, bytes_to_write);
539           if (bytes_written == -1)
540             {
541               if (errno == EINTR)
542                 continue;
543               
544               g_set_error (error, G_IO_ERROR,
545                            g_io_error_from_errno (errno),
546                            _("Error writing to file: %s"),
547                            g_strerror (errno));
548               ret = FALSE;
549               break;
550             }
551           
552           bytes_to_write -= bytes_written;
553           write_buffer += bytes_written;
554         }
555       while (bytes_to_write > 0);
556       
557     } while ((bytes_read != 0) && (ret == TRUE));
558
559   g_free (buffer);
560   
561   return ret;
562 }
563
564 static int
565 handle_overwrite_open (const char    *filename,
566                        const char    *etag,
567                        gboolean       create_backup,
568                        char         **temp_filename,
569                        GCancellable  *cancellable,
570                        GError       **error)
571 {
572   int fd = -1;
573   struct stat original_stat;
574   char *current_etag;
575   gboolean is_symlink;
576   int open_flags;
577
578   /* We only need read access to the original file if we are creating a backup.
579    * We also add O_CREATE to avoid a race if the file was just removed */
580   if (create_backup)
581     open_flags = O_RDWR | O_CREAT;
582   else
583     open_flags = O_WRONLY | O_CREAT;
584   
585   /* Some systems have O_NOFOLLOW, which lets us avoid some races
586    * when finding out if the file we opened was a symlink */
587 #ifdef O_NOFOLLOW
588   is_symlink = FALSE;
589   fd = g_open (filename, open_flags | O_NOFOLLOW, 0666);
590   if (fd == -1 && errno == ELOOP)
591     {
592       /* Could be a symlink, or it could be a regular ELOOP error,
593        * but then the next open will fail too. */
594       is_symlink = TRUE;
595       fd = g_open (filename, open_flags, 0666);
596     }
597 #else
598   fd = g_open (filename, open_flags, 0666);
599   /* This is racy, but we do it as soon as possible to minimize the race */
600   is_symlink = g_file_test (filename, G_FILE_TEST_IS_SYMLINK);
601 #endif
602     
603   if (fd == -1)
604     {
605       g_set_error (error, G_IO_ERROR,
606                    g_io_error_from_errno (errno),
607                    _("Error opening file '%s': %s"),
608                    filename, g_strerror (errno));
609       return -1;
610     }
611   
612   if (fstat (fd, &original_stat) != 0) 
613     {
614       g_set_error (error, G_IO_ERROR,
615                    g_io_error_from_errno (errno),
616                    _("Error stating file '%s': %s"),
617                    filename, g_strerror (errno));
618       goto err_out;
619     }
620   
621   /* not a regular file */
622   if (!S_ISREG (original_stat.st_mode))
623     {
624       if (S_ISDIR (original_stat.st_mode))
625         g_set_error (error,
626                      G_IO_ERROR,
627                      G_IO_ERROR_IS_DIRECTORY,
628                      _("Target file is a directory"));
629       else
630         g_set_error (error,
631                      G_IO_ERROR,
632                      G_IO_ERROR_NOT_REGULAR_FILE,
633                      _("Target file is not a regular file"));
634       goto err_out;
635     }
636   
637   if (etag != NULL)
638     {
639       current_etag = _g_local_file_info_create_etag (&original_stat);
640       if (strcmp (etag, current_etag) != 0)
641         {
642           g_set_error (error,
643                        G_IO_ERROR,
644                        G_IO_ERROR_WRONG_ETAG,
645                        _("The file was externally modified"));
646           g_free (current_etag);
647           goto err_out;
648         }
649       g_free (current_etag);
650     }
651
652   /* We use two backup strategies.
653    * The first one (which is faster) consist in saving to a
654    * tmp file then rename the original file to the backup and the
655    * tmp file to the original name. This is fast but doesn't work
656    * when the file is a link (hard or symbolic) or when we can't
657    * write to the current dir or can't set the permissions on the
658    * new file. 
659    * The second strategy consist simply in copying the old file
660    * to a backup file and rewrite the contents of the file.
661    */
662   
663   if (!(original_stat.st_nlink > 1) && !is_symlink)
664     {
665       char *dirname, *tmp_filename;
666       int tmpfd;
667       
668       dirname = g_path_get_dirname (filename);
669       tmp_filename = g_build_filename (dirname, ".goutputstream-XXXXXX", NULL);
670       g_free (dirname);
671
672       tmpfd = g_mkstemp (tmp_filename);
673       if (tmpfd == -1)
674         {
675           g_free (tmp_filename);
676           goto fallback_strategy;
677         }
678       
679       /* try to keep permissions */
680
681       if (
682 #ifdef F_CHOWN
683           fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 ||
684 #endif
685 #ifdef F_CHMOD
686           fchmod (tmpfd, original_stat.st_mode) == -1 ||
687 #endif
688           0
689           )
690         {
691           struct stat tmp_statbuf;
692           
693           /* Check that we really needed to change something */
694           if (fstat (tmpfd, &tmp_statbuf) != 0 ||
695               original_stat.st_uid != tmp_statbuf.st_uid ||
696               original_stat.st_gid != tmp_statbuf.st_gid ||
697               original_stat.st_mode != tmp_statbuf.st_mode)
698             {
699               close (tmpfd);
700               unlink (tmp_filename);
701               g_free (tmp_filename);
702               goto fallback_strategy;
703             }
704         }
705
706       close (fd);
707       *temp_filename = tmp_filename;
708       return tmpfd;
709     }
710
711  fallback_strategy:
712
713   if (create_backup)
714     {
715       struct stat tmp_statbuf;      
716       char *backup_filename;
717       int bfd;
718       
719       backup_filename = create_backup_filename (filename);
720
721       if (unlink (backup_filename) == -1 && errno != ENOENT)
722         {
723           g_set_error (error,
724                        G_IO_ERROR,
725                        G_IO_ERROR_CANT_CREATE_BACKUP,
726                        _("Backup file creation failed"));
727           g_free (backup_filename);
728           goto err_out;
729         }
730
731       bfd = g_open (backup_filename,
732                     O_WRONLY | O_CREAT | O_EXCL,
733                     original_stat.st_mode & 0777);
734
735       if (bfd == -1)
736         {
737           g_set_error (error,
738                        G_IO_ERROR,
739                        G_IO_ERROR_CANT_CREATE_BACKUP,
740                        _("Backup file creation failed"));
741           g_free (backup_filename);
742           goto err_out;
743         }
744
745       /* If needed, Try to set the group of the backup same as the
746        * original file. If this fails, set the protection
747        * bits for the group same as the protection bits for
748        * others. */
749 #ifdef HAVE_FCHOWN
750       if (fstat (bfd, &tmp_statbuf) != 0)
751         {
752           g_set_error (error,
753                        G_IO_ERROR,
754                        G_IO_ERROR_CANT_CREATE_BACKUP,
755                        _("Backup file creation failed"));
756           unlink (backup_filename);
757           g_free (backup_filename);
758           goto err_out;
759         }
760       
761       if ((original_stat.st_gid != tmp_statbuf.st_gid)  &&
762           fchown (bfd, (uid_t) -1, original_stat.st_gid) != 0)
763         {
764           if (fchmod (bfd,
765                       (original_stat.st_mode & 0707) |
766                       ((original_stat.st_mode & 07) << 3)) != 0)
767             {
768               g_set_error (error,
769                            G_IO_ERROR,
770                            G_IO_ERROR_CANT_CREATE_BACKUP,
771                            _("Backup file creation failed"));
772               unlink (backup_filename);
773               close (bfd);
774               g_free (backup_filename);
775               goto err_out;
776             }
777         }
778 #endif
779
780       if (!copy_file_data (fd, bfd, NULL))
781         {
782           g_set_error (error,
783                        G_IO_ERROR,
784                        G_IO_ERROR_CANT_CREATE_BACKUP,
785                        _("Backup file creation failed"));
786           unlink (backup_filename);
787           close (bfd);
788           g_free (backup_filename);
789           
790           goto err_out;
791         }
792       
793       close (bfd);
794       g_free (backup_filename);
795
796       /* Seek back to the start of the file after the backup copy */
797       if (lseek (fd, 0, SEEK_SET) == -1)
798         {
799           g_set_error (error, G_IO_ERROR,
800                        g_io_error_from_errno (errno),
801                        _("Error seeking in file: %s"),
802                        g_strerror (errno));
803           goto err_out;
804         }
805     }
806
807   /* Truncate the file at the start */
808   if (ftruncate (fd, 0) == -1)
809     {
810       g_set_error (error, G_IO_ERROR,
811                    g_io_error_from_errno (errno),
812                    _("Error truncating file: %s"),
813                    g_strerror (errno));
814       goto err_out;
815     }
816     
817   return fd;
818
819  err_out:
820   close (fd);
821   return -1;
822 }
823
824 GFileOutputStream *
825 _g_local_file_output_stream_replace (const char        *filename,
826                                      const char        *etag,
827                                      gboolean           create_backup,
828                                      GFileCreateFlags   flags,
829                                      GCancellable      *cancellable,
830                                      GError           **error)
831 {
832   GLocalFileOutputStream *stream;
833   int mode;
834   int fd;
835   char *temp_file;
836
837   if (g_cancellable_set_error_if_cancelled (cancellable, error))
838     return NULL;
839
840   temp_file = NULL;
841
842   if (flags & G_FILE_CREATE_FLAGS_PRIVATE)
843     mode = 0600;
844   else
845     mode = 0666;
846
847   /* If the file doesn't exist, create it */
848   fd = g_open (filename,
849                O_CREAT | O_EXCL | O_WRONLY,
850                mode);
851
852   if (fd == -1 && errno == EEXIST)
853     {
854       /* The file already exists */
855       fd = handle_overwrite_open (filename, etag, create_backup, &temp_file,
856                                   cancellable, error);
857       if (fd == -1)
858         return NULL;
859     }
860   else if (fd == -1)
861     {
862       int errsv = errno;
863
864       if (errsv == EINVAL)
865         /* This must be an invalid filename, on e.g. FAT */
866         g_set_error (error, G_IO_ERROR,
867                      G_IO_ERROR_INVALID_FILENAME,
868                      _("Invalid filename"));
869       else
870         g_set_error (error, G_IO_ERROR,
871                      g_io_error_from_errno (errsv),
872                      _("Error opening file '%s': %s"),
873                      filename, g_strerror (errsv));
874       return NULL;
875     }
876   
877  
878   stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL);
879   stream->priv->fd = fd;
880   stream->priv->tmp_filename = temp_file;
881   if (create_backup)
882     stream->priv->backup_filename = create_backup_filename (filename);
883   stream->priv->original_filename =  g_strdup (filename);
884   
885   return G_FILE_OUTPUT_STREAM (stream);
886 }