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