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