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