| OLD | NEW |
| 1 /////////////////////////////////////////////////////////////////////////////// | 1 /////////////////////////////////////////////////////////////////////////////// |
| 2 // | 2 // |
| 3 /// \file file_io.c | 3 /// \file file_io.c |
| 4 /// \brief File opening, unlinking, and closing | 4 /// \brief File opening, unlinking, and closing |
| 5 // | 5 // |
| 6 // Author: Lasse Collin | 6 // Author: Lasse Collin |
| 7 // | 7 // |
| 8 // This file has been put into the public domain. | 8 // This file has been put into the public domain. |
| 9 // You can do whatever you want with this file. | 9 // You can do whatever you want with this file. |
| 10 // | 10 // |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 | 34 |
| 35 #ifndef O_NOCTTY | 35 #ifndef O_NOCTTY |
| 36 # define O_NOCTTY 0 | 36 # define O_NOCTTY 0 |
| 37 #endif | 37 #endif |
| 38 | 38 |
| 39 | 39 |
| 40 /// If true, try to create sparse files when decompressing. | 40 /// If true, try to create sparse files when decompressing. |
| 41 static bool try_sparse = true; | 41 static bool try_sparse = true; |
| 42 | 42 |
| 43 #ifndef TUKLIB_DOSLIKE | 43 #ifndef TUKLIB_DOSLIKE |
| 44 /// File status flags of standard output. This is used by io_open_dest() | 44 /// Original file status flags of standard output. This is used by |
| 45 /// and io_close_dest(). | 45 /// io_open_dest() and io_close_dest() to save and restore the flags. |
| 46 static int stdout_flags = 0; | 46 static int stdout_flags; |
| 47 static bool restore_stdout_flags = false; |
| 47 #endif | 48 #endif |
| 48 | 49 |
| 49 | 50 |
| 50 static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size); | 51 static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size); |
| 51 | 52 |
| 52 | 53 |
| 53 extern void | 54 extern void |
| 54 io_init(void) | 55 io_init(void) |
| 55 { | 56 { |
| 56 // Make sure that stdin, stdout, and stderr are connected to | 57 // Make sure that stdin, stdout, and stderr are connected to |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 | 391 |
| 391 # if defined(__FreeBSD__) || defined(__DragonFly__) | 392 # if defined(__FreeBSD__) || defined(__DragonFly__) |
| 392 if (errno == EMLINK) | 393 if (errno == EMLINK) |
| 393 was_symlink = true; | 394 was_symlink = true; |
| 394 | 395 |
| 395 # elif defined(__digital__) && defined(__unix__) | 396 # elif defined(__digital__) && defined(__unix__) |
| 396 if (errno == ENOTSUP) | 397 if (errno == ENOTSUP) |
| 397 was_symlink = true; | 398 was_symlink = true; |
| 398 | 399 |
| 399 # elif defined(__NetBSD__) | 400 # elif defined(__NetBSD__) |
| 400 // As of 2010-09-05, NetBSD doesn't document what errno is | |
| 401 // used with O_NOFOLLOW. It is EFTYPE though, and I | |
| 402 // understood that is very unlikely to change even though | |
| 403 // it is undocumented. | |
| 404 if (errno == EFTYPE) | 401 if (errno == EFTYPE) |
| 405 was_symlink = true; | 402 was_symlink = true; |
| 406 | 403 |
| 407 # else | 404 # else |
| 408 if (errno == ELOOP && !follow_symlinks) { | 405 if (errno == ELOOP && !follow_symlinks) { |
| 409 const int saved_errno = errno; | 406 const int saved_errno = errno; |
| 410 struct stat st; | 407 struct stat st; |
| 411 if (lstat(pair->src_name, &st) == 0 | 408 if (lstat(pair->src_name, &st) == 0 |
| 412 && S_ISLNK(st.st_mode)) | 409 && S_ISLNK(st.st_mode)) |
| 413 was_symlink = true; | 410 was_symlink = true; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 434 // Drop O_NONBLOCK, which is used only when we are accepting only | 431 // Drop O_NONBLOCK, which is used only when we are accepting only |
| 435 // regular files. After the open() call, we want things to block | 432 // regular files. After the open() call, we want things to block |
| 436 // instead of giving EAGAIN. | 433 // instead of giving EAGAIN. |
| 437 if (reg_files_only) { | 434 if (reg_files_only) { |
| 438 flags = fcntl(pair->src_fd, F_GETFL); | 435 flags = fcntl(pair->src_fd, F_GETFL); |
| 439 if (flags == -1) | 436 if (flags == -1) |
| 440 goto error_msg; | 437 goto error_msg; |
| 441 | 438 |
| 442 flags &= ~O_NONBLOCK; | 439 flags &= ~O_NONBLOCK; |
| 443 | 440 |
| 444 » » if (fcntl(pair->src_fd, F_SETFL, flags)) | 441 » » if (fcntl(pair->src_fd, F_SETFL, flags) == -1) |
| 445 goto error_msg; | 442 goto error_msg; |
| 446 } | 443 } |
| 447 #endif | 444 #endif |
| 448 | 445 |
| 449 // Stat the source file. We need the result also when we copy | 446 // Stat the source file. We need the result also when we copy |
| 450 // the permissions, and when unlinking. | 447 // the permissions, and when unlinking. |
| 451 if (fstat(pair->src_fd, &pair->src_st)) | 448 if (fstat(pair->src_fd, &pair->src_st)) |
| 452 goto error_msg; | 449 goto error_msg; |
| 453 | 450 |
| 454 if (S_ISDIR(pair->src_st.st_mode)) { | 451 if (S_ISDIR(pair->src_st.st_mode)) { |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 // - O_APPEND may be active. | 624 // - O_APPEND may be active. |
| 628 // | 625 // |
| 629 // TODO: I'm keeping this disabled for DOS-like systems | 626 // TODO: I'm keeping this disabled for DOS-like systems |
| 630 // for now. FAT doesn't support sparse files, but NTFS | 627 // for now. FAT doesn't support sparse files, but NTFS |
| 631 // does, so maybe this should be enabled on Windows after | 628 // does, so maybe this should be enabled on Windows after |
| 632 // some testing. | 629 // some testing. |
| 633 if (pair->dest_fd == STDOUT_FILENO) { | 630 if (pair->dest_fd == STDOUT_FILENO) { |
| 634 if (!S_ISREG(pair->dest_st.st_mode)) | 631 if (!S_ISREG(pair->dest_st.st_mode)) |
| 635 return false; | 632 return false; |
| 636 | 633 |
| 637 » » » const int flags = fcntl(STDOUT_FILENO, F_GETFL); | 634 » » » stdout_flags = fcntl(STDOUT_FILENO, F_GETFL); |
| 638 » » » if (flags == -1) | 635 » » » if (stdout_flags == -1) |
| 639 return false; | 636 return false; |
| 640 | 637 |
| 641 » » » if (flags & O_APPEND) { | 638 » » » if (stdout_flags & O_APPEND) { |
| 642 // Creating a sparse file is not possible | 639 // Creating a sparse file is not possible |
| 643 // when O_APPEND is active (it's used by | 640 // when O_APPEND is active (it's used by |
| 644 // shell's >> redirection). As I understand | 641 // shell's >> redirection). As I understand |
| 645 // it, it is safe to temporarily disable | 642 // it, it is safe to temporarily disable |
| 646 // O_APPEND in xz, because if someone | 643 // O_APPEND in xz, because if someone |
| 647 // happened to write to the same file at the | 644 // happened to write to the same file at the |
| 648 // same time, results would be bad anyway | 645 // same time, results would be bad anyway |
| 649 // (users shouldn't assume that xz uses any | 646 // (users shouldn't assume that xz uses any |
| 650 // specific block size when writing data). | 647 // specific block size when writing data). |
| 651 // | 648 // |
| 652 // The write position may be something else | 649 // The write position may be something else |
| 653 // than the end of the file, so we must fix | 650 // than the end of the file, so we must fix |
| 654 // it to start writing at the end of the file | 651 // it to start writing at the end of the file |
| 655 // to imitate O_APPEND. | 652 // to imitate O_APPEND. |
| 656 if (lseek(STDOUT_FILENO, 0, SEEK_END) == -1) | 653 if (lseek(STDOUT_FILENO, 0, SEEK_END) == -1) |
| 657 return false; | 654 return false; |
| 658 | 655 |
| 659 if (fcntl(STDOUT_FILENO, F_SETFL, | 656 if (fcntl(STDOUT_FILENO, F_SETFL, |
| 660 » » » » » » stdout_flags & ~O_APPEND)) | 657 » » » » » » stdout_flags & ~O_APPEND) |
| 658 » » » » » » == -1) |
| 661 return false; | 659 return false; |
| 662 | 660 |
| 663 » » » » // Remember the flags so that io_close_dest() | 661 » » » » // Disabling O_APPEND succeeded. Mark |
| 664 » » » » // can restore them. | 662 » » » » // that the flags should be restored |
| 665 » » » » stdout_flags = flags; | 663 » » » » // in io_close_dest(). |
| 664 » » » » restore_stdout_flags = true; |
| 666 | 665 |
| 667 } else if (lseek(STDOUT_FILENO, 0, SEEK_CUR) | 666 } else if (lseek(STDOUT_FILENO, 0, SEEK_CUR) |
| 668 != pair->dest_st.st_size) { | 667 != pair->dest_st.st_size) { |
| 669 // Writing won't start exactly at the end | 668 // Writing won't start exactly at the end |
| 670 // of the file. We cannot use sparse output, | 669 // of the file. We cannot use sparse output, |
| 671 // because it would probably corrupt the file. | 670 // because it would probably corrupt the file. |
| 672 return false; | 671 return false; |
| 673 } | 672 } |
| 674 } | 673 } |
| 675 | 674 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 696 /// \param pair File whose dest_fd should be closed | 695 /// \param pair File whose dest_fd should be closed |
| 697 /// \param success If false, the file will be removed from the disk. | 696 /// \param success If false, the file will be removed from the disk. |
| 698 /// | 697 /// |
| 699 /// \return Zero if closing succeeds. On error, -1 is returned and | 698 /// \return Zero if closing succeeds. On error, -1 is returned and |
| 700 /// error message printed. | 699 /// error message printed. |
| 701 static bool | 700 static bool |
| 702 io_close_dest(file_pair *pair, bool success) | 701 io_close_dest(file_pair *pair, bool success) |
| 703 { | 702 { |
| 704 #ifndef TUKLIB_DOSLIKE | 703 #ifndef TUKLIB_DOSLIKE |
| 705 // If io_open_dest() has disabled O_APPEND, restore it here. | 704 // If io_open_dest() has disabled O_APPEND, restore it here. |
| 706 » if (stdout_flags != 0) { | 705 » if (restore_stdout_flags) { |
| 707 assert(pair->dest_fd == STDOUT_FILENO); | 706 assert(pair->dest_fd == STDOUT_FILENO); |
| 708 | 707 |
| 709 » » const int fail = fcntl(STDOUT_FILENO, F_SETFL, stdout_flags); | 708 » » restore_stdout_flags = false; |
| 710 » » stdout_flags = 0; | |
| 711 | 709 |
| 712 » » if (fail) { | 710 » » if (fcntl(STDOUT_FILENO, F_SETFL, stdout_flags) == -1) { |
| 713 message_error(_("Error restoring the O_APPEND flag " | 711 message_error(_("Error restoring the O_APPEND flag " |
| 714 "to standard output: %s"), | 712 "to standard output: %s"), |
| 715 strerror(errno)); | 713 strerror(errno)); |
| 716 return true; | 714 return true; |
| 717 } | 715 } |
| 718 } | 716 } |
| 719 #endif | 717 #endif |
| 720 | 718 |
| 721 if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO) | 719 if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO) |
| 722 return false; | 720 return false; |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 static bool | 873 static bool |
| 876 io_write_buf(file_pair *pair, const uint8_t *buf, size_t size) | 874 io_write_buf(file_pair *pair, const uint8_t *buf, size_t size) |
| 877 { | 875 { |
| 878 assert(size < SSIZE_MAX); | 876 assert(size < SSIZE_MAX); |
| 879 | 877 |
| 880 while (size > 0) { | 878 while (size > 0) { |
| 881 const ssize_t amount = write(pair->dest_fd, buf, size); | 879 const ssize_t amount = write(pair->dest_fd, buf, size); |
| 882 if (amount == -1) { | 880 if (amount == -1) { |
| 883 if (errno == EINTR) { | 881 if (errno == EINTR) { |
| 884 if (user_abort) | 882 if (user_abort) |
| 885 » » » » » return -1; | 883 » » » » » return true; |
| 886 | 884 |
| 887 continue; | 885 continue; |
| 888 } | 886 } |
| 889 | 887 |
| 890 // Handle broken pipe specially. gzip and bzip2 | 888 // Handle broken pipe specially. gzip and bzip2 |
| 891 // don't print anything on SIGPIPE. In addition, | 889 // don't print anything on SIGPIPE. In addition, |
| 892 // gzip --quiet uses exit status 2 (warning) on | 890 // gzip --quiet uses exit status 2 (warning) on |
| 893 // broken pipe instead of whatever raise(SIGPIPE) | 891 // broken pipe instead of whatever raise(SIGPIPE) |
| 894 // would make it return. It is there to hide "Broken | 892 // would make it return. It is there to hide "Broken |
| 895 // pipe" message on some old shells (probably old | 893 // pipe" message on some old shells (probably old |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 strerror(errno)); | 946 strerror(errno)); |
| 949 return true; | 947 return true; |
| 950 } | 948 } |
| 951 | 949 |
| 952 pair->dest_pending_sparse = 0; | 950 pair->dest_pending_sparse = 0; |
| 953 } | 951 } |
| 954 } | 952 } |
| 955 | 953 |
| 956 return io_write_buf(pair, buf->u8, size); | 954 return io_write_buf(pair, buf->u8, size); |
| 957 } | 955 } |
| OLD | NEW |