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